UNPKG

@lcap/nasl-parser

Version:

Take Nasl text to Nasl AST with the help of generalized parsing.

362 lines 15.2 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.toNaslSqlGroupBy = exports.toNaslCallQueryOrderBy = exports.collapseSqlJoinCondProp = exports.toNaslQJExpr = exports.mkSelVProp = exports.mkNamedProp = exports.handleSqlMultiProp = exports.toNaslQueryFieldExpr = exports.handleSqlSingleProp = exports.toNaslCallQueryComponentImpl = void 0; const nasl = __importStar(require("@lcap/nasl")); const common_util_1 = require("./common-util"); const util_1 = require("util"); /** * 现在 IDE 的可视化数据查询 * - 压根就不支持别名 */ const isSqlSingleProp = (e) => e?.cst['__type'] === 'SqlSingleProp'; const isSqlMultiProp = (e) => e?.cst['__type'] === 'SqlMultiProp'; let entityNameEnv = null; const sqlPartsToMap = (arrObjs) => { const m = {}; arrObjs.forEach(obj => { for (const [key, value] of Object.entries(obj)) { if (m[key]) { m[key].push(value); } else { m[key] = [value]; } } }); return m; }; const toNaslCallQueryComponentImpl = ([from, _heteroParts, finalSelect, pagin]) => { // 据说 sql 的 join where group 可以不连续,骚得很。 // 这里先按只能相邻地写来处理吧。毕竟仅仅是 demo。 const heteroParts = (0, common_util_1.PackNaslAndCstSeq)(_heteroParts.flat()); const partsNasl = sqlPartsToMap(heteroParts.nasl); const partsCst = sqlPartsToMap(heteroParts.cst); entityNameEnv = new Map(); entityNameEnv.set(from.obj, (from.colle)); // joins.forEach(j => { // // console.log(j) // entityNameEnv.set(j.obj, coerceExpressionToShortName(j.collection.expr)) // }) const fm = toNaslCallQueryFrom(from, partsNasl['join']); const ncqc = new nasl.CallQueryComponent({ select: finalSelect?.nasl, from: fm, where: toConjunction(partsNasl['where']), // toNaslCallQueryWhere(head(wheres)), // 第一个啦 groupBy: partsNasl['group'], orderBy: partsNasl['order'], }); entityNameEnv = null; let finalCst = { from, parts: heteroParts.cst, finalSelect: finalSelect.cst, pagination: pagin?.cst }; if (pagin?.nasl) { let res = new nasl.Paginate({ page: pagin.nasl.page, size: pagin.nasl.size, list: ncqc, label: '查询组件分页', }); return (0, common_util_1.PackNaslAndCst)(res, (0, common_util_1.TYPE)('CallQueryComponent', finalCst)); } else { return (0, common_util_1.PackNaslAndCst)(ncqc, (0, common_util_1.TYPE)('CallQueryComponent', finalCst)); } }; exports.toNaslCallQueryComponentImpl = toNaslCallQueryComponentImpl; // function toNaslCallQueryWhere(w) : nasl.LogicItem { // // 先看后面的代码。放在前面,是因为需要先定义后使用。 // const lam1 = (env, node) => { // if (!isMemberExpression(node)) { // return node; // } // let oName; // if (isStringLiteral(node.object)) { // oName = env.get(node?.object?.value) ?? node?.object?.value; // } else if(isIdentifier(node.object)) { // oName = env.get(node?.object?.name) ?? node?.object?.name; // } // let pName; // if (isStringLiteral(node.property)) { // pName = env.get(node?.property?.value) ?? node?.property?.value; // } else if(isIdentifier(node.property)) { // pName = env.get(node?.property?.name) ?? node?.property?.name; // } // if (isStringLiteral(node.object) || isIdentifier(node.object)) { // if (isStringLiteral(node.property) || isIdentifier(node.property)) { // return new nasl.QueryFieldExpression({ // isDotStar: false, // entityAsName: oName, // propertyName: pName, // label: '查询组件实体属性', // }) // } // } // return node; // } // const refineQFE = (env : Map<string, string>, nl : nasl.LogicItem): nasl.LogicItem => { // new Visitor().preOrderVisitAll(env, nl, lam1); // return nl; // } // let nl = dispatchToNaslExpr(w.cond.expr); // // Query 的 where 里的 BinaryExpression 里的 MemberExpression 需要改成 QueryFieldExpression // // 非常,奇葩 // nl = new Visitor().preOrderVisitAll(entityNameEnv, nl, (env, node) => { // if (!node || !isNaslBinaryExpression) { // return node; // } // const nm = node as nasl.BinaryExpression; // if (!['startwith', 'endwith', 'like', 'in'].includes(nm.operator)) { // return nm; // } // return refineQFE(env, nm); // }) // return nl; // } // leaf // SqlSingleProp | SqlMultiProp const handleSqlSingleProp = (rawIdent, sfx) => { const nqse = new nasl.QueryFieldExpression({ isDotStar: false, entityAsName: rawIdent, propertyName: sfx?.nasl?.[0]?.name, // IDE 只支持一级 }); return (0, common_util_1.PackNaslAndCst)(nqse, (0, common_util_1.TYPE)('SqlSingleProp', { rawIdent, suffix: sfx?.cst })); }; exports.handleSqlSingleProp = handleSqlSingleProp; exports.toNaslQueryFieldExpr = exports.handleSqlSingleProp; // return a List const handleSqlMultiProp = (props) => { return (0, common_util_1.PackNaslAndCst)(props.nasl, (0, common_util_1.TYPE)('SqlMultiProp', { props: props.cst })); }; exports.handleSqlMultiProp = handleSqlMultiProp; const mkNamedProp = (prop, alias) => { // alias 是废的,IDE 不支持 // IDE 只支持选取第一层的属性 if (isSqlSingleProp(prop)) { // let nqfe; // if (isMemberExpression(prop.nasl)) { // nqfe = [new nasl.QueryFieldExpression({ // isDotStar: true, // entityAsName: prop.nasl.object.name, // should be alias, // propertyName: prop.nasl.property.name, // })] // } else { // nqfe = [new nasl.QueryFieldExpression({ // isDotStar: false, // entityAsName: prop, // should be alias, // propertyName: null, // })] // } // return PackNaslAndCst(nqfe, TYPE('NamedProp', { prop, alias })) return (0, common_util_1.PackNaslAndCst)([prop.nasl], (0, common_util_1.TYPE)('NamedProp', { prop: [prop.cst], alias })); } if (isSqlMultiProp(prop)) { // IDE 目前不支持嵌套 select(好吧大部分数据库查询也不支持),所以用 flatMap return (0, common_util_1.PackNaslAndCst)(prop.nasl, (0, common_util_1.TYPE)('NamedProp', { prop: prop.cst, alias })); } throw new Error(`selectAliasedProp: ${(0, util_1.inspect)(prop)}`); }; exports.mkNamedProp = mkNamedProp; const mkSelVProp = (name, fields) => { let res; if (fields?.nasl && !(0, common_util_1.isEmpty)(fields.nasl)) { res = fields.nasl.map(field => new nasl.QueryFieldExpression({ isDotStar: false, entityAsName: name, propertyName: field.name, })); } else { res = [new nasl.QueryFieldExpression({ isDotStar: true, entityAsName: name, propertyName: "", })]; } return (0, common_util_1.PackNaslAndCst)(res, (0, common_util_1.TYPE)('SelVProp', { name, fields: fields?.cst })); }; exports.mkSelVProp = mkSelVProp; const toNaslCallQueryFrom = (from, jns) => new nasl.QueryFromExpression({ entityNamespace: "app.dataSources.defaultDS.entities", // DANGEROUS entityName: from.colle, // from.obj is not used joinParts: jns?.length > 0 ? [toRightDenseJoin(jns)] : null }); const toRightDenseJoin = (0, common_util_1.foldR1)((a, acc) => { a['joinParts'] = [acc]; return a; }, common_util_1.identity); // Array<Join> -> Array<nasl.QueryJoinExpression> const toNaslQJExpr = (obj, colle, on) => { const jnNasl = new nasl.QueryJoinExpression({ entityNamespace: "app.dataSources.defaultDS.entities", // DANGEROUS jn.collection ? coerceExpressionToNamespace(jn.collection) : // entityName: entityNameEnv.get(obj), // asName: , joinType: 'INNER', // onExpressions: on?.nasl, joinParts: [] }); return (0, common_util_1.PackNaslAndCst)({ join: jnNasl }, (0, common_util_1.TYPE)('Join', { join: { obj, colle: colle?.cst, on: on?.cst } })); }; exports.toNaslQJExpr = toNaslQJExpr; // -> Array<nasl.BinaryExpression> const collapseSqlJoinCondProp = (l, r) => { if (isSqlSingleProp(l) && isSqlSingleProp(r)) { const nbe = new nasl.BinaryExpression({ left: l.nasl, right: r.nasl, operator: '==', }); const cst = new nasl.BinaryExpression({ left: l.cst, right: r.cst, operator: '==' }); return (0, common_util_1.PackNaslAndCst)([nbe], (0, common_util_1.TYPE)('JoinCond-onExpressions', { 'onExpressions': cst })); } if (isSqlMultiProp(l) && isSqlMultiProp(r)) { if (l.nasl.length !== r.nasl.length) { throw new Error(`join 的条件的结构不一致`); } // let res: Array<nasl.BinaryExpression> = []; const nasls = (0, common_util_1.zipWith)((l1, r1) => new nasl.BinaryExpression({ // @ts-ignore left: l1, // @ts-ignore right: r1, operator: '==', }), l.nasl, r.nasl); const csts = (0, common_util_1.zipWith)((l1, r1) => (0, common_util_1.TYPE)('BinaryExpression', { left: l1, right: r1, op: '==' }), l.cst.props, r.cst.props); return (0, common_util_1.PackNaslAndCst)(nasls, (0, common_util_1.TYPE)('JoinCond-onExpressions', { 'onExpressions': csts })); } throw new Error(`join 的条件的结构不一致`); }; exports.collapseSqlJoinCondProp = collapseSqlJoinCondProp; const toNaslCallQueryOrderBy = ([by, __ord]) => { const ord = __ord[0]; const makeOrd = () => { switch (ord['__type']) { case 'AscOrd': { return new nasl.StringLiteral({ value: 'ASC' }); } case 'DescOrd': { return new nasl.StringLiteral({ value: 'DESC' }); } case 'DynOrd': { const ni = new nasl.Identifier({ name: ord?.ref?.name, }); ni.qName = ord?.ref; return ni; } default: throw new Error(`toNaslCallQueryOrder: ${(0, util_1.inspect)(ord)}`); } }; const nqobe = new nasl.QueryOrderByExpression({ orderElement: by.nasl, order: makeOrd(), label: '查询组件OrderBy元素', }); return (0, common_util_1.PackNaslAndCst)(nqobe, (0, common_util_1.TYPE)('OrderBy', { by: by.cst, ord })); }; exports.toNaslCallQueryOrderBy = toNaslCallQueryOrderBy; const toNaslSqlGroupBy = (by) => { if (isSqlSingleProp(by)) { const nqgbe = [new nasl.QueryGroupByExpression({ groupElement: by.nasl, label: '查询组件GroupBy元素', })]; return (0, common_util_1.PackNaslAndCst)(nqgbe, (0, common_util_1.TYPE)('GroupBy', { by: by.cst })); } if (isSqlMultiProp(by)) { const nasls = by.nasl.map(e => new nasl.QueryGroupByExpression({ groupElement: e, label: '查询组件GroupBy元素', })); return (0, common_util_1.PackNaslAndCst)({ group: nasls }, (0, common_util_1.TYPE)('GroupBy', { group: by?.cst?.props })); } }; exports.toNaslSqlGroupBy = toNaslSqlGroupBy; const toConjunction = (list) => { if (list?.length > 0) { const lam = (l, r) => // @ts-ignore new nasl.BinaryExpression({ left: l, right: r, operator: '&&' }); return (0, common_util_1.foldR1)(lam, common_util_1.identity)(list); } else { return null; } }; // IDE 仅支持 e1 && e2 && ... 这种形式 // function collapseConjunction(e : Expression): Array<nasl.BinaryExpression> { // if (!isBinaryExpression(e)) { // throw new Error(`The current VisualQuery in the IDE only supports predicate as binary expressions\n // collapseConjunction : ${inspect(e)}`) // } // let normL : Array<nasl.BinaryExpression> = []; // let normR : Array<nasl.BinaryExpression> = []; // if (e.operator !== '&&') { // return [dispatchToNaslExpr(e) as nasl.BinaryExpression] // } // if (isBinaryExpression(e.left)) { // normL = collapseConjunction(e.left) // } else { // normL = [dispatchToNaslExpr(e.left) as nasl.BinaryExpression] // } // if (isBinaryExpression(e.right)) { // normR = collapseConjunction(e.right) // } else { // normR = [dispatchToNaslExpr(e.right) as nasl.BinaryExpression] // } // return normL.concat(normR) // } // {x.a, x.b.c} // export const toNaslSqlMultiProp = ([props]) => { // let se = props.nasl.flatMap(toNaslSelectedProp); // const nqse = new nasl.QuerySelectExpression({ // distinct: false, // ??? // star: se.some(e => e.isDotStar), // ??? // selectElements: se.nasl, // }) // return PackNaslAndCst(nqse, TYPE('SqlMultiProp', { props: props.cst })) // } // function toNaslCallQuerySelect(env: Map<string, string>, s) // : nasl.QuerySelectExpression { // if (isSqlSingleProp(s)) { // return // } // if (isSqlMultiProp(s)) { // } // throw new Error(`toNaslCallQuerySelect: ${inspect(s)}`) // } // select a.b, select { a: b.c } 啥的 // const toNaslSelectedProp = // (expr, sfx) => // s : SqlSingleProp | NamedProp res : Array<nasl.QueryFieldExpression> // { // if(isSqlSingleProp(s)) { // return [propToNaslQueryFieldExpr(expr, sfx)] // } // if (isNamedProp(s)) { // return mkNamedProp(expr, sfx) // } // throw new Error(`dispatchToNaslQueryFieldExpr: ${inspect(expr, sfx)}`) // } //# sourceMappingURL=to-nasl-call-query.js.map