Skip to content

Commit 57abf30

Browse files
committed
Update Readme.md and Use one transaction for UpsertAction
1 parent 224da76 commit 57abf30

File tree

13 files changed

+207
-282
lines changed

13 files changed

+207
-282
lines changed

README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Following actions are inside:
2222
### Requirements
2323
Before you can deploy any code into elastic.io **you must be a registered elastic.io platform user**. Please see our home page at [http://www.elastic.io](http://www.elastic.io) to learn how.
2424
#### Environment variables
25-
For unit-testing is needed specify following environment variables:
25+
For unit-testing is needed to specify following environment variables:
2626
1. Connection to MSSQL:
2727
- ``CONN_USER_MSSQL`` - user login
2828
- ``CONN_PASSWORD_MSSQL`` - user password
@@ -192,15 +192,15 @@ Checkbox ``Don't throw Error on an Empty Result`` allows to emit an empty respon
192192
As an input metadata you will get a Primary Key field to provide the data inside as a clause value.
193193

194194
## Current limitations
195-
1. Only tables with one [PRIMARY KEY](https://en.wikipedia.org/wiki/Primary_key "PRIMARY KEY") is supported. Message ``Table has not Primary Key. Should be one Primary Key
196-
`` should be displayed if the table without any primary key will be selected and message ``Composite Primary Key is not supported
197-
`` should be displayed if the table with composite primary key will be selected.
198-
2. Only following versions of DataBase are supported:
195+
1. Only tables with one [PRIMARY KEY](https://en.wikipedia.org/wiki/Primary_key "PRIMARY KEY") is supported. You will see the message ``Table has not Primary Key. Should be one Primary Key
196+
``, if the selected table doesn't have a primary key. Also, you will see the message ``Composite Primary Key is not supported
197+
``, if the selected table has composite primary key.
198+
2. Only following versions of database types are supported:
199199
- ``MySQL`` - compatible with MySQL Server 5.5, 5.6, 5.7 and 8.0.
200200
- ``PostgreSQL`` - compatible with PostgreSQL 8.2 and higher
201201
- ``Oracle`` - compatible with Oracle Database 8.1.7 - 12.1.0.2
202202
- ``MSSQL`` - compatible with Microsoft SQL Server 2008 R2 and higher
203-
3. For Action "Upsert by primary key" metadata analysis ignores nullable/non-nullable fields, it will be throw SQL Server exception ``Cannot insert the value NULL into...`` if non-nullable fields don't fill for Insert operation.
203+
3. The current implementation of the action ``Upsert By Primary Key`` doesn't mark non-nullable fields as required fields at a dynamic metadata. In case of updating such fields with an empty value you will get SQL Exception ``Cannot insert the value NULL into...``. You should manually fill in all non-nullable fields with previous data, if you want to update part of columns in a row, even if data in that fields doesn't change.
204204

205205
## Known issues
206206
No known issues are there yet.

src/main/java/io/elastic/jdbc/QueryBuilders/MSSQL.java

Lines changed: 0 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -148,51 +148,4 @@ public void executeUpdate(Connection connection, String tableName, String idColu
148148
}
149149
}
150150

151-
public void executeUpsert(Connection connection, String idColumn, JsonObject body)
152-
throws SQLException {
153-
validateQuery();
154-
155-
StringBuilder keys = new StringBuilder();
156-
StringBuilder values = new StringBuilder();
157-
StringBuilder setString = new StringBuilder();
158-
for (Map.Entry<String, JsonValue> entry : body.entrySet()) {
159-
if (setString.length() > 0) {
160-
setString.append(",");
161-
}
162-
setString.append(entry.getKey()).append(" = ?");
163-
if (keys.length() > 0) {
164-
keys.append(",");
165-
}
166-
keys.append(entry.getKey());
167-
if (values.length() > 0) {
168-
values.append(",");
169-
}
170-
values.append("?");
171-
}
172-
String sql = "BEGIN TRANSACTION;" +
173-
" IF EXISTS (SELECT * FROM " + tableName +
174-
" WHERE " + idColumn + "= ?)" +
175-
" UPDATE " + tableName +
176-
" SET " + setString.toString() +
177-
" WHERE " + idColumn + " = ?" +
178-
" ELSE INSERT INTO " + tableName +
179-
" (" + keys.toString() + ")" +
180-
" VALUES (" + values.toString() + ")" +
181-
" COMMIT;";
182-
try (PreparedStatement stmt = connection.prepareStatement(sql)) {
183-
Utils.setStatementParam(stmt, 1, idColumn, body);
184-
int i = 2;
185-
for (Map.Entry<String, JsonValue> entry : body.entrySet()) {
186-
Utils.setStatementParam(stmt, i, entry.getKey(), body);
187-
i++;
188-
}
189-
Utils.setStatementParam(stmt, i++, idColumn, body);
190-
for (Map.Entry<String, JsonValue> entry : body.entrySet()) {
191-
Utils.setStatementParam(stmt, i, entry.getKey(), body);
192-
i++;
193-
}
194-
stmt.execute();
195-
}
196-
}
197-
198151
}

src/main/java/io/elastic/jdbc/QueryBuilders/MySQL.java

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -139,40 +139,4 @@ public void executeUpdate(Connection connection, String tableName, String idColu
139139
}
140140
}
141141

