Skip to content

Commit

Permalink
feat(sql.ts): add drop table functionality.
Browse files Browse the repository at this point in the history
  • Loading branch information
mmc-jmur11 committed Jan 12, 2024
1 parent 87cd851 commit 1071f6e
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 123 deletions.
15 changes: 9 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# excel-to-postgres

Quickly export an Excel Workbook to a Postgres DB

# Installation
Expand Down Expand Up @@ -32,12 +33,14 @@ excelToPostgresDb({

Supports four options, all of which are optional:

* *createDatabase* - _true | false_ (Defaults to false)
* *createTables* - _true | false_ (Defaults to false)
* *generatePrimaryKey* - _true | false_ (Defaults to false. Generates 'id' column to be used as a primary key. Cannot be used with 'useExistingPrimaryKeys' option)
* *useExistingPrimaryKeys* - _true | false_ (Defaults to false. Supports multiple primary keys. Append '_pk' to the column name in the workbook that will be the primary key. Cannot be used with 'generatePrimaryKey' option)
- _createDatabase_ - _true | false_ (Defaults to false)
- _createTables_ - _true | false_ (Defaults to false)
- _dropTables_ - _true | false_ (Defaults to false. When creating table, drop the table if it already exists)
- _generatePrimaryKey_ - _true | false_ (Defaults to false. Generates 'id' column to be used as a primary key. Cannot be used with 'useExistingPrimaryKeys' option)
- _useExistingPrimaryKeys_ - _true | false_ (Defaults to false. Supports multiple primary keys. Append '\_pk' to the column name in the workbook that will be the primary key. Cannot be used with 'generatePrimaryKey' option)

# Testing

This package's tests are written using [Jest](https://jestjs.io/). To execute, run:
This package's tests are written using [Jest](https://jestjs.io/). To execute, run:

`npm test`
`npm test`
17 changes: 1 addition & 16 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1 @@
import { excelToPostgresDb } from './sql';

excelToPostgresDb(
{
host: 'localhost',
user: 'postgres',
password: 'postgres',
port: 5432,
database: 'test',
},
'/Users/jim/Documents/workspace/multi-sport-draft-aid/server/data/baseball.xlsx',
{
createDatabase: true,
createTables: true,
}
).then((t) => console.log(t));
export { excelToPostgresDb } from './sql';
15 changes: 11 additions & 4 deletions src/sql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export interface Connection {
export interface Options {
createDatabase?: boolean;
createTables?: boolean;
dropTables?: boolean;
generatePrimaryKey?: boolean;
useExistingPrimaryKeys?: boolean;
}
Expand Down Expand Up @@ -63,7 +64,7 @@ export function createTable<T>(

export function dropTable(tableName: string) {
try {
return `DROP TABLE ${tableName.replace(/\s/g, '')};`;
return `DROP TABLE IF EXISTS ${tableName.replace(/\s/g, '')};`;
} catch (err) {
throw new Error(err);
}
Expand Down Expand Up @@ -185,11 +186,12 @@ export async function excelToPostgresDb(
insertQuery
);
} else if (options && !options.createDatabase && options.createTables) {
await executeQuery(connectionInfo, dropTableQuery);
await executeQueryWithCreateTable(
connectionInfo,
options,
tableQuery,
insertQuery
insertQuery,
dropTableQuery
);
} else if (!options.createDatabase && !options.createTables) {
await executeQuery(connectionInfo, insertQuery);
Expand Down Expand Up @@ -224,10 +226,15 @@ async function executeQueryWithCreateDB(

async function executeQueryWithCreateTable(
connectionInfo: Connection,
options: Options,
tableQuery: string,
insertQuery: string
insertQuery: string,
dropTableQuery: string
) {
try {
if (options.dropTables) {
await executeQuery(connectionInfo, dropTableQuery);
}
await executeQuery(connectionInfo, tableQuery);
await executeQuery(connectionInfo, insertQuery);
} catch (err) {
Expand Down
111 changes: 59 additions & 52 deletions src/tests/sql.test.ts
Original file line number Diff line number Diff line change
@@ -1,60 +1,67 @@
import {
createDatabase,
createTable,
handlePrimaryKey,
insert,
PrimaryKeyOptions,
} from "../sql";
import { etlProcesses, sqlInfo, sqlResults } from "./test-data";
createDatabase,
createTable,
dropTable,
handlePrimaryKey,
insert,
PrimaryKeyOptions,
} from '../sql';
import { etlProcesses, sqlInfo, sqlResults } from './test-data';

describe("SQL tests", () => {
test("create database", () => {
expect(createDatabase(sqlInfo.database)).toEqual(sqlResults.createDatabase);
});
describe('SQL tests', () => {
test('create database', () => {
expect(createDatabase(sqlInfo.database)).toEqual(
sqlResults.createDatabase
);
});

test("create table generate primary key", () => {
expect(
createTable(
sqlInfo.tableName,
etlProcesses.sheet_one_pk,
PrimaryKeyOptions.GENERATE
)
).toEqual(sqlResults.createTableGeneratedPrimaryKey);
});
test('create table generate primary key', () => {
expect(
createTable(
sqlInfo.tableName,
etlProcesses.sheet_one_pk,
PrimaryKeyOptions.GENERATE
)
).toEqual(sqlResults.createTableGeneratedPrimaryKey);
});

test("create table one existing primary key", () => {
expect(
createTable(
sqlInfo.tableName,
etlProcesses.sheet_one_pk,
PrimaryKeyOptions.USE_EXISTING
)
).toEqual(sqlResults.createTableOnePrimaryKey);
});
test('create table one existing primary key', () => {
expect(
createTable(
sqlInfo.tableName,
etlProcesses.sheet_one_pk,
PrimaryKeyOptions.USE_EXISTING
)
).toEqual(sqlResults.createTableOnePrimaryKey);
});

test("create table multiple existing primary keys", () => {
expect(
createTable(
sqlInfo.tableName,
etlProcesses.sheet_multiple_pk,
PrimaryKeyOptions.USE_EXISTING
)
).toEqual(sqlResults.createTableMultiplePrimaryKeys);
});
test('drop table', () => {
expect(dropTable(sqlInfo.tableName)).toEqual(sqlResults.dropTable);
});

test("insert", () => {
expect(insert(sqlInfo.tableName, [etlProcesses.sheet_one_pk])).toEqual(
sqlResults.insert
);
});
test('create table multiple existing primary keys', () => {
expect(
createTable(
sqlInfo.tableName,
etlProcesses.sheet_multiple_pk,
PrimaryKeyOptions.USE_EXISTING
)
).toEqual(sqlResults.createTableMultiplePrimaryKeys);
});

test("handle primary key options", () => {
expect(handlePrimaryKey({ generatePrimaryKey: true })).toEqual(
PrimaryKeyOptions.GENERATE
);
expect(handlePrimaryKey({ useExistingPrimaryKeys: true })).toEqual(
PrimaryKeyOptions.USE_EXISTING
);
expect(handlePrimaryKey({})).toEqual(PrimaryKeyOptions.NO_PRIMARY_KEY);
});
test('insert', () => {
expect(insert(sqlInfo.tableName, [etlProcesses.sheet_one_pk])).toEqual(
sqlResults.insert
);
});

test('handle primary key options', () => {
expect(handlePrimaryKey({ generatePrimaryKey: true })).toEqual(
PrimaryKeyOptions.GENERATE
);
expect(handlePrimaryKey({ useExistingPrimaryKeys: true })).toEqual(
PrimaryKeyOptions.USE_EXISTING
);
expect(handlePrimaryKey({})).toEqual(PrimaryKeyOptions.NO_PRIMARY_KEY);
});
});
75 changes: 30 additions & 45 deletions src/tests/test-data.ts
Original file line number Diff line number Diff line change
@@ -1,116 +1,96 @@
import { SQLKeyword, SQLType } from '../etl-processes';

const col_names_one_pk = [
'name_pk',
'age',
'isDev'
];
const col_names_one_pk = ['name_pk', 'age', 'isDev'];

const col_names_multiple_pk = [
'name_pk',
'age_pk',
'isDev'
];
const col_names_multiple_pk = ['name_pk', 'age_pk', 'isDev'];

const mockJSON = {
name_pk: 'Person 1',
age: 18,
isDev: true
isDev: true,
};

export const columns_one_pk = [
{
name: col_names_one_pk[0],
type: SQLType.VARCHAR
type: SQLType.VARCHAR,
},
{
name: col_names_one_pk[1],
type: SQLType.FLOAT
type: SQLType.FLOAT,
},
{
name: col_names_one_pk[2],
type: SQLType.BOOLEAN
}
type: SQLType.BOOLEAN,
},
];

export const columns_multiple_pk = [
{
name: col_names_multiple_pk[0],
type: SQLType.VARCHAR
type: SQLType.VARCHAR,
},
{
name: col_names_multiple_pk[1],
type: SQLType.FLOAT
type: SQLType.FLOAT,
},
{
name: col_names_multiple_pk[2],
type: SQLType.BOOLEAN
}
type: SQLType.BOOLEAN,
},
];

export const etlProcesses = {
sheet_one_pk: {
name_pk: mockJSON.name_pk,
age: mockJSON.age,
isDev: mockJSON.isDev
isDev: mockJSON.isDev,
},
sheet_multiple_pk: {
name_pk: mockJSON.name_pk,
age_pk: mockJSON.age,
isDev: mockJSON.isDev
isDev: mockJSON.isDev,
},
fields_one_pk: {
names: [
...col_names_one_pk
],
values: [
mockJSON.name_pk,
mockJSON.age,
mockJSON.isDev
]
names: [...col_names_one_pk],
values: [mockJSON.name_pk, mockJSON.age, mockJSON.isDev],
},
fields_multiple_pks: {
names: [
...col_names_multiple_pk
],
values: [
mockJSON.name_pk,
mockJSON.age,
mockJSON.isDev
]
names: [...col_names_multiple_pk],
values: [mockJSON.name_pk, mockJSON.age, mockJSON.isDev],
},
formattedColumns: [
`${columns_one_pk[0].name} ${columns_one_pk[0].type}`,
`${columns_one_pk[1].name} ${columns_one_pk[1].type}`,
`${columns_one_pk[2].name} ${columns_one_pk[2].type}`
`${columns_one_pk[2].name} ${columns_one_pk[2].type}`,
],
formattedColumns_multiple_pk: [
`${columns_multiple_pk[0].name} ${columns_multiple_pk[0].type}`,
`${columns_multiple_pk[1].name} ${columns_multiple_pk[1].type}`,
`${columns_multiple_pk[2].name} ${columns_multiple_pk[2].type}`
`${columns_multiple_pk[2].name} ${columns_multiple_pk[2].type}`,
],
formattedColumnsOnePrimaryKey: [
`${columns_one_pk[0].name} ${columns_one_pk[0].type} ${SQLKeyword.PRIMARY_KEY}`,
`${columns_one_pk[1].name} ${columns_one_pk[1].type}`,
`${columns_one_pk[2].name} ${columns_one_pk[2].type}`
`${columns_one_pk[2].name} ${columns_one_pk[2].type}`,
],
formattedColumnsMultiplePrimaryKeys: [
`${columns_multiple_pk[0].name} ${columns_multiple_pk[0].type}`,
`${columns_multiple_pk[1].name} ${columns_multiple_pk[1].type}`,
`${columns_multiple_pk[2].name} ${columns_multiple_pk[2].type}`,
`${SQLKeyword.PRIMARY_KEY} (${columns_multiple_pk[0].name},${columns_multiple_pk[1].name})`
`${SQLKeyword.PRIMARY_KEY} (${columns_multiple_pk[0].name},${columns_multiple_pk[1].name})`,
],
formattedColumnsGeneratedPrimaryKey: [
`${columns_one_pk[0].name} ${columns_one_pk[0].type}`,
`${columns_one_pk[1].name} ${columns_one_pk[1].type}`,
`${columns_one_pk[2].name} ${columns_one_pk[2].type}`,
`id ${SQLKeyword.SERIAL} ${SQLKeyword.NOT_NULL} ${SQLKeyword.PRIMARY_KEY}`
`id ${SQLKeyword.SERIAL} ${SQLKeyword.NOT_NULL} ${SQLKeyword.PRIMARY_KEY}`,
],
};

export const sqlInfo = {
database: 'database',
tableName: 'tableName'
tableName: 'tableName',
};

export const sqlResults = {
Expand All @@ -124,5 +104,10 @@ export const sqlResults = {
createTableMultiplePrimaryKeys: `CREATE TABLE ${sqlInfo.tableName} (
${etlProcesses.formattedColumnsMultiplePrimaryKeys}
);`,
insert: `INSERT INTO ${sqlInfo.tableName.replace(/\s/g, '')}(${col_names_one_pk[0]},${col_names_one_pk[1]},${col_names_one_pk[2]}) VALUES ('${mockJSON.name_pk}',${mockJSON.age},${mockJSON.isDev});`
};
dropTable: `DROP TABLE IF EXISTS ${sqlInfo.tableName};`,
insert: `INSERT INTO ${sqlInfo.tableName.replace(/\s/g, '')}(${
col_names_one_pk[0]
},${col_names_one_pk[1]},${col_names_one_pk[2]}) VALUES ('${
mockJSON.name_pk
}',${mockJSON.age},${mockJSON.isDev});`,
};

0 comments on commit 1071f6e

Please sign in to comment.