deno.land / x / pg_mem@2.8.1 / interfaces.ts

نووسراو ببینە
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
import { TableConstraint, CreateColumnDef, NodeLocation, DataTypeDef, FunctionArgumentMode, BinaryOperator, Statement } from 'https://deno.land/x/pgsql_ast_parser@12.0.1/mod.ts';import { MigrationParams } from './migrate/migrate-interfaces.ts';

export type nil = undefined | null;
export type Schema = { name: string; fields: SchemaField[]; constraints?: TableConstraint[];}

export interface SchemaField extends Omit<CreateColumnDef, 'dataType' | 'kind' | 'name'> { type: IType | DataType; name: string; serial?: boolean;}
export interface IType { /** Data type */ readonly primary: DataType; readonly name: string; toString(): string;
/** Create an array type of this type */ asArray(): IType;}
// todo support all types https://www.postgresql.org/docs/9.5/datatype.htmlexport enum DataType {
inet = 'inet', record = 'record', uuid = 'uuid', text = 'text', citext = 'citext', array = 'array', list = 'list', bigint = 'bigint', float = 'float', decimal = 'decimal', integer = 'integer', jsonb = 'jsonb', regtype = 'regtype', regclass = 'regclass', json = 'json', bytea = 'bytea', interval = 'interval', timestamp = 'timestamp', timestamptz = 'timestamptz', date = 'date', time = 'time', timetz = 'timetz', null = 'null', bool = 'bool',
point = 'point', line = 'line', lseg = 'lseg', box = 'box', path = 'path', polygon = 'polygon', circle = 'circle',}
export interface MemoryDbOptions { /** * If set to true, pg-mem will stop embbeding info about the SQL statement * that has failed in exception messages. */ noErrorDiagnostic?: boolean; /** * If set to true, then the query runner will not check that no AST part * has been left behind when parsing the request. * * ... so setting it to true could lead to unnoticed ignored query parts. * * (advice: only set it to true as a workaround while an issue on https://github.com/oguimbal/pg-mem is being fixed... ) */ noAstCoverageCheck?: boolean; /** * If set to true, this will throw an exception if * you try to use an unsupported index type * (only BTREE is supported at time of writing) */ noIgnoreUnsupportedIndices?: boolean; /** * When set to true, this will auto create an index on foreign table when adding a foreign key. * 👉 Recommanded when using Typeorm .synchronize(), which creates foreign keys but not indices ! **/ readonly autoCreateForeignKeyIndices?: boolean;}
export interface IMemoryDb { /** * Adapters to create wrappers of this db compatible with known libraries */ readonly adapters: LibAdapters; /** * The default 'public' schema */ readonly public: ISchema; /** * Get an existing schema */ getSchema(db?: string | null): ISchema; /** * Create a schema in this database */ createSchema(name: string): ISchema; /** * Get a table to inspect it (in the public schema... this is a shortcut for db.public.getTable()) */ getTable<T = any>(table: string): IMemoryTable<T>; getTable<T = any>(table: string, nullIfNotFound?: boolean): IMemoryTable<T> | null;
/** Subscribe to a global event */ on(event: 'query', handler: (query: string) => any): ISubscription; on(event: GlobalEvent, handler: () => any): ISubscription; on(event: GlobalEvent, handler: () => any): ISubscription; /** Subscribe to an event on all tables */ on(event: TableEvent, handler: (table: string) => any): ISubscription;
/** * Creates a restore point. * 👉 This operation is O(1) (instantaneous, even with millions of records). * */ backup(): IBackup;
/** * Registers an extension (that can be installed using the 'create extension' statement) * @param name Extension name * @param install How to install this extension on a given schema */ registerExtension(name: string, install: (schema: ISchema) => void): this;
/** Registers a new language, usable in 'DO' blocks, or in 'CREATE FUNCTION' blocks */ registerLanguage(languageName: string, compiler: LanguageCompiler): this;}
export type QueryInterceptor = (query: string) => any[] | nil;

