@lcap/nasl-parser
Version:
Take Nasl text to Nasl AST with the help of generalized parsing.
362 lines • 15.2 kB
JavaScript
;
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