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

Reply via email to