export type ArgDef = DataType | IType | ArgDefDetails;
export interface ArgDefDetails { /** Argument type */ type: IType; /** Optional argument name */ name?: string; /** * Arguments are 'in' by default, but you can change that. */ mode?: FunctionArgumentMode;}
export type LanguageCompiler = (options: ToCompile) => CompiledFunction;
export interface ToCompile { /** Function being compiled (null for "DO" statements compilations) */ functionName?: string | nil; /** Code to compile */ code: string; /** Schema against which this compilation is performed */ schema: ISchema; /** Expected arguments */ args: ArgDefDetails[]; /** Expected return type (if any) */ returns?: IType | nil;}
export class AdvancedResult { constructor(readonly result: any, outArgs: any[]) { }}
export type CompiledFunction = (...inArguments: any[]) => AdvancedResult | PlainResult;
export type PlainResult = Object | number | Date | null | void;
export interface CompiledFunctionResult { /** The function result, if function "returns" something */ result?: any; /** The functions out arguments, as indexed in the `args` passed to your language compiler function */ outArgs?: any[];}
export interface IBackup { /** * Restores data to the state when this backup has been performed. * 👉 This operation is O(1). * 👉 Schema must not have been changed since then ! **/ restore(): void;}
export interface LibAdapters { /** Create a PG module that will be equivalent to require('pg') */ createPg(queryLatency?: number): { Pool: any; Client: any };
/** Create a pg-promise instance bound to this db */ createPgPromise(queryLatency?: number): any;
/** Create a slonik pool bound to this db */ createSlonik(queryLatency?: number): any;
/** Create a pg-native instance bound to this db */ createPgNative(queryLatency?: number): any;
/** Create a Typeorm connection bound to this db * @deprecated Use `createTypeormDataSource` instead. See https://github.com/oguimbal/pg-mem/pull/238. */ createTypeormConnection(typeOrmConnection: any, queryLatency?: number): any;
/** Create a Typeorm data source bound to this db */ createTypeormDataSource(typeOrmConnection: any, queryLatency?: number): any;
/** Create a Knex.js instance bound to this db */ createKnex(queryLatency?: number, knexConfig?: object): any;
/** Create a Kysely instance bound to this db */ createKysely(queryLatency?: number, kyselyConfig?: object): any;
/** Create a mikro-orm instance bound to this db */ createMikroOrm(mikroOrmOptions: any, queryLatency?: number): Promise<any>}
export type QueryOrAst = string | Statement | Statement[];
export interface ISchema { /** * Execute a query and return many results */ many(query: QueryOrAst): any[]; /** * Execute a query without results */ none(query: QueryOrAst): void; /** * Execute a query with a single result */ one(query: QueryOrAst): any; /** * Another way to create tables (equivalent to "create table" queries") */ declareTable(table: Schema): IMemoryTable; /** * Execute a query */ query(text: QueryOrAst): QueryResult;

/** * Progressively executes a query, yielding results until the end of enumeration (or an exception) */ queries(text: QueryOrAst): Iterable<QueryResult>;
/** * Get a table in this db to inspect it */ getTable(table: string): IMemoryTable; getTable(table: string, nullIfNotFound?: boolean): IMemoryTable | null;
/** * List all tables in this schema */ listTables(): Iterable<IMemoryTable>
/** Register a function */ registerFunction(fn: FunctionDefinition, orReplace?: boolean): this;

/** Register a binary operator */ registerOperator(fn: OperatorDefinition): this;
/** Register a simple type, which is equivalent to another */ registerEquivalentType(type: IEquivalentType): IType;
/** Get an existing type */ getType(name: DataType): IType;
/** * Registers an enum type on this schema * @param name Enum name * @param values Possible values */ registerEnum(name: string, values: string[]): void;
/** * Database migration, node-sqlite flavor * ⚠ Only working when runnin nodejs ! */ migrate(config?: MigrationParams): Promise<void>;

/** * Intecept queries. * If your interceptor returns an array, then the query will not be executed. * The given result will be returned instead. */ interceptQueries(interceptor: QueryInterceptor): ISubscription;}
export interface FunctionDefinition { /** Function name (casing doesnt matter) */ name: string;
/** Expected arguments */ args?: ArgDef[] | nil;
/** Other arguments type (variadic arguments) */ argsVariadic?: DataType | IType | nil;
/** Returned data type */ returns?: DataType | IType | nil;
/** * If the function is marked as impure, it will not be simplified * (ex: "select myFn(1) from myTable" will call myFn() for each row in myTable, even if it does not depend on its result) */ impure?: boolean;
/** If true, the function will also be called when passing null arguments */ allowNullArguments?: boolean;
/** Actual implementation of the function */ implementation: CompiledFunction;}
export interface OperatorDefinition { /** Function name (casing doesnt matter) */ operator: BinaryOperator;
/** Expected left argument */ left: DataType | IType;
/** Expected right argument */ right: DataType | IType;
/** True if the operator is commutative (if left & right can be inverted) */ commutative?: boolean;
/** Returned data type */ returns: DataType | IType;
/** * If the function is marked as impure, it will not be simplified * (ex: "select myFn(1) from myTable" will call myFn() for each row in myTable, even if it does not depend on its result) */ impure?: boolean;
/** If true, the function will also be called when passing null arguments */ allowNullArguments?: boolean;
/** Actual implementation of the function */ implementation: CompiledFunction;}

