Skip to content

Commit

Permalink
fix: handle null
Browse files Browse the repository at this point in the history
  • Loading branch information
gajus committed Apr 30, 2019
1 parent 8f27b6d commit 16ee95f
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 36 deletions.
22 changes: 11 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,25 @@
"lodash": "^4.17.11",
"roarr": "^2.13.0",
"serialize-error": "^4.1.0",
"slonik": "^16.15.1"
"slonik": "^16.18.0"
},
"description": "Utilities for manipulating data in PostgreSQL database using Slonik.",
"devDependencies": {
"@babel/cli": "^7.4.3",
"@babel/core": "^7.4.3",
"@babel/plugin-transform-flow-strip-types": "^7.4.0",
"@babel/preset-env": "^7.4.3",
"@babel/register": "^7.4.0",
"@babel/cli": "^7.4.4",
"@babel/core": "^7.4.4",
"@babel/plugin-transform-flow-strip-types": "^7.4.4",
"@babel/preset-env": "^7.4.4",
"@babel/register": "^7.4.4",
"ava": "^1.4.1",
"babel-plugin-istanbul": "^5.1.2",
"babel-plugin-istanbul": "^5.1.3",
"babel-plugin-transform-export-default-name": "^2.0.4",
"coveralls": "^3.0.3",
"eslint": "^5.16.0",
"eslint-config-canonical": "^16.2.0",
"flow-bin": "^0.97.0",
"flow-copy-source": "^2.0.3",
"eslint-config-canonical": "^17.0.1",
"flow-bin": "^0.98.0",
"flow-copy-source": "^2.0.4",
"gitdown": "^2.5.7",
"husky": "^1.3.1",
"husky": "^2.1.0",
"nyc": "^14.0.0",
"semantic-release": "^15.13.3",
"sinon": "^7.3.2"
Expand Down
13 changes: 12 additions & 1 deletion src/routines/upsert.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,21 @@ export default async (
]);

const whereClause = sql.booleanExpression(targetColumnNames.map((targetColumnName) => {
const value = normalizedNamedValueBindings[normalizeNamedValueBindingName(targetColumnName)];

if (value === null) {
return sql.raw(
'$1 IS NULL',
[
sql.identifier([targetColumnName])
]
);
}

return sql.comparisonPredicate(
sql.identifier([targetColumnName]),
'=',
normalizedNamedValueBindings[normalizeNamedValueBindingName(targetColumnName)]
value
);
}), 'AND');

Expand Down
16 changes: 8 additions & 8 deletions test/slonik-utilities/routines/update.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ test('executes UPDATE query without WHERE condition (single column)', async (t)
}
);

t.true(connection.query.callCount === 1);
t.assert(connection.query.callCount === 1);

t.true(normalizeQuery(connection.query.firstCall.args[0].sql) === 'UPDATE "foo" SET "bar" = $1');
t.assert(normalizeQuery(connection.query.firstCall.args[0].sql) === 'UPDATE "foo" SET "bar" = $1');
t.deepEqual(connection.query.firstCall.args[0].values, [
'baz'
]);
Expand All @@ -50,9 +50,9 @@ test('executes UPDATE query without WHERE condition (multiple columns)', async (
}
);

t.true(connection.query.callCount === 1);
t.assert(connection.query.callCount === 1);

t.true(normalizeQuery(connection.query.firstCall.args[0].sql) === 'UPDATE "foo" SET "bar_0" = $1, "bar_1" = $2, "bar_2" = $3');
t.assert(normalizeQuery(connection.query.firstCall.args[0].sql) === 'UPDATE "foo" SET "bar_0" = $1, "bar_1" = $2, "bar_2" = $3');
t.deepEqual(connection.query.firstCall.args[0].values, [
'baz0',
'baz1',
Expand All @@ -73,9 +73,9 @@ test('executes UPDATE query without WHERE condition (SQL token)', async (t) => {
}
);

t.true(connection.query.callCount === 1);
t.assert(connection.query.callCount === 1);

t.true(normalizeQuery(connection.query.firstCall.args[0].sql) === 'UPDATE "foo" SET "bar_0" = $1, "bar_1" = to_timestamp($2), "bar_2" = $3');
t.assert(normalizeQuery(connection.query.firstCall.args[0].sql) === 'UPDATE "foo" SET "bar_0" = $1, "bar_1" = to_timestamp($2), "bar_2" = $3');
t.deepEqual(connection.query.firstCall.args[0].values, [
'baz0',
'baz1',
Expand All @@ -97,9 +97,9 @@ test('executes UPDATE query with WHERE condition (AND boolean expression short-h
}
);

t.true(connection.query.callCount === 1);
t.assert(connection.query.callCount === 1);

t.true(normalizeQuery(connection.query.firstCall.args[0].sql) === 'UPDATE "foo" SET "bar" = $1 WHERE ("qux" = $2)');
t.assert(normalizeQuery(connection.query.firstCall.args[0].sql) === 'UPDATE "foo" SET "bar" = $1 WHERE ("qux" = $2)');
t.deepEqual(connection.query.firstCall.args[0].values, [
'baz',
'quux'
Expand Down
32 changes: 16 additions & 16 deletions test/slonik-utilities/routines/upsert.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ test('first attempts SELECT using named value bindings', async (t) => {
]
);

t.true(recordId === 1);
t.assert(recordId === 1);

t.true(connection.query.callCount === 1);
t.assert(connection.query.callCount === 1);

t.true(normalizeQuery(connection.query.firstCall.args[0].sql) === 'SELECT "id" FROM "foo" WHERE ("bar" = $1)');
t.assert(normalizeQuery(connection.query.firstCall.args[0].sql) === 'SELECT "id" FROM "foo" WHERE ("bar" = $1)');
t.deepEqual(connection.query.firstCall.args[0].values, [
'baz'
]);
Expand All @@ -61,11 +61,11 @@ test('executes INSERT .. DO UPDATE if SELECT returns NULL and update column name
]
);

t.true(recordId === 1);
t.assert(recordId === 1);

t.true(connection.query.callCount === 2);
t.assert(connection.query.callCount === 2);

t.true(normalizeQuery(connection.query.secondCall.args[0].sql) === 'INSERT INTO "foo" ("bar", "qux") VALUES ($1, $2) ON CONFLICT ("bar") DO UPDATE SET "qux" = EXCLUDED."qux" RETURNING "id"');
t.assert(normalizeQuery(connection.query.secondCall.args[0].sql) === 'INSERT INTO "foo" ("bar", "qux") VALUES ($1, $2) ON CONFLICT ("bar") DO UPDATE SET "qux" = EXCLUDED."qux" RETURNING "id"');
t.deepEqual(connection.query.secondCall.args[0].values, [
'baz',
'quux'
Expand All @@ -90,16 +90,16 @@ test('executes INSERT .. DO NOTHING followed by SELECT if SELECT returns NULL an
]
);

t.true(recordId === 1);
t.assert(recordId === 1);

t.true(connection.query.callCount === 3);
t.assert(connection.query.callCount === 3);

t.true(normalizeQuery(connection.query.secondCall.args[0].sql) === 'INSERT INTO "foo" ("bar") VALUES ($1) ON CONFLICT ("bar") DO NOTHING');
t.assert(normalizeQuery(connection.query.secondCall.args[0].sql) === 'INSERT INTO "foo" ("bar") VALUES ($1) ON CONFLICT ("bar") DO NOTHING');
t.deepEqual(connection.query.secondCall.args[0].values, [
'baz'
]);

t.true(normalizeQuery(connection.query.thirdCall.args[0].sql) === 'SELECT "id" FROM "foo" WHERE ("bar" = $1)');
t.assert(normalizeQuery(connection.query.thirdCall.args[0].sql) === 'SELECT "id" FROM "foo" WHERE ("bar" = $1)');
t.deepEqual(connection.query.thirdCall.args[0].values, [
'baz'
]);
Expand All @@ -124,9 +124,9 @@ test('uses unique constraint column name values and update column name values to
]
);

t.true(connection.query.callCount === 1);
t.assert(connection.query.callCount === 1);

t.true(normalizeQuery(connection.query.firstCall.args[0].sql) === 'SELECT "id" FROM "foo" WHERE ("bar_0" = $1 AND "bar_1" = $2 AND "bar_2" = $3)');
t.assert(normalizeQuery(connection.query.firstCall.args[0].sql) === 'SELECT "id" FROM "foo" WHERE ("bar_0" = $1 AND "bar_1" = $2 AND "bar_2" = $3)');
t.deepEqual(connection.query.firstCall.args[0].values, [
'baz0',
'baz1',
Expand All @@ -150,9 +150,9 @@ test('converts named value bindings to snake case (SELECT)', async (t) => {
]
);

t.true(connection.query.callCount === 1);
t.assert(connection.query.callCount === 1);

t.true(normalizeQuery(connection.query.firstCall.args[0].sql) === 'SELECT "id" FROM "foo" WHERE ("bar_baz" = $1)');
t.assert(normalizeQuery(connection.query.firstCall.args[0].sql) === 'SELECT "id" FROM "foo" WHERE ("bar_baz" = $1)');
t.deepEqual(connection.query.firstCall.args[0].values, [
'baz'
]);
Expand All @@ -176,9 +176,9 @@ test('converts named value bindings to snake case (INSERT)', async (t) => {
]
);

t.true(connection.query.callCount === 2);
t.assert(connection.query.callCount === 2);

t.true(normalizeQuery(connection.query.secondCall.args[0].sql) === 'INSERT INTO "foo" ("bar_baz", "qux_quux") VALUES ($1, $2) ON CONFLICT ("bar_baz") DO UPDATE SET "qux_quux" = EXCLUDED."qux_quux" RETURNING "id"');
t.assert(normalizeQuery(connection.query.secondCall.args[0].sql) === 'INSERT INTO "foo" ("bar_baz", "qux_quux") VALUES ($1, $2) ON CONFLICT ("bar_baz") DO UPDATE SET "qux_quux" = EXCLUDED."qux_quux" RETURNING "id"');
t.deepEqual(connection.query.secondCall.args[0].values, [
'baz',
'quux'
Expand Down

0 comments on commit 16ee95f

Please sign in to comment.