Date: Friday, February 24, 2006 @ 16:12:43
  Author: marc
    Path: /cvsroot/carob/odbsequoia/src

   Added: descriptors.cpp (1.1) descriptors.hpp (1.1)
          descriptors_records.cpp (1.1) descriptors_records.hpp (1.1)
Modified: GNUmakefile (1.5 -> 1.6) stmt.cpp (1.13 -> 1.14) stmt.hpp (1.10
          -> 1.11)

First draft implementation of SQLBindCol() and SQLFetch(). Features new 
descriptor and descriptor_records classes.


-------------------------+
 GNUmakefile             |   12 ++-
 descriptors.cpp         |  152 +++++++++++++++++++++++++++++++++++++++++++
 descriptors.hpp         |  161 ++++++++++++++++++++++++++++++++++++++++++++++
 descriptors_records.cpp |   60 +++++++++++++++++
 descriptors_records.hpp |  116 +++++++++++++++++++++++++++++++++
 stmt.cpp                |   65 ++++++++++++++++++
 stmt.hpp                |   27 ++++++-
 7 files changed, 586 insertions(+), 7 deletions(-)


Index: odbsequoia/src/GNUmakefile
diff -u odbsequoia/src/GNUmakefile:1.5 odbsequoia/src/GNUmakefile:1.6
--- odbsequoia/src/GNUmakefile:1.5      Thu Jan 12 23:42:37 2006
+++ odbsequoia/src/GNUmakefile  Fri Feb 24 16:12:43 2006
@@ -29,7 +29,7 @@
 CAROB=carob
 
 
-OBJS=util.o explicit_type.o env.o connect.o stmt.o abstract_item.o
+OBJS=util.o explicit_type.o env.o connect.o stmt.o abstract_item.o 
descriptors.o descriptors_records.o
 CXXFLAGS=-Wall -g3 -I${CAROB_PATH}/include
 
 all: a.out
@@ -43,11 +43,17 @@
 
 # libcarob.a needs -lpthread
 ${LIB}:        ${OBJS} ${CAROB_PATH}/lib${CAROB}.a
-       c++ ${CXXFLAGS} -shared $^ -lpthread -lodbcinst -o $@
+       ${CXX} ${CXXFLAGS} -shared $^ -lpthread -lodbcinst -o $@
 
 clean:
        rm -f ${LIB} ${LIBSHORT} a.out ${OBJS}
 
 # useful to detect linking issues *before* the driver manager gets them
 linktest: ${LIBSHORT}
-       c++ dummymain.cpp ${LIBSHORT} -lodbc -lodbcinst -o $@
+       ${CXX} dummymain.cpp ${LIBSHORT} -lodbc -lodbcinst -o $@
+
+# compile each .hpp, isolated
+checkheaders:
+       for h in *.hpp; do ln -sf $$h someheader.cpp; \
+       printf "compiling $$h\n"; \
+       ${CXX} -c ${CXXFLAGS} someheader.cpp; done
Index: odbsequoia/src/descriptors.cpp
diff -u /dev/null odbsequoia/src/descriptors.cpp:1.1
--- /dev/null   Fri Feb 24 16:12:43 2006
+++ odbsequoia/src/descriptors.cpp      Fri Feb 24 16:12:43 2006
@@ -0,0 +1,152 @@
+/*
+ * Sequoia: Database clustering technology.
+ * Copyright (C) 2006 Continuent, Inc.
+ * Contact: [EMAIL PROTECTED]
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Initial developer(s): Marc Herbert
+ * Contributor(s): 
+ */
+
+
+#include "descriptors.hpp"
+
+#include "util.hpp"
+
+// scatter these classes into multiple files when this file becomes too big
+
+using namespace ODBSeqNS;
+
+/*** BaseDesc methods ***/
+
+ODBCBaseDesc::~ODBCBaseDesc()
+{
+    // unbind all remaining records
+    for (std::vector<BaseDescRecord *>::const_iterator reci = records.begin();
+         reci != records.end(); reci++)
+        if (*reci != 0)
+            delete *reci;
+
+}
+
+SQLRETURN
+ODBCBaseDesc::resize(size_t newsize)
+{
+    if (newsize > records.capacity())
+        records.reserve(4 * records.capacity());
+    records.resize(newsize, 0);
+
+    return SQL_SUCCESS;
+}
+
+
+/*** AppDesc methods ***/
+
+ODBCAppDesc::~ODBCAppDesc()
+{
+    // TODO: if we were alloc'ed by user, browse all statements owned
+    // by our connection and re-tie them to their default AppDesc.
+}
+
+SQLRETURN
+ODBCAppDesc::unbind_record(size_t recnum)
+{
+    delete records.at(recnum);
+    
+    if (recnum == count() // unbounding highest record
+        && recnum > 0 ) // unbounding a regular record (not a bookmark)        
+    {
+        // adjustment needed
+        SQLUSMALLINT newcount = recnum-1;
+        while (newcount > 0 && records[newcount] == 0)
+            newcount--;
+
+        recount(newcount);
+    }
+
+    return SQL_SUCCESS;
+
+}
+
+
+SQLRETURN
+ODBCAppDesc::bind_col(SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType,
+                      SQLPOINTER TargetValuePtr, SQLINTEGER BufferLength,
+                      SQLLEN * StrLen_or_Ind)
+{
+    if (ColumnNumber > count())
+    {
+        recount(ColumnNumber);
+        records.at(ColumnNumber) = new AppDescRecord();
+    }
+
+    AppDescRecord * apprec = static_cast<AppDescRecord 
*>(records[ColumnNumber]);
+
+    return apprec->bind_col(TargetType, TargetValuePtr, BufferLength, 
StrLen_or_Ind);
+}
+
+
+/** Fetch the current row of the DriverResultSet into our buffers */
+SQLRETURN
+ODBCAppDesc::fetchRow(CarobNS::DriverResultSet& rs)
+{
+    // FIXME: work in progress, not even half-implemented
+
+    int rs_col_end = rs.getNumberOfColumns() + 1;
+
+    std::vector<BaseDescRecord *>::const_iterator rec_col = records.begin();
+    rec_col++; // skip bookmark 0
+    int rs_col = 1;
+    for ( ;
+          rec_col != records.end() && rs_col < rs_col_end;
+          rec_col++, rs_col++)
+    {
+        if (*rec_col != 0) // is this row bound ? Else ignore it
+        {
+            AppDescRecord& rec = * static_cast<AppDescRecord *>(*rec_col);
+
+            if (rs.isNull(rs_col))
+            {
+                if (0 == rec.indicator_ptr)
+                    throw ODBSeqException(L"22002",
+                                          L"Cannot flag SQL_NULL_DATA"
+                                          L"because indicator_ptr is null");
+   
+                * rec.indicator_ptr = SQL_NULL_DATA;
+                continue;
+            }
+
+            // case (type == SQL_C_INT)
+            * static_cast<int *>(rec.data_ptr) = rs.getAsInt(rs_col);
+            if (rec.octet_length_ptr != 0)
+                * rec.octet_length_ptr = sizeof(int);
+
+        }
+    }
+
+    // if (rec_col != records.end())
+    //     not enough columns for the descriptor!!
+    //     Unfortunately we should have reported this error at SQLBindCol() 
time
+
+
+    return SQL_SUCCESS;
+}
+
+/*
+ * Local Variables:
+ * c-file-style: "bsd"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
Index: odbsequoia/src/descriptors.hpp
diff -u /dev/null odbsequoia/src/descriptors.hpp:1.1
--- /dev/null   Fri Feb 24 16:12:43 2006
+++ odbsequoia/src/descriptors.hpp      Fri Feb 24 16:12:43 2006
@@ -0,0 +1,161 @@
+
+/*
+ * Sequoia: Database clustering technology.
+ * Copyright (C) 2006 Continuent, Inc.
+ * Contact: [EMAIL PROTECTED]
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Initial developer(s): Marc Herbert
+ * Contributor(s): 
+ */
+
+#ifndef ODBSEQ_DESCRIPTORS
+#define ODBSEQ_DESCRIPTORS
+
+#include "abstract_item.hpp"
+
+#include "descriptors_records.hpp"
+
+#include "DriverResultSet.hpp"
+
+#include <vector>
+
+#include <sql.h>
+#include <sqlucode.h>
+
+class CarobNS::DriverResultSet;
+
+namespace ODBSeqNS {
+
+
+/** Base class for descriptors */
+
+class ODBCBaseDesc : public ODBCItem
+{
+
+public:
+
+    size_t
+    size() { return records.size(); }
+
+    size_t
+    count() { return (this->size() - 1); }
+
+    virtual
+    ~ODBCBaseDesc();
+
+protected:
+    /** Only derived classes can be constructed */
+    ODBCBaseDesc(const ODBCItem &creator, bool explicit_alloc) :
+        ODBCItem(creator),
+        alloc_user(explicit_alloc),
+        // column 0 (bookmark) is always there, even when not supported and 
NULL
+        records(1, static_cast<BaseDescRecord*>(0))
+    {  }
+
+    /** Warning: caller must manually allocate/delete pointed-to records! */
+    SQLRETURN
+    resize(size_t newsize);
+
+    SQLRETURN
+    recount(size_t newcount) { return resize(newcount + 1); }
+
+    const bool alloc_user; //  SQL_DESC_ALLOC_USER / SQL_DESC_ALLOC_AUTO
+
+protected:
+    std::vector<BaseDescRecord *> records;
+
+private:
+    // forbid copy ctor & assignement because of the pointers to records
+    ODBCBaseDesc(const ODBCBaseDesc& orig);
+    ODBCBaseDesc& operator=(const ODBCBaseDesc& orig);
+
+};
+
+
+/** Application Row/Parameter Descriptor */
+
+class ODBCAppDesc : public ODBCBaseDesc
+{
+public:
+
+    ODBCAppDesc(const ODBCItem &creator, bool explicit_alloc) :
+        ODBCBaseDesc(creator, explicit_alloc)
+    { };
+
+    ~ODBCAppDesc();
+
+    /** Takes care of size (count) adjustment */
+    SQLRETURN
+    unbind_record(size_t col);
+
+    /** Takes care of size (count) adjustment */
+    SQLRETURN
+    bind_col(SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType,
+             SQLPOINTER TargetValuePtr, SQLINTEGER BufferLength,
+             SQLLEN * StrLen_or_Ind);
+
+    SQLRETURN
+    ODBCAppDesc::fetchRow(CarobNS::DriverResultSet& rs);
+
+};
+
+
+/** Abstract Implementation Descriptor */
+
+class ODBCImplDesc : public ODBCBaseDesc
+{
+
+protected:
+    ODBCImplDesc(const ODBCItem& creator) :
+        ODBCBaseDesc(creator, false)
+    { } ;
+};
+
+/** Implementation Row Descriptor */
+
+class ODBCImplRowDesc : public ODBCImplDesc
+{
+public:
+    ODBCImplRowDesc(const ODBCItem& creator) :
+        ODBCImplDesc(creator)
+    { } ;
+};
+
+/** Implementation Parameter Descriptor */
+
+class ODBCImplParamDesc : public ODBCImplDesc
+{
+public:
+    ODBCImplParamDesc(const ODBCItem& creator) :
+        ODBCImplDesc(creator)
+    { } ;
+};
+
+
+} // namespace ODBSeqNS
+
+
+#endif // include only once
+
+
+
+/*
+ * Local Variables:
+ * c-file-style: "bsd"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
+
Index: odbsequoia/src/descriptors_records.cpp
diff -u /dev/null odbsequoia/src/descriptors_records.cpp:1.1
--- /dev/null   Fri Feb 24 16:12:43 2006
+++ odbsequoia/src/descriptors_records.cpp      Fri Feb 24 16:12:43 2006
@@ -0,0 +1,60 @@
+/*
+ * Sequoia: Database clustering technology.
+ * Copyright (C) 2006 Continuent, Inc.
+ * Contact: [EMAIL PROTECTED]
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Initial developer(s): Marc Herbert
+ * Contributor(s): 
+ */
+
+
+#include "descriptors_records.hpp"
+
+using namespace ODBSeqNS;
+
+/**** Base records ***/
+
+SQLRETURN
+BaseDescRecord::set_type(SQLSMALLINT concise_arg)
+{
+    // FIXME: set all other interdependent fields
+    concise_type = concise_arg;
+    return SQL_SUCCESS;
+}
+
+/**** Application records ***/
+
+SQLRETURN
+AppDescRecord::bind_col(SQLSMALLINT TargetType, SQLPOINTER TargetValuePtr,
+                        SQLINTEGER BufferLength, SQLLEN * StrLen_or_Ind)
+{
+    set_type(TargetType);
+
+    octet_length = BufferLength;
+    data_ptr = TargetValuePtr;
+
+    indicator_ptr = StrLen_or_Ind;
+    octet_length_ptr = StrLen_or_Ind;
+
+    return SQL_SUCCESS;
+}
+
+/*
+ * Local Variables:
+ * c-file-style: "bsd"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
Index: odbsequoia/src/descriptors_records.hpp
diff -u /dev/null odbsequoia/src/descriptors_records.hpp:1.1
--- /dev/null   Fri Feb 24 16:12:43 2006
+++ odbsequoia/src/descriptors_records.hpp      Fri Feb 24 16:12:43 2006
@@ -0,0 +1,116 @@
+
+/*
+ * Sequoia: Database clustering technology.
+ * Copyright (C) 2006 Continuent, Inc.
+ * Contact: [EMAIL PROTECTED]
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Initial developer(s): Marc Herbert
+ * Contributor(s): 
+ */
+
+#ifndef ODBSEQ_DESC_RECORDS
+#define ODBSEQ_DESC_RECORDS
+
+
+#include <sql.h>
+#include <sqlucode.h>
+
+
+namespace ODBSeqNS {
+
+
+/** Part of records common to all descriptors */
+
+class BaseDescRecord
+{
+public: 
+    // Very simple fields are public to avoid cluttering the code with
+    // getters/setters You did not believe descriptors and records
+    // classes are well separated by a clear interface, did you?
+    SQLINTEGER octet_length;
+
+    /** Sets the concise type as well as all other interdependent fields */
+    SQLRETURN
+    set_type(SQLSMALLINT concise_arg);
+
+    virtual ~BaseDescRecord() { }
+
+private:
+    // Those are private because we want to enforce some consistency.
+    // concise = type + datetime_interval_code, see
+    // table in "Data Type Identifiers and Descriptors" ODBC page.
+    SQLSMALLINT concise_type;
+//     SQLSMALLINT type;
+//     SQLSMALLINT datetime_interval_code;
+};
+
+/** Derived class specific to Application Descriptors */
+
+class AppDescRecord : public BaseDescRecord
+{
+public:
+    /** Default constructor */
+    AppDescRecord() : data_ptr(0) { }
+
+    SQLRETURN
+    bind_col(SQLSMALLINT TargetType, SQLPOINTER TargetValuePtr,
+             SQLINTEGER BufferLength, SQLLEN * StrLen_or_Ind);
+
+public: // public to avoid cluttering the code with getters/setters
+    SQLPOINTER data_ptr;
+    /** Warning: null is allowed. Check SQLBindCol() documentation */
+    SQLINTEGER * indicator_ptr;
+    /** Warning: null is allowed. Check SQLBindCol() documentation */
+    SQLINTEGER * octet_length_ptr;
+};
+
+/** Derived class specific to Implementation Descriptors */
+
+class ImplDescRecord : public BaseDescRecord
+{
+
+};
+
+/** Derived class for Implementation Row Descriptor record */
+
+class ImplRowDescRecord : public ImplDescRecord
+{
+
+};
+
+/** Derived class for Implementation Parameter Descriptor record */
+
+class ImplParamDescRecord : public ImplDescRecord
+{
+
+};
+
+
+
+} // namespace ODBSeqNS
+
+
+#endif // include only once
+
+
+
+/*
+ * Local Variables:
+ * c-file-style: "bsd"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
+
Index: odbsequoia/src/stmt.cpp
diff -u odbsequoia/src/stmt.cpp:1.13 odbsequoia/src/stmt.cpp:1.14
--- odbsequoia/src/stmt.cpp:1.13        Fri Feb 24 16:08:55 2006
+++ odbsequoia/src/stmt.cpp     Fri Feb 24 16:12:43 2006
@@ -83,6 +83,71 @@
     return SQL_SUCCESS;
 }
 
+SQLRETURN
+SQLBindCol(SQLHSTMT StatementHandle,
+           SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType,
+           SQLPOINTER TargetValuePtr, SQLINTEGER BufferLength,
+           SQLLEN * StrLen_or_Ind)
+{
+    ODBCStatement * self_p = objectify(StatementHandle);
+    self_p->clear_diags();
+
+    _PROTECT_SQLRETURN(self_p,
+                       bind_col(ColumnNumber, TargetType, TargetValuePtr,
+                                BufferLength, StrLen_or_Ind));
+}
+
+SQLRETURN
+ODBCStatement::bind_col(SQLUSMALLINT col, SQLSMALLINT type,
+                        SQLPOINTER buf, SQLINTEGER buflen,
+                        SQLLEN * len_or_ind)
+{
+    if (0 == buf) // unbinding
+    {       
+        if (col < ARD->size())
+            return ARD->unbind_record(col);
+        // else the spec does not ask for an error?
+    }
+
+    SQLRETURN retcode = ARD->bind_col(col, type, buf, buflen, len_or_ind);
+
+    return retcode;
+}
+
+SQLRETURN
+SQLFetch(SQLHSTMT StatementHandle)
+{
+    ODBCStatement * self_p = objectify(StatementHandle);
+    self_p->clear_diags();
+
+    _PROTECT_SQLRETURN(self_p, fetch());
+
+}
+
+SQLRETURN
+ODBCStatement::fetch()
+{
+    // FIXME: work in progress, not even half-implemented
+
+    if (this->state == S4)
+        throw ODBSeqException(L"24000",
+                              L"No ResultSet available");
+
+    if (this->state != S5 && this->state != S6)
+        throw ODBSeqException(L"HY010",
+                              L"Invalid state, no current ResultSet"
+                              " (TODO: print current state)");
+
+    // FIXME: catch exception to set the correct SQLState here?
+    // Or rather ask carob to set it.
+    carob_stmt->getResultSet()->next();
+
+    if (this->state == S5)
+        this->state = S6;
+
+    return ARD->fetchRow(*(carob_stmt->getResultSet()));
+
+}
 
 SQLRETURN
 ODBCStatement::get_header_diag_fieldw(SQLSMALLINT DiagIdentifier,
Index: odbsequoia/src/stmt.hpp
diff -u odbsequoia/src/stmt.hpp:1.10 odbsequoia/src/stmt.hpp:1.11
--- odbsequoia/src/stmt.hpp:1.10        Fri Feb 24 15:55:45 2006
+++ odbsequoia/src/stmt.hpp     Fri Feb 24 16:12:43 2006
@@ -19,8 +19,10 @@
  * Contributor(s): 
  */
 
-#ifndef ODBSEQ_NS
-#define ODBSEQ_NS
+#ifndef ODBSEQ_STMT
+#define ODBSEQ_STMT
+
+#include "descriptors.hpp"
 
 #include "connect.hpp"
 
@@ -31,7 +33,7 @@
 
 namespace ODBSeqNS {
 
-enum stmt_state_t { S0, S1, S4, S5 };
+    enum stmt_state_t { S0, S1, S4, S5, S6 };
 
 class ODBCStatement : public ODBCItem
 {
@@ -40,11 +42,20 @@
     stmt_state_t state;  // state according to "Statement Transitions"
                          // in the ODBC reference (as far as
                          // possible).
-    ODBCStatement(const ODBCConnection& creator) : ODBCItem(creator)
+    ODBCStatement(const ODBCConnection& creator) : 
+        ODBCItem(creator),
+        IRD(*this), IPD(*this),
+        implicit_ARD(*this, false), implicit_APD(*this, false),
+        ARD(&implicit_ARD), APD(&implicit_APD)
     { state = S0; };
     SQLRETURN
     exec_directw(const SQLWCHAR *StatementText, SQLINTEGER TextLength);
     
+    SQLRETURN
+    bind_col(SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType,
+             SQLPOINTER TargetValuePtr, SQLINTEGER BufferLength,
+             SQLLEN * StrLen_or_Ind);
+
     const std::wstring&
     get_carob_diagids() const
     {   // the owning connection has the prefix/knows the source 
@@ -72,6 +83,14 @@
                            SQLPOINTER DiagInfoPtr,
                            SQLSMALLINT BufferLength, SQLSMALLINT * 
StringLengthPtr)
         const;
+
+private:
+    ODBCImplParamDesc IRD;
+    ODBCImplRowDesc IPD;
+    ODBCAppDesc implicit_ARD;
+    ODBCAppDesc implicit_APD;
+    ODBCAppDesc *ARD, *APD; // pointers because these one can be overriden
+
 };
 
 

_______________________________________________
Carob-commits mailing list
[email protected]
https://forge.continuent.org/mailman/listinfo/carob-commits

Reply via email to