1616import java .sql .ResultSet ;
1717import java .sql .SQLException ;
1818import java .sql .Statement ;
19- import java .util .Enumeration ;
2019import java .util .Map ;
21- import java .util .Properties ;
2220
2321import com .ibm .opl .customdatasource .JdbcConfiguration .OutputParameters ;
22+ import com .ibm .opl .customdatasource .sql .NamedParametersPreparedStatement ;
2423
2524/**
2625 * The class to write data using JDBC.
@@ -111,20 +110,83 @@ String getInsertQuery(IloTupleSchema schema, String table) {
111110 query += ") VALUES(" + getPlaceholderString (schema .getSize ()) + ")" ;
112111 return query ;
113112 }
114-
115- void updateValues (IloTuple tuple , IloTupleSchema schema ,
116- IloOplTupleSchemaDefinition tupleSchemaDef , PreparedStatement stmt ) throws SQLException {
117- for (int i = 0 ; i < schema .getSize (); i ++) {
118- int index = i + 1 ; // index in PreparedStatement
119- Type columnType = tupleSchemaDef .getComponent (i ).getElementDefinitionType ();
120- if (columnType == Type .INTEGER )
121- stmt .setInt (index , tuple .getIntValue (i ));
122- else if (columnType == Type .FLOAT )
123- stmt .setDouble (index , tuple .getNumValue (i ));
124- else if (columnType == Type .STRING )
125- stmt .setString (index , tuple .getStringValue (i ));
113+
114+ /**
115+ * ValuesUpdater update the values in a PreparedStatement with the contents of the specified IloTuple.
116+ *
117+ */
118+ public static interface ValuesUpdater {
119+ /**
120+ * Update the parameters in a PreparedStatement with the values of the specified tuple.
121+ * @param tuple
122+ * @throws SQLException
123+ */
124+ void updateValues (IloTuple tuple ) throws SQLException ;
125+ }
126+
127+ /**
128+ * A ValuesUpdater updating values by name.
129+ *
130+ */
131+ public static class NamedValuesUpdater implements ValuesUpdater {
132+ String [] _names = null ;
133+ Type [] _types = null ;
134+ NamedParametersPreparedStatement _stmt ;
135+ NamedValuesUpdater (IloTupleSchema schema , IloOplTupleSchemaDefinition tupleSchemaDef ,
136+ NamedParametersPreparedStatement stmt ) {
137+ _names = new String [schema .getSize ()];
138+ _types = new Type [schema .getSize ()];
139+ for (int i =0 ; i < schema .getSize (); i ++) {
140+ _names [i ] = tupleSchemaDef .getComponent (i ).getName ();
141+ _types [i ] = tupleSchemaDef .getComponent (i ).getElementDefinitionType ();
142+ }
143+ _stmt = stmt ;
144+ }
145+ public void updateValues (IloTuple tuple ) throws SQLException {
146+ final NamedParametersPreparedStatement stmt = _stmt ;
147+ for (int i =0 ; i < _names .length ; i ++) {
148+ final Type columnType = _types [i ];
149+ final String name = _names [i ];
150+ if (columnType == Type .INTEGER )
151+ stmt .setInt (name , tuple .getIntValue (i ));
152+ else if (columnType == Type .FLOAT )
153+ stmt .setDouble (name , tuple .getNumValue (i ));
154+ else if (columnType == Type .STRING )
155+ stmt .setString (name , tuple .getStringValue (i ));
156+ }
126157 }
127158 }
159+
160+ /**
161+ * A ValuesUpdater updating values by index.
162+ *
163+ */
164+ public static class IndexedValuesUpdater implements ValuesUpdater {
165+ Type [] _types = null ;
166+ PreparedStatement _stmt ;
167+ IndexedValuesUpdater (IloTupleSchema schema , IloOplTupleSchemaDefinition tupleSchemaDef ,
168+ PreparedStatement stmt ) {
169+ _types = new Type [schema .getSize ()];
170+ for (int i =0 ; i < schema .getSize (); i ++) {
171+ _types [i ] = tupleSchemaDef .getComponent (i ).getElementDefinitionType ();
172+ }
173+ _stmt = stmt ;
174+ }
175+ public void updateValues (IloTuple tuple ) throws SQLException {
176+ PreparedStatement stmt = _stmt ;
177+ for (int i =0 ; i < _types .length ; i ++) {
178+ int columnIndex = i + 1 ;
179+ Type columnType = _types [i ];
180+ if (columnType == Type .INTEGER )
181+ stmt .setInt (columnIndex , tuple .getIntValue (i ));
182+ else if (columnType == Type .FLOAT )
183+ stmt .setDouble (columnIndex , tuple .getNumValue (i ));
184+ else if (columnType == Type .STRING )
185+ stmt .setString (columnIndex , tuple .getStringValue (i ));
186+ }
187+ }
188+ }
189+
128190
129191 static final String DROP_QUERY = "DROP TABLE %" ;
130192
@@ -139,10 +201,8 @@ void customWrite(String name, OutputParameters op) {
139201 IloOplElement elt = _model .getElement (name );
140202 ilog .opl_core .cppimpl .IloTupleSet tupleSet = (ilog .opl_core .cppimpl .IloTupleSet ) elt .asTupleSet ();
141203 IloTupleSchema schema = tupleSet .getSchema_cpp ();
142- Connection conn = null ;
143- try {
144- conn = DriverManager .getConnection (_configuration .getUrl (), _configuration .getUser (),
145- _configuration .getPassword ());
204+ try (Connection conn = DriverManager .getConnection (_configuration .getUrl (), _configuration .getUser (),
205+ _configuration .getPassword ())) {
146206 try (Statement stmt = conn .createStatement ()) {
147207 String sql ;
148208 // drop existing table if exists
@@ -172,7 +232,7 @@ void customWrite(String name, OutputParameters op) {
172232 stmt .execute (sql );
173233 }
174234 }
175- PreparedStatement insert = null ;
235+ NamedParametersPreparedStatement np_stmt = null ;
176236 try {
177237 IloOplElementDefinition tupleDef = _def .getElementDefinition (schema .getName ());
178238 IloOplTupleSchemaDefinition tupleSchemaDef = tupleDef .asTupleSchema ();
@@ -186,46 +246,50 @@ void customWrite(String name, OutputParameters op) {
186246 } else {
187247 psql = op .insertStatement ;
188248 }
189- insert = conn .prepareStatement (psql );
190-
249+ np_stmt = new NamedParametersPreparedStatement (conn , psql );
191250 conn .setAutoCommit (false ); // begin transaction
192- // iterate the set and create the final insert statement
251+
252+ // The helper to updater a statement given a tuple
253+ ValuesUpdater updater = null ;
254+ if (np_stmt .hasNamedParameters ()) {
255+ updater = new NamedValuesUpdater (schema , tupleSchemaDef , np_stmt );
256+ } else {
257+ // the named parameters prepared statement did not parse any named parameters
258+ // assume this is then regular prepared statement, and use the statement instead.
259+ updater = new IndexedValuesUpdater (schema , tupleSchemaDef , np_stmt .getStatement ());
260+ }
261+
262+ // the insert loop
193263 long icount = 1 ;
194264 for (java .util .Iterator it1 = tupleSet .iterator (); it1 .hasNext ();) {
195265 IloTuple tuple = (IloTuple ) it1 .next ();
196- updateValues (tuple , schema , tupleSchemaDef , insert );
266+ updater . updateValues (tuple );
197267 if (_batch_size == 0 ) {
198- // no batch
199- insert .executeUpdate ();
268+ np_stmt .executeUpdate (); // no batch
200269 }
201270 else {
202- insert .addBatch ();
271+ np_stmt .addBatch ();
203272 if ((icount % _batch_size ) == 0 ) {
204- insert .executeBatch ();
273+ np_stmt .executeBatch ();
205274 }
206275 }
207276 icount ++;
208277 }
278+
279+ // flush batches if any
209280 if (_batch_size != 0 ) {
210- insert .executeBatch ();
281+ np_stmt .executeBatch ();
211282 }
212283 conn .commit ();
213284 } catch (SQLException e ) {
214285 conn .rollback ();
215286 throw e ;
216287 } finally {
217- if (insert != null )
218- insert .close ();
288+ if (np_stmt != null )
289+ np_stmt .close ();
219290 }
220291 } catch (SQLException e ) {
221292 e .printStackTrace ();
222- } finally {
223- if (conn != null )
224- try {
225- conn .close ();
226- } catch (SQLException e ) {
227- e .printStackTrace ();
228- }
229293 }
230294 }
231295}
0 commit comments