142-
public void executeUpsert(Connection connection, String idColumn, JsonObject body)
143-
throws SQLException {
144-
validateQuery();
145-
StringBuilder keys = new StringBuilder();
146-
StringBuilder values = new StringBuilder();
147-
StringBuilder setString = new StringBuilder();
148-
for (Map.Entry<String, JsonValue> entry : body.entrySet()) {
149-
if (setString.length() > 0) {
150-
setString.append(",");
151-
}
152-
setString.append(entry.getKey()).append(" = ?");
153-
if (keys.length() > 0) {
154-
keys.append(",");
155-
}
156-
keys.append(entry.getKey());
157-
if (values.length() > 0) {
158-
values.append(",");
159-
}
160-
values.append("?");
161-
}
162-
String sql = "INSERT INTO " + tableName +
163-
" (" + keys.toString() + ")" +
164-
" VALUES (" + values.toString() + ")" +
165-
" ON DUPLICATE KEY UPDATE " + setString + ";";
166-
try (PreparedStatement stmt = connection.prepareStatement(sql)) {
167-
int i = 1;
168-
int countBodyEntry = body.size();
169-
for (Map.Entry<String, JsonValue> entry : body.entrySet()) {
170-
Utils.setStatementParam(stmt, i, entry.getKey(), body);
171-
Utils.setStatementParam(stmt, i + countBodyEntry, entry.getKey(), body);
172-
i++;
173-
}
174-
stmt.execute();
175-
}
176-
}
177-
178142
}

src/main/java/io/elastic/jdbc/QueryBuilders/Oracle.java

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -133,47 +133,4 @@ public void executeUpdate(Connection connection, String tableName, String idColu
133133
}
134134
}
135135

136-
public void executeUpsert(Connection connection, String idColumn, JsonObject body)
137-
throws SQLException {
138-
validateQuery();
139-
StringBuilder keys = new StringBuilder();
140-
StringBuilder values = new StringBuilder();
141-
StringBuilder setString = new StringBuilder();
142-
for (Map.Entry<String, JsonValue> entry : body.entrySet()) {
143-
if (setString.length() > 0) {
144-
setString.append(",");
145-
}
146-
setString.append(entry.getKey()).append(" = ?");
147-
if (keys.length() > 0) {
148-
keys.append(",");
149-
}
150-
keys.append(entry.getKey());
151-
if (values.length() > 0) {
152-
values.append(",");
153-
}
154-
values.append("?");
155-
}
156-
String sql = "BEGIN " +
157-
" INSERT INTO " + tableName +
158-
" (" + keys.toString() + ")" +
159-
" VALUES (" + values.toString() + ");" +
160-
" EXCEPTION" +
161-
" WHEN DUP_VAL_ON_INDEX THEN" +
162-
" UPDATE " + tableName +
163-
" SET " + setString.toString() +
164-
" WHERE " + idColumn + " = ?;" +
165-
" END;";
166-
try (PreparedStatement stmt = connection.prepareStatement(sql)) {
167-
//set Statement parameters for Insert (i) and Update operation (i + countBodyEntry)
168-
int i = 1;
169-
int countBodyEntry = body.size();
170-
for (Map.Entry<String, JsonValue> entry : body.entrySet()) {
171-
Utils.setStatementParam(stmt, i, entry.getKey(), body);
172-
Utils.setStatementParam(stmt, i + countBodyEntry, entry.getKey(), body);
173-
i++;
174-
}
175-
Utils.setStatementParam(stmt, i + countBodyEntry, idColumn, body);
176-
stmt.execute();
177-
}
178-
}
179136
}

src/main/java/io/elastic/jdbc/QueryBuilders/PostgreSQL.java

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -149,42 +149,4 @@ public void executeUpdate(Connection connection, String tableName, String idColu
149149
}
150150
}
151151

152-
public void executeUpsert(Connection connection, String idColumn, JsonObject body)
153-
throws SQLException {
154-
validateQuery();
155-
StringBuilder keys = new StringBuilder();
156-
StringBuilder values = new StringBuilder();
157-
StringBuilder setString = new StringBuilder();
158-
for (Map.Entry<String, JsonValue> entry : body.entrySet()) {
159-
if (setString.length() > 0) {
160-
setString.append(",");
161-
}
162-
setString.append(entry.getKey()).append(" = ?");
163-
if (keys.length() > 0) {
164-
keys.append(",");
165-
}
166-
keys.append(entry.getKey());
167-
if (values.length() > 0) {
168-
values.append(",");
169-
}
170-
values.append("?");
171-
}
172-
String sql = "INSERT INTO " + tableName +
173-
" (" + keys.toString() + ")" +
174-
" VALUES (" + values.toString() + ")" +
175-
" ON CONFLICT (" + idColumn + ")" +
176-
" DO UPDATE " +
177-
" SET " + setString.toString() + ";";
178-
try (PreparedStatement stmt = connection.prepareStatement(sql)) {
179-
//set Statement parameters for Insert (i) and Update operation (i + countBodyEntry)
180-
int i = 1;
181-
int countBodyEntry = body.size();
182-
for (Map.Entry<String, JsonValue> entry : body.entrySet()) {
183-
Utils.setStatementParam(stmt, i, entry.getKey(), body);
184-
Utils.setStatementParam(stmt, i + countBodyEntry, entry.getKey(), body);
185-
i++;
186-
}
187-
stmt.execute();
188-
}
189-
}
190152
}

src/main/java/io/elastic/jdbc/QueryBuilders/Query.java

Lines changed: 114 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import java.sql.SQLException;
99
import java.sql.Timestamp;
1010
import java.util.ArrayList;
11+
import java.util.Map;
1112
import java.util.Map.Entry;
1213
import javax.json.Json;
1314
import javax.json.JsonObject;
@@ -95,9 +96,6 @@ abstract public void executeInsert(Connection connection, String tableName, Json
9596
abstract public void executeUpdate(Connection connection, String tableName, String idColumn,
9697
String idValue, JsonObject body) throws SQLException;
9798

98-
abstract public void executeUpsert(Connection connection, String idColumn,
99-
JsonObject body) throws SQLException;
100-
10199
public ArrayList executeSelectTrigger(Connection connection, String sqlQuery)
102100
throws SQLException {
103101
try (PreparedStatement stmt = connection.prepareStatement(sqlQuery)) {
@@ -142,6 +140,119 @@ public ArrayList executeSelectQuery(Connection connection, String sqlQuery, Json
142140
}
143141
}
144142

143+
public JsonObject executeUpsert(Connection connection, String idColumn,
144+
JsonObject body) throws SQLException {
145+
validateQuery();
146+
JsonObject foundRow;
147+
JsonObjectBuilder row = Json.createObjectBuilder();
148+
int rowsCount = 0;
149+
int i;
150+
ResultSet rs;
151+
ResultSetMetaData metaData;
152+
153+
StringBuilder keys = new StringBuilder();
154+
StringBuilder values = new StringBuilder();
155+
StringBuilder setString = new StringBuilder();
156+
for (Map.Entry<String, JsonValue> entry : body.entrySet()) {
157+
if (keys.length() > 0) {
158+
keys.append(",");
159+
}
160+
keys.append(entry.getKey());
161+
if (values.length() > 0) {
162+
values.append(",");
163+
}
164+
values.append("?");
165+
if (!entry.getKey().equals(idColumn)) {
166+
if (setString.length() > 0) {
167+
setString.append(",");
168+
}
169+
setString.append(entry.getKey()).append(" = ?");
170+
}
171+
}
172+
173+
String sqlSELECT =
174+
" SELECT" +
175+
" *" +
176+
" FROM " + tableName +
177+
" WHERE " + idColumn + " = ?";
178+
String sqlInsert = "INSERT INTO " + tableName +
179+
" (" + keys.toString() + ")" +
180+
" VALUES (" + values.toString() + ")";
181+
String sqlUpdate = "UPDATE " + tableName +
182+
" SET " + setString.toString() +
183+
" WHERE " + idColumn + " = ?";
184+
185+
PreparedStatement stmtSelect = null;
186+
PreparedStatement stmtInsert = null;
187+
PreparedStatement stmtUpdate = null;
188+
189+
try {
190+
connection.setAutoCommit(false);
191+
192+
stmtSelect = connection.prepareStatement(sqlSELECT);
193+
Utils.setStatementParam(stmtSelect, 1, idColumn, body);
194+
rs = stmtSelect.executeQuery();
195+
metaData = rs.getMetaData();
196+
while (rs.next()) {
197+
for (i = 1; i <= metaData.getColumnCount(); i++) {
198+
row = Utils.getColumnDataByType(rs, metaData, i, row);
199+
}
200+
rowsCount++;
201+
if (rowsCount > 1) {
202+
throw new RuntimeException("Error: the number of matching rows is not exactly one");
203+
}
204+
}
205+
foundRow = row.build();
206+
207+
i = 1;
208+
if (foundRow.size() == 0) {
209+
stmtInsert = connection.prepareStatement(sqlInsert);
210+
for (Map.Entry<String, JsonValue> entry : body.entrySet()) {
211+
Utils.setStatementParam(stmtInsert, i, entry.getKey(), body);
212+
i++;
213+
}
214+
stmtInsert.execute();
215+
} else {
216+
stmtUpdate = connection.prepareStatement(sqlUpdate);
217+
for (Map.Entry<String, JsonValue> entry : body.entrySet()) {
218+
if (!entry.getKey().equals(idColumn)) {
219+
Utils.setStatementParam(stmtUpdate, i, entry.getKey(), body);
220+
i++;
221+
}
222+
}
223+
Utils.setStatementParam(stmtUpdate, i, idColumn, body);
224+
stmtUpdate.execute();
225+
}
226+
227+
rs = stmtSelect.executeQuery();
228+
metaData = rs.getMetaData();
229+
rowsCount = 0;
230+
while (rs.next()) {
231+
for (i = 1; i <= metaData.getColumnCount(); i++) {
232+
row = Utils.getColumnDataByType(rs, metaData, i, row);
233+
}
234+
rowsCount++;
235+
if (rowsCount > 1) {
236+
throw new RuntimeException("Error: the number of matching rows is not exactly one");
237+
}
238+
}
239+
connection.commit();
240+
241+
} finally {
242+
if (stmtSelect != null) {
243+
stmtSelect.close();
244+
}
245+
if (stmtInsert != null) {
246+
stmtInsert.close();
247+
}
248+
if (stmtUpdate != null) {
249+
stmtUpdate.close();
250+
}
251+
connection.setAutoCommit(true);
252+
}
253+
return row.build();
254+
}
255+
145256
public void validateQuery() {
146257
if (tableName == null) {
147258
throw new RuntimeException("Table name is required field");

0 commit comments

Comments
 (0)