UNPKG

nukak

Version:

flexible and efficient ORM, with declarative JSON syntax and smart type-safety

650 lines 99.3 kB
import { getMeta } from '../entity/index.js'; import { QueryRaw, } from '../type/index.js'; import { buildSortMap, buldQueryWhereAsMap, escapeSqlId, fillOnFields, filterFieldKeys, filterRelationKeys, flatObject, getFieldCallbackValue, getFieldKeys, getKeys, hasKeys, isSelectingRelations, raw, } from '../util/index.js'; import { AbstractDialect } from './abstractDialect.js'; import { SqlQueryContext } from './queryContext.js'; export class AbstractSqlDialect extends AbstractDialect { escapeIdChar; beginTransactionCommand; commitTransactionCommand; rollbackTransactionCommand; constructor(namingStrategy, escapeIdChar = '`', beginTransactionCommand = 'START TRANSACTION', commitTransactionCommand = 'COMMIT', rollbackTransactionCommand = 'ROLLBACK') { super(namingStrategy); this.escapeIdChar = escapeIdChar; this.beginTransactionCommand = beginTransactionCommand; this.commitTransactionCommand = commitTransactionCommand; this.rollbackTransactionCommand = rollbackTransactionCommand; } createContext() { return new SqlQueryContext(this); } addValue(values, value) { values.push(value ?? null); return this.placeholder(values.length); } placeholder(_index) { return '?'; } returningId(entity) { const meta = getMeta(entity); const idName = this.resolveColumnName(meta.id, meta.fields[meta.id]); return `RETURNING ${this.escapeId(idName)} ${this.escapeId('id')}`; } search(ctx, entity, q = {}, opts = {}) { const meta = getMeta(entity); const tableName = this.resolveTableName(entity, meta); const prefix = (opts.prefix ?? (opts.autoPrefix || isSelectingRelations(meta, q.$select))) ? tableName : undefined; opts = { ...opts, prefix }; this.where(ctx, entity, q.$where, opts); this.sort(ctx, entity, q.$sort, opts); this.pager(ctx, q); } selectFields(ctx, entity, select, opts = {}) { const meta = getMeta(entity); const prefix = opts.prefix ? opts.prefix + '.' : ''; const escapedPrefix = this.escapeId(opts.prefix, true, true); let selectArr; if (select) { if (Array.isArray(select)) { selectArr = select; } else { const selectPositive = getKeys(select).filter((it) => select[it]); selectArr = selectPositive.length ? selectPositive : getFieldKeys(meta.fields).filter((it) => !(it in select)); } selectArr = selectArr.filter((it) => it instanceof QueryRaw || it in meta.fields); if (opts.prefix && !selectArr.includes(meta.id)) { selectArr = [meta.id, ...selectArr]; } } else { selectArr = getFieldKeys(meta.fields); } if (!selectArr.length) { ctx.append(escapedPrefix + '*'); return; } selectArr.forEach((key, index) => { if (index > 0) ctx.append(', '); if (key instanceof QueryRaw) { this.getRawValue(ctx, { value: key, prefix: opts.prefix, escapedPrefix, autoPrefixAlias: opts.autoPrefixAlias, }); } else { const field = meta.fields[key]; const columnName = this.resolveColumnName(key, field); if (field.virtual) { this.getRawValue(ctx, { value: raw(field.virtual.value, key), prefix: opts.prefix, escapedPrefix, autoPrefixAlias: opts.autoPrefixAlias, }); } else { ctx.append(escapedPrefix + this.escapeId(columnName)); } if (!field.virtual && (columnName !== key || opts.autoPrefixAlias)) { const aliasStr = (prefix + key); // Replace dots with underscores for alias to avoid syntax errors const safeAlias = aliasStr.replace(/\./g, '_'); ctx.append(' ' + this.escapeId(safeAlias, true)); } } }); } select(ctx, entity, select, opts = {}) { const meta = getMeta(entity); const tableName = this.resolveTableName(entity, meta); const prefix = (opts.prefix ?? (opts.autoPrefix || isSelectingRelations(meta, select))) ? tableName : undefined; ctx.append('SELECT '); this.selectFields(ctx, entity, select, { prefix }); // Add related fields BEFORE FROM clause this.selectRelationFields(ctx, entity, select, { prefix }); ctx.append(` FROM ${this.escapeId(tableName)}`); // Add JOINs AFTER FROM clause this.selectRelationJoins(ctx, entity, select, { prefix }); } selectRelationFields(ctx, entity, select, opts = {}) { if (Array.isArray(select)) { return; } const meta = getMeta(entity); const tableName = this.resolveTableName(entity, meta); const relKeys = filterRelationKeys(meta, select); const isSelectArray = Array.isArray(select); const prefix = opts.prefix; for (const relKey of relKeys) { const relOpts = meta.relations[relKey]; if (relOpts.cardinality === '1m' || relOpts.cardinality === 'mm') { continue; } const isFirstLevel = prefix === tableName; const joinRelAlias = isFirstLevel ? relKey : prefix ? prefix + '.' + relKey : relKey; const relEntity = relOpts.entity(); const relSelect = select[relKey]; const relQuery = isSelectArray ? {} : Array.isArray(relSelect) ? { $select: relSelect } : relSelect; ctx.append(', '); this.selectFields(ctx, relEntity, relQuery.$select, { prefix: joinRelAlias, autoPrefixAlias: true, }); // Recursively add nested relation fields this.selectRelationFields(ctx, relEntity, relQuery.$select, { prefix: joinRelAlias, }); } } selectRelationJoins(ctx, entity, select, opts = {}) { if (Array.isArray(select)) { return; } const meta = getMeta(entity); const tableName = this.resolveTableName(entity, meta); const relKeys = filterRelationKeys(meta, select); const isSelectArray = Array.isArray(select); const prefix = opts.prefix; for (const relKey of relKeys) { const relOpts = meta.relations[relKey]; if (relOpts.cardinality === '1m' || relOpts.cardinality === 'mm') { continue; } const isFirstLevel = prefix === tableName; const joinRelAlias = isFirstLevel ? relKey : prefix ? prefix + '.' + relKey : relKey; const relEntity = relOpts.entity(); const relSelect = select[relKey]; const relQuery = isSelectArray ? {} : Array.isArray(relSelect) ? { $select: relSelect } : relSelect; const relMeta = getMeta(relEntity); const relTableName = this.resolveTableName(relEntity, relMeta); const relEntityName = this.escapeId(relTableName); const relPath = prefix ? this.escapeId(prefix, true) : this.escapeId(tableName); const joinType = relQuery.$required ? 'INNER' : 'LEFT'; const joinAlias = this.escapeId(joinRelAlias, true); ctx.append(` ${joinType} JOIN ${relEntityName} ${joinAlias} ON `); ctx.append(relOpts.references .map((it) => { const foreignColumnName = this.resolveColumnName(it.foreign, relMeta.fields[it.foreign]); const localColumnName = this.resolveColumnName(it.local, meta.fields[it.local]); return `${joinAlias}.${this.escapeId(foreignColumnName)} = ${relPath}.${this.escapeId(localColumnName)}`; }) .join(' AND ')); if (relQuery.$where) { ctx.append(' AND '); this.where(ctx, relEntity, relQuery.$where, { prefix: joinRelAlias, clause: false }); } // Recursively add nested relation JOINs this.selectRelationJoins(ctx, relEntity, relQuery.$select, { prefix: joinRelAlias, }); } } where(ctx, entity, where = {}, opts = {}) { const meta = getMeta(entity); const { usePrecedence, clause = 'WHERE', softDelete } = opts; where = buldQueryWhereAsMap(meta, where); if (meta.softDelete && (softDelete || softDelete === undefined) && !where[meta.softDelete]) { where[meta.softDelete] = null; } const entries = Object.entries(where); if (!entries.length) { return; } if (clause) { ctx.append(` ${clause} `); } if (usePrecedence) { ctx.append('('); } entries.forEach(([key, val], index) => { if (index > 0) { ctx.append(' AND '); } this.compare(ctx, entity, key, val, { ...opts, usePrecedence: entries.length > 1, }); }); if (usePrecedence) { ctx.append(')'); } } compare(ctx, entity, key, val, opts = {}) { const meta = getMeta(entity); if (val instanceof QueryRaw) { if (key === '$exists' || key === '$nexists') { ctx.append(key === '$exists' ? 'EXISTS (' : 'NOT EXISTS ('); const tableName = this.resolveTableName(entity, meta); this.getRawValue(ctx, { value: val, prefix: tableName, escapedPrefix: this.escapeId(tableName, false, true), }); ctx.append(')'); return; } this.getComparisonKey(ctx, entity, key, opts); ctx.append(' = '); this.getRawValue(ctx, { value: val }); return; } if (key === '$text') { const search = val; const fields = search.$fields.map((fKey) => { const field = meta.fields[fKey]; const columnName = this.resolveColumnName(fKey, field); return this.escapeId(columnName); }); ctx.append(`MATCH(${fields.join(', ')}) AGAINST(`); ctx.addValue(search.$value); ctx.append(')'); return; } if (key === '$and' || key === '$or' || key === '$not' || key === '$nor') { const negateOperatorMap = { $not: '$and', $nor: '$or', }; const op = negateOperatorMap[key] ?? key; const negate = key in negateOperatorMap ? 'NOT' : ''; const valArr = val; const hasManyItems = valArr.length > 1; if ((opts.usePrecedence || negate) && hasManyItems) { ctx.append((negate ? negate + ' ' : '') + '('); } else if (negate) { ctx.append(negate + ' '); } valArr.forEach((whereEntry, index) => { if (index > 0) { ctx.append(op === '$or' ? ' OR ' : ' AND '); } if (whereEntry instanceof QueryRaw) { this.getRawValue(ctx, { value: whereEntry, prefix: opts.prefix, escapedPrefix: this.escapeId(opts.prefix, true, true), }); } else { this.where(ctx, entity, whereEntry, { prefix: opts.prefix, usePrecedence: hasManyItems && !Array.isArray(whereEntry) && getKeys(whereEntry).length > 1, clause: false, }); } }); if ((opts.usePrecedence || negate) && hasManyItems) { ctx.append(')'); } return; } const value = Array.isArray(val) ? { $in: val } : typeof val === 'object' && val !== null ? val : { $eq: val }; const operators = getKeys(value); if (operators.length > 1) { ctx.append('('); } operators.forEach((op, index) => { if (index > 0) { ctx.append(' AND '); } this.compareFieldOperator(ctx, entity, key, op, value[op], opts); }); if (operators.length > 1) { ctx.append(')'); } } compareFieldOperator(ctx, entity, key, op, val, opts = {}) { switch (op) { case '$eq': this.getComparisonKey(ctx, entity, key, opts); if (val === null) { ctx.append(' IS NULL'); } else { ctx.append(' = '); ctx.addValue(val); } break; case '$ne': this.getComparisonKey(ctx, entity, key, opts); if (val === null) { ctx.append(' IS NOT NULL'); } else { ctx.append(' <> '); ctx.addValue(val); } break; case '$not': ctx.append('NOT ('); this.compare(ctx, entity, key, val, opts); ctx.append(')'); break; case '$gt': this.getComparisonKey(ctx, entity, key, opts); ctx.append(' > '); ctx.addValue(val); break; case '$gte': this.getComparisonKey(ctx, entity, key, opts); ctx.append(' >= '); ctx.addValue(val); break; case '$lt': this.getComparisonKey(ctx, entity, key, opts); ctx.append(' < '); ctx.addValue(val); break; case '$lte': this.getComparisonKey(ctx, entity, key, opts); ctx.append(' <= '); ctx.addValue(val); break; case '$startsWith': this.getComparisonKey(ctx, entity, key, opts); ctx.append(' LIKE '); ctx.addValue(`${val}%`); break; case '$istartsWith': this.getComparisonKey(ctx, entity, key, opts); ctx.append(' LIKE '); ctx.addValue(`${val.toLowerCase()}%`); break; case '$endsWith': this.getComparisonKey(ctx, entity, key, opts); ctx.append(' LIKE '); ctx.addValue(`%${val}`); break; case '$iendsWith': this.getComparisonKey(ctx, entity, key, opts); ctx.append(' LIKE '); ctx.addValue(`%${val.toLowerCase()}`); break; case '$includes': this.getComparisonKey(ctx, entity, key, opts); ctx.append(' LIKE '); ctx.addValue(`%${val}%`); break; case '$iincludes': this.getComparisonKey(ctx, entity, key, opts); ctx.append(' LIKE '); ctx.addValue(`%${val.toLowerCase()}%`); break; case '$ilike': this.getComparisonKey(ctx, entity, key, opts); ctx.append(' LIKE '); ctx.addValue(val.toLowerCase()); break; case '$like': this.getComparisonKey(ctx, entity, key, opts); ctx.append(' LIKE '); ctx.addValue(val); break; case '$in': this.getComparisonKey(ctx, entity, key, opts); if (Array.isArray(val) && val.length > 0) { ctx.append(' IN ('); this.addValues(ctx, val); ctx.append(')'); } else { ctx.append(' IN (NULL)'); } break; case '$nin': this.getComparisonKey(ctx, entity, key, opts); if (Array.isArray(val) && val.length > 0) { ctx.append(' NOT IN ('); this.addValues(ctx, val); ctx.append(')'); } else { ctx.append(' NOT IN (NULL)'); } break; case '$regex': this.getComparisonKey(ctx, entity, key, opts); ctx.append(' REGEXP '); ctx.addValue(val); break; default: throw TypeError(`unknown operator: ${op}`); } } addValues(ctx, vals) { vals.forEach((val, index) => { if (index > 0) { ctx.append(', '); } ctx.addValue(val); }); } getComparisonKey(ctx, entity, key, { prefix } = {}) { const meta = getMeta(entity); const escapedPrefix = this.escapeId(prefix, true, true); const field = meta.fields[key]; if (field?.virtual) { this.getRawValue(ctx, { value: field.virtual, prefix, escapedPrefix, }); return; } const columnName = this.resolveColumnName(key, field); ctx.append(escapedPrefix + this.escapeId(columnName)); } sort(ctx, entity, sort, { prefix }) { const sortMap = buildSortMap(sort); if (!hasKeys(sortMap)) { return; } const meta = getMeta(entity); const flattenedSort = flatObject(sortMap, prefix); const directionMap = { 1: '', asc: '', '-1': ' DESC', desc: ' DESC' }; ctx.append(' ORDER BY '); Object.entries(flattenedSort).forEach(([key, sort], index) => { if (index > 0) { ctx.append(', '); } const field = meta.fields[key]; const name = this.resolveColumnName(key, field); const direction = directionMap[sort]; ctx.append(this.escapeId(name) + direction); }); } pager(ctx, opts) { if (opts.$limit) { ctx.append(` LIMIT ${Number(opts.$limit)}`); } if (opts.$skip !== undefined) { ctx.append(` OFFSET ${Number(opts.$skip)}`); } } count(ctx, entity, q, opts) { const search = { ...q }; delete search.$sort; this.select(ctx, entity, [raw('COUNT(*)', 'count')], undefined); this.search(ctx, entity, search, opts); } find(ctx, entity, q = {}, opts) { this.select(ctx, entity, q.$select, opts); this.search(ctx, entity, q, opts); } insert(ctx, entity, payload, opts) { const meta = getMeta(entity); const payloads = fillOnFields(meta, payload, 'onInsert'); const keys = filterFieldKeys(meta, payloads[0], 'onInsert'); const columns = keys.map((key) => { const field = meta.fields[key]; return this.escapeId(this.resolveColumnName(key, field)); }); const tableName = this.resolveTableName(entity, meta); ctx.append(`INSERT INTO ${this.escapeId(tableName)} (${columns.join(', ')}) VALUES (`); payloads.forEach((it, recordIndex) => { if (recordIndex > 0) { ctx.append('), ('); } keys.forEach((key, keyIndex) => { if (keyIndex > 0) { ctx.append(', '); } const field = meta.fields[key]; this.formatPersistableValue(ctx, field, it[key]); }); }); ctx.append(')'); } update(ctx, entity, q, payload, opts) { const meta = getMeta(entity); const [filledPayload] = fillOnFields(meta, payload, 'onUpdate'); const keys = filterFieldKeys(meta, filledPayload, 'onUpdate'); const tableName = this.resolveTableName(entity, meta); ctx.append(`UPDATE ${this.escapeId(tableName)} SET `); keys.forEach((key, index) => { if (index > 0) { ctx.append(', '); } const field = meta.fields[key]; const columnName = this.resolveColumnName(key, field); ctx.append(`${this.escapeId(columnName)} = `); this.formatPersistableValue(ctx, field, filledPayload[key]); }); this.search(ctx, entity, q, opts); } upsert(ctx, entity, conflictPaths, payload) { const meta = getMeta(entity); const update = this.getUpsertUpdateAssignments(ctx, meta, conflictPaths, payload, (name) => `VALUES(${name})`); if (update) { this.insert(ctx, entity, payload); ctx.append(` ON DUPLICATE KEY UPDATE ${update}`); } else { const insertCtx = this.createContext(); this.insert(insertCtx, entity, payload); ctx.append(insertCtx.sql.replace(/^INSERT/, 'INSERT IGNORE')); insertCtx.values.forEach((val) => { ctx.pushValue(val); }); } } getUpsertUpdateAssignments(ctx, meta, conflictPaths, payload, callback) { const [filledPayload] = fillOnFields(meta, payload, 'onUpdate'); const fields = filterFieldKeys(meta, filledPayload, 'onUpdate'); return fields .filter((col) => !conflictPaths[col]) .map((col) => { const field = meta.fields[col]; const columnName = this.resolveColumnName(col, field); if (callback) { return `${this.escapeId(columnName)} = ${callback(this.escapeId(columnName))}`; } const valCtx = this.createContext(); this.formatPersistableValue(valCtx, field, filledPayload[col]); valCtx.values.forEach((val) => { ctx.pushValue(val); }); return `${this.escapeId(columnName)} = ${valCtx.sql}`; }) .join(', '); } getUpsertConflictPathsStr(meta, conflictPaths) { return getKeys(conflictPaths) .map((key) => { const field = meta.fields[key]; const columnName = this.resolveColumnName(key, field); return this.escapeId(columnName); }) .join(', '); } delete(ctx, entity, q, opts = {}) { const meta = getMeta(entity); const tableName = this.resolveTableName(entity, meta); if (opts.softDelete || opts.softDelete === undefined) { if (meta.softDelete) { const field = meta.fields[meta.softDelete]; const value = getFieldCallbackValue(field.onDelete); const columnName = this.resolveColumnName(meta.softDelete, field); ctx.append(`UPDATE ${this.escapeId(tableName)} SET ${this.escapeId(columnName)} = `); ctx.addValue(value); this.search(ctx, entity, q, opts); return; } if (opts.softDelete) { throw TypeError(`'${tableName}' has not enabled 'softDelete'`); } } ctx.append(`DELETE FROM ${this.escapeId(tableName)}`); this.search(ctx, entity, q, opts); } escapeId(val, forbidQualified, addDot) { return escapeSqlId(val, this.escapeIdChar, forbidQualified, addDot); } getPersistables(ctx, meta, payload, callbackKey) { const payloads = fillOnFields(meta, payload, callbackKey); return payloads.map((it) => this.getPersistable(ctx, meta, it, callbackKey)); } getPersistable(ctx, meta, payload, callbackKey) { const filledPayload = fillOnFields(meta, payload, callbackKey)[0]; const keys = filterFieldKeys(meta, filledPayload, callbackKey); return keys.reduce((acc, key) => { const field = meta.fields[key]; const valCtx = this.createContext(); this.formatPersistableValue(valCtx, field, filledPayload[key]); valCtx.values.forEach((val) => { ctx.pushValue(val); }); acc[key] = valCtx.sql; return acc; }, {}); } formatPersistableValue(ctx, field, value) { if (value instanceof QueryRaw) { this.getRawValue(ctx, { value }); return; } if (field?.type === 'json' || field?.type === 'jsonb') { ctx.addValue(value ? JSON.stringify(value) : null); return; } if (field?.type === 'vector' && Array.isArray(value)) { ctx.addValue(`[${value.join(',')}]`); return; } ctx.addValue(value); } getRawValue(ctx, opts) { const { value, prefix = '', escapedPrefix, autoPrefixAlias } = opts; if (typeof value.value === 'function') { const res = value.value({ ...opts, ctx, dialect: this, prefix, escapedPrefix: escapedPrefix ?? this.escapeId(prefix, true, true), }); if (typeof res === 'string' || (typeof res === 'number' && !Number.isNaN(res))) { ctx.append(String(res)); } } else { ctx.append(prefix + String(value.value)); } const alias = value.alias; if (alias) { const fullAlias = autoPrefixAlias ? prefix + alias : alias; // Replace dots with underscores for alias to avoid syntax errors const safeAlias = fullAlias.replace(/\./g, '_'); const escapedFullAlias = this.escapeId(safeAlias, true); ctx.append(' ' + escapedFullAlias); } } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWJzdHJhY3RTcWxEaWFsZWN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2RpYWxlY3QvYWJzdHJhY3RTcWxEaWFsZWN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUM3QyxPQUFPLEVBWUwsUUFBUSxHQWdCVCxNQUFNLGtCQUFrQixDQUFDO0FBRTFCLE9BQU8sRUFDTCxZQUFZLEVBQ1osbUJBQW1CLEVBRW5CLFdBQVcsRUFDWCxZQUFZLEVBQ1osZUFBZSxFQUNmLGtCQUFrQixFQUNsQixVQUFVLEVBQ1YscUJBQXFCLEVBQ3JCLFlBQVksRUFDWixPQUFPLEVBQ1AsT0FBTyxFQUNQLG9CQUFvQixFQUNwQixHQUFHLEdBQ0osTUFBTSxrQkFBa0IsQ0FBQztBQUUxQixPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDdkQsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBRXBELE1BQU0sT0FBZ0Isa0JBQW1CLFNBQVEsZUFBZTtJQUduRDtJQUNBO0lBQ0E7SUFDQTtJQUxYLFlBQ0UsY0FBK0IsRUFDdEIsZUFBMEIsR0FBRyxFQUM3QiwwQkFBa0MsbUJBQW1CLEVBQ3JELDJCQUFtQyxRQUFRLEVBQzNDLDZCQUFxQyxVQUFVO1FBRXhELEtBQUssQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUxiLGlCQUFZLEdBQVosWUFBWSxDQUFpQjtRQUM3Qiw0QkFBdUIsR0FBdkIsdUJBQXVCLENBQThCO1FBQ3JELDZCQUF3QixHQUF4Qix3QkFBd0IsQ0FBbUI7UUFDM0MsK0JBQTBCLEdBQTFCLDBCQUEwQixDQUFxQjtJQUcxRCxDQUFDO0lBRUQsYUFBYTtRQUNYLE9BQU8sSUFBSSxlQUFlLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDbkMsQ0FBQztJQUVELFFBQVEsQ0FBQyxNQUFpQixFQUFFLEtBQWM7UUFDeEMsTUFBTSxDQUFD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