Skip to content

Commit

Permalink
Support mysql
Browse files Browse the repository at this point in the history
  • Loading branch information
simonrw committed Jan 31, 2024
1 parent 64a05e4 commit e243e0e
Show file tree
Hide file tree
Showing 3 changed files with 179 additions and 43 deletions.
49 changes: 46 additions & 3 deletions __tests__/__snapshots__/resolvers.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,50 @@ exports[`dynamodb resolvers something 2`] = `
]
`;

exports[`rds resolvers createPgStatement-remove 1`] = `
exports[`rds resolvers mysql remove 1`] = `
{
"statements": [
"DELETE FROM \`persons\` WHERE \`id\` = :P0",
],
"variableMap": {
":P0": "1232",
},
"variableTypeHintMap": {},
}
`;

exports[`rds resolvers mysql select 1`] = `
{
"statements": [
"SELECT \`id\`, \`name\` FROM \`UserGroup\` WHERE (\`name\` = :P0) OR (\`id\` > :P1) ORDER BY \`name\` ASC, \`id\` DESC LIMIT :P2 OFFSET :P3",
],
"variableMap": {
":P0": "Stephane",
":P1": 10,
":P2": 10,
":P3": 1,
},
"variableTypeHintMap": {},
}
`;

exports[`rds resolvers mysql type hints 1`] = `
{
"statements": [
"SELECT * FROM \`UserGroup\` WHERE (\`id\` = :P0) AND (\`started\` < :P1)",
],
"variableMap": {
":P0": "1232",
":P1": "2022-03-02T00:00:00.000Z",
},
"variableTypeHintMap": {
":P0": "UUID",
":P1": "TIMESTAMP",
},
}
`;

exports[`rds resolvers postgresql remove 1`] = `
{
"statements": [
"DELETE FROM "persons" WHERE "id" = :P0 RETURNING "id", "name"",
Expand All @@ -50,7 +93,7 @@ exports[`rds resolvers createPgStatement-remove 1`] = `
}
`;

exports[`rds resolvers createPgStatement-select 1`] = `
exports[`rds resolvers postgresql select 1`] = `
{
"statements": [
"SELECT "id", "name" FROM "UserGroup" WHERE ("name" = :P0) OR ("id" > :P1) ORDER BY "name" ASC, "id" DESC LIMIT :P2 OFFSET :P3",
Expand All @@ -65,7 +108,7 @@ exports[`rds resolvers createPgStatement-select 1`] = `
}
`;

exports[`rds resolvers createPgStatement-typeHint 1`] = `
exports[`rds resolvers postgresql type hints 1`] = `
{
"statements": [
"SELECT * FROM "UserGroup" WHERE ("id" = :P0) AND ("started" < :P1)",
Expand Down
130 changes: 106 additions & 24 deletions __tests__/resolvers.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -201,35 +201,116 @@ describe("rds resolvers", () => {
await checkResolverValid(code, responseContext, "response");
});

test("createPgStatement-typeHint", async () => {
const code = `
describe("mysql", () => {
test("type hints", async () => {
const code = `
export function request(ctx) {
const whereClause = { and:[
{ id: { eq: rds.typeHint.UUID(ctx.args.id) } },
{ started: { lt: rds.typeHint.TIMESTAMP(ctx.args.started) } }
] };
return rds.createPgStatement(rds.select({
return rds.createMySQLStatement(rds.select({
table: "UserGroup",
where: whereClause,
}));
}
export function response(ctx) {}
`
const requestContext = {
arguments: {
id: "1232",
name: "hello",
started: new Date(2022, 2, 2),
}
};
const requestContext = {
arguments: {
id: "1232",
name: "hello",
started: new Date(2022, 2, 2),
}
};

await checkResolverValid(code, requestContext, "request");
await checkResolverValid(code, requestContext, "request");

});

test("select", async () => {
const code = `
export function request(ctx) {
const whereClause = { or: [
{ name: { eq: 'Stephane'} },
{ id: { gt: 10 } }
]}
return rds.createMySQLStatement(rds.select({
table: "UserGroup",
where: whereClause,
limit: 10,
offset: 1,
columns: ['id', 'name'],
orderBy: [{column: 'name'}, {column: 'id', dir: 'DESC'}]
}));
}
export function response(ctx) {}
`;

const requestContext = {};

await checkResolverValid(code, requestContext, "request");

});

test("remove", async () => {
const code = `
export function request(ctx) {
const id = ctx.args.id;
const where = { id: { eq: id } };
const deleteStatement = rds.remove({
table: 'persons',
where: where,
});
return rds.createMySQLStatement(deleteStatement);
}
export function response(ctx) {}
`;

const requestContext = {
arguments: {
id: "1232"
}
};

await checkResolverValid(code, requestContext, "request");

});
});

test("createPgStatement-select", async () => {
const code = `
describe("postgresql", () => {
test("type hints", async () => {
const code = `
export function request(ctx) {
const whereClause = { and:[
{ id: { eq: rds.typeHint.UUID(ctx.args.id) } },
{ started: { lt: rds.typeHint.TIMESTAMP(ctx.args.started) } }
] };
return rds.createPgStatement(rds.select({
table: "UserGroup",
where: whereClause,
}));
}
export function response(ctx) {}
`
const requestContext = {
arguments: {
id: "1232",
name: "hello",
started: new Date(2022, 2, 2),
}
};

await checkResolverValid(code, requestContext, "request");

});

test("select", async () => {
const code = `
export function request(ctx) {
const whereClause = { or: [
{ name: { eq: 'Stephane'} },
Expand All @@ -248,14 +329,14 @@ describe("rds resolvers", () => {
export function response(ctx) {}
`;

const requestContext = {};
const requestContext = {};

await checkResolverValid(code, requestContext, "request");
await checkResolverValid(code, requestContext, "request");

});
});

test("createPgStatement-remove", async () => {
const code = `
test("remove", async () => {
const code = `
export function request(ctx) {
const id = ctx.args.id;
const where = { id: { eq: id } };
Expand All @@ -270,14 +351,15 @@ describe("rds resolvers", () => {
export function response(ctx) {}
`;

const requestContext = {
arguments: {
id: "1232"
}
};
const requestContext = {
arguments: {
id: "1232"
}
};

await checkResolverValid(code, requestContext, "request");
await checkResolverValid(code, requestContext, "request");

});
});
});

43 changes: 27 additions & 16 deletions rds/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ export function remove(s) {
return { type: "REMOVE", properties: s };
}

class PgStatementBuilder {
constructor() {
class StatementBuilder {
constructor({ quoteChar }) {
this.quoteChar = quoteChar;
this.result = {
statements: [],
variableMap: {},
Expand All @@ -54,11 +55,11 @@ class PgStatementBuilder {
switch (type) {
case "SELECT": {
const { table, columns, where, orderBy, limit, offset } = properties;
const tableName = `"${table}"`;
const tableName = `${this.quoteChar}${table}${this.quoteChar}`;
let query;

if (columns) {
const columnNames = columns.map(name => `"${name}"`).join(', ');
const columnNames = columns.map(name => `${this.quoteChar}${name}${this.quoteChar}`).join(', ');
query = `SELECT ${columnNames} FROM ${tableName}`;
} else {
query = `SELECT * FROM ${tableName}`;
Expand All @@ -74,7 +75,7 @@ class PgStatementBuilder {
let orderByParts = [];
for (let { column, dir } of orderBy) {
dir = dir || "ASC";
orderByParts.push(`"${column}" ${dir}`);
orderByParts.push(`${this.quoteChar}${column}${this.quoteChar} ${dir}`);
}

query = `${query} ORDER BY ${orderByParts.join(', ')}`;
Expand All @@ -96,7 +97,7 @@ class PgStatementBuilder {
}
case "REMOVE": {
const { table, where, returning, } = properties;
const tableName = `"${table}"`;
const tableName = `${this.quoteChar}${table}${this.quoteChar}`;

let query = `DELETE FROM ${tableName}`;

Expand All @@ -106,7 +107,7 @@ class PgStatementBuilder {
}

if (returning) {
const columnNames = returning.map(name => `"${name}"`).join(', ');
const columnNames = returning.map(name => `${this.quoteChar}${name}${this.quoteChar}`).join(', ');
query = `${query} RETURNING ${columnNames}`;
}

Expand Down Expand Up @@ -163,32 +164,42 @@ class PgStatementBuilder {
const value = this.newVariable(condition[conditionType]);
switch (conditionType) {
case "eq":
return `${startGrouping}"${columnName}" = ${value}${endGrouping}`;
return `${startGrouping}${this.quoteChar}${columnName}${this.quoteChar} = ${value}${endGrouping}`;
case "ne":
return `${startGrouping}"${columnName}" != ${value}${endGrouping}`;
return `${startGrouping}${this.quoteChar}${columnName}${this.quoteChar} != ${value}${endGrouping}`;
case "gt":
return `${startGrouping}"${columnName}" > ${value}${endGrouping}`;
return `${startGrouping}${this.quoteChar}${columnName}${this.quoteChar} > ${value}${endGrouping}`;
case "lt":
return `${startGrouping}"${columnName}" < ${value}${endGrouping}`;
return `${startGrouping}${this.quoteChar}${columnName}${this.quoteChar} < ${value}${endGrouping}`;
case "ge":
return `${startGrouping}"${columnName}" >= ${value}${endGrouping}`;
return `${startGrouping}${this.quoteChar}${columnName}${this.quoteChar} >= ${value}${endGrouping}`;
case "le":
return `${startGrouping}"${columnName}" <= ${value}${endGrouping}`;
return `${startGrouping}${this.quoteChar}${columnName}${this.quoteChar} <= ${value}${endGrouping}`;
case "contains":
return `${startGrouping}"${columnName}" LIKE ${value}${endGrouping}`;
return `${startGrouping}${this.quoteChar}${columnName}${this.quoteChar} LIKE ${value}${endGrouping}`;
case "notContains":
return `${startGrouping}"${columnName}" NOT LIKE ${value}${endGrouping}`;
return `${startGrouping}${this.quoteChar}${columnName}${this.quoteChar} NOT LIKE ${value}${endGrouping}`;
default:
throw new Error(`Unhandled condition type ${conditionType}`);
}
}
}

export function createPgStatement(...statements) {
let builder = new PgStatementBuilder();
let builder = new StatementBuilder({
quoteChar: '"',
});
return builder.render(statements);
}

export function createMySQLStatement(...statements) {
let builder = new StatementBuilder({
quoteChar: '`',
});
return builder.render(statements);
}


export const typeHint = {
DECIMAL: function(value) {
return {
Expand Down

0 comments on commit e243e0e

Please sign in to comment.