Spreadsheet-UX op een echte relationele engine

main

Deze repository wordt als momentopname gepubliceerd: een clone bevat de volledige inhoud, maar geen commitgeschiedenis.

3.6 kB Ruw bestand
export interface FunctionSpec {
  name: string;
  kind: 'scalar' | 'aggregate';
  minArgs: number;
  maxArgs: number;
  signature: string;
  description: string;
}

/**
 * The formula surface area. Anything not listed here is rejected at compile
 * time, so a typo never reaches SQLite as a bare function call.
 */
export const FUNCTIONS: FunctionSpec[] = [
  // aggregates — first argument is `table.Column` (or just `table` for COUNT)
  { name: 'SUM', kind: 'aggregate', minArgs: 1, maxArgs: 2, signature: 'SUM(table.Column [, "LinkColumn"])', description: 'Total of a column across linked rows.' },
  { name: 'COUNT', kind: 'aggregate', minArgs: 1, maxArgs: 2, signature: 'COUNT(table [, "LinkColumn"])', description: 'Number of linked rows.' },
  { name: 'AVG', kind: 'aggregate', minArgs: 1, maxArgs: 2, signature: 'AVG(table.Column [, "LinkColumn"])', description: 'Average across linked rows.' },
  { name: 'MIN', kind: 'aggregate', minArgs: 1, maxArgs: 2, signature: 'MIN(table.Column) or MIN(a, b, …)', description: 'Smallest linked value, or smallest of the arguments.' },
  { name: 'MAX', kind: 'aggregate', minArgs: 1, maxArgs: 2, signature: 'MAX(table.Column) or MAX(a, b, …)', description: 'Largest linked value, or largest of the arguments.' },

  // logic
  { name: 'IF', kind: 'scalar', minArgs: 2, maxArgs: 3, signature: 'IF(test, then [, else])', description: 'Branch on a condition.' },
  { name: 'COALESCE', kind: 'scalar', minArgs: 1, maxArgs: 8, signature: 'COALESCE(a, b, …)', description: 'First value that is not empty.' },
  { name: 'ISBLANK', kind: 'scalar', minArgs: 1, maxArgs: 1, signature: 'ISBLANK(value)', description: 'True when the value is empty or null.' },

  // numbers
  { name: 'ROUND', kind: 'scalar', minArgs: 1, maxArgs: 2, signature: 'ROUND(number [, digits])', description: 'Round to the given number of digits.' },
  { name: 'ABS', kind: 'scalar', minArgs: 1, maxArgs: 1, signature: 'ABS(number)', description: 'Absolute value.' },

  // text
  { name: 'CONCAT', kind: 'scalar', minArgs: 1, maxArgs: 8, signature: 'CONCAT(a, b, …)', description: 'Join values into text.' },
  { name: 'UPPER', kind: 'scalar', minArgs: 1, maxArgs: 1, signature: 'UPPER(text)', description: 'Uppercase.' },
  { name: 'LOWER', kind: 'scalar', minArgs: 1, maxArgs: 1, signature: 'LOWER(text)', description: 'Lowercase.' },
  { name: 'TRIM', kind: 'scalar', minArgs: 1, maxArgs: 1, signature: 'TRIM(text)', description: 'Strip surrounding whitespace.' },
  { name: 'LENGTH', kind: 'scalar', minArgs: 1, maxArgs: 1, signature: 'LENGTH(text)', description: 'Number of characters.' },

  // dates
  { name: 'TODAY', kind: 'scalar', minArgs: 0, maxArgs: 0, signature: 'TODAY()', description: "Today's date, as YYYY-MM-DD." },
  { name: 'NOW', kind: 'scalar', minArgs: 0, maxArgs: 0, signature: 'NOW()', description: 'Current UTC timestamp.' },
  { name: 'DATEDIFF', kind: 'scalar', minArgs: 2, maxArgs: 2, signature: 'DATEDIFF(later, earlier)', description: 'Whole days between two dates.' },
  { name: 'YEAR', kind: 'scalar', minArgs: 1, maxArgs: 1, signature: 'YEAR(date)', description: 'Four-digit year.' },
  { name: 'MONTH', kind: 'scalar', minArgs: 1, maxArgs: 1, signature: 'MONTH(date)', description: 'Month number, 1–12.' },
  { name: 'DAY', kind: 'scalar', minArgs: 1, maxArgs: 1, signature: 'DAY(date)', description: 'Day of month.' },
];

export const FUNCTIONS_BY_NAME = new Map(FUNCTIONS.map((f) => [f.name, f]));

/** Aggregates may be interpreted as a rollup over a linked table. */
export const AGGREGATE_NAMES = new Set(
  FUNCTIONS.filter((f) => f.kind === 'aggregate').map((f) => f.name),
);