export interface QueryResult { /** Last command that has been executed */ command: string; rowCount: number; fields: Array<FieldInfo>; rows: any[];
/** Location of the last ";" prior to this statement */ location: NodeLocation;}
export interface FieldInfo { name: string; type: DataType;}


export type TableEvent = 'seq-scan';export type GlobalEvent = 'query' | 'query-failed' | 'catastrophic-join-optimization' | 'schema-change' | 'create-extension';
export interface IMemoryTable<T = unknown> { readonly name: string; readonly primaryIndex: IndexDef | nil;
/** List columns in this table */ getColumns(): Iterable<ColumnDef>;
/** Subscribe to an event on this table */ on(event: TableEvent, handler: () => any): ISubscription; /** List existing indices defined on this table */ listIndices(): IndexDef[];

/** * Inserts a raw item into this table. * ⚠ Neither the record you provided, nor the returned value are the actual item stored. You wont be able to mutate internal state. * @returns A copy of the inserted item (with assigned defaults) */ insert(item: Partial<T>): T | null;
/** Find all items matching a specific template */ find(template?: Partial<T> | nil, columns?: (keyof T)[]): Iterable<T>;}

export interface ColumnDef { readonly name: string; readonly type: IType; readonly nullable: boolean;}

export interface ISubscription { unsubscribe(): void;}
export interface IndexDef { readonly name: string; readonly expressions: string[];}
export class NotSupported extends Error { constructor(what?: string) { super('🔨 Not supported 🔨 ' + (what ? ': ' + what : '')); }
static never(value: never, msg?: string) { return new NotSupported(`${msg ?? ''} ${JSON.stringify(value)}`); }}

interface ErrorData { readonly error: string; readonly details?: string; readonly hint?: string; readonly code?: string;}export class QueryError extends Error { readonly data: ErrorData; readonly code: string | undefined; constructor(err: string | ErrorData, code?: string) { super(typeof err === 'string' ? err : errDataToStr(err)); if (typeof err === 'string') { this.data = { error: err, code }; this.code = code; } else { this.data = err; this.code = err.code; } }}
function errDataToStr(data: ErrorData) { const ret = ['ERROR: ' + data.error]; if (data.details) { ret.push('DETAIL: ' + data.details); } if (data.hint) { ret.push('HINT: ' + data.hint) } return ret.join('\n');}

export class CastError extends QueryError { constructor(from: string | DataType | IType, to: string | DataType | IType, inWhat?: string) { super(`cannot cast type ${typeof from === 'string' ? from : from.name} to ${typeof to === 'string' ? to : to.name}` + (inWhat ? ' in ' + inWhat : '')); }}

export class ColumnNotFound extends QueryError { constructor(col: string) { super(`column "${col}" does not exist`); }}
export class AmbiguousColumn extends QueryError { constructor(col: string) { super(`column reference "${col}" is ambiguous`); }}
export class RelationNotFound extends QueryError { constructor(tableName: string) { super(`relation "${tableName}" does not exist`); }}export class TypeNotFound extends QueryError { constructor(t: string | number | DataTypeDef) { super(`type "${typeof t !== 'object' ? t : typeDefToStr(t)}" does not exist`); }}
export class RecordExists extends QueryError { constructor() { super('Records already exists'); }}

export class PermissionDeniedError extends QueryError { constructor(what?: string) { super(what ? `permission denied: "${what}" is a system catalog` : 'permission denied'); }}

export function typeDefToStr(t: DataTypeDef): string { if (t.kind === 'array') { return typeDefToStr(t.arrayOf) + '[]'; } let ret = t.name; if (t.schema) { ret = t.schema + '.' + ret; } if (t.config?.length) { ret = ret + '(' + t.config.join(',') + ')'; } return ret;}
/** A type definition that is equivalent to another type */export interface IEquivalentType { /** Type name */ readonly name: string; /** Which underlying type is it equivalent to ? */ readonly equivalentTo: DataType | IType; /** * Is this value valid ? */ isValid(value: any): boolean;}
pg_mem

Version Info

Tagged at
3 months ago