diff --git a/pom.xml b/pom.xml index 43b16a88..d68b2c69 100644 --- a/pom.xml +++ b/pom.xml @@ -67,6 +67,7 @@ test + org.apache.maven.plugins diff --git a/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSDeleteAction.java b/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSDeleteAction.java index 3495a621..ee75105d 100644 --- a/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSDeleteAction.java +++ b/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSDeleteAction.java @@ -65,16 +65,18 @@ public class RDBMSDeleteAction extends AbstractRDBMSAction implements DeleteInte // todo sql customization - can edit sql and/or param list - Connection connection = getConnection(deleteRequest); - QueryManager.executeUpdateForRowCount(connection, sql, params); - List outputRecords = new ArrayList<>(); - rs.setRecords(outputRecords); - for(Serializable primaryKey : deleteRequest.getPrimaryKeys()) + try(Connection connection = getConnection(deleteRequest)) { - QRecord qRecord = new QRecord().withTableName(deleteRequest.getTableName()).withValue("id", primaryKey); - // todo uh, identify any errors? - QRecord outputRecord = new QRecord(qRecord); - outputRecords.add(outputRecord); + QueryManager.executeUpdateForRowCount(connection, sql, params); + List outputRecords = new ArrayList<>(); + rs.setRecords(outputRecords); + for(Serializable primaryKey : deleteRequest.getPrimaryKeys()) + { + QRecord qRecord = new QRecord().withTableName(deleteRequest.getTableName()).withValue("id", primaryKey); + // todo uh, identify any errors? + QRecord outputRecord = new QRecord(qRecord); + outputRecords.add(outputRecord); + } } return rs; diff --git a/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSInsertAction.java b/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSInsertAction.java index b8fa89a6..dcda8e85 100644 --- a/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSInsertAction.java +++ b/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSInsertAction.java @@ -99,17 +99,19 @@ public class RDBMSInsertAction extends AbstractRDBMSAction implements InsertInte // todo - non-serial-id style tables // todo - other generated values, e.g., createDate... maybe need to re-select? - Connection connection = getConnection(insertRequest); - List idList = QueryManager.executeInsertForGeneratedIds(connection, sql.toString(), params); - List outputRecords = new ArrayList<>(); - rs.setRecords(outputRecords); - int index = 0; - for(QRecord record : insertRequest.getRecords()) + try(Connection connection = getConnection(insertRequest)) { - Integer id = idList.get(index++); - QRecord outputRecord = new QRecord(record); - outputRecord.setValue(table.getPrimaryKeyField(), id); - outputRecords.add(outputRecord); + List idList = QueryManager.executeInsertForGeneratedIds(connection, sql.toString(), params); + List outputRecords = new ArrayList<>(); + rs.setRecords(outputRecords); + int index = 0; + for(QRecord record : insertRequest.getRecords()) + { + Integer id = idList.get(index++); + QRecord outputRecord = new QRecord(record); + outputRecord.setValue(table.getPrimaryKeyField(), id); + outputRecords.add(outputRecord); + } } return rs; diff --git a/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSQueryAction.java b/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSQueryAction.java index 65f1eba9..1a7d3d3f 100644 --- a/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSQueryAction.java +++ b/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSQueryAction.java @@ -104,29 +104,31 @@ public class RDBMSQueryAction extends AbstractRDBMSAction implements QueryInterf List records = new ArrayList<>(); rs.setRecords(records); - Connection connection = getConnection(queryRequest); - QueryManager.executeStatement(connection, sql, ((ResultSet resultSet) -> + try(Connection connection = getConnection(queryRequest)) { - ResultSetMetaData metaData = resultSet.getMetaData(); - while(resultSet.next()) + QueryManager.executeStatement(connection, sql, ((ResultSet resultSet) -> { - // todo - should refactor this for view etc to use too. - // todo - Add display values (String labels for possibleValues, formatted #'s, etc) - QRecord record = new QRecord(); - records.add(record); - record.setTableName(table.getName()); - LinkedHashMap values = new LinkedHashMap<>(); - record.setValues(values); - - for(int i = 1; i <= metaData.getColumnCount(); i++) + ResultSetMetaData metaData = resultSet.getMetaData(); + while(resultSet.next()) { - QFieldMetaData qFieldMetaData = fieldList.get(i - 1); - Serializable value = getValue(qFieldMetaData, resultSet, i); - values.put(qFieldMetaData.getName(), value); - } - } + // todo - should refactor this for view etc to use too. + // todo - Add display values (String labels for possibleValues, formatted #'s, etc) + QRecord record = new QRecord(); + records.add(record); + record.setTableName(table.getName()); + LinkedHashMap values = new LinkedHashMap<>(); + record.setValues(values); - }), params); + for(int i = 1; i <= metaData.getColumnCount(); i++) + { + QFieldMetaData qFieldMetaData = fieldList.get(i - 1); + Serializable value = getValue(qFieldMetaData, resultSet, i); + values.put(qFieldMetaData.getName(), value); + } + } + + }), params); + } return rs; } diff --git a/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSUpdateAction.java b/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSUpdateAction.java index 89419bf3..1adb3473 100644 --- a/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSUpdateAction.java +++ b/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSUpdateAction.java @@ -97,10 +97,6 @@ public class RDBMSUpdateAction extends AbstractRDBMSAction implements UpdateInte outputRecords.add(outputRecord); } - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // todo - further optimization: if setting a bunch of records to have the same value, a single update where id IN ? // - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - try(Connection connection = getConnection(updateRequest)) { ///////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/main/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/ConnectionManager.java b/src/main/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/ConnectionManager.java index 8da72d21..6f2488e1 100644 --- a/src/main/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/ConnectionManager.java +++ b/src/main/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/ConnectionManager.java @@ -45,9 +45,9 @@ public class ConnectionManager { case "aurora": { - //TODO AWS version not working and why ssl=false required? + // TODO aws-mysql-jdbc driver not working when running on AWS + // jdbcURL = "jdbc:mysql:aws://" + backend.getHostName() + ":" + backend.getPort() + "/" + backend.getDatabaseName() + "?rewriteBatchedStatements=true&zeroDateTimeBehavior=CONVERT_TO_NULL"; jdbcURL = "jdbc:mysql://" + backend.getHostName() + ":" + backend.getPort() + "/" + backend.getDatabaseName() + "?rewriteBatchedStatements=true&zeroDateTimeBehavior=convertToNull&useSSL=false"; - //jdbcURL = "jdbc:mysql:aws://" + backend.getHostName() + ":" + backend.getPort() + "/" + backend.getDatabaseName() + "?rewriteBatchedStatements=true&zeroDateTimeBehavior=convertToNull"; break; } case "mysql": diff --git a/src/main/java/com/kingsrook/qqq/backend/module/rdbms/model/metadata/RDBMSBackendMetaData.java b/src/main/java/com/kingsrook/qqq/backend/module/rdbms/model/metadata/RDBMSBackendMetaData.java index 627c7557..5425c3e1 100644 --- a/src/main/java/com/kingsrook/qqq/backend/module/rdbms/model/metadata/RDBMSBackendMetaData.java +++ b/src/main/java/com/kingsrook/qqq/backend/module/rdbms/model/metadata/RDBMSBackendMetaData.java @@ -52,6 +52,18 @@ public class RDBMSBackendMetaData extends QBackendMetaData + /******************************************************************************* + ** Fluent setter, override to help fluent flows + *******************************************************************************/ + @Override + public RDBMSBackendMetaData withName(String name) + { + setName(name); + return this; + } + + + /******************************************************************************* ** Getter for vendor ** diff --git a/src/test/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/ConnectionManagerTest.java b/src/test/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/ConnectionManagerTest.java new file mode 100644 index 00000000..a51a041b --- /dev/null +++ b/src/test/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/ConnectionManagerTest.java @@ -0,0 +1,113 @@ +/* + * QQQ - Low-code Application Framework for Engineers. + * Copyright (C) 2021-2022. Kingsrook, LLC + * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States + * contact@kingsrook.com + * https://github.com/Kingsrook/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package com.kingsrook.qqq.backend.module.rdbms.jdbc; + + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.Collections; +import com.kingsrook.qqq.backend.module.rdbms.model.metadata.RDBMSBackendMetaData; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertNotNull; + + +/******************************************************************************* + ** Unit test for ConnectionManager + *******************************************************************************/ +@Disabled("This was okay for POC, but shouldn't run in CI") +class ConnectionManagerTest +{ + @Test + public void test() throws SQLException + { + Connection connection = new ConnectionManager().getConnection(getAuroraBacked()); + assertNotNull(connection); + + String sql = """ + insert into raw_parcel_invoice_line_ups (id, create_date, modify_date, parcel_invoice_line_id, account_country, account_number, account_split_payment_indicator, account_tax_id, alternate_invoice_amount, alternate_invoice_number, alternate_invoicing_currency_code, bol__number_1, bol__number_2, bol__number_3, bol__number_4, bol__number_5, basis_currency_code, basis_value, bill_option_code, + billed_weight, billed_weight_type, billed_weight_unit_of_measure, cccd_number, cpc_code, carrier_name_clinical_trial_identification_number__sds_id, charge_category_code, charge_category_detail_code, charge_classification_code, charge_description, charge_description_code, charge_source, charged_unit_quantity, class_number, contact_name, container_type, + corrected_zone, currency_variance_amount, customer_reference_number, customs_number, customs_office_name, cycle_date, cycle_number, declaration_number, declared_freight_class, detail_class, detail_keyed_billed_dimension, detail_keyed_billed_unit_of_measure, detail_keyed_dim, detail_keyed_unit_of_measure, direct_shipment_date, document_number, document_type, + duty_amount, duty_rate, duty_value, eft_date, eori_number, epu, entered_currency_code, entered_value, entered_weight, entered_weight_unit_of_measure, entry_date, entry_number, entry_port, entry_type, exchange_rate, excise_tax_amount, excise_tax_rate, export_place, foreign_trade_reference_number, freight_sequence_number, gst_amount, gst_rate, + goods_description, import_tax_id, incentive_amount, invoice_amount, invoice_currency_code, invoice_date, invoice_due_date, invoice_exchange_rate, invoice_level_charge, invoice_number, invoice_remit_amount, invoice_type_code, invoice_type_detail_code, item_quantity, item_quantity_unit_of_measure, job_number, lead_shipment_number, line_item_number, + master_air_waybill_number, miscellaneous_address_1_address_line_1, miscellaneous_address_1_address_line_2, miscellaneous_address_1_city, miscellaneous_address_1_company_name, miscellaneous_address_1_country, miscellaneous_address_1_name, miscellaneous_address_1_postal, miscellaneous_address_1_state, miscellaneous_address_2_address_line_1, + miscellaneous_address_2_address_line_2, miscellaneous_address_2_city, miscellaneous_address_2_company_name, miscellaneous_address_2_country, miscellaneous_address_2_name, miscellaneous_address_2_postal, miscellaneous_address_2_state, miscellaneous_address_qual_1, miscellaneous_address_qual_2, miscellaneous_currency_code, miscellaneous_incentive_amount, + miscellaneous_line_1, miscellaneous_line_10, miscellaneous_line_11, miscellaneous_line_2, miscellaneous_line_3, miscellaneous_line_4, miscellaneous_line_5, miscellaneous_line_7, miscellaneous_line_8, miscellaneous_line_9, miscellaneous_net_amount, nmfc, net_amount, office_number, order_in_council, origin_country, original_service_description, + original_shipment_package_quantity, original_tracking_number, other_amount, other_basis_amount, other_customs_number, other_customs_number_indicator, other_rate, oversize_quantity, po__number_1, po__number_10, po__number_2, po__number_3, po__number_4, po__number_5, po__number_6, po__number_7, po__number_8, po__number_9, package_dimension_unit_of_measure, + package_dimensions, package_quantity, package_reference_number_1, package_reference_number_2, package_reference_number_3, package_reference_number_4, package_reference_number_5, payer_role_code, pickup_record_number, place_holder_46, place_holder_47, place_holder_48, place_holder_52, place_holder_53, place_holder_54, place_holder_55, place_holder_56, + place_holder_57, place_holder_58, place_holder_59, promo_discount_alias, promo_discount_applied_indicator, raw_dimension_unit_of_measure, raw_dimensions, receiver_address_line_1, receiver_address_line_2, receiver_city, receiver_company_name, receiver_country, receiver_name, receiver_postal, receiver_state, recipient_number, scc_scale_weight, + sds_delivery_date, sds_error_code, sds_match_level_cd, sds_rnr_date, sima_access, scale_weight_unit_of_measure, scale_weight_quantity, sender_address_line_1, sender_address_line_2, sender_city, sender_company_name, sender_country, sender_name, sender_postal, sender_state, shipment_date, shipment_delivery_date, shipment_description, shipment_export_date, + shipment_import_date, shipment_reference_number_1, shipment_reference_number_2, shipment_release_date, shipment_value_amount, sold_to_address_line_1, sold_to_address_line_2, sold_to_city, sold_to_company_name, sold_to_country, sold_to_name, sold_to_postal, sold_to_state, store_number, tariff_code, tariff_rate, tariff_treatment_number, tax_indicator, + tax_type, tax_value, tax_variance_amount, tax_law_article_basis_amount, tax_law_article_number, third_party_address_line_1, third_party_address_line_2, third_party_city, third_party_company_name, third_party_country, third_party_name, third_party_postal, third_party_state, total_customs_amount, total_value_for_duty, tracking_number, + transaction_currency_code, transaction_date, transport_mode, type_code_1, type_code_2, type_detail_code_1, type_detail_code_2, type_detail_value_1, type_detail_value_2, unit_of_measure, vat_amount, vat_basis_amount, vat_rate, validation_date, version, weight, world_ease_number, zone, data_lake_id) + values + """; + + String values = """ + (0, '2022-06-13 13:07:52.0', '2022-06-13 13:07:52.0', null, 'US', '00000F2098', null, null, 0, null, null, null, null, null, null, null, null, 0.00, null, 0, null, null, null, null, + null, 'MIS', 'SVCH', 'FRT', 'Service Charge', null, null, 0, null, null, null, null, 0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, 0, 0, 0, null, null, null, null, 0, + 0, null, null, null, null, null, 0, 0, 0, null, null, 0, 0, 0, null, null, 0.00, 36, 'USD', '2022-01-01', '2022-01-10', 0, 0, '0000000F2098012', null, 'E', null, 0, null, null, null, + 0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, 0, null, null, null, null, null, null, null, null, null, null, 0, null, 36.00, null, null, null, null, 0, null, 0, + 0, null, null, 0, 0, null, null, null, null, null, null, null, null, null, null, null, null, 0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, '00000F2098', 0, null, null, null, null, 0, null, 0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, 0, null, null, null, null, null, null, null, null, null, null, + 0, null, null, null, 0, 0, 0, null, null, null, null, null, null, null, null, null, 0, 0, null, 'USD', '2022-01-01', null, null, null, null, null, null, null, null, 0, 0, 0, null, 2, null, null, null, 'XXXXXX') + """; + sql += String.join(",", Collections.nCopies(1000, values)); + + for(int i = 0; i < 10; i++) + { + System.out.println("== Cycle " + i); + QueryManager.executeUpdate(connection, "BEGIN WORK"); + System.out.println("Begin work..."); + Integer insertCount = QueryManager.executeUpdateForRowCount(connection, sql); + System.out.println("Inserted: " + insertCount); + Integer deleteCount = QueryManager.executeUpdateForRowCount(connection, "DELETE from raw_parcel_invoice_line_ups WHERE data_lake_id='XXXXXX'"); + System.out.println("Deleted: " + deleteCount); + + boolean commit = true; + if(commit) + { + QueryManager.executeUpdate(connection, "COMMIT WORK"); + System.out.println("Commit."); + } + else + { + QueryManager.executeUpdate(connection, "ROLLBACK WORK"); + System.out.println("Rollback."); + } + } + } + + + + private RDBMSBackendMetaData getAuroraBacked() + { + return new RDBMSBackendMetaData() + .withName("aurora-test") + .withVendor("aurora") + .withHostName("nf-one-development-aurora.cwuhqcx1inwx.us-east-2.rds.amazonaws.com") + .withPort(3306) + .withDatabaseName("nutrifresh_one") + .withUsername("nf_admin") + .withPassword("%!2rwcH+fb#WgPg"); + } +}