gristlabs_grist-core/app/gen-server/sqlUtils.ts
Paul Fitzpatrick 5ef889addd (core) move home server into core
Summary: This moves enough server material into core to run a home server.  The data engine is not yet incorporated (though in manual testing it works when ported).

Test Plan: existing tests pass

Reviewers: dsagal

Reviewed By: dsagal

Differential Revision: https://phab.getgrist.com/D2552
2020-07-21 20:39:10 -04:00

91 lines
2.5 KiB
TypeScript

import {DatabaseType} from 'typeorm';
/**
*
* Generates an expression to simulate postgres's bit_or
* aggregate function in sqlite. The expression is verbose,
* and has a term for each bit in the permission bitmap,
* but this seems ok since sqlite is only used in the dev
* environment.
* @param column: the sql column to aggregate
* @param bits: the maximum number of bits to consider
*
*/
export function sqliteBitOr(column: string, bits: number): string {
const parts: string[] = [];
let mask: number = 1;
for (let b = 0; b < bits; b++) {
parts.push(`((sum(${column}&${mask})>0)<<${b})`);
mask *= 2;
}
return `(${parts.join('+')})`;
}
/**
* Generates an expression to aggregate the named column
* by taking the bitwise-or of all the values it takes on.
* @param dbType: the type of database (sqlite and postgres are supported)
* @param column: the sql column to aggregate
* @param bits: the maximum number of bits to consider (used for sqlite variant)
*/
export function bitOr(dbType: DatabaseType, column: string, bits: number): string {
switch (dbType) {
case 'postgres':
return `bit_or(${column})`;
case 'sqlite':
return sqliteBitOr(column, bits);
default:
throw new Error(`bitOr not implemented for ${dbType}`);
}
}
/**
* Convert a json value returned by the database into a javascript
* object. For postgres, the value is already unpacked, but for sqlite
* it is a string.
*/
export function readJson(dbType: DatabaseType, selection: any) {
switch (dbType) {
case 'postgres':
return selection;
case 'sqlite':
return JSON.parse(selection);
default:
throw new Error(`readJson not implemented for ${dbType}`);
}
}
export function now(dbType: DatabaseType) {
switch (dbType) {
case 'postgres':
return 'now()';
case 'sqlite':
return "datetime('now')";
default:
throw new Error(`now not implemented for ${dbType}`);
}
}
// Understands strings like: "-30 days" or "1 year"
export function fromNow(dbType: DatabaseType, relative: string) {
switch (dbType) {
case 'postgres':
return `(now() + interval '${relative}')`;
case 'sqlite':
return `datetime('now','${relative}')`;
default:
throw new Error(`fromNow not implemented for ${dbType}`);
}
}
export function datetime(dbType: DatabaseType) {
switch (dbType) {
case 'postgres':
return 'timestamp with time zone';
case 'sqlite':
return "datetime";
default:
throw new Error(`now not implemented for ${dbType}`);
}
}