Skip to content

Commit e42327b

Browse files
committed
Merge branch 'vlkong-master'
2 parents c0a6d1c + 74a31f4 commit e42327b

File tree

3 files changed

+102
-38
lines changed

3 files changed

+102
-38
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ using a jdbc-custom-data-source from `oplrun` or OPL Studio.
7575

7676
## Limitations
7777

78-
* The custom data source reader supports scalar values, tuples and tuplessets. Arrays are not supported.
78+
* The custom data source reader supports scalar values, sets and tuplessets. Arrays are not supported.
7979
* Inner tuples are not supported.
8080

8181
## License

lib/jdbc-custom-data-source.jar

2.58 KB
Binary file not shown.

src/main/java/com/ibm/opl/customdatasource/JdbcWriter.java

Lines changed: 101 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,10 @@
1616
import java.sql.ResultSet;
1717
import java.sql.SQLException;
1818
import java.sql.Statement;
19-
import java.util.Enumeration;
2019
import java.util.Map;
21-
import java.util.Properties;
2220

2321
import 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

Comments
 (0)