Skip to content

Commit 1071f6e

Browse files
committed
feat(sql.ts): add drop table functionality.
1 parent 87cd851 commit 1071f6e

File tree

5 files changed

+110
-123
lines changed

5 files changed

+110
-123
lines changed

README.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# excel-to-postgres
2+
23
Quickly export an Excel Workbook to a Postgres DB
34

45
# Installation
@@ -32,12 +33,14 @@ excelToPostgresDb({
3233

3334
Supports four options, all of which are optional:
3435

35-
* *createDatabase* - _true | false_ (Defaults to false)
36-
* *createTables* - _true | false_ (Defaults to false)
37-
* *generatePrimaryKey* - _true | false_ (Defaults to false. Generates 'id' column to be used as a primary key. Cannot be used with 'useExistingPrimaryKeys' option)
38-
* *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)
36+
- _createDatabase_ - _true | false_ (Defaults to false)
37+
- _createTables_ - _true | false_ (Defaults to false)
38+
- _dropTables_ - _true | false_ (Defaults to false. When creating table, drop the table if it already exists)
39+
- _generatePrimaryKey_ - _true | false_ (Defaults to false. Generates 'id' column to be used as a primary key. Cannot be used with 'useExistingPrimaryKeys' option)
40+
- _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)
41+
3942
# Testing
4043

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

43-
`npm test`
46+
`npm test`

src/main.ts

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1 @@
1-
import { excelToPostgresDb } from './sql';
2-
3-
excelToPostgresDb(
4-
{
5-
host: 'localhost',
6-
user: 'postgres',
7-
password: 'postgres',
8-
port: 5432,
9-
database: 'test',
10-
},
11-
'/Users/jim/Documents/workspace/multi-sport-draft-aid/server/data/baseball.xlsx',
12-
{
13-
createDatabase: true,
14-
createTables: true,
15-
}
16-
).then((t) => console.log(t));
1+
export { excelToPostgresDb } from './sql';

src/sql.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export interface Connection {
2727
export interface Options {
2828
createDatabase?: boolean;
2929
createTables?: boolean;
30+
dropTables?: boolean;
3031
generatePrimaryKey?: boolean;
3132
useExistingPrimaryKeys?: boolean;
3233
}
@@ -63,7 +64,7 @@ export function createTable<T>(
6364

6465
export function dropTable(tableName: string) {
6566
try {
66-
return `DROP TABLE ${tableName.replace(/\s/g, '')};`;
67+
return `DROP TABLE IF EXISTS ${tableName.replace(/\s/g, '')};`;
6768
} catch (err) {
6869
throw new Error(err);
6970
}
@@ -185,11 +186,12 @@ export async function excelToPostgresDb(
185186
insertQuery
186187
);
187188
} else if (options && !options.createDatabase && options.createTables) {
188-
await executeQuery(connectionInfo, dropTableQuery);
189189
await executeQueryWithCreateTable(
190190
connectionInfo,
191+
options,
191192
tableQuery,
192-
insertQuery
193+
insertQuery,
194+
dropTableQuery
193195
);
194196
} else if (!options.createDatabase && !options.createTables) {
195197
await executeQuery(connectionInfo, insertQuery);
@@ -224,10 +226,15 @@ async function executeQueryWithCreateDB(
224226

225227
async function executeQueryWithCreateTable(
226228
connectionInfo: Connection,
229+
options: Options,
227230
tableQuery: string,
228-
insertQuery: string
231+
insertQuery: string,
232+
dropTableQuery: string
229233
) {
230234
try {
235+
if (options.dropTables) {
236+
await executeQuery(connectionInfo, dropTableQuery);
237+
}
231238
await executeQuery(connectionInfo, tableQuery);
232239
await executeQuery(connectionInfo, insertQuery);
233240
} catch (err) {

src/tests/sql.test.ts

Lines changed: 59 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,67 @@
11
import {
2-
createDatabase,
3-
createTable,
4-
handlePrimaryKey,
5-
insert,
6-
PrimaryKeyOptions,
7-
} from "../sql";
8-
import { etlProcesses, sqlInfo, sqlResults } from "./test-data";
2+
createDatabase,
3+
createTable,
4+
dropTable,
5+
handlePrimaryKey,
6+
insert,
7+
PrimaryKeyOptions,
8+
} from '../sql';
9+
import { etlProcesses, sqlInfo, sqlResults } from './test-data';
910

10-
describe("SQL tests", () => {
11-
test("create database", () => {
12-
expect(createDatabase(sqlInfo.database)).toEqual(sqlResults.createDatabase);
13-
});
11+
describe('SQL tests', () => {
12+
test('create database', () => {
13+
expect(createDatabase(sqlInfo.database)).toEqual(
14+
sqlResults.createDatabase
15+
);
16+
});
1417

15-
test("create table generate primary key", () => {
16-
expect(
17-
createTable(
18-
sqlInfo.tableName,
19-
etlProcesses.sheet_one_pk,
20-
PrimaryKeyOptions.GENERATE
21-
)
22-
).toEqual(sqlResults.createTableGeneratedPrimaryKey);
23-
});
18+
test('create table generate primary key', () => {
19+
expect(
20+
createTable(
21+
sqlInfo.tableName,
22+
etlProcesses.sheet_one_pk,
23+
PrimaryKeyOptions.GENERATE
24+
)
25+
).toEqual(sqlResults.createTableGeneratedPrimaryKey);
26+
});
2427

25-
test("create table one existing primary key", () => {
26-
expect(
27-
createTable(
28-
sqlInfo.tableName,
29-
etlProcesses.sheet_one_pk,
30-
PrimaryKeyOptions.USE_EXISTING
31-
)
32-
).toEqual(sqlResults.createTableOnePrimaryKey);
33-
});
28+
test('create table one existing primary key', () => {
29+
expect(
30+
createTable(
31+
sqlInfo.tableName,
32+
etlProcesses.sheet_one_pk,
33+
PrimaryKeyOptions.USE_EXISTING
34+
)
35+
).toEqual(sqlResults.createTableOnePrimaryKey);
36+
});
3437

35-
test("create table multiple existing primary keys", () => {
36-
expect(
37-
createTable(
38-
sqlInfo.tableName,
39-
etlProcesses.sheet_multiple_pk,
40-
PrimaryKeyOptions.USE_EXISTING
41-
)
42-
).toEqual(sqlResults.createTableMultiplePrimaryKeys);
43-
});
38+
test('drop table', () => {
39+
expect(dropTable(sqlInfo.tableName)).toEqual(sqlResults.dropTable);
40+
});
4441

45-
test("insert", () => {
46-
expect(insert(sqlInfo.tableName, [etlProcesses.sheet_one_pk])).toEqual(
47-
sqlResults.insert
48-
);
49-
});
42+
test('create table multiple existing primary keys', () => {
43+
expect(
44+
createTable(
45+
sqlInfo.tableName,
46+
etlProcesses.sheet_multiple_pk,
47+
PrimaryKeyOptions.USE_EXISTING
48+
)
49+
).toEqual(sqlResults.createTableMultiplePrimaryKeys);
50+
});
5051

51-
test("handle primary key options", () => {
52-
expect(handlePrimaryKey({ generatePrimaryKey: true })).toEqual(
53-
PrimaryKeyOptions.GENERATE
54-
);
55-
expect(handlePrimaryKey({ useExistingPrimaryKeys: true })).toEqual(
56-
PrimaryKeyOptions.USE_EXISTING
57-
);
58-
expect(handlePrimaryKey({})).toEqual(PrimaryKeyOptions.NO_PRIMARY_KEY);
59-
});
52+
test('insert', () => {
53+
expect(insert(sqlInfo.tableName, [etlProcesses.sheet_one_pk])).toEqual(
54+
sqlResults.insert
55+
);
56+
});
57+
58+
test('handle primary key options', () => {
59+
expect(handlePrimaryKey({ generatePrimaryKey: true })).toEqual(
60+
PrimaryKeyOptions.GENERATE
61+
);
62+
expect(handlePrimaryKey({ useExistingPrimaryKeys: true })).toEqual(
63+
PrimaryKeyOptions.USE_EXISTING
64+
);
65+
expect(handlePrimaryKey({})).toEqual(PrimaryKeyOptions.NO_PRIMARY_KEY);
66+
});
6067
});

src/tests/test-data.ts

Lines changed: 30 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,116 +1,96 @@
11
import { SQLKeyword, SQLType } from '../etl-processes';
22

3-
const col_names_one_pk = [
4-
'name_pk',
5-
'age',
6-
'isDev'
7-
];
3+
const col_names_one_pk = ['name_pk', 'age', 'isDev'];
84

9-
const col_names_multiple_pk = [
10-
'name_pk',
11-
'age_pk',
12-
'isDev'
13-
];
5+
const col_names_multiple_pk = ['name_pk', 'age_pk', 'isDev'];
146

157
const mockJSON = {
168
name_pk: 'Person 1',
179
age: 18,
18-
isDev: true
10+
isDev: true,
1911
};
2012

2113
export const columns_one_pk = [
2214
{
2315
name: col_names_one_pk[0],
24-
type: SQLType.VARCHAR
16+
type: SQLType.VARCHAR,
2517
},
2618
{
2719
name: col_names_one_pk[1],
28-
type: SQLType.FLOAT
20+
type: SQLType.FLOAT,
2921
},
3022
{
3123
name: col_names_one_pk[2],
32-
type: SQLType.BOOLEAN
33-
}
24+
type: SQLType.BOOLEAN,
25+
},
3426
];
3527

3628
export const columns_multiple_pk = [
3729
{
3830
name: col_names_multiple_pk[0],
39-
type: SQLType.VARCHAR
31+
type: SQLType.VARCHAR,
4032
},
4133
{
4234
name: col_names_multiple_pk[1],
43-
type: SQLType.FLOAT
35+
type: SQLType.FLOAT,
4436
},
4537
{
4638
name: col_names_multiple_pk[2],
47-
type: SQLType.BOOLEAN
48-
}
39+
type: SQLType.BOOLEAN,
40+
},
4941
];
5042

5143
export const etlProcesses = {
5244
sheet_one_pk: {
5345
name_pk: mockJSON.name_pk,
5446
age: mockJSON.age,
55-
isDev: mockJSON.isDev
47+
isDev: mockJSON.isDev,
5648
},
5749
sheet_multiple_pk: {
5850
name_pk: mockJSON.name_pk,
5951
age_pk: mockJSON.age,
60-
isDev: mockJSON.isDev
52+
isDev: mockJSON.isDev,
6153
},
6254
fields_one_pk: {
63-
names: [
64-
...col_names_one_pk
65-
],
66-
values: [
67-
mockJSON.name_pk,
68-
mockJSON.age,
69-
mockJSON.isDev
70-
]
55+
names: [...col_names_one_pk],
56+
values: [mockJSON.name_pk, mockJSON.age, mockJSON.isDev],
7157
},
7258
fields_multiple_pks: {
73-
names: [
74-
...col_names_multiple_pk
75-
],
76-
values: [
77-
mockJSON.name_pk,
78-
mockJSON.age,
79-
mockJSON.isDev
80-
]
59+
names: [...col_names_multiple_pk],
60+
values: [mockJSON.name_pk, mockJSON.age, mockJSON.isDev],
8161
},
8262
formattedColumns: [
8363
`${columns_one_pk[0].name} ${columns_one_pk[0].type}`,
8464
`${columns_one_pk[1].name} ${columns_one_pk[1].type}`,
85-
`${columns_one_pk[2].name} ${columns_one_pk[2].type}`
65+
`${columns_one_pk[2].name} ${columns_one_pk[2].type}`,
8666
],
8767
formattedColumns_multiple_pk: [
8868
`${columns_multiple_pk[0].name} ${columns_multiple_pk[0].type}`,
8969
`${columns_multiple_pk[1].name} ${columns_multiple_pk[1].type}`,
90-
`${columns_multiple_pk[2].name} ${columns_multiple_pk[2].type}`
70+
`${columns_multiple_pk[2].name} ${columns_multiple_pk[2].type}`,
9171
],
9272
formattedColumnsOnePrimaryKey: [
9373
`${columns_one_pk[0].name} ${columns_one_pk[0].type} ${SQLKeyword.PRIMARY_KEY}`,
9474
`${columns_one_pk[1].name} ${columns_one_pk[1].type}`,
95-
`${columns_one_pk[2].name} ${columns_one_pk[2].type}`
75+
`${columns_one_pk[2].name} ${columns_one_pk[2].type}`,
9676
],
9777
formattedColumnsMultiplePrimaryKeys: [
9878
`${columns_multiple_pk[0].name} ${columns_multiple_pk[0].type}`,
9979
`${columns_multiple_pk[1].name} ${columns_multiple_pk[1].type}`,
10080
`${columns_multiple_pk[2].name} ${columns_multiple_pk[2].type}`,
101-
`${SQLKeyword.PRIMARY_KEY} (${columns_multiple_pk[0].name},${columns_multiple_pk[1].name})`
81+
`${SQLKeyword.PRIMARY_KEY} (${columns_multiple_pk[0].name},${columns_multiple_pk[1].name})`,
10282
],
10383
formattedColumnsGeneratedPrimaryKey: [
10484
`${columns_one_pk[0].name} ${columns_one_pk[0].type}`,
10585
`${columns_one_pk[1].name} ${columns_one_pk[1].type}`,
10686
`${columns_one_pk[2].name} ${columns_one_pk[2].type}`,
107-
`id ${SQLKeyword.SERIAL} ${SQLKeyword.NOT_NULL} ${SQLKeyword.PRIMARY_KEY}`
87+
`id ${SQLKeyword.SERIAL} ${SQLKeyword.NOT_NULL} ${SQLKeyword.PRIMARY_KEY}`,
10888
],
10989
};
11090

11191
export const sqlInfo = {
11292
database: 'database',
113-
tableName: 'tableName'
93+
tableName: 'tableName',
11494
};
11595

11696
export const sqlResults = {
@@ -124,5 +104,10 @@ export const sqlResults = {
124104
createTableMultiplePrimaryKeys: `CREATE TABLE ${sqlInfo.tableName} (
125105
${etlProcesses.formattedColumnsMultiplePrimaryKeys}
126106
);`,
127-
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});`
128-
};
107+
dropTable: `DROP TABLE IF EXISTS ${sqlInfo.tableName};`,
108+
insert: `INSERT INTO ${sqlInfo.tableName.replace(/\s/g, '')}(${
109+
col_names_one_pk[0]
110+
},${col_names_one_pk[1]},${col_names_one_pk[2]}) VALUES ('${
111+
mockJSON.name_pk
112+
}',${mockJSON.age},${mockJSON.isDev});`,
113+
};

0 commit comments

Comments
 (0)