You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
gristlabs_grist-core/app/gen-server/sqlUtils.ts

91 lines
2.5 KiB

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}`);
}
}