UNPKG

arquero

Version:

Query processing and transformation of array-backed data tables.

65 lines (59 loc) 2.25 kB
import { codegen } from './codegen.js'; import { parse } from './parse.js'; import { aggregate } from '../verbs/reduce/util.js'; // generate code to compare a single field const _compare = (u, v, lt, gt) => `((u = ${u}) < (v = ${v}) || u == null) && v != null ? ${lt} : (u > v || v == null) && u != null ? ${gt} : ((v = v instanceof Date ? +v : v), (u = u instanceof Date ? +u : u)) !== u && v === v ? ${lt} : v !== v && u === u ? ${gt} : `; const _collate = (u, v, lt, gt, f) => `(v = ${v}, (u = ${u}) == null && v == null) ? 0 : v == null ? ${gt} : u == null ? ${lt} : (u = ${f}(u,v)) ? u : `; export function compare(table, fields) { // parse expressions, generate code for both a and b values const names = []; const exprs = []; const fn = []; let keys = null, opA = '0', opB = '0'; if (table.isGrouped()) { keys = table.groups().keys; opA = 'ka'; opB = 'kb'; } const { ops } = parse(fields, { table, value: (name, node) => { names.push(name); if (node.escape) { // if an escaped function, invoke it directly const f = i => `fn[${fn.length}](${i}, data)`; exprs.push([f('a'), f('b')]); fn.push(node.escape); } else { // generate code to extract values to compare exprs.push([ codegen(node, { index: 'a', op: opA }), codegen(node, { index: 'b', op: opB }) ]); } }, window: false }); // calculate aggregate values if needed const result = aggregate(table, ops); const op = (id, row) => result[id][row]; // generate comparison code for each field const n = names.length; let code = 'return (a, b) => {' + (op && table.isGrouped() ? 'const ka = keys[a], kb = keys[b];' : '') + 'let u, v; return '; for (let i = 0; i < n; ++i) { const field = fields.get(names[i]); const o = field.desc ? -1 : 1; const [u, v] = exprs[i]; if (field.collate) { code += _collate(u, v, -o, o, `${o < 0 ? '-' : ''}fn[${fn.length}]`); fn.push(field.collate); } else { code += _compare(u, v, -o, o); } } code += '0;};'; // instantiate and return comparator function return Function('op', 'keys', 'fn', 'data', code)(op, keys, fn, table.data()); }