UNPKG

@eggjs/dal-runtime

Version:
310 lines (302 loc) 20.3 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.BaseSqlMapGenerator = void 0; const lodash_1 = __importDefault(require("lodash")); const tegg_types_1 = require("@eggjs/tegg-types"); const TemplateUtil_1 = require("./TemplateUtil"); class BaseSqlMapGenerator { constructor(tableModel, logger) { this.tableModel = tableModel; this.logger = logger; } generateAllColumns(countIf) { const str = this.tableModel.columns.map(t => `\`${t.columnName}\``) .join(','); return countIf ? `{% if $$count == true %}0{% else %}${str}{% endif %}` : str; } generateFindByPrimary() { const result = []; const primary = this.tableModel.getPrimary(); if (!primary) { this.logger.warn(`表 \`${this.tableModel.name}\` 没有主键,无法生成主键查询语句。`); return result; } let sql = `SELECT ${this.generateAllColumns(true)} FROM \`${this.tableModel.name}\` WHERE `; sql += primary.keys.map(indexKey => `\`${indexKey.columnName}\` = {{$${indexKey.propertyName}}}`) .join(' AND '); if (primary.keys.length === 1) { result.push({ type: tegg_types_1.SqlType.SELECT, name: `findBy${lodash_1.default.upperFirst(primary.keys[0].propertyName)}`, sql, }); } result.push({ name: 'findByPrimary', type: tegg_types_1.SqlType.SELECT, sql, }); return result; } // TODO index 的左匹配 generateFindByIndexes() { const sqlMaps = []; for (const index of this.tableModel.indices) { if (index.type === tegg_types_1.IndexType.PRIMARY) continue; let sql = `SELECT ${this.generateAllColumns(true)} FROM \`${this.tableModel.name}\` WHERE `; sql += index.keys.map(indexKey => { const s = `\`${indexKey.columnName}\` {{ "IS" if $${indexKey.propertyName} == null else "=" }} {{$${indexKey.propertyName}}}`; return s; }) .join(' AND '); const tempName = lodash_1.default.upperFirst(lodash_1.default.camelCase(index.keys.length === 1 ? index.keys[0].propertyName : index.name)); sqlMaps.push({ name: `findBy${tempName}`, type: tegg_types_1.SqlType.SELECT, sql, }); sqlMaps.push({ name: `findOneBy${tempName}`, type: tegg_types_1.SqlType.SELECT, sql: `${sql} LIMIT 0, 1`, }); } return sqlMaps; } generateInsert() { let sql = `INSERT INTO \`${this.tableModel.name}\` `; sql += '{% set ___first = true %}'; const keys = []; const values = []; for (const column of this.tableModel.columns) { const { propertyName, columnName, type } = column; if (column.propertyName !== 'gmtCreate' && column.propertyName !== 'gmtModified') { // Add filter for Spatial Type // - toPoint // - toLine // - toPolygon // - toGeometry // - toMultiPoint // - toMultiLine // - toMultiPolygon // - toGeometryCollection keys.push((` {% if $${propertyName} !== undefined %} {% if ___first %} {% set ___first = false %} {% else %} , {% endif %} \`${columnName}\` {% endif %} `).trim()); if (TemplateUtil_1.TemplateUtil.isSpatialType(column)) { const filter = TemplateUtil_1.TemplateUtil.getSpatialFilter(column.type.type); values.push((` {% if $${propertyName} !== undefined %} {% if ___first %} {% set ___first = false %} {% else %} , {% endif %} {{$${propertyName} | ${filter}}} {% endif %} `).trim()); } else if (column.type.type === tegg_types_1.ColumnType.JSON) { values.push((` {% if $${propertyName} !== undefined %} {% if ___first %} {% set ___first = false %} {% else %} , {% endif %} {{$${propertyName} | toJson}} {% endif %} `).trim()); } else { values.push((` {% if $${propertyName} !== undefined %} {% if ___first %} {% set ___first = false %} {% else %} , {% endif %} {{$${propertyName}}} {% endif %} `).trim()); } } else { let now; // Default value for gmtCreate/gmtModified // int:UNIX_TEIMESTAMP // bigint: ROUND(UNIX_TIMESTAMP(CURTIME(4)) * 1000) // datetime/timestamp Now() if (type.type === tegg_types_1.ColumnType.INT) { // 秒级时间戳 now = 'UNIX_TIMESTAMP()'; } else if (type.type === tegg_types_1.ColumnType.BIGINT) { // 毫秒级时间戳 now = 'ROUND(UNIX_TIMESTAMP(CURTIME(4)) * 1000)'; } else if (type.type === tegg_types_1.ColumnType.DATETIME || type.type === tegg_types_1.ColumnType.TIMESTAMP) { now = type.precision ? `NOW(${type.precision})` : 'NOW()'; } else { this.logger.warn(`unknown type ${type.type} for ${propertyName}`); } keys.push((` {% if ___first %} {% set ___first = false %} {% else %} , {% endif %} \`${columnName}\` `).trim()); values.push((` {% if ___first %} {% set ___first = false %} {% else %} , {% endif %} {{ $${propertyName} if $${propertyName} !== undefined else '${now}' }} `).trim()); } } sql += `(${keys.join('')})`; sql += '{% set ___first = true %}'; sql += `VALUES(${values.join('')});`; return sql; } generateUpdate() { const primary = this.tableModel.getPrimary(); if (!primary) { this.logger.warn(`表 \`${this.tableModel.name}\` 没有主键,无法生成主键更新语句。`); return; } let sql = `UPDATE \`${this.tableModel.name}\` SET`; sql += '{% set ___first = true %}'; const kv = []; for (const column of this.tableModel.columns) { const { type, propertyName, columnName } = column; let now; if (type.type === tegg_types_1.ColumnType.INT) { // 秒级时间戳 now = 'UNIX_TIMESTAMP()'; } else if (type.type === tegg_types_1.ColumnType.BIGINT) { // 毫秒级时间戳 now = 'ROUND(UNIX_TIMESTAMP(CURTIME(4)) * 1000)'; } else if (type.type === tegg_types_1.ColumnType.TIMESTAMP || type.type === tegg_types_1.ColumnType.DATETIME) { now = type.precision ? `NOW(${type.precision})` : 'NOW()'; } // 若无更新时间字段,则自动更新该字段 const temp = propertyName !== 'gmtModified' ? ` {% if $${propertyName} !== undefined %} {% if ___first %} {% set ___first = false %} {% else %} , {% endif %} \`${columnName}\` = {{$${propertyName}}} {% endif %} ` : ` {% if ___first %} {% set ___first = false %} {% else %} , {% endif %} \`${columnName}\` = {{ $${propertyName} if $${propertyName} !== undefined else '${now}' }} `; kv.push(temp); } sql += kv.join(''); sql += `WHERE ${primary.keys.map(indexKey => `\`${indexKey.columnName}\` = {{primary.${indexKey.propertyName}}}`) .join(' AND ')}`; return sql; } generateDelete() { const primary = this.tableModel.getPrimary(); if (!primary) { this.logger.warn(`表 \`${this.tableModel.name}\` 没有主键,无法生成主键删除语句。`); return; } let sql = `DELETE FROM \`${this.tableModel.name}\` WHERE `; sql += primary.keys.map(indexKey => `\`${indexKey.columnName}\` = {{${indexKey.propertyName}}}`) .join(' AND '); return sql; } load() { const map = {}; map.allColumns = { type: tegg_types_1.SqlType.BLOCK, content: this.generateAllColumns(false), }; const sqlMaps = [ /** * 以主键进行索引 * * + `findByPrimary` * + 若为单主键,则再加 `findBy键名` */ ...this.generateFindByPrimary(), /** * findBy 各索引 * * + 若为多列索引,则为 `findBy索引名` * + 若为单列索引,则为 `findBy列名` */ ...this.generateFindByIndexes(), /** * 插入 */ { name: 'insert', type: tegg_types_1.SqlType.INSERT, sql: this.generateInsert(), }, /** * 主键更新 */ { name: 'update', type: tegg_types_1.SqlType.UPDATE, sql: this.generateUpdate(), }, /** * 主键删除 */ { name: 'delete', type: tegg_types_1.SqlType.DELETE, sql: this.generateDelete(), }, ]; for (const sqlMap of sqlMaps) { map[sqlMap.name] = { type: sqlMap.type, sql: sqlMap.sql, }; } return map; } } exports.BaseSqlMapGenerator = BaseSqlMapGenerator; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQmFzZVNxbE1hcC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9CYXNlU3FsTWFwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLG9EQUF1QjtBQUV2QixrREFBMkU7QUFFM0UsaURBQThDO0FBRTlDLE1BQWEsbUJBQW1CO0lBSTlCLFlBQVksVUFBc0IsRUFBRSxNQUFjO1FBQ2hELElBQUksQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFDO1FBQzdCLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO0lBQ3ZCLENBQUM7SUFFRCxrQkFBa0IsQ0FBQyxPQUFnQjtRQUNqQyxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxVQUFVLElBQUksQ0FBQzthQUNoRSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDYixPQUFPLE9BQU8sQ0FBQyxDQUFDLENBQUMsc0NBQXNDLEdBQUcsYUFBYSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUM7SUFDaEYsQ0FBQztJQUVELHFCQUFxQjtRQUNuQixNQUFNLE1BQU0sR0FBMEIsRUFBRSxDQUFDO1FBQ3pDLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDN0MsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2IsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUkscUJBQXFCLENBQUMsQ0FBQztZQUNuRSxPQUFPLE1BQU0sQ0FBQztRQUNoQixDQUFDO1FBRUQsSUFBSSxHQUFHLEdBQUcsVUFBVSxJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDO3dCQUM3QixJQUFJLENBQUMsVUFBVSxDQUFDLElBQUk7c0JBQ3RCLENBQUM7UUFFbkIsR0FBRyxJQUFJLE9BQU8s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