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 @@
-
-
-
-
-
-
-
-
-
-
-
+
+ 9.0.1
+ JavaOnly
+ true
+
+
+
+
+
+
+ (bundled)
+ (bundled)
+ $PROJECT_DIR$/checkstyle.xml
+
\ 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');