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