Comparing version 1.0.225 to 1.0.226
@@ -125,3 +125,3 @@ "use strict"; | ||
paths: [mutation_pieces[1].path], | ||
sql_string: "UPDATE users SET first_name = 'john' WHERE (id) = (1)", | ||
sql_string: "UPDATE users SET first_name = 'john' WHERE id = 1", | ||
}, | ||
@@ -139,3 +139,3 @@ { | ||
paths: [mutation_pieces[2].path], | ||
sql_string: 'DELETE FROM products WHERE (id) = (1)', | ||
sql_string: 'DELETE FROM products WHERE id = 1', | ||
}, | ||
@@ -142,0 +142,0 @@ ], |
@@ -110,3 +110,3 @@ "use strict"; | ||
path: [key], | ||
original_data: mutation, | ||
// original_data: mutation, | ||
}, | ||
@@ -152,3 +152,3 @@ ]; | ||
message: `Records must have an operation or an inherited operation.`, | ||
original_data: mutation, | ||
// original_data: mutation, | ||
path: [...record_path, '$operation'], | ||
@@ -194,3 +194,3 @@ }, | ||
path: [...record_path, key], | ||
original_data: mutation, | ||
// original_data: mutation, | ||
}, | ||
@@ -208,3 +208,3 @@ ]; | ||
path: [...record_path, key], | ||
original_data: mutation, | ||
// original_data: mutation, | ||
}, | ||
@@ -221,3 +221,3 @@ ]; | ||
path: [...record_path, key], | ||
original_data: mutation, | ||
// original_data: mutation, | ||
}, | ||
@@ -258,3 +258,3 @@ ]; | ||
path: field_path, | ||
original_data: mutation, | ||
// original_data: mutation, | ||
}, | ||
@@ -270,3 +270,3 @@ ]; | ||
path: field_path, | ||
original_data: mutation, | ||
// original_data: mutation, | ||
}, | ||
@@ -290,3 +290,3 @@ ]; | ||
path: field_path, | ||
original_data: mutation, | ||
// original_data: mutation, | ||
additional_info: { | ||
@@ -315,3 +315,3 @@ enum_values, | ||
path: field_path, | ||
original_data: mutation, | ||
// original_data: mutation, | ||
additional_info: { | ||
@@ -338,3 +338,3 @@ given_character_count, | ||
path: field_path, | ||
original_data: mutation, | ||
// original_data: mutation, | ||
}, | ||
@@ -348,3 +348,3 @@ ]; | ||
path: field_path, | ||
original_data: mutation, | ||
// original_data: mutation, | ||
}, | ||
@@ -362,3 +362,3 @@ ]; | ||
path: field_path, | ||
original_data: mutation, | ||
// original_data: mutation, | ||
additional_info: { | ||
@@ -379,3 +379,3 @@ given_character_count, | ||
path: field_path, | ||
original_data: mutation, | ||
// original_data: mutation, | ||
additional_info: { | ||
@@ -393,3 +393,3 @@ given_decimals, | ||
path: field_path, | ||
original_data: mutation, | ||
// original_data: mutation, | ||
additional_info: { | ||
@@ -411,3 +411,3 @@ given_decimals, | ||
path: field_path, | ||
original_data: mutation, | ||
// original_data: mutation, | ||
}, | ||
@@ -428,3 +428,3 @@ ]; | ||
path: field_path, | ||
original_data: mutation, | ||
// original_data: mutation, | ||
additional_info: { | ||
@@ -457,3 +457,3 @@ required_data_type, | ||
path: [...record_path, required_field], | ||
original_data: mutation, | ||
// original_data: mutation, | ||
}, | ||
@@ -510,3 +510,3 @@ ]; | ||
// // path: [...record_path, '$operation'], | ||
// // original_data: mutation, | ||
// // // original_data: mutation, | ||
// // additional_info: { | ||
@@ -546,3 +546,3 @@ // // parent_entity, | ||
// path: record_path, | ||
// original_data: mutation, | ||
// // original_data: mutation, | ||
// // stack_trace: new Error().stack, | ||
@@ -549,0 +549,0 @@ // additional_info: { |
@@ -221,6 +221,6 @@ "use strict"; | ||
// DML commands | ||
$select: args => `SELECT ${args.join(', ')}`, $as: args => `(${args[0]}) AS ${args[1]}`, $entity: args => `${args}`, $field: args => `.${args}`, $from: args => `FROM ${args}`, $where: args => `WHERE ${args}`, $group_by: args => `GROUP BY ${args.join(', ')}`, $having: args => `HAVING ${args}`, $order_by: args => `ORDER BY ${args.join(', ')}`, $asc: args => `${args} ASC`, $desc: args => `${args} DESC`, $limit: args => `LIMIT ${args}`, $offset: args => `OFFSET ${args}`, $in: (args, path) => { | ||
$select: args => `SELECT ${args.join(', ')}`, $as: args => `${wrap_if_subquery(args[0])} AS ${args[1]}`, $entity: args => `${escape_field(args)}`, $field: args => `.${escape_field(args)}`, $from: args => `FROM ${escape_field(args)}`, $where: args => `WHERE ${args}`, $group_by: args => `GROUP BY ${args.join(', ')}`, $having: args => `HAVING ${args}`, $order_by: args => `ORDER BY ${args.join(', ')}`, $asc: args => `${args} ASC`, $desc: args => `${args} DESC`, $limit: args => `LIMIT ${args}`, $offset: args => `OFFSET ${args}`, $in: (args, path) => { | ||
const [left_arg, right_arg] = args; | ||
const left_arg_string = Array.isArray(left_arg) | ||
? left_arg.map(val => `(${val})`).join(', ') | ||
? `(${left_arg.map(val => `${wrap_if_subquery(val)}`).join(', ')})` | ||
: left_arg; | ||
@@ -231,7 +231,9 @@ const not_string = nested_under_odd_nots(path) ? ' NOT' : ''; | ||
.map(val => Array.isArray(val) | ||
? `(${val.map(el => `(${el})`).join(', ')})` | ||
: `(${val})`) | ||
? `(${val | ||
.map(el => wrap_if_subquery(el)) | ||
.join(', ')})` | ||
: wrap_if_subquery(val)) | ||
.join(', ') | ||
: right_arg; | ||
return `(${left_arg_string})${not_string} IN (${right_arg_string})`; | ||
return `${wrap_if_subquery(left_arg_string)}${not_string} IN (${right_arg_string})`; | ||
}, $and: (args, path) => { | ||
@@ -245,4 +247,4 @@ const res = `(${args.join(') AND (')})`; | ||
const simple_eq = (left_val, right_val) => is_sql_null(right_val) | ||
? `(${left_val}) IS${nested_under_odd_nots(path) ? ' NOT' : ''} NULL` | ||
: `(${left_val}) ${nested_under_odd_nots(path) ? '!' : ''}= (${right_val})`; | ||
? `${wrap_if_subquery(left_val)} IS${nested_under_odd_nots(path) ? ' NOT' : ''} NULL` | ||
: `${wrap_if_subquery(left_val)} ${nested_under_odd_nots(path) ? '!' : ''}= ${wrap_if_subquery(right_val)}`; | ||
const [left_arg, right_arg] = args; | ||
@@ -259,3 +261,5 @@ // tuple equality, e.g. (id, parent_id) = (1, 2) | ||
else { | ||
return `(${left_arg.map(val => `(${val})`).join(', ')}) ${nested_under_odd_nots(path) ? '!' : ''}= (${right_arg.map(val => `(${val})`).join(', ')})`; | ||
return `(${left_arg | ||
.map(val => wrap_if_subquery(val)) | ||
.join(', ')}) ${nested_under_odd_nots(path) ? '!' : ''}= (${right_arg.map(val => wrap_if_subquery(val)).join(', ')})`; | ||
} | ||
@@ -265,3 +269,3 @@ } | ||
return simple_eq(left_arg, right_arg); | ||
}, $gt: (args, path) => `(${args[0]}) ${nested_under_odd_nots(path) ? '<=' : '>'} (${args[1]})`, $lt: (args, path) => `(${args[0]}) ${nested_under_odd_nots(path) ? '>=' : '<'} (${args[1]})`, $gte: (args, path) => `(${args[0]}) ${nested_under_odd_nots(path) ? '<' : '>='} (${args[1]})`, $lte: (args, path) => `(${args[0]}) ${nested_under_odd_nots(path) ? '>' : '<='} (${args[1]})`, $exists: (args, path) => `${nested_under_odd_nots(path) ? 'NOT ' : ''}EXISTS (${args})`, $like: (args, path) => { | ||
}, $gt: (args, path) => `${wrap_if_subquery(args[0])} ${nested_under_odd_nots(path) ? '<=' : '>'} ${wrap_if_subquery(args[1])}`, $lt: (args, path) => `${wrap_if_subquery(args[0])} ${nested_under_odd_nots(path) ? '>=' : '<'} ${wrap_if_subquery(args[1])}`, $gte: (args, path) => `${wrap_if_subquery(args[0])} ${nested_under_odd_nots(path) ? '<' : '>='} ${wrap_if_subquery(args[1])}`, $lte: (args, path) => `${wrap_if_subquery(args[0])} ${nested_under_odd_nots(path) ? '>' : '<='} ${wrap_if_subquery(args[1])}`, $exists: (args, path) => `${nested_under_odd_nots(path) ? 'NOT ' : ''}EXISTS (${args})`, $like: (args, path) => { | ||
// const string_arg = args[1].toString() | ||
@@ -272,3 +276,3 @@ // const search_value = string_arg.replace(/^\'/, '').replace(/\'$/, '') // get rid of quotes if they were put there by escape() | ||
// } LIKE '%${search_value}%'` | ||
return `(${args[0]})${nested_under_odd_nots(path) ? ' NOT' : ''} LIKE (${args[1]})`; | ||
return `${wrap_if_subquery(args[0])}${nested_under_odd_nots(path) ? ' NOT' : ''} LIKE ${wrap_if_subquery(args[1])}`; | ||
}, $not: args => args }, Object.keys(exports.sql_function_definitions).reduce((acc, key) => { | ||
@@ -283,3 +287,3 @@ acc[key] = exports.sql_function_definitions[key].ast_to_sql; | ||
// alter | ||
$alter_table: table_name => `ALTER TABLE ${table_name}`, | ||
$alter_table: table_name => `ALTER TABLE \`${table_name}\``, | ||
// definitions | ||
@@ -344,2 +348,8 @@ $definitions: args => ((args === null || args === void 0 ? void 0 : args.length) ? `(${args.join(', ')})` : ''), $alter_operation: arg => arg === null || arg === void 0 ? void 0 : arg.toUpperCase(), $old_name: (arg, path, obj) => get_neighbour_field(obj, path, '$alter_operation') === 'rename' | ||
$create_index: arg => `CREATE INDEX \`${arg}\``, $on: arg => `ON ${arg}` }); | ||
/** | ||
* Only wrap SELECT ... statments with (), since sqlite doesnt support wrapping primitive values like | ||
* numbers in (), I think its interpreting them as tuples when you do that | ||
*/ | ||
const wrap_if_subquery = (val) => { var _a; return ((_a = val === null || val === void 0 ? void 0 : val.startsWith) === null || _a === void 0 ? void 0 : _a.call(val, 'SELECT')) ? `(${val})` : val; }; | ||
const escape_field = val => typeof val === 'string' && !['*'].includes(val) ? `\`${val}\`` : val; | ||
const is_sql_null = val => { | ||
@@ -346,0 +356,0 @@ var _a; |
@@ -15,3 +15,3 @@ "use strict"; | ||
const sql = (0, sql_formatter_1.format)((0, json_sql_1.json_to_sql)(json)); | ||
const goal = (0, sql_formatter_1.format)(`SELECT a FROM b`); | ||
const goal = (0, sql_formatter_1.format)(`SELECT a FROM \`b\``); | ||
(0, chai_1.expect)(sql).to.equal(goal); | ||
@@ -26,5 +26,14 @@ }); | ||
const sql = (0, sql_formatter_1.format)((0, json_sql_1.json_to_sql)(json)); | ||
const goal = (0, sql_formatter_1.format)('WHERE (a) = (b)'); | ||
const goal = (0, sql_formatter_1.format)('WHERE a = b'); | ||
(0, chai_1.expect)(sql).to.equal(goal); | ||
}); | ||
(0, mocha_1.test)('handles selecting functions', () => { | ||
const json = { | ||
$select: [{ $as: ['SUM(views)', 'total_views'] }], | ||
$from: 'posts', | ||
}; | ||
const sql = (0, sql_formatter_1.format)((0, json_sql_1.json_to_sql)(json)); | ||
const goal = (0, sql_formatter_1.format)('SELECT SUM(views) AS total_views FROM \`posts\`'); | ||
(0, chai_1.expect)(sql).to.equal(goal); | ||
}); | ||
(0, mocha_1.test)("'$not' command works", () => { | ||
@@ -37,3 +46,3 @@ const json = { | ||
const sql = (0, sql_formatter_1.format)((0, json_sql_1.json_to_sql)(json)); | ||
const goal = (0, sql_formatter_1.format)('(a) NOT IN ((1), (2))'); | ||
const goal = (0, sql_formatter_1.format)('a NOT IN (1, 2)'); | ||
(0, chai_1.expect)(sql).to.equal(goal); | ||
@@ -59,3 +68,3 @@ }); | ||
const sql = (0, sql_formatter_1.format)((0, json_sql_1.json_to_sql)(json)); | ||
const goal = (0, sql_formatter_1.format)('((a) IS NOT NULL) AND ((a) IS NOT NULL)'); | ||
const goal = (0, sql_formatter_1.format)('(a IS NOT NULL) AND (a IS NOT NULL)'); | ||
(0, chai_1.expect)(sql).to.equal(goal); | ||
@@ -71,3 +80,3 @@ }); | ||
const sql = (0, sql_formatter_1.format)((0, json_sql_1.json_to_sql)(json)); | ||
const goal = (0, sql_formatter_1.format)('((id), (parent_id)) = ((1), (2))'); | ||
const goal = (0, sql_formatter_1.format)('(id, parent_id) = (1, 2)'); | ||
(0, chai_1.expect)(sql).to.equal(goal); | ||
@@ -85,3 +94,3 @@ }); | ||
const sql = (0, sql_formatter_1.format)((0, json_sql_1.json_to_sql)(json)); | ||
const goal = (0, sql_formatter_1.format)('((id) != (1)) AND ((parent_id) IS NOT NULL)'); | ||
const goal = (0, sql_formatter_1.format)('(id != 1) AND (parent_id IS NOT NULL)'); | ||
(0, chai_1.expect)(sql).to.equal(goal); | ||
@@ -131,3 +140,3 @@ }); | ||
const sql = (0, sql_formatter_1.format)((0, json_sql_1.json_to_sql)(json)); | ||
const goal = (0, sql_formatter_1.format)(`IF ((1) = (1), "yes", "no")`); | ||
const goal = (0, sql_formatter_1.format)(`IF (1 = 1, "yes", "no")`); | ||
(0, chai_1.expect)(sql).to.equal(goal); | ||
@@ -154,3 +163,3 @@ }); | ||
const sql = (0, sql_formatter_1.format)((0, json_sql_1.json_to_sql)(json)); | ||
const goal = (0, sql_formatter_1.format)('(a) IN ((1), (2))'); | ||
const goal = (0, sql_formatter_1.format)('a IN (1, 2)'); | ||
(0, chai_1.expect)(sql).to.equal(goal); | ||
@@ -170,3 +179,3 @@ }); | ||
const sql = (0, sql_formatter_1.format)((0, json_sql_1.json_to_sql)(json)); | ||
const goal = (0, sql_formatter_1.format)("((a), (b)) IN (((1), ('c')), ((COALESCE(null, 2)), (3)))"); | ||
const goal = (0, sql_formatter_1.format)("(a, b) IN ((1, 'c'), (COALESCE(null, 2), 3))"); | ||
(0, chai_1.expect)(sql).to.equal(goal); | ||
@@ -190,3 +199,3 @@ }); | ||
const sql = (0, sql_formatter_1.format)((0, json_sql_1.json_to_sql)(json)); | ||
const goal = (0, sql_formatter_1.format)('items.sku'); | ||
const goal = (0, sql_formatter_1.format)('`items`.`sku`'); | ||
(0, chai_1.expect)(sql).to.equal(goal); | ||
@@ -210,8 +219,8 @@ }); | ||
HAVING | ||
(SELECT | ||
* | ||
FROM | ||
reviews | ||
WHERE | ||
(listing_id) = (0)) >= (4)`); | ||
(SELECT | ||
* | ||
FROM | ||
\`reviews\` | ||
WHERE | ||
listing_id = 0) >= 4`); | ||
(0, chai_1.expect)(sql).to.equal(goal); | ||
@@ -269,3 +278,3 @@ }); | ||
const goal = (0, sql_formatter_1.format)(` | ||
ALTER TABLE my_table ( | ||
ALTER TABLE \`my_table\` ( | ||
ADD id INT, | ||
@@ -414,3 +423,3 @@ DROP id, | ||
const goal = (0, sql_formatter_1.format)(` | ||
ALTER TABLE my_table ( | ||
ALTER TABLE \`my_table\` ( | ||
ADD INDEX invisible (label) INVISIBLE COMMENT "invis" | ||
@@ -433,3 +442,3 @@ )`); | ||
const goal = (0, sql_formatter_1.format)(` | ||
ALTER TABLE my_table ( | ||
ALTER TABLE \`my_table\` ( | ||
ADD CONSTRAINT \`uq_ind\` UNIQUE (label) | ||
@@ -452,3 +461,3 @@ )`); | ||
const goal = (0, sql_formatter_1.format)(` | ||
ALTER TABLE my_table ( | ||
ALTER TABLE \`my_table\` ( | ||
ADD FULLTEXT INDEX ft (size, label) | ||
@@ -467,3 +476,3 @@ )`); | ||
const goal = (0, sql_formatter_1.format)(` | ||
CREATE INDEX \`my_index\` ON my_table (field1, field2) | ||
CREATE INDEX \`my_index\` ON \`my_table\` (field1, field2) | ||
`); | ||
@@ -485,3 +494,3 @@ (0, chai_1.expect)((0, sql_formatter_1.format)((0, json_sql_1.json_to_sql)(json))).to.equal(goal); | ||
const goal = (0, sql_formatter_1.format)(` | ||
ALTER TABLE my_table ( | ||
ALTER TABLE \`my_table\` ( | ||
ADD CONSTRAINT \`primary\` PRIMARY KEY (id) | ||
@@ -518,7 +527,7 @@ )`); | ||
const goal = (0, sql_formatter_1.format)(` | ||
ALTER TABLE my_table ( | ||
ADD FOREIGN KEY (parent_id) REFERENCES parents (id), | ||
ADD CONSTRAINT \`my_foreign_key\` FOREIGN KEY (parent_id) REFERENCES parents (id) | ||
ALTER TABLE \`my_table\` ( | ||
ADD FOREIGN KEY (parent_id) REFERENCES \`parents\` (id), | ||
ADD CONSTRAINT \`my_foreign_key\` FOREIGN KEY (parent_id) REFERENCES \`parents\` (id) | ||
ON DELETE CASCADE ON UPDATE RESTRICT, | ||
ADD FOREIGN KEY (parent_id) REFERENCES parents (id) | ||
ADD FOREIGN KEY (parent_id) REFERENCES \`parents\` (id) | ||
ON DELETE NO ACTION ON UPDATE SET NULL | ||
@@ -525,0 +534,0 @@ )`); |
import { GetAllEdges, GetAllEntities, GetFieldNotNull, GetFields, GetFieldType } from '../schema/schema_helper_types'; | ||
import { OrmaSchema } from '../schema/schema_types'; | ||
export type OrmaMutation<Schema extends OrmaSchema> = { | ||
readonly [Entity in GetAllEntities<Schema>]?: readonly MutationRecord<Schema, Entity, true>[]; | ||
} | ({ | ||
readonly [Entity in GetAllEntities<Schema>]?: readonly MutationRecord<Schema, Entity, false>[]; | ||
} & { | ||
readonly [Entity in GetAllEntities<Schema>]?: readonly MutationRecord<Schema, Entity>[]; | ||
} & OperationObj; | ||
type MutationRecord<Schema extends OrmaSchema, Entity extends GetAllEntities<Schema>> = FieldsObj<Schema, Entity> & OperationObj & ForeignKeyFieldsObj<Schema, Entity, GetAllEdges<Schema, Entity>>; | ||
type OperationObj = { | ||
readonly $operation?: Operation; | ||
}); | ||
type MutationRecord<Schema extends OrmaSchema, Entity extends GetAllEntities<Schema>, RequireOperation extends boolean> = FieldsObj<Schema, Entity> & OperationObj<RequireOperation> & ForeignKeyFieldsObj<Schema, Entity, GetAllEdges<Schema, Entity>>; | ||
type OperationObj<RequireOperation extends boolean> = RequireOperation extends true ? { | ||
readonly $operation: Operation; | ||
} : { | ||
readonly $operation?: Operation; | ||
}; | ||
@@ -23,3 +17,3 @@ type Operation = 'create' | 'update' | 'delete' | 'upsert'; | ||
export type ForeignKeyFieldsObj<Schema extends OrmaSchema, Entity extends GetAllEntities<Schema>, AllEdges extends GetAllEdges<Schema, Entity>> = AllEdges extends never ? {} : AllEdges extends GetAllEdges<Schema, Entity> ? { | ||
readonly [Field in AllEdges['to_entity']]?: readonly MutationRecord<Schema, Field, false>[]; | ||
readonly [Field in AllEdges['to_entity']]?: readonly MutationRecord<Schema, Field>[]; | ||
} : never; | ||
@@ -26,0 +20,0 @@ export type FieldType<Schema extends OrmaSchema, Entity extends GetAllEntities<Schema>, Field extends GetFields<Schema, Entity>> = GetFieldType<Schema, Entity, Field> | NullableField<Schema, Entity, Field>; |
@@ -49,2 +49,15 @@ "use strict"; | ||
} | ||
{ | ||
// supports nesting with double map (not sure why, but double nested map can cause intellisense to fail) | ||
const t = { | ||
posts: [ | ||
{ | ||
title: 'test', | ||
likes: [].map(el => ({ | ||
posts: [].map(el => ({})), | ||
})), | ||
}, | ||
], | ||
}; | ||
} | ||
}; |
{ | ||
"name": "orma", | ||
"version": "1.0.225", | ||
"version": "1.0.226", | ||
"description": "A declarative relational syncronous orm", | ||
@@ -5,0 +5,0 @@ "main": "build/index.js", |
@@ -140,3 +140,3 @@ import { expect } from 'chai' | ||
sql_string: | ||
"UPDATE users SET first_name = 'john' WHERE (id) = (1)", | ||
"UPDATE users SET first_name = 'john' WHERE id = 1", | ||
}, | ||
@@ -154,3 +154,3 @@ { | ||
paths: [mutation_pieces[2].path], | ||
sql_string: 'DELETE FROM products WHERE (id) = (1)', | ||
sql_string: 'DELETE FROM products WHERE id = 1', | ||
}, | ||
@@ -157,0 +157,0 @@ ], |
@@ -130,3 +130,3 @@ import { validate } from 'jsonschema' | ||
path: [key], | ||
original_data: mutation, | ||
// original_data: mutation, | ||
}, | ||
@@ -201,3 +201,3 @@ ] as OrmaError[] | ||
message: `Records must have an operation or an inherited operation.`, | ||
original_data: mutation, | ||
// original_data: mutation, | ||
path: [...record_path, '$operation'], | ||
@@ -264,3 +264,3 @@ }, | ||
path: [...record_path, key], | ||
original_data: mutation, | ||
// original_data: mutation, | ||
}, | ||
@@ -286,3 +286,3 @@ ] as OrmaError[] | ||
path: [...record_path, key], | ||
original_data: mutation, | ||
// original_data: mutation, | ||
}, | ||
@@ -305,3 +305,3 @@ ] as OrmaError[] | ||
path: [...record_path, key], | ||
original_data: mutation, | ||
// original_data: mutation, | ||
}, | ||
@@ -353,3 +353,3 @@ ] as OrmaError[] | ||
path: field_path, | ||
original_data: mutation, | ||
// original_data: mutation, | ||
}, | ||
@@ -366,3 +366,3 @@ ] | ||
path: field_path, | ||
original_data: mutation, | ||
// original_data: mutation, | ||
}, | ||
@@ -388,3 +388,3 @@ ] | ||
path: field_path, | ||
original_data: mutation, | ||
// original_data: mutation, | ||
additional_info: { | ||
@@ -425,3 +425,3 @@ enum_values, | ||
path: field_path, | ||
original_data: mutation, | ||
// original_data: mutation, | ||
additional_info: { | ||
@@ -460,3 +460,3 @@ given_character_count, | ||
path: field_path, | ||
original_data: mutation, | ||
// original_data: mutation, | ||
}, | ||
@@ -471,3 +471,3 @@ ] | ||
path: field_path, | ||
original_data: mutation, | ||
// original_data: mutation, | ||
}, | ||
@@ -488,3 +488,3 @@ ] | ||
path: field_path, | ||
original_data: mutation, | ||
// original_data: mutation, | ||
additional_info: { | ||
@@ -508,3 +508,3 @@ given_character_count, | ||
path: field_path, | ||
original_data: mutation, | ||
// original_data: mutation, | ||
additional_info: { | ||
@@ -524,3 +524,3 @@ given_decimals, | ||
path: field_path, | ||
original_data: mutation, | ||
// original_data: mutation, | ||
additional_info: { | ||
@@ -544,3 +544,3 @@ given_decimals, | ||
path: field_path, | ||
original_data: mutation, | ||
// original_data: mutation, | ||
}, | ||
@@ -569,3 +569,3 @@ ] | ||
path: field_path, | ||
original_data: mutation, | ||
// original_data: mutation, | ||
additional_info: { | ||
@@ -617,3 +617,3 @@ required_data_type, | ||
path: [...record_path, required_field], | ||
original_data: mutation, | ||
// original_data: mutation, | ||
}, | ||
@@ -676,3 +676,3 @@ ] | ||
// // path: [...record_path, '$operation'], | ||
// // original_data: mutation, | ||
// // // original_data: mutation, | ||
// // additional_info: { | ||
@@ -715,3 +715,3 @@ // // parent_entity, | ||
// path: record_path, | ||
// original_data: mutation, | ||
// // original_data: mutation, | ||
// // stack_trace: new Error().stack, | ||
@@ -718,0 +718,0 @@ // additional_info: { |
@@ -19,3 +19,3 @@ import { expect } from 'chai' | ||
const sql = format(json_to_sql(json)) | ||
const goal = format(`SELECT a FROM b`) | ||
const goal = format(`SELECT a FROM \`b\``) | ||
@@ -32,6 +32,17 @@ expect(sql).to.equal(goal) | ||
const sql = format(json_to_sql(json)) | ||
const goal = format('WHERE (a) = (b)') | ||
const goal = format('WHERE a = b') | ||
expect(sql).to.equal(goal) | ||
}) | ||
test('handles selecting functions', () => { | ||
const json = { | ||
$select: [{ $as: ['SUM(views)', 'total_views'] }], | ||
$from: 'posts', | ||
} | ||
const sql = format(json_to_sql(json)) | ||
const goal = format('SELECT SUM(views) AS total_views FROM \`posts\`') | ||
expect(sql).to.equal(goal) | ||
}) | ||
test("'$not' command works", () => { | ||
@@ -45,3 +56,3 @@ const json = { | ||
const sql = format(json_to_sql(json)) | ||
const goal = format('(a) NOT IN ((1), (2))') | ||
const goal = format('a NOT IN (1, 2)') | ||
@@ -69,3 +80,3 @@ expect(sql).to.equal(goal) | ||
const sql = format(json_to_sql(json)) | ||
const goal = format('((a) IS NOT NULL) AND ((a) IS NOT NULL)') | ||
const goal = format('(a IS NOT NULL) AND (a IS NOT NULL)') | ||
@@ -83,3 +94,3 @@ expect(sql).to.equal(goal) | ||
const sql = format(json_to_sql(json)) | ||
const goal = format('((id), (parent_id)) = ((1), (2))') | ||
const goal = format('(id, parent_id) = (1, 2)') | ||
@@ -99,3 +110,3 @@ expect(sql).to.equal(goal) | ||
const sql = format(json_to_sql(json)) | ||
const goal = format('((id) != (1)) AND ((parent_id) IS NOT NULL)') | ||
const goal = format('(id != 1) AND (parent_id IS NOT NULL)') | ||
@@ -152,3 +163,3 @@ expect(sql).to.equal(goal) | ||
const sql = format(json_to_sql(json)) | ||
const goal = format(`IF ((1) = (1), "yes", "no")`) | ||
const goal = format(`IF (1 = 1, "yes", "no")`) | ||
expect(sql).to.equal(goal) | ||
@@ -177,3 +188,3 @@ }) | ||
const sql = format(json_to_sql(json)) | ||
const goal = format('(a) IN ((1), (2))') | ||
const goal = format('a IN (1, 2)') | ||
@@ -195,5 +206,3 @@ expect(sql).to.equal(goal) | ||
const sql = format(json_to_sql(json)) | ||
const goal = format( | ||
"((a), (b)) IN (((1), ('c')), ((COALESCE(null, 2)), (3)))" | ||
) | ||
const goal = format("(a, b) IN ((1, 'c'), (COALESCE(null, 2), 3))") | ||
@@ -219,3 +228,3 @@ expect(sql).to.equal(goal) | ||
const sql = format(json_to_sql(json)) | ||
const goal = format('items.sku') | ||
const goal = format('`items`.`sku`') | ||
@@ -242,8 +251,8 @@ expect(sql).to.equal(goal) | ||
HAVING | ||
(SELECT | ||
* | ||
FROM | ||
reviews | ||
WHERE | ||
(listing_id) = (0)) >= (4)`) | ||
(SELECT | ||
* | ||
FROM | ||
\`reviews\` | ||
WHERE | ||
listing_id = 0) >= 4`) | ||
@@ -305,3 +314,3 @@ expect(sql).to.equal(goal) | ||
const goal = format(` | ||
ALTER TABLE my_table ( | ||
ALTER TABLE \`my_table\` ( | ||
ADD id INT, | ||
@@ -464,3 +473,3 @@ DROP id, | ||
const goal = format(` | ||
ALTER TABLE my_table ( | ||
ALTER TABLE \`my_table\` ( | ||
ADD INDEX invisible (label) INVISIBLE COMMENT "invis" | ||
@@ -485,3 +494,3 @@ )`) | ||
const goal = format(` | ||
ALTER TABLE my_table ( | ||
ALTER TABLE \`my_table\` ( | ||
ADD CONSTRAINT \`uq_ind\` UNIQUE (label) | ||
@@ -506,3 +515,3 @@ )`) | ||
const goal = format(` | ||
ALTER TABLE my_table ( | ||
ALTER TABLE \`my_table\` ( | ||
ADD FULLTEXT INDEX ft (size, label) | ||
@@ -523,3 +532,3 @@ )`) | ||
const goal = format(` | ||
CREATE INDEX \`my_index\` ON my_table (field1, field2) | ||
CREATE INDEX \`my_index\` ON \`my_table\` (field1, field2) | ||
`) | ||
@@ -543,3 +552,3 @@ | ||
const goal = format(` | ||
ALTER TABLE my_table ( | ||
ALTER TABLE \`my_table\` ( | ||
ADD CONSTRAINT \`primary\` PRIMARY KEY (id) | ||
@@ -588,7 +597,7 @@ )`) | ||
const goal = format(` | ||
ALTER TABLE my_table ( | ||
ADD FOREIGN KEY (parent_id) REFERENCES parents (id), | ||
ADD CONSTRAINT \`my_foreign_key\` FOREIGN KEY (parent_id) REFERENCES parents (id) | ||
ALTER TABLE \`my_table\` ( | ||
ADD FOREIGN KEY (parent_id) REFERENCES \`parents\` (id), | ||
ADD CONSTRAINT \`my_foreign_key\` FOREIGN KEY (parent_id) REFERENCES \`parents\` (id) | ||
ON DELETE CASCADE ON UPDATE RESTRICT, | ||
ADD FOREIGN KEY (parent_id) REFERENCES parents (id) | ||
ADD FOREIGN KEY (parent_id) REFERENCES \`parents\` (id) | ||
ON DELETE NO ACTION ON UPDATE SET NULL | ||
@@ -595,0 +604,0 @@ )`) |
@@ -310,6 +310,6 @@ /** | ||
$select: args => `SELECT ${args.join(', ')}`, | ||
$as: args => `(${args[0]}) AS ${args[1]}`, | ||
$entity: args => `${args}`, | ||
$field: args => `.${args}`, | ||
$from: args => `FROM ${args}`, | ||
$as: args => `${wrap_if_subquery(args[0])} AS ${args[1]}`, | ||
$entity: args => `${escape_field(args)}`, | ||
$field: args => `.${escape_field(args)}`, | ||
$from: args => `FROM ${escape_field(args)}`, | ||
$where: args => `WHERE ${args}`, | ||
@@ -326,3 +326,3 @@ $group_by: args => `GROUP BY ${args.join(', ')}`, | ||
const left_arg_string = Array.isArray(left_arg) | ||
? left_arg.map(val => `(${val})`).join(', ') | ||
? `(${left_arg.map(val => `${wrap_if_subquery(val)}`).join(', ')})` | ||
: left_arg | ||
@@ -334,4 +334,6 @@ const not_string = nested_under_odd_nots(path) ? ' NOT' : '' | ||
Array.isArray(val) | ||
? `(${val.map(el => `(${el})`).join(', ')})` | ||
: `(${val})` | ||
? `(${val | ||
.map(el => wrap_if_subquery(el)) | ||
.join(', ')})` | ||
: wrap_if_subquery(val) | ||
) | ||
@@ -341,3 +343,5 @@ .join(', ') | ||
return `(${left_arg_string})${not_string} IN (${right_arg_string})` | ||
return `${wrap_if_subquery( | ||
left_arg_string | ||
)}${not_string} IN (${right_arg_string})` | ||
}, | ||
@@ -357,8 +361,8 @@ $and: (args, path) => { | ||
is_sql_null(right_val) | ||
? `(${left_val}) IS${ | ||
? `${wrap_if_subquery(left_val)} IS${ | ||
nested_under_odd_nots(path) ? ' NOT' : '' | ||
} NULL` | ||
: `(${left_val}) ${ | ||
: `${wrap_if_subquery(left_val)} ${ | ||
nested_under_odd_nots(path) ? '!' : '' | ||
}= (${right_val})` | ||
}= ${wrap_if_subquery(right_val)}` | ||
@@ -375,5 +379,7 @@ const [left_arg, right_arg] = args | ||
} else { | ||
return `(${left_arg.map(val => `(${val})`).join(', ')}) ${ | ||
return `(${left_arg | ||
.map(val => wrap_if_subquery(val)) | ||
.join(', ')}) ${ | ||
nested_under_odd_nots(path) ? '!' : '' | ||
}= (${right_arg.map(val => `(${val})`).join(', ')})` | ||
}= (${right_arg.map(val => wrap_if_subquery(val)).join(', ')})` | ||
} | ||
@@ -386,9 +392,17 @@ } | ||
$gt: (args, path) => | ||
`(${args[0]}) ${nested_under_odd_nots(path) ? '<=' : '>'} (${args[1]})`, | ||
`${wrap_if_subquery(args[0])} ${ | ||
nested_under_odd_nots(path) ? '<=' : '>' | ||
} ${wrap_if_subquery(args[1])}`, | ||
$lt: (args, path) => | ||
`(${args[0]}) ${nested_under_odd_nots(path) ? '>=' : '<'} (${args[1]})`, | ||
`${wrap_if_subquery(args[0])} ${ | ||
nested_under_odd_nots(path) ? '>=' : '<' | ||
} ${wrap_if_subquery(args[1])}`, | ||
$gte: (args, path) => | ||
`(${args[0]}) ${nested_under_odd_nots(path) ? '<' : '>='} (${args[1]})`, | ||
`${wrap_if_subquery(args[0])} ${ | ||
nested_under_odd_nots(path) ? '<' : '>=' | ||
} ${wrap_if_subquery(args[1])}`, | ||
$lte: (args, path) => | ||
`(${args[0]}) ${nested_under_odd_nots(path) ? '>' : '<='} (${args[1]})`, | ||
`${wrap_if_subquery(args[0])} ${ | ||
nested_under_odd_nots(path) ? '>' : '<=' | ||
} ${wrap_if_subquery(args[1])}`, | ||
$exists: (args, path) => | ||
@@ -402,5 +416,5 @@ `${nested_under_odd_nots(path) ? 'NOT ' : ''}EXISTS (${args})`, | ||
// } LIKE '%${search_value}%'` | ||
return `(${args[0]})${ | ||
return `${wrap_if_subquery(args[0])}${ | ||
nested_under_odd_nots(path) ? ' NOT' : '' | ||
} LIKE (${args[1]})` | ||
} LIKE ${wrap_if_subquery(args[1])}` | ||
}, | ||
@@ -428,3 +442,3 @@ $not: args => args, // not logic is different depending on the children, so the children handle it | ||
// alter | ||
$alter_table: table_name => `ALTER TABLE ${table_name}`, | ||
$alter_table: table_name => `ALTER TABLE \`${table_name}\``, | ||
// definitions | ||
@@ -522,2 +536,12 @@ $definitions: args => (args?.length ? `(${args.join(', ')})` : ''), | ||
/** | ||
* Only wrap SELECT ... statments with (), since sqlite doesnt support wrapping primitive values like | ||
* numbers in (), I think its interpreting them as tuples when you do that | ||
*/ | ||
const wrap_if_subquery = (val: string) => | ||
val?.startsWith?.('SELECT') ? `(${val})` : val | ||
const escape_field = val => | ||
typeof val === 'string' && !['*'].includes(val) ? `\`${val}\`` : val | ||
const is_sql_null = val => { | ||
@@ -524,0 +548,0 @@ const is_regular_null = val === null |
@@ -49,2 +49,17 @@ import { GlobalTestMutation } from '../../test_data/global_test_schema' | ||
} | ||
{ | ||
// supports nesting with double map (not sure why, but double nested map can cause intellisense to fail) | ||
const t = { | ||
posts: [ | ||
{ | ||
title: 'test', | ||
likes: [].map(el => ({ | ||
posts: [].map(el => ({ | ||
})), | ||
})), | ||
}, | ||
], | ||
} as const satisfies GlobalTestMutation | ||
} | ||
} |
@@ -12,38 +12,19 @@ import { GlobalTestSchema } from '../../test_data/global_test_schema' | ||
export type OrmaMutation<Schema extends OrmaSchema> = | ||
| { | ||
readonly [Entity in GetAllEntities<Schema>]?: readonly MutationRecord< | ||
Schema, | ||
Entity, | ||
// we only need to do this on the top level, since after the highest entity everything will have an operation, | ||
// either directly provided or through cascading from the highest entity | ||
true | ||
>[] | ||
} | ||
| ({ | ||
readonly [Entity in GetAllEntities<Schema>]?: readonly MutationRecord< | ||
Schema, | ||
Entity, | ||
false | ||
>[] | ||
} & { | ||
readonly $operation?: Operation | ||
}) | ||
export type OrmaMutation<Schema extends OrmaSchema> = { | ||
readonly [Entity in GetAllEntities<Schema>]?: readonly MutationRecord< | ||
Schema, | ||
Entity | ||
>[] | ||
} & OperationObj | ||
type MutationRecord< | ||
Schema extends OrmaSchema, | ||
Entity extends GetAllEntities<Schema>, | ||
RequireOperation extends boolean | ||
Entity extends GetAllEntities<Schema> | ||
> = FieldsObj<Schema, Entity> & | ||
OperationObj<RequireOperation> & | ||
OperationObj & | ||
ForeignKeyFieldsObj<Schema, Entity, GetAllEdges<Schema, Entity>> | ||
type OperationObj<RequireOperation extends boolean> = | ||
RequireOperation extends true | ||
? { | ||
readonly $operation: Operation | ||
} | ||
: { | ||
readonly $operation?: Operation | ||
} | ||
type OperationObj = { | ||
readonly $operation?: Operation | ||
} | ||
@@ -56,4 +37,4 @@ type Operation = 'create' | 'update' | 'delete' | 'upsert' | ||
> = { | ||
readonly // baseline for regular props | ||
[Field in GetFields<Schema, Entity>]?: | ||
// baseline for regular props | ||
readonly [Field in GetFields<Schema, Entity>]?: | ||
| FieldType<Schema, Entity, Field> | ||
@@ -87,4 +68,3 @@ // primary or foreign keys can have guids | ||
Schema, | ||
Field, | ||
false | ||
Field | ||
>[] | ||
@@ -91,0 +71,0 @@ } |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1595609
38886