From 3d1652c85213d13ea53aa130fdafe916a9b09e79 Mon Sep 17 00:00:00 2001 From: Darin Kelkhoff Date: Thu, 28 Jul 2022 15:16:22 -0500 Subject: [PATCH] Re-enabling sample project, now that it can use h2 database (so it can run & pass in CI); cleanup some warnings, and some initial IJ configs --- .gitignore | 1 + .idea/checkstyle-idea.xml | 25 ++++--- .idea/compiler.xml | 1 + .idea/inspectionProfiles/Project_Default.xml | 6 ++ .idea/misc.xml | 1 + .../All_in_qqq_sample_project.xml | 18 +++++ .idea/runConfigurations/Sample_Javalin.xml | 16 +++++ pom.xml | 2 +- .../serialization/DeserializerUtils.java | 2 +- .../etl/basic/BasicETLProcess.java | 8 +-- qqq-sample-project/pom.xml | 6 ++ .../sampleapp/SampleJavalinServer.java | 20 +++++- .../sampleapp/SampleMetaDataProvider.java | 46 ++++++++----- .../FedExInvoiceCSVSyntaxFixer.java | 46 ------------- .../sampleapp/SampleJavalinServerTest.java | 24 +++++++ .../sampleapp/SampleMetaDataProviderTest.java | 67 +++++++++++++++++++ .../test/resources/prime-test-database.sql | 60 +++++++++++++++++ 17 files changed, 267 insertions(+), 82 deletions(-) create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/runConfigurations/All_in_qqq_sample_project.xml create mode 100644 .idea/runConfigurations/Sample_Javalin.xml delete mode 100644 qqq-sample-project/src/main/java/com/kingsrook/sampleapp/customizers/FedExInvoiceCSVSyntaxFixer.java create mode 100644 qqq-sample-project/src/test/java/com/kingsrook/sampleapp/SampleJavalinServerTest.java create mode 100644 qqq-sample-project/src/test/resources/prime-test-database.sql diff --git a/.gitignore b/.gitignore index 2c7054c0..64c6c21c 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,4 @@ target/ # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* .DS_Store +*.swp diff --git a/.idea/checkstyle-idea.xml b/.idea/checkstyle-idea.xml index e2be48c1..dea9ddd5 100644 --- a/.idea/checkstyle-idea.xml +++ b/.idea/checkstyle-idea.xml @@ -1,16 +1,19 @@ - - \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 1624ce59..30cff7e5 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -22,6 +22,7 @@ + diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 00000000..977e7b3b --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 67e1e611..0d9906f3 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -5,6 +5,7 @@ diff --git a/.idea/runConfigurations/All_in_qqq_sample_project.xml b/.idea/runConfigurations/All_in_qqq_sample_project.xml new file mode 100644 index 00000000..8603bc2c --- /dev/null +++ b/.idea/runConfigurations/All_in_qqq_sample_project.xml @@ -0,0 +1,18 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations/Sample_Javalin.xml b/.idea/runConfigurations/Sample_Javalin.xml new file mode 100644 index 00000000..4978e9e5 --- /dev/null +++ b/.idea/runConfigurations/Sample_Javalin.xml @@ -0,0 +1,16 @@ + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 7eae74b7..0e78e1d0 100644 --- a/pom.xml +++ b/pom.xml @@ -34,7 +34,7 @@ qqq-backend-module-filesystem qqq-middleware-picocli qqq-middleware-javalin - + qqq-sample-project diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/serialization/DeserializerUtils.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/serialization/DeserializerUtils.java index 6de95075..036a4d85 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/serialization/DeserializerUtils.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/serialization/DeserializerUtils.java @@ -225,7 +225,7 @@ public class DeserializerUtils // otherwise, either find some jackson annotation that makes sense, and apply it to the setter method, // // or if no jackson annotation is right, then come up with annotation of our own. // ///////////////////////////////////////////////////////////////////////////////////////////////////////// - method.invoke(output, reflectivelyDeserialize((Class) parameterType, (TreeNode) value)); + method.invoke(output, reflectivelyDeserialize((Class) parameterType, (TreeNode) value)); } } catch(IllegalAccessException | InvocationTargetException | NoSuchMethodException | IOException e) diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/etl/basic/BasicETLProcess.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/etl/basic/BasicETLProcess.java index 5d213fa9..1cdcb132 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/etl/basic/BasicETLProcess.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/etl/basic/BasicETLProcess.java @@ -62,7 +62,7 @@ public class BasicETLProcess .withCodeType(QCodeType.JAVA) .withCodeUsage(QCodeUsage.BACKEND_STEP)) .withInputData(new QFunctionInputMetaData() - .addField(new QFieldMetaData(FIELD_SOURCE_TABLE, QFieldType.STRING))); + .withField(new QFieldMetaData(FIELD_SOURCE_TABLE, QFieldType.STRING))); QStepMetaData transformFunction = new QBackendStepMetaData() .withName(FUNCTION_NAME_TRANSFORM) @@ -71,8 +71,8 @@ public class BasicETLProcess .withCodeType(QCodeType.JAVA) .withCodeUsage(QCodeUsage.BACKEND_STEP)) .withInputData(new QFunctionInputMetaData() - .addField(new QFieldMetaData(FIELD_MAPPING_JSON, QFieldType.STRING)) - .addField(new QFieldMetaData(FIELD_DESTINATION_TABLE, QFieldType.STRING))); + .withField(new QFieldMetaData(FIELD_MAPPING_JSON, QFieldType.STRING)) + .withField(new QFieldMetaData(FIELD_DESTINATION_TABLE, QFieldType.STRING))); QStepMetaData loadFunction = new QBackendStepMetaData() .withName(FUNCTION_NAME_LOAD) @@ -81,7 +81,7 @@ public class BasicETLProcess .withCodeType(QCodeType.JAVA) .withCodeUsage(QCodeUsage.BACKEND_STEP)) .withInputData(new QFunctionInputMetaData() - .addField(new QFieldMetaData(FIELD_DESTINATION_TABLE, QFieldType.STRING))) + .withField(new QFieldMetaData(FIELD_DESTINATION_TABLE, QFieldType.STRING))) .withOutputMetaData(new QFunctionOutputMetaData() .addField(new QFieldMetaData(FIELD_RECORD_COUNT, QFieldType.INTEGER))); diff --git a/qqq-sample-project/pom.xml b/qqq-sample-project/pom.xml index 2808ec54..917a1c4f 100644 --- a/qqq-sample-project/pom.xml +++ b/qqq-sample-project/pom.xml @@ -65,6 +65,12 @@ qqq-middleware-picocli ${revision} + + com.h2database + h2 + 2.1.212 + test + diff --git a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleJavalinServer.java b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleJavalinServer.java index 3a3406c0..434b4362 100644 --- a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleJavalinServer.java +++ b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleJavalinServer.java @@ -40,6 +40,8 @@ public class SampleJavalinServer private QInstance qInstance; + private Javalin javalinService; + /******************************************************************************* @@ -62,13 +64,13 @@ public class SampleJavalinServer qInstance = SampleMetaDataProvider.defineInstance(); QJavalinImplementation qJavalinImplementation = new QJavalinImplementation(qInstance); - Javalin service = Javalin.create(config -> + javalinService = Javalin.create(config -> { // todo - not all!! config.enableCorsForAllOrigins(); }).start(PORT); - service.routes(qJavalinImplementation.getRoutes()); - service.after(ctx -> + javalinService.routes(qJavalinImplementation.getRoutes()); + javalinService.after(ctx -> ctx.res.setHeader("Access-Control-Allow-Origin", "http://localhost:3000")); } catch(Exception e) @@ -77,4 +79,16 @@ public class SampleJavalinServer } } + + + /******************************************************************************* + ** + *******************************************************************************/ + public void stopJavalinServer() + { + if(javalinService != null) + { + javalinService.stop(); + } + } } diff --git a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleMetaDataProvider.java b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleMetaDataProvider.java index b8f1020d..a86b7ad4 100644 --- a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleMetaDataProvider.java +++ b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleMetaDataProvider.java @@ -59,12 +59,14 @@ import io.github.cdimascio.dotenv.Dotenv; *******************************************************************************/ public class SampleMetaDataProvider { - public static final String MYSQL_BACKEND_NAME = "mysql"; + public static boolean USE_MYSQL = false; + + public static final String RDBMS_BACKEND_NAME = "rdbms"; public static final String FILESYSTEM_BACKEND_NAME = "filesystem"; public static final String AUTH0_AUTHENTICATION_MODULE_NAME = "auth0"; // public static final String AUTH0_BASE_URL = "https://kingsrook.us.auth0.com/"; - public static final String AUTH0_BASE_URL = "https://nutrifresh-one-development.us.auth0.com/"; + public static final String AUTH0_BASE_URL = "https://nutrifresh-one-development.us.auth0.com/"; public static final String PROCESS_NAME_GREET = "greet"; public static final String PROCESS_NAME_GREET_INTERACTIVE = "greetInteractive"; @@ -88,7 +90,7 @@ public class SampleMetaDataProvider QInstance qInstance = new QInstance(); qInstance.setAuthentication(defineAuthentication()); - qInstance.addBackend(defineMysqlBackend()); + qInstance.addBackend(defineRdbmsBackend()); qInstance.addBackend(defineFilesystemBackend()); qInstance.addTable(defineTableCarrier()); qInstance.addTable(defineTablePerson()); @@ -119,17 +121,29 @@ public class SampleMetaDataProvider /******************************************************************************* ** *******************************************************************************/ - public static QBackendMetaData defineMysqlBackend() + public static RDBMSBackendMetaData defineRdbmsBackend() { - Dotenv dotenv = Dotenv.configure().load(); - return new RDBMSBackendMetaData() - .withVendor("mysql") - .withHostName("127.0.0.1") - .withPort(3306) - .withDatabaseName("qqq") - .withUsername("root") - .withPassword(dotenv.get("RDBMS_PASSWORD")) - .withName(MYSQL_BACKEND_NAME); + if(USE_MYSQL) + { + Dotenv dotenv = Dotenv.configure().load(); + return new RDBMSBackendMetaData() + .withName(RDBMS_BACKEND_NAME) + .withVendor("mysql") + .withHostName("127.0.0.1") + .withPort(3306) + .withDatabaseName("qqq") + .withUsername("root") + .withPassword(dotenv.get("RDBMS_PASSWORD")); + } + else + { + return (new RDBMSBackendMetaData() + .withName(RDBMS_BACKEND_NAME) + .withVendor("h2") + .withHostName("mem") + .withDatabaseName("test_database") + .withUsername("sa")); + } } @@ -153,7 +167,7 @@ public class SampleMetaDataProvider { QTableMetaData table = new QTableMetaData(); table.setName("carrier"); - table.setBackendName(MYSQL_BACKEND_NAME); + table.setBackendName(RDBMS_BACKEND_NAME); table.setPrimaryKeyField("id"); table.addField(new QFieldMetaData("id", QFieldType.INTEGER)); @@ -182,7 +196,7 @@ public class SampleMetaDataProvider return new QTableMetaData() .withName("person") .withLabel("Person") - .withBackendName(MYSQL_BACKEND_NAME) + .withBackendName(RDBMS_BACKEND_NAME) .withPrimaryKeyField("id") .withField(new QFieldMetaData("id", QFieldType.INTEGER)) .withField(new QFieldMetaData("createDate", QFieldType.DATE_TIME).withBackendName("create_date")) @@ -443,7 +457,7 @@ public class SampleMetaDataProvider .withCodeType(QCodeType.JAVA) .withCodeUsage(QCodeUsage.BACKEND_STEP)) .withInputData(new QFunctionInputMetaData() - .addField(new QFieldMetaData(ThrowerStep.FIELD_SLEEP_MILLIS, QFieldType.INTEGER)))); + .withField(new QFieldMetaData(ThrowerStep.FIELD_SLEEP_MILLIS, QFieldType.INTEGER)))); } } diff --git a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/customizers/FedExInvoiceCSVSyntaxFixer.java b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/customizers/FedExInvoiceCSVSyntaxFixer.java deleted file mode 100644 index ec76b244..00000000 --- a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/customizers/FedExInvoiceCSVSyntaxFixer.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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.sampleapp.customizers; - - -import java.util.function.Function; - - -/******************************************************************************* - ** The fedex invoice files - they're CSV, but they have a handful of values - ** that we can't read, because they have an extra quote (") character within - ** a field. - ** - ** It always looks like: {"u - ** This function fixes it by stripping the " out of the middle, to just be: {u - *******************************************************************************/ -public class FedExInvoiceCSVSyntaxFixer implements Function -{ - /******************************************************************************* - ** - *******************************************************************************/ - @Override - public String apply(String s) - { - return (s.replaceAll("\\{\"u", "{u")); - } -} diff --git a/qqq-sample-project/src/test/java/com/kingsrook/sampleapp/SampleJavalinServerTest.java b/qqq-sample-project/src/test/java/com/kingsrook/sampleapp/SampleJavalinServerTest.java new file mode 100644 index 00000000..06bcd1e7 --- /dev/null +++ b/qqq-sample-project/src/test/java/com/kingsrook/sampleapp/SampleJavalinServerTest.java @@ -0,0 +1,24 @@ +package com.kingsrook.sampleapp; + + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + + +/******************************************************************************* + ** Unit test for com.kingsrook.sampleapp.SampleJavalinServer + *******************************************************************************/ +class SampleJavalinServerTest +{ + /******************************************************************************* + ** + *******************************************************************************/ + @Test + void testStartStop() + { + SampleJavalinServer sampleJavalinServer = new SampleJavalinServer(); + sampleJavalinServer.startJavalinServer(); + sampleJavalinServer.stopJavalinServer(); + } + +} \ No newline at end of file diff --git a/qqq-sample-project/src/test/java/com/kingsrook/sampleapp/SampleMetaDataProviderTest.java b/qqq-sample-project/src/test/java/com/kingsrook/sampleapp/SampleMetaDataProviderTest.java index 38fdeb33..1b145b57 100644 --- a/qqq-sample-project/src/test/java/com/kingsrook/sampleapp/SampleMetaDataProviderTest.java +++ b/qqq-sample-project/src/test/java/com/kingsrook/sampleapp/SampleMetaDataProviderTest.java @@ -24,9 +24,13 @@ package com.kingsrook.sampleapp; import java.io.File; import java.io.IOException; +import java.io.InputStream; +import java.sql.Connection; +import java.util.List; import java.util.UUID; import com.kingsrook.qqq.backend.core.actions.processes.RunProcessAction; import com.kingsrook.qqq.backend.core.actions.tables.QueryAction; +import com.kingsrook.qqq.backend.core.exceptions.QException; import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessInput; import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessOutput; import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryInput; @@ -37,10 +41,16 @@ import com.kingsrook.qqq.backend.core.model.session.QSession; import com.kingsrook.qqq.backend.core.processes.implementations.mock.MockBackendStep; import com.kingsrook.qqq.backend.module.filesystem.local.actions.FilesystemQueryAction; import com.kingsrook.qqq.backend.module.filesystem.local.model.metadata.FilesystemTableBackendDetails; +import com.kingsrook.qqq.backend.module.rdbms.jdbc.ConnectionManager; +import com.kingsrook.qqq.backend.module.rdbms.jdbc.QueryManager; +import junit.framework.Assert; import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -50,6 +60,40 @@ import static org.junit.jupiter.api.Assertions.assertTrue; class SampleMetaDataProviderTest { + /******************************************************************************* + ** + *******************************************************************************/ + @BeforeEach + void beforeEach() throws Exception + { + primeTestDatabase("prime-test-database.sql"); + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + @SuppressWarnings("unchecked") + private void primeTestDatabase(String sqlFileName) throws Exception + { + ConnectionManager connectionManager = new ConnectionManager(); + try(Connection connection = connectionManager.getConnection(SampleMetaDataProvider.defineRdbmsBackend())) + { + InputStream primeTestDatabaseSqlStream = SampleMetaDataProviderTest.class.getResourceAsStream("/" + sqlFileName); + Assert.assertNotNull(primeTestDatabaseSqlStream); + List lines = (List) IOUtils.readLines(primeTestDatabaseSqlStream); + lines = lines.stream().filter(line -> !line.startsWith("-- ")).toList(); + String joinedSQL = String.join("\n", lines); + for(String sql : joinedSQL.split(";")) + { + QueryManager.executeUpdate(connection, sql); + } + } + } + + + /******************************************************************************* ** *******************************************************************************/ @@ -77,6 +121,9 @@ class SampleMetaDataProviderTest + /******************************************************************************* + ** + *******************************************************************************/ private File copyTestFileToRandomNameUnderTable(QTableMetaData fedExTable) throws IOException { File destinationDir = new File(SampleMetaDataProvider.defineFilesystemBackend().getBasePath() + File.separator + @@ -121,4 +168,24 @@ class SampleMetaDataProviderTest assertTrue(result.getRecords().stream().allMatch(r -> r.getValues().containsKey("id")), "records should have an id, set by the process"); } + + + /******************************************************************************* + ** + *******************************************************************************/ + @Test + public void testThrowProcess() throws Exception + { + QInstance qInstance = SampleMetaDataProvider.defineInstance(); + RunProcessInput request = new RunProcessInput(qInstance); + request.setSession(new QSession()); + request.setProcessName(SampleMetaDataProvider.PROCESS_NAME_SIMPLE_THROW); + request.addValue(SampleMetaDataProvider.ThrowerStep.FIELD_SLEEP_MILLIS, 10); + + assertThrows(QException.class, () -> + { + new RunProcessAction().execute(request); + }); + } + } \ No newline at end of file diff --git a/qqq-sample-project/src/test/resources/prime-test-database.sql b/qqq-sample-project/src/test/resources/prime-test-database.sql new file mode 100644 index 00000000..07ab6ac6 --- /dev/null +++ b/qqq-sample-project/src/test/resources/prime-test-database.sql @@ -0,0 +1,60 @@ +-- +-- 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 . +-- + +DROP TABLE IF EXISTS person; +CREATE TABLE person +( + id INT AUTO_INCREMENT primary key , + create_date TIMESTAMP DEFAULT now(), + modify_date TIMESTAMP DEFAULT now(), + + first_name VARCHAR(80) NOT NULL, + last_name VARCHAR(80) NOT NULL, + birth_date DATE, + email VARCHAR(250) NOT NULL +); + +INSERT INTO person (id, first_name, last_name, birth_date, email) VALUES (1, 'Darin', 'Kelkhoff', '1980-05-31', 'darin.kelkhoff@gmail.com'); +INSERT INTO person (id, first_name, last_name, birth_date, email) VALUES (2, 'James', 'Maes', '1980-05-15', 'jmaes@mmltholdings.com'); +INSERT INTO person (id, first_name, last_name, birth_date, email) VALUES (3, 'Tim', 'Chamberlain', '1976-05-28', 'tchamberlain@mmltholdings.com'); +INSERT INTO person (id, first_name, last_name, birth_date, email) VALUES (4, 'Tyler', 'Samples', NULL, 'tsamples@mmltholdings.com'); +INSERT INTO person (id, first_name, last_name, birth_date, email) VALUES (5, 'Garret', 'Richardson', '1981-01-01', 'grichardson@mmltholdings.com'); + +DROP TABLE IF EXISTS carrier; +CREATE TABLE carrier +( + id INT AUTO_INCREMENT PRIMARY KEY, + name VARCHAR(80) NOT NULL, + company_code VARCHAR(80) NOT NULL, + service_level VARCHAR(80) NOT NULL +); + +INSERT INTO carrier (id, name, company_code, service_level) VALUES (1, 'UPS Ground', 'UPS', 'G'); +INSERT INTO carrier (id, name, company_code, service_level) VALUES (2, 'UPS 2Day', 'UPS', '2'); +INSERT INTO carrier (id, name, company_code, service_level) VALUES (3, 'UPS International', 'UPS', 'I'); +INSERT INTO carrier (id, name, company_code, service_level) VALUES (4, 'Fedex Ground', 'FEDEX', 'G'); +INSERT INTO carrier (id, name, company_code, service_level) VALUES (5, 'Fedex Next Day', 'UPS', '1'); +INSERT INTO carrier (id, name, company_code, service_level) VALUES (6, 'Will Call', 'WILL_CALL', 'W'); +INSERT INTO carrier (id, name, company_code, service_level) VALUES (7, 'USPS Priority', 'USPS', '1'); +INSERT INTO carrier (id, name, company_code, service_level) VALUES (8, 'USPS Super Slow', 'USPS', '4'); +INSERT INTO carrier (id, name, company_code, service_level) VALUES (9, 'USPS Super Fast', 'USPS', '0'); +INSERT INTO carrier (id, name, company_code, service_level) VALUES (10, 'DHL International', 'DHL', 'I'); +INSERT INTO carrier (id, name, company_code, service_level) VALUES (11, 'GSO', 'GSO', 'G');