Date: Monday, December 19, 2005 @ 19:41:57
Author: zsolt
Path: /cvsroot/carob/carob
Added: include/PreparedStatement.hpp (1.1) src/PreparedStatement.cpp
(1.1)
Modified: .cdtproject (1.5 -> 1.6) Makefile (1.26 -> 1.27)
include/Connection.hpp (1.36 -> 1.37) include/Statement.hpp
(1.15 -> 1.16) src/Connection.cpp (1.43 -> 1.44)
src/Statement.cpp (1.16 -> 1.17)
implemented prepared statements
-------------------------------+
.cdtproject | 34 ++--
Makefile | 1
include/Connection.hpp | 10 +
include/PreparedStatement.hpp | 292 ++++++++++++++++++++++++++++++++++++++++
include/Statement.hpp | 20 +-
src/Connection.cpp | 11 +
src/PreparedStatement.cpp | 180 ++++++++++++++++++++++++
src/Statement.cpp | 22 +--
8 files changed, 535 insertions(+), 35 deletions(-)
Index: carob/.cdtproject
diff -u carob/.cdtproject:1.5 carob/.cdtproject:1.6
--- carob/.cdtproject:1.5 Mon Dec 19 17:19:38 2005
+++ carob/.cdtproject Mon Dec 19 19:41:57 2005
@@ -2,14 +2,14 @@
<?eclipse-cdt version="2.0"?>
<cdtproject id="org.eclipse.cdt.make.core.make">
-<extension point="org.eclipse.cdt.core.BinaryParser"
id="org.eclipse.cdt.core.ELF"/>
-<extension point="org.eclipse.cdt.core.CIndexer"
id="org.eclipse.cdt.core.nullindexer"/>
+<extension id="org.eclipse.cdt.core.ELF"
point="org.eclipse.cdt.core.BinaryParser"/>
+<extension id="org.eclipse.cdt.core.domsourceindexer"
point="org.eclipse.cdt.core.CIndexer"/>
<data>
<item id="org.eclipse.cdt.core.pathentry">
-<pathentry kind="inc" path="contrib/PHP/php_carob.h"
include="/usr/include/php5/main" system="true"/>
-<pathentry kind="inc" path="" include="/usr/include" system="true"/>
-<pathentry kind="inc" path="" include="/usr/include/c++/4.0" system="true"/>
-<pathentry kind="inc" path="" include="include" system="true"
base-path="carob"/>
+<pathentry include="/usr/include/php5/main" kind="inc"
path="contrib/PHP/php_carob.h" system="true"/>
+<pathentry include="/usr/include" kind="inc" path="" system="true"/>
+<pathentry include="/usr/include/c++/4.0" kind="inc" path="" system="true"/>
+<pathentry base-path="carob" include="include" kind="inc" path=""
system="true"/>
<pathentry kind="src" path=""/>
<pathentry kind="out" path=""/>
<pathentry kind="con"
path="org.eclipse.cdt.make.core.DISCOVERED_SCANNER_INFO"/>
@@ -20,42 +20,42 @@
</item>
<item id="org.eclipse.cdt.make.core.buildtargets">
<buildTargets>
-<target name="all" targetID="org.eclipse.cdt.make.MakeTargetBuilder" path="">
+<target name="all" path="" targetID="org.eclipse.cdt.make.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>all</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
</target>
-<target name="clean" targetID="org.eclipse.cdt.make.MakeTargetBuilder" path="">
+<target name="clean" path="" targetID="org.eclipse.cdt.make.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>clean</buildTarget>
<stopOnError>false</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
</target>
-<target name="doc" targetID="org.eclipse.cdt.make.MakeTargetBuilder" path="">
+<target name="doc" path="" targetID="org.eclipse.cdt.make.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>doc</buildTarget>
<stopOnError>false</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
</target>
-<target name="test" targetID="org.eclipse.cdt.make.MakeTargetBuilder" path="">
+<target name="test" path="" targetID="org.eclipse.cdt.make.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>test</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
</target>
-<target name="clean-test" targetID="org.eclipse.cdt.make.MakeTargetBuilder"
path="">
+<target name="clean-test" path=""
targetID="org.eclipse.cdt.make.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>clean-test</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
</target>
-<target name="clean-doc" targetID="org.eclipse.cdt.make.MakeTargetBuilder"
path="">
+<target name="clean-doc" path=""
targetID="org.eclipse.cdt.make.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>clean-doc</buildTarget>
@@ -65,14 +65,14 @@
</buildTargets>
</item>
<item id="scannerConfiguration">
-<autodiscovery enabled="true"
selectedProfileId="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile"
problemReportingEnabled="true"/>
+<autodiscovery enabled="true" problemReportingEnabled="true"
selectedProfileId="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile"/>
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
-<runAction useDefault="true" command="gcc" arguments="-E -P -v -dD
${plugin_state_location}/${specs_file}"/>
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}"
command="gcc" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
@@ -82,7 +82,7 @@
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="makefileGenerator">
-<runAction useDefault="true" command="make" arguments="-f
${project_name}_scd.mk"/>
+<runAction arguments="-f ${project_name}_scd.mk" command="make"
useDefault="true"/>
<parser enabled="false"/>
</scannerInfoProvider>
</profile>
@@ -92,7 +92,7 @@
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
-<runAction useDefault="true" command="gcc" arguments="-E -P -v -dD
${plugin_state_location}/${specs_file}"/>
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}"
command="gcc" useDefault="true"/>
<parser enabled="false"/>
</scannerInfoProvider>
</profile>
@@ -102,7 +102,7 @@
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
-<runAction useDefault="true" command="gcc" arguments="-E -P -v -dD
${plugin_state_location}/${specs_file}"/>
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}"
command="gcc" useDefault="true"/>
<parser enabled="false"/>
</scannerInfoProvider>
</profile>
Index: carob/Makefile
diff -u carob/Makefile:1.26 carob/Makefile:1.27
--- carob/Makefile:1.26 Thu Dec 15 21:05:43 2005
+++ carob/Makefile Mon Dec 19 19:41:57 2005
@@ -50,6 +50,7 @@
${SRCDIR}/DriverResultSet.o\
${SRCDIR}/Field.o\
${SRCDIR}/Statement.o\
+ ${SRCDIR}/PreparedStatement.o\
${SRCDIR}/BigDecimal.o\
${SRCDIR}/SQLDataSerialization.o\
${SRCDIR}/StringCodecs.o\
Index: carob/include/Connection.hpp
diff -u carob/include/Connection.hpp:1.36 carob/include/Connection.hpp:1.37
--- carob/include/Connection.hpp:1.36 Mon Dec 19 09:35:13 2005
+++ carob/include/Connection.hpp Mon Dec 19 19:41:57 2005
@@ -16,7 +16,7 @@
* limitations under the License.
*
* Initial developer(s): Gilles Rayrat
- * Contributor(s):
+ * Contributor(s): Zsolt Simon
*/
#ifndef _CONNECTION_H_
@@ -94,6 +94,7 @@
//#define DatabaseStaticMetadata 80
class Statement;
+class PreparedStatement;
/**
* This class implements the communication protocol to the Controller.
* <p>
@@ -172,6 +173,13 @@
Statement* createStatement() throw (SocketIOException,
UnexpectedException);
/**
+ * Creates a prepared statement.
+ * @param query a sql skeleton query
+ * @return a new <code>PreparedStatement</code> object
+ */
+ PreparedStatement* prepareStatement(const std::wstring &query)
+ throw (SocketIOException, UnexpectedException);
+ /**
* Performs a read request and returns the reply.
*
* @param request the read request with result set parameters to execute
Index: carob/include/PreparedStatement.hpp
diff -u /dev/null carob/include/PreparedStatement.hpp:1.1
--- /dev/null Mon Dec 19 19:41:57 2005
+++ carob/include/PreparedStatement.hpp Mon Dec 19 19:41:57 2005
@@ -0,0 +1,292 @@
+/*
+ * Sequoia: Database clustering technology.
+ * Copyright (C) 2005 Emic Networks
+ * 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): Zsolt Simon
+ * Contributor(s):
+ */
+#ifndef PREPAREDSTATEMENT_HPP_
+#define PREPAREDSTATEMENT_HPP_
+
+#include <string>
+#include <list>
+#include <vector>
+
+#include "CarobException.hpp"
+#include "Statement.hpp"
+#include "BigDecimal.hpp"
+
+namespace CarobNS {
+
+/**
+ * All tags must have the same length
+ */
+const std::wstring BYTE_TAG = L"b|";
+const std::wstring BYTES_TAG = L"B|";
+const std::wstring BLOB_TAG = L"c|";
+const std::wstring CLOB_TAG = L"C|";
+const std::wstring BOOLEAN_TAG = L"0|";
+const std::wstring BIG_DECIMAL_TAG = L"1|";
+const std::wstring DATE_TAG = L"d|";
+const std::wstring DOUBLE_TAG = L"D|";
+const std::wstring FLOAT_TAG = L"F|";
+const std::wstring INTEGER_TAG = L"I|";
+const std::wstring LONG_TAG = L"L|";
+const std::wstring NULL_TAG = L"N|";
+const std::wstring NULL_STRING_TAG = L"n|";
+const std::wstring OBJECT_TAG = L"O|";
+const std::wstring REF_TAG = L"R|";
+const std::wstring SHORT_TAG = L"s|";
+const std::wstring STRING_TAG = L"S|";
+const std::wstring TIME_TAG = L"t|";
+const std::wstring TIMESTAMP_TAG = L"T|";
+const std::wstring URL_TAG = L"U|";
+const std::wstring REGISTER_OUT_PARAMETER = L"o|";
+const std::wstring REGISTER_OUT_PARAMETER_WITH_SCALE = L"w|";
+const std::wstring REGISTER_OUT_PARAMETER_WITH_NAME = L"W|";
+
+/** Tag maker for parameters */
+const std::wstring TAG_MARKER = L"!%";
+/** Escape for tag maker */
+const std::wstring TAG_MARKER_ESCAPE = TAG_MARKER
+ + L";";
+
+/** Tag for parameters start delimiter */
+const std::wstring START_PARAM_TAG = L"<"
+ + TAG_MARKER;
+/** Tag for parameters end delimiter */
+const std::wstring END_PARAM_TAG = L"|"
+ + TAG_MARKER
+ + L">";
+
+const std::wstring wsBoolFalse = L"false";
+const std::wstring wsBoolTrue = L"true";
+
+class Connection;
+
+/**
+ * A SQL Statement is pre-compiled and stored in a
+ * <code>PreparedStatement</code> object. This object can then be used to
+ * efficiently execute this statement multiple times.
+ * <p>
+ * <b>Note: </b> The setXXX methods for setting IN parameter values must
specify
+ * types that are compatible with the defined SQL type of the input parameter.
+ * For instance, if the IN parameter has SQL type Integer, then setInt should
be
+ * used.
+ * open one exists.
+ */
+class PreparedStatement: public Statement
+{
+friend class Connection;
+
+public:
+ //No constructor, statements must be created by connections
+ virtual ~PreparedStatement();
+
+ /**
+ * Release objects and call Statement.close().
+ */
+ virtual void close();
+
+ /**
+ * Execute a SQL statement that may return multiple results.
+ * @return true if the result is a ResultSet or false if it is an integer
+ * @throw DriverException if the statement is closed
+ */
+ bool execute() throw (DriverException, SocketIOException,
+ BackendException, ControllerException,
ProtocolException,
+ NotImplementedException, UnexpectedException)
+ { return Statement::execute(compileQuery(), sql); }
+
+ /**
+ * Executes a SQL statement that returns a single ResultSet
+ * @param sql typically a static SQL <code>SELECT</code> statement
+ * @return a ResulSet pointer that contains the data produced by the query
+ * @throw DriverException if the statement is closed
+ */
+ DriverResultSet * executeQuery() throw (DriverException,
SocketIOException,
+ BackendException, ControllerException,
+ ProtocolException, UnexpectedException)
+ { return Statement::executeQuery(compileQuery(),
sql); }
+ /**
+ * Execute a SQL INSERT, UPDATE or DELETE statement. In addition SQL
+ * statements that return nothing such as SQL DDL statements can be executed
+ *
+ * @param sql a SQL statement
+ * @return either a row count, or 0 for SQL commands
+ */
+ int executeUpdate() throw (DriverException,
SocketIOException,
+ BackendException, ControllerException,
+ ProtocolException, UnexpectedException)
+ { return Statement::executeUpdate(compileQuery(),
sql); }
+
+ /**
+ * Helper - this compiles the SQL query, inlining the parameters in the
+ * request String. This is identical to <code>operator wstring()</code>
except
+ * it throws an exception if a parameter was not set.
+ *
+ * @return the compiled query
+ * @throws DriverException if a parameter was not set
+ */
+ std::wstring compileQuery() throw (DriverException)
+ { return compileQuery(true); }
+
+ /**
+ * Sets a parameter to SQL NULL.
+ * @param parameterIndex the first parameter is 1, etc...
+ * @param sqlType the SQL type code defined in java.sql.Types
+ * @exception SQLException if a database access error occurs
+ */
+ void setNull(const int parameterIndex);
+
+ /**
+ * Sets a parameter to a boolean value. The driver converts this to a SQL
+ * BIT value when it sends it to the database.
+ * @param parameterIndex the first parameter is 1...
+ * @param x the parameter value
+ */
+ void setBoolean(const int parameterIndex, const bool x);
+
+ /**
+ * Sets a parameter to a Java byte value.
+ * @param parameterIndex the first parameter is 1...
+ * @param x the parameter value
+ */
+ void setByte(const int parameterIndex, const java_byte x);
+
+ /**
+ * Sets a parameter to a short value. The driver converts this to a SQL
+ * SMALLINT value when it sends it to the database.
+ * @param parameterIndex the first parameter is 1...
+ * @param x the parameter value
+ */
+ void setShort(const int parameterIndex, const short x);
+
+ /**
+ * Sets a parameter to an int value. The driver converts this to a SQL
+ * INTEGER value when it sends it to the database.
+ * @param parameterIndex the first parameter is 1...
+ * @param x the parameter value
+ */
+ void setInt(const int parameterIndex, const int x);
+
+ /**
+ * Sets a parameter to a long value. The driver converts this to a SQL
+ * BIGINT value when it sends it to the database.
+ * @param parameterIndex the first parameter is 1...
+ * @param x the parameter value
+ */
+ void setLong(const int parameterIndex, const long long x);
+
+ /**
+ * Sets a parameter to a float value. The driver converts this to a SQL
+ * FLOAT value when it sends it to the database.
+ * @param parameterIndex the first parameter is 1...
+ * @param x the parameter value
+ */
+ void setFloat(const int parameterIndex, const float x);
+
+ /**
+ * Sets a parameter to a double value. The driver converts this to a SQL
+ * DOUBLE value when it sends it to the database.
+ * @param parameterIndex the first parameter is 1...
+ * @param x the parameter value
+ */
+ void setDouble(const int parameterIndex, const double x);
+
+ /**
+ * Sets a parameter to a BigDecimal value. The driver converts this
+ * to a SQL NUMERIC value when it sends it to the database.
+ * @param parameterIndex the first parameter is 1...
+ * @param x the parameter value
+ */
+ void setBigDecimal(const int parameterIndex, const
BigDecimal &x);
+
+ /**
+ * Sets a parameter to string value. The driver converts this to a SQL
+ * VARCHAR or LONGVARCHAR value (depending on the arguments size relative to
+ * the driver's limits on VARCHARs) when it sends it to the database.
+ * @param parameterIndex the first parameter is 1...
+ * @param x the parameter value
+ */
+ void setString(const int parameterIndex, const
std::wstring &x);
+
+ /**
+ * In general, parameter values remain in force for repeated used of a
+ * <code>Statement</code>. Setting a parameter value automatically clears
+ * its previous value. However, in coms cases, it is useful to immediately
+ * release the resources used by the current parameter values; this can be
+ * done by calling <code>clearParameters()</code>.
+ */
+ void clearParameters();
+
+ /**
+ * Returns the SQL statement with the current template values substituted.
+ * <p>
+ * <b>Note: </b>: This is identical to <code>compileQuery()</code> except
+ * instead of throwing SQLException if a parameter is <code>null</code>, it
+ * places ? instead.
+ * @return the SQL statement
+ */
+ operator std::wstring()
+ { return compileQuery(false); }
+
+protected:
+ /**
+ * Constructor. Parses/Splits the SQL statement into segments - string parts
+ * separated by question mark placeholders. When we rebuild the thing with
the
+ * arguments, we can substitute the args by joining segments and parameters
+ * back together.
+ *
+ * @param connection the instantiating connection
+ * @param sqlStatement the SQL statement with ? for IN markers
+ * @param driver the Driver used to create connections
+ */
+ PreparedStatement(Connection *c, const std::wstring &sqlStatement);
+
+ /**
+ * Actually stores the IN parameter into parameters String array. Called by
+ * most setXXX() methods.
+ * @param paramIndex the index into the inString
+ * @param typeTag type of the parameter
+ * @exception DriverException if something goes wrong
+ */
+ template <class T> void set(const int paramIndex, const std::wstring
&typeTag,
+ const T& value)
+ throw (DriverException, UnexpectedException);
+
+private:
+ /** Original, untouched request (only trimmed) */
+ std::wstring sql;
+ /** IN parameters, ready to be inlined in the request */
+ std::vector<std::wstring> inStrings;
+ /** segments: the request splitted by question marks placeholders */
+ std::list<std::wstring> templateStrings;
+
+ /**
+ * Helper - this compiles the SQL query, inlining the parameters in the
+ * request String.
+ * If a parameter was not set, throws a NullValueException if throwException
is true,
+ * otherwise replace the missing parameter with ?
+ * @param throwException to throw a NullValueException if a parameter is
missing
+ * @return the compiled query
+ * @throws DriverException if a parameter was not set
+ */
+ std::wstring compileQuery(bool throwException) throw
(DriverException);
+};
+
+} //namespace CarobNS
+#endif /*PREPAREDSTATEMENT_HPP_*/
Index: carob/include/Statement.hpp
diff -u carob/include/Statement.hpp:1.15 carob/include/Statement.hpp:1.16
--- carob/include/Statement.hpp:1.15 Fri Dec 16 11:45:04 2005
+++ carob/include/Statement.hpp Mon Dec 19 19:41:57 2005
@@ -16,7 +16,7 @@
* limitations under the License.
*
* Initial developer(s): Gilles Rayrat
- * Contributor(s):
+ * Contributor(s): Zsolt Simon
*/
#ifndef STATEMENT_HPP_
#define STATEMENT_HPP_
@@ -48,6 +48,8 @@
*/
#define CLOSE_ALL_RESULTS 3
+const std::wstring emptyString = L"";
+
class Connection;
/**
@@ -80,13 +82,15 @@
/**
* Execute a SQL statement that may return multiple results.
* @param sql any SQL statement
+ * @param skeleton SQL skeleton statement
* @return true if the result is a ResultSet or false if it is an integer
* @throw DriverException if the statement is closed
*/
- bool execute(std::wstring sql) throw (DriverException,
- SocketIOException, BackendException,
- ControllerException, ProtocolException,
- NotImplementedException, UnexpectedException);
+ bool execute(std::wstring sql, const std::wstring
&skeleton = emptyString)
+ throw (DriverException,
+ SocketIOException, BackendException,
+ ControllerException, ProtocolException,
+ NotImplementedException,
UnexpectedException);
/**
* Executes a SQL statement that returns a single ResultSet
@@ -94,7 +98,7 @@
* @return a ResulSet pointer that contains the data produced by the query
* @throw DriverException if the statement is closed
*/
- DriverResultSet* executeQuery(std::wstring sql)
+ DriverResultSet* executeQuery(std::wstring sql, const std::wstring
&skeleton = emptyString)
throw (DriverException, SocketIOException,
BackendException, ControllerException,
ProtocolException, NotImplementedException,
@@ -106,7 +110,7 @@
* @param sql a SQL statement
* @return either a row count, or 0 for SQL commands
*/
- int executeUpdate(std::wstring sql)
+ int executeUpdate(std::wstring sql, const std::wstring
&skeleton = emptyString)
throw (DriverException, SocketIOException,
BackendException, ControllerException,
ProtocolException, UnexpectedException);
@@ -265,7 +269,7 @@
* is automatically closed. The close method provides this immediate release.
* <p>
*/
- void close();
+ virtual void close();
protected:
/**
* Constructs a Statement with the given connection. Protected access so that
Index: carob/src/Connection.cpp
diff -u carob/src/Connection.cpp:1.43 carob/src/Connection.cpp:1.44
--- carob/src/Connection.cpp:1.43 Fri Dec 16 11:43:57 2005
+++ carob/src/Connection.cpp Mon Dec 19 19:41:57 2005
@@ -16,11 +16,12 @@
* limitations under the License.
*
* Initial developer(s): Gilles Rayrat
- * Contributor(s): Marc Herbert
+ * Contributor(s): Marc Herbert, Zsolt Simon
*/
#include "Connection.hpp"
#include "Statement.hpp"
+#include "PreparedStatement.hpp"
using std::wstring;
@@ -456,6 +457,14 @@
return new Statement(this);
}
+PreparedStatement* Connection::prepareStatement(const std::wstring &query)
+ throw (SocketIOException, UnexpectedException)
+{
+ checkIfConnected();
+ return new PreparedStatement(this, query);
+}
+
+
void Connection::checkIfConnected() const throw (SocketIOException,
UnexpectedException)
{
Index: carob/src/PreparedStatement.cpp
diff -u /dev/null carob/src/PreparedStatement.cpp:1.1
--- /dev/null Mon Dec 19 19:41:57 2005
+++ carob/src/PreparedStatement.cpp Mon Dec 19 19:41:57 2005
@@ -0,0 +1,180 @@
+/*
+ * Sequoia: Database clustering technology.
+ * Copyright (C) 2005 Emic Networks
+ * 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): Zsolt Simon
+ * Contributor(s):
+ */
+
+#include "Common.hpp"
+#include "PreparedStatement.hpp"
+
+using std::wstring;
+
+using namespace CarobNS;
+
+PreparedStatement::PreparedStatement(Connection *c, const wstring
&sqlStatement) :
+Statement(c)
+{
+ sql = trim(sqlStatement);
+
+ // The following two boolean switches are used to make sure we're not
+ // counting "?" in either strings or metadata strings. For instance the
+ // following query:
+ // select '?' "A ? value" from dual
+ // doesn't have any parameters.
+ bool inString = false, inMetaString = false;
+
+ std::wstring::const_iterator isql = sql.begin();
+ std::wstring::const_iterator isql_end = sql.end();
+ std::wstring::const_iterator ilast = isql;
+
+ templateStrings.clear();
+ inStrings.clear();
+
+ for (; isql != isql_end; ++isql)
+ {
+ switch (*isql)
+ {
+ case L'\'':
+ inString = !inString;
+ break;
+ case L'"':
+ inMetaString = !inMetaString;
+ break;
+ case L'?':
+ if (!inString && !inMetaString)
+ {
+ templateStrings.push_back(wstring(ilast, isql-1));
+ inStrings.push_back(wstring());
+ ilast=isql+1;
+ }
+ }
+ }
+ templateStrings.push_back(wstring(ilast, isql_end));
+}
+
+PreparedStatement::~PreparedStatement()
+{
+}
+
+void PreparedStatement::close()
+{
+ Statement::close();
+
+ sql.clear();
+ templateStrings.clear();
+ inStrings.clear();
+}
+
+void PreparedStatement::clearParameters()
+{
+ std::vector<wstring>::iterator iparam = inStrings.begin();
+ std::vector<wstring>::iterator iparam_end = inStrings.end();
+
+ for (; iparam != iparam_end; (*iparam++).clear()) ;
+}
+
+template <class T> void PreparedStatement::set(const int paramIndex, const
std::wstring &typeTag,
+ const T& value)
+ throw (DriverException, UnexpectedException)
+{
+ if (paramIndex < 1 || paramIndex > (int)inStrings.size())
+ throw new DriverException(L"Parameter index out of range.");
+
+ std::wostringstream buffer;
+ buffer << START_PARAM_TAG << typeTag << value << END_PARAM_TAG;
+ inStrings[paramIndex-1] = buffer.str();
+}
+
+wstring PreparedStatement::compileQuery(bool throwException)
+ throw (DriverException)
+{
+ std::list<wstring>::const_iterator itemplate = templateStrings.begin();
+ std::vector<wstring>::const_iterator iparam = inStrings.begin();
+ std::vector<wstring>::const_iterator iparam_end = inStrings.end();
+ std::wostringstream sbuf;
+
+ sbuf << *itemplate++;
+
+ for (int i=1; iparam != iparam_end; ++itemplate, ++iparam, ++i)
+ {
+ if (iparam->empty())
+ {
+ if (throwException)
+ throw new DriverException(L"Parameter " + toWString(i) + L" is
incorrect");
+ else
+ sbuf << L"?";
+ }
+ else
+ sbuf << *iparam;
+
+ sbuf << *itemplate;
+ }
+
+ return sbuf.str();
+}
+
+void PreparedStatement::setNull(const int parameterIndex)
+{
+ set<std::wstring>(parameterIndex, NULL_TAG, emptyString);
+}
+
+void PreparedStatement::setBoolean(const int parameterIndex, const bool x)
+{
+ set<wstring>(parameterIndex, BOOLEAN_TAG, x ? wsBoolTrue : wsBoolFalse);
+}
+
+void PreparedStatement::setByte(const int parameterIndex, const java_byte x)
+{
+ set<java_byte>(parameterIndex, BYTE_TAG, x);
+}
+
+void PreparedStatement::setShort(const int parameterIndex, const short x)
+{
+ set<short>(parameterIndex, SHORT_TAG, x);
+}
+
+void PreparedStatement::setInt(const int parameterIndex, const int x)
+{
+ set<int>(parameterIndex, INTEGER_TAG, x);
+}
+
+void PreparedStatement::setLong(const int parameterIndex, const long long x)
+{
+ set<long long>(parameterIndex, LONG_TAG, x);
+}
+
+void PreparedStatement::setFloat(const int parameterIndex, const float x)
+{
+ set<float>(parameterIndex, FLOAT_TAG, x);
+}
+
+void PreparedStatement::setDouble(const int parameterIndex, const double x)
+{
+ set<double>(parameterIndex, DOUBLE_TAG, x);
+}
+
+void PreparedStatement::setBigDecimal(const int parameterIndex, const
BigDecimal &x)
+{
+ set<wstring>(parameterIndex, BIG_DECIMAL_TAG, x);
+}
+
+void PreparedStatement::setString(const int parameterIndex, const std::wstring
&x)
+{
+ set<wstring>(parameterIndex, STRING_TAG,
+ x == NULL_TAG ? NULL_STRING_TAG : replaceAll(x, TAG_MARKER,
TAG_MARKER_ESCAPE));
+}
Index: carob/src/Statement.cpp
diff -u carob/src/Statement.cpp:1.16 carob/src/Statement.cpp:1.17
--- carob/src/Statement.cpp:1.16 Tue Dec 13 18:17:43 2005
+++ carob/src/Statement.cpp Mon Dec 19 19:41:57 2005
@@ -16,7 +16,7 @@
* limitations under the License.
*
* Initial developer(s): Gilles Rayrat
- * Contributor(s):
+ * Contributor(s): Zsolt Simon
*/
#include "CarobException.hpp"
@@ -56,9 +56,9 @@
request.setCursorName(cursorName);
}
-bool Statement::execute(std::wstring sql) throw (DriverException,
- SocketIOException, BackendException, ControllerException,
ProtocolException,
- NotImplementedException, UnexpectedException)
+bool Statement::execute(std::wstring sql, const std::wstring &skeleton)
+ throw (DriverException, SocketIOException, BackendException,
ControllerException, ProtocolException,
+ NotImplementedException, UnexpectedException)
{
wstring fctName(L"Statement::execute");
if (isClosed())
@@ -69,13 +69,15 @@
RequestWithResultSetParameters request(sql);
request.setEscapeProcessing(escapeProcessing).setTimeoutInSeconds(timeout);
+ if (!skeleton.empty())
+ request.setSqlTemplate(skeleton);
setReadRequestParameters(request);
resultList = connectionPtr->statementExecute(request);
resultListIterator = resultList.begin();
return getMoreResults();
}
-DriverResultSet* Statement::executeQuery(std::wstring sql)
+DriverResultSet* Statement::executeQuery(std::wstring sql, const std::wstring
&skeleton)
throw (DriverException, SocketIOException, BackendException,
ControllerException, ProtocolException, NotImplementedException,
UnexpectedException)
@@ -97,6 +99,8 @@
RequestWithResultSetParameters request(sql);
request.setEscapeProcessing(escapeProcessing).setTimeoutInSeconds(timeout);
+ if (!skeleton.empty())
+ request.setSqlTemplate(skeleton);
setReadRequestParameters(request);
resultPtr = connectionPtr->statementExecuteQuery(request);
@@ -104,9 +108,9 @@
return resultPtr;
}
//TODO: executeUpdateWithKeys
-int Statement::executeUpdate(std::wstring sql) throw (DriverException,
- SocketIOException, BackendException, ControllerException,
ProtocolException,
- UnexpectedException)
+int Statement::executeUpdate(std::wstring sql, const std::wstring &skeleton)
+ throw (DriverException, SocketIOException, BackendException,
+ ControllerException, ProtocolException, UnexpectedException)
{
wstring fctName(L"Statement::executeUpdate");
if (isClosed())
@@ -122,6 +126,8 @@
}
Request request(sql);
request.setEscapeProcessing(escapeProcessing).setTimeoutInSeconds(timeout);
+ if (!skeleton.empty())
+ request.setSqlTemplate(skeleton);
int updateCount = connectionPtr->statementExecuteUpdate(request);
return updateCount;
}
_______________________________________________
Carob-commits mailing list
[email protected]
https://forge.continuent.org/mailman/listinfo/carob-commits