@deterministic-code/datasources-postgres 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/PostgresAlterTableStatementRenderer.d.ts +6 -0
- package/dist/PostgresAlterTableStatementRenderer.js +20 -0
- package/dist/PostgresBulkUpdateStatementTextRenderer.d.ts +4 -0
- package/dist/PostgresBulkUpdateStatementTextRenderer.js +24 -0
- package/dist/PostgresCreateRoutineStatementRenderer.d.ts +4 -0
- package/dist/PostgresCreateTableStatementRenderer.d.ts +6 -0
- package/dist/PostgresCreateTableStatementRenderer.js +26 -0
- package/dist/PostgresCreateTriggerStatementRenderer.d.ts +4 -0
- package/dist/PostgresCreateTriggerStatementRenderer.js +13 -0
- package/dist/PostgresDriver.d.ts +16 -0
- package/dist/PostgresDriver.js +75 -0
- package/dist/PostgresDropRoutineStatementRenderer.d.ts +4 -0
- package/dist/PostgresDropRoutineStatementRenderer.js +6 -0
- package/dist/PostgresDropTriggerStatementRenderer.d.ts +4 -0
- package/dist/PostgresDropTriggerStatementRenderer.js +6 -0
- package/dist/PostgresIdentityInsertStatementRenderer.d.ts +4 -0
- package/dist/PostgresIdentityInsertStatementRenderer.js +11 -0
- package/dist/PostgresStatementRenderer.d.ts +19 -0
- package/dist/PostgresStatementRenderer.js +64 -0
- package/dist/PostgresStoredProcedureStatementRenderer.d.ts +10 -0
- package/dist/PostgresStoredProcedureStatementRenderer.js +111 -0
- package/dist/bind.d.ts +7 -0
- package/dist/bind.js +35 -0
- package/dist/columnTypes.d.ts +1 -0
- package/dist/columnTypes.js +10 -0
- package/dist/command.d.ts +14 -0
- package/dist/command.js +92 -0
- package/dist/connection-options.d.ts +6 -0
- package/dist/connection-options.js +1 -0
- package/dist/connection.d.ts +21 -0
- package/dist/connection.js +72 -0
- package/dist/converters/BinaryConverter.d.ts +6 -0
- package/dist/converters/BinaryConverter.js +14 -0
- package/dist/converters/BoolConverter.d.ts +5 -0
- package/dist/converters/BoolConverter.js +5 -0
- package/dist/converters/DateTimeConverter.d.ts +6 -0
- package/dist/converters/DateTimeConverter.js +6 -0
- package/dist/converters/DecimalConverter.d.ts +5 -0
- package/dist/converters/DecimalConverter.js +5 -0
- package/dist/converters/PostgresRowTypeConverters.d.ts +3 -0
- package/dist/converters/PostgresRowTypeConverters.js +19 -0
- package/dist/converters/UuidConverter.d.ts +5 -0
- package/dist/converters/UuidConverter.js +5 -0
- package/dist/i-postgres-driver.d.ts +38 -0
- package/dist/i-postgres-driver.js +22 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/scalar.js +1 -0
- package/dist/transaction.d.ts +9 -0
- package/dist/transaction.js +15 -0
- package/package.json +10 -7
- package/src/PostgresBulkUpdateStatementTextRenderer.ts +0 -27
- package/src/PostgresCreateTableStatementRenderer.ts +0 -33
- package/src/PostgresDriver.ts +0 -55
- package/src/PostgresStatementRenderer.ts +0 -34
- package/src/bind.ts +0 -50
- package/src/columnTypes.ts +0 -10
- package/src/command.ts +0 -129
- package/src/connection-options.ts +0 -7
- package/src/connection.ts +0 -95
- package/src/converters/BinaryConverter.ts +0 -20
- package/src/converters/BoolConverter.ts +0 -6
- package/src/converters/DateTimeConverter.ts +0 -11
- package/src/converters/DecimalConverter.ts +0 -7
- package/src/converters/PostgresRowTypeConverters.ts +0 -24
- package/src/converters/UuidConverter.ts +0 -6
- package/src/i-postgres-driver.ts +0 -61
- package/src/index.ts +0 -1
- package/src/transaction.ts +0 -21
- /package/{src/scalar.ts → dist/scalar.d.ts} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type DatasourceOptions, type ICommand, type IConnection, type IsolationLevelName, type ITransaction } from "@deterministic-code/datasources";
|
|
2
|
+
import type { PostgresConnectionOptions } from "./connection-options.js";
|
|
3
|
+
import { type IPgClient } from "./i-postgres-driver.js";
|
|
4
|
+
export declare class PostgresConnection implements IConnection {
|
|
5
|
+
readonly provider = "postgres";
|
|
6
|
+
url: string;
|
|
7
|
+
schema?: string;
|
|
8
|
+
isOpen: boolean;
|
|
9
|
+
private client?;
|
|
10
|
+
private readonly Client?;
|
|
11
|
+
static from: (options?: DatasourceOptions) => PostgresConnection;
|
|
12
|
+
constructor(options?: PostgresConnectionOptions);
|
|
13
|
+
createCommand: () => ICommand;
|
|
14
|
+
open(): Promise<void>;
|
|
15
|
+
close(): Promise<void>;
|
|
16
|
+
[Symbol.asyncDispose]: () => Promise<void>;
|
|
17
|
+
startTransaction(isolation?: IsolationLevelName): Promise<ITransaction>;
|
|
18
|
+
ensureOpen(): void;
|
|
19
|
+
require(): IPgClient;
|
|
20
|
+
exec(sql: string): Promise<void>;
|
|
21
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { DatasourceError, DatasourceUrlParser, IsolationLevel, StatementTextRenderer, } from "@deterministic-code/datasources";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { PostgresCommand } from "./command.js";
|
|
4
|
+
import { pgClient } from "./i-postgres-driver.js";
|
|
5
|
+
import { PostgresStatementRenderer } from "./PostgresStatementRenderer.js";
|
|
6
|
+
import { PostgresTransaction } from "./transaction.js";
|
|
7
|
+
const require = createRequire(import.meta.url);
|
|
8
|
+
const isoSql = (isolation) => isolation === IsolationLevel.ReadUncommitted
|
|
9
|
+
? "READ UNCOMMITTED"
|
|
10
|
+
: isolation === IsolationLevel.ReadCommitted
|
|
11
|
+
? "READ COMMITTED"
|
|
12
|
+
: isolation === IsolationLevel.RepeatableRead
|
|
13
|
+
? "REPEATABLE READ"
|
|
14
|
+
: "SERIALIZABLE";
|
|
15
|
+
export class PostgresConnection {
|
|
16
|
+
provider = "postgres";
|
|
17
|
+
url;
|
|
18
|
+
schema;
|
|
19
|
+
isOpen = false;
|
|
20
|
+
client;
|
|
21
|
+
Client;
|
|
22
|
+
static from = (options) => {
|
|
23
|
+
const url = options?.DATASOURCE_URL ?? "";
|
|
24
|
+
return new PostgresConnection({
|
|
25
|
+
url,
|
|
26
|
+
schema: DatasourceUrlParser.parse(url)?.schema,
|
|
27
|
+
Client: pgClient(require("pg")),
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
constructor(options = {}) {
|
|
31
|
+
this.url = options.url ?? "";
|
|
32
|
+
this.schema = options.schema;
|
|
33
|
+
this.Client = options.Client;
|
|
34
|
+
}
|
|
35
|
+
createCommand = () => new PostgresCommand(this, new StatementTextRenderer(t => new PostgresStatementRenderer(t)));
|
|
36
|
+
async open() {
|
|
37
|
+
if (this.isOpen)
|
|
38
|
+
throw new DatasourceError("Connection is already open");
|
|
39
|
+
if (!this.client) {
|
|
40
|
+
if (!this.Client)
|
|
41
|
+
throw new DatasourceError("Postgres driver is required");
|
|
42
|
+
this.client = new this.Client({ connectionString: this.url });
|
|
43
|
+
}
|
|
44
|
+
await this.client.connect();
|
|
45
|
+
if (this.schema)
|
|
46
|
+
await this.client.query(`SET search_path TO ${this.schema}`);
|
|
47
|
+
this.isOpen = true;
|
|
48
|
+
}
|
|
49
|
+
async close() {
|
|
50
|
+
await this.client?.end();
|
|
51
|
+
this.client = undefined;
|
|
52
|
+
this.isOpen = false;
|
|
53
|
+
}
|
|
54
|
+
[Symbol.asyncDispose] = () => this.close();
|
|
55
|
+
async startTransaction(isolation = IsolationLevel.Serializable) {
|
|
56
|
+
this.ensureOpen();
|
|
57
|
+
await this.exec(`BEGIN ISOLATION LEVEL ${isoSql(isolation)}`);
|
|
58
|
+
return new PostgresTransaction(this, isolation);
|
|
59
|
+
}
|
|
60
|
+
ensureOpen() {
|
|
61
|
+
if (!this.isOpen)
|
|
62
|
+
throw new DatasourceError("Connection is not open");
|
|
63
|
+
}
|
|
64
|
+
require() {
|
|
65
|
+
if (!this.client)
|
|
66
|
+
throw new DatasourceError("Connection is not open");
|
|
67
|
+
return this.client;
|
|
68
|
+
}
|
|
69
|
+
async exec(sql) {
|
|
70
|
+
await this.require().query(sql);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { TypeConverter, type Cell } from "@deterministic-code/datasources";
|
|
2
|
+
export declare const isBase64: (value: string) => boolean;
|
|
3
|
+
export declare class BinaryConverter extends TypeConverter<Cell, Cell> {
|
|
4
|
+
convert: (from: Cell) => Cell;
|
|
5
|
+
reverseConvert: (to: Cell) => Cell;
|
|
6
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { TypeConverter } from "@deterministic-code/datasources";
|
|
2
|
+
export const isBase64 = (value) => {
|
|
3
|
+
const text = value.trim();
|
|
4
|
+
return (text.length >= 4 &&
|
|
5
|
+
text.length % 4 === 0 &&
|
|
6
|
+
text.includes("=") &&
|
|
7
|
+
/^[A-Za-z0-9+/]+=*$/.test(text) &&
|
|
8
|
+
Buffer.from(text, "base64").toString("base64") === text);
|
|
9
|
+
};
|
|
10
|
+
const bytes = (value) => typeof value === "string" ? Uint8Array.from(Buffer.from(value, "base64")) : value;
|
|
11
|
+
export class BinaryConverter extends TypeConverter {
|
|
12
|
+
convert = (from) => bytes(from);
|
|
13
|
+
reverseConvert = (to) => bytes(to);
|
|
14
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { TypeConverter, type Cell } from "@deterministic-code/datasources";
|
|
2
|
+
export declare const isIsoDate: (value: string) => boolean;
|
|
3
|
+
export declare class DateTimeConverter extends TypeConverter<Cell, Cell> {
|
|
4
|
+
convert: (from: Cell) => Cell;
|
|
5
|
+
reverseConvert: (to: Cell) => Cell;
|
|
6
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { TypeConverter } from "@deterministic-code/datasources";
|
|
2
|
+
export const isIsoDate = (value) => /^\d{4}-\d{2}-\d{2}T/.test(value) && !Number.isNaN(Date.parse(value));
|
|
3
|
+
export class DateTimeConverter extends TypeConverter {
|
|
4
|
+
convert = (from) => typeof from === "string" ? new Date(from) : from;
|
|
5
|
+
reverseConvert = (to) => to instanceof Date ? to.toISOString() : to;
|
|
6
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { BinaryConverter } from "./BinaryConverter.js";
|
|
2
|
+
import { BoolConverter } from "./BoolConverter.js";
|
|
3
|
+
import { DateTimeConverter } from "./DateTimeConverter.js";
|
|
4
|
+
import { DecimalConverter } from "./DecimalConverter.js";
|
|
5
|
+
import { UuidConverter } from "./UuidConverter.js";
|
|
6
|
+
export const PostgresRowTypeConverters = {
|
|
7
|
+
bool: new BoolConverter(),
|
|
8
|
+
datetime: new DateTimeConverter(),
|
|
9
|
+
uuid: new UuidConverter(),
|
|
10
|
+
decimal: new DecimalConverter(),
|
|
11
|
+
binary: new BinaryConverter(),
|
|
12
|
+
};
|
|
13
|
+
export const reverse = (value) => typeof value === "boolean"
|
|
14
|
+
? PostgresRowTypeConverters.bool.reverseConvert(value)
|
|
15
|
+
: value instanceof Date
|
|
16
|
+
? PostgresRowTypeConverters.datetime.reverseConvert(value)
|
|
17
|
+
: value instanceof Uint8Array
|
|
18
|
+
? PostgresRowTypeConverters.binary.reverseConvert(value)
|
|
19
|
+
: value;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Parameter } from "@deterministic-code/datasources";
|
|
2
|
+
import QueryStream from "pg-query-stream";
|
|
3
|
+
import type { Cells, Scalar, Wire } from "./scalar.js";
|
|
4
|
+
export interface PostgresExecuteResult {
|
|
5
|
+
rowsAffected: number;
|
|
6
|
+
result?: Scalar;
|
|
7
|
+
parameters?: Parameter[];
|
|
8
|
+
}
|
|
9
|
+
export interface PgQueryResult {
|
|
10
|
+
rowCount: number | null;
|
|
11
|
+
rows: Cells[];
|
|
12
|
+
}
|
|
13
|
+
export interface IPgClient {
|
|
14
|
+
connect(): Promise<void>;
|
|
15
|
+
query(text: string, values?: Wire[]): Promise<PgQueryResult>;
|
|
16
|
+
rows(text: string, values?: Wire[]): AsyncIterable<Cells>;
|
|
17
|
+
end(): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
interface PgNativeClient {
|
|
20
|
+
connect(): Promise<void>;
|
|
21
|
+
query(text: string, values?: Wire[]): Promise<PgQueryResult>;
|
|
22
|
+
query(query: QueryStream): AsyncIterable<Cells>;
|
|
23
|
+
end(): Promise<void>;
|
|
24
|
+
}
|
|
25
|
+
export type PgClientCtor = new (options: {
|
|
26
|
+
connectionString: string;
|
|
27
|
+
}) => IPgClient;
|
|
28
|
+
type PgNativeCtor = new (options: {
|
|
29
|
+
connectionString: string;
|
|
30
|
+
}) => PgNativeClient;
|
|
31
|
+
export type PgModule = {
|
|
32
|
+
Client: PgNativeCtor;
|
|
33
|
+
default?: {
|
|
34
|
+
Client: PgNativeCtor;
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
export declare const pgClient: (imported: PgModule) => PgClientCtor;
|
|
38
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import QueryStream from "pg-query-stream";
|
|
2
|
+
export const pgClient = (imported) => {
|
|
3
|
+
const Client = imported.default?.Client ?? imported.Client;
|
|
4
|
+
return class {
|
|
5
|
+
inner;
|
|
6
|
+
constructor(options) {
|
|
7
|
+
this.inner = new Client(options);
|
|
8
|
+
}
|
|
9
|
+
connect() {
|
|
10
|
+
return this.inner.connect();
|
|
11
|
+
}
|
|
12
|
+
query(text, values) {
|
|
13
|
+
return this.inner.query(text, values);
|
|
14
|
+
}
|
|
15
|
+
rows(text, values) {
|
|
16
|
+
return this.inner.query(new QueryStream(text, values ?? []));
|
|
17
|
+
}
|
|
18
|
+
end() {
|
|
19
|
+
return this.inner.end();
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { PostgresDriver } from "./PostgresDriver.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { PostgresDriver } from "./PostgresDriver.js";
|
package/dist/scalar.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type ITransaction, type IsolationLevelName } from "@deterministic-code/datasources";
|
|
2
|
+
import type { PostgresConnection } from "./connection.js";
|
|
3
|
+
export declare class PostgresTransaction implements ITransaction {
|
|
4
|
+
readonly connection: PostgresConnection;
|
|
5
|
+
readonly isolation: IsolationLevelName;
|
|
6
|
+
constructor(connection: PostgresConnection, isolation?: IsolationLevelName);
|
|
7
|
+
commit(): Promise<void>;
|
|
8
|
+
abort(): Promise<void>;
|
|
9
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { IsolationLevel, } from "@deterministic-code/datasources";
|
|
2
|
+
export class PostgresTransaction {
|
|
3
|
+
connection;
|
|
4
|
+
isolation;
|
|
5
|
+
constructor(connection, isolation = IsolationLevel.ReadCommitted) {
|
|
6
|
+
this.connection = connection;
|
|
7
|
+
this.isolation = isolation;
|
|
8
|
+
}
|
|
9
|
+
async commit() {
|
|
10
|
+
await this.connection.exec("COMMIT");
|
|
11
|
+
}
|
|
12
|
+
async abort() {
|
|
13
|
+
await this.connection.exec("ROLLBACK");
|
|
14
|
+
}
|
|
15
|
+
}
|
package/package.json
CHANGED
|
@@ -1,21 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deterministic-code/datasources-postgres",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"main": "./
|
|
6
|
-
"types": "./
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"types": "./dist/index.d.js",
|
|
7
7
|
"exports": {
|
|
8
|
-
".":
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.js",
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"default": "./dist/index.js"
|
|
12
|
+
}
|
|
9
13
|
},
|
|
10
14
|
"files": [
|
|
11
|
-
"
|
|
15
|
+
"dist"
|
|
12
16
|
],
|
|
13
17
|
"publishConfig": {
|
|
14
18
|
"access": "public"
|
|
15
19
|
},
|
|
16
|
-
"license": "MIT",
|
|
17
20
|
"dependencies": {
|
|
18
|
-
"@deterministic-code/datasources": "^0.1.
|
|
21
|
+
"@deterministic-code/datasources": "^0.1.2",
|
|
19
22
|
"@types/pg": "^8.15.5",
|
|
20
23
|
"pg": "^8.16.0",
|
|
21
24
|
"pg-query-stream": "^4.17.0"
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { BulkUpdateStatementTextRenderer, type Cell } from "@deterministic-code/datasources";
|
|
2
|
-
import { columnTypes } from "./columnTypes.ts";
|
|
3
|
-
import { isBase64 } from "./converters/BinaryConverter.ts";
|
|
4
|
-
import { isIsoDate } from "./converters/DateTimeConverter.ts";
|
|
5
|
-
|
|
6
|
-
const logical = (value: Cell): string | undefined =>
|
|
7
|
-
value === null
|
|
8
|
-
? undefined
|
|
9
|
-
: typeof value === "boolean"
|
|
10
|
-
? "bool"
|
|
11
|
-
: typeof value === "bigint" || (typeof value === "number" && Number.isInteger(value))
|
|
12
|
-
? "int"
|
|
13
|
-
: typeof value === "number"
|
|
14
|
-
? "float"
|
|
15
|
-
: value instanceof Date || (typeof value === "string" && isIsoDate(value))
|
|
16
|
-
? "datetime"
|
|
17
|
-
: value instanceof Uint8Array || (typeof value === "string" && isBase64(value))
|
|
18
|
-
? "binary"
|
|
19
|
-
: "string";
|
|
20
|
-
|
|
21
|
-
export class PostgresBulkUpdateStatementTextRenderer extends BulkUpdateStatementTextRenderer {
|
|
22
|
-
protected override cell = (column: string, index: number, value: Cell): string => {
|
|
23
|
-
const type = logical(value);
|
|
24
|
-
const sql = type ? columnTypes[type] : undefined;
|
|
25
|
-
return sql ? `$${column}__${index}::${sql} AS ${column}` : `$${column}__${index} AS ${column}`;
|
|
26
|
-
};
|
|
27
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ColumnDefault,
|
|
3
|
-
CreateTableStatementTextRenderer,
|
|
4
|
-
type Column,
|
|
5
|
-
} from "@deterministic-code/datasources";
|
|
6
|
-
import { PostgresRowTypeConverters } from "./converters/PostgresRowTypeConverters.ts";
|
|
7
|
-
import { columnTypes } from "./columnTypes.ts";
|
|
8
|
-
|
|
9
|
-
export class PostgresCreateTableStatementRenderer extends CreateTableStatementTextRenderer {
|
|
10
|
-
protected typeName(column: Column): string {
|
|
11
|
-
return columnTypes[column.type] ?? column.type;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
protected columnDefault(column: Column): string {
|
|
15
|
-
const literal = sqlLiteral(column);
|
|
16
|
-
const value = column.default;
|
|
17
|
-
return value == null || literal == null
|
|
18
|
-
? super.columnDefault(column)
|
|
19
|
-
: super.columnDefault({ ...column, default: new ColumnDefault(literal, value.name) });
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
protected identity(column: Column): string {
|
|
23
|
-
return column.identity ? " GENERATED BY DEFAULT AS IDENTITY" : "";
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function sqlLiteral(column: Column): string | undefined {
|
|
28
|
-
const raw = column.default?.value;
|
|
29
|
-
const converter = PostgresRowTypeConverters[column.type];
|
|
30
|
-
if (raw == null || !converter || !/^-?\d+$/.test(raw)) return undefined;
|
|
31
|
-
const converted = converter.convert(Number(raw));
|
|
32
|
-
return converted === true ? "TRUE" : converted === false ? "FALSE" : undefined;
|
|
33
|
-
}
|
package/src/PostgresDriver.ts
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
DatasourceError,
|
|
3
|
-
StatementTextRenderer,
|
|
4
|
-
type Cell,
|
|
5
|
-
type DatasourceOptions,
|
|
6
|
-
type ICommand,
|
|
7
|
-
type IConnection,
|
|
8
|
-
type IDriver,
|
|
9
|
-
type Information,
|
|
10
|
-
type ITransaction,
|
|
11
|
-
type IsolationLevel,
|
|
12
|
-
type TypeConverter,
|
|
13
|
-
} from "@deterministic-code/datasources";
|
|
14
|
-
import { PostgresConnection } from "./connection.ts";
|
|
15
|
-
import { PostgresCommand } from "./command.ts";
|
|
16
|
-
import { PostgresTransaction } from "./transaction.ts";
|
|
17
|
-
import { PostgresRowTypeConverters } from "./converters/PostgresRowTypeConverters.ts";
|
|
18
|
-
import { PostgresStatementRenderer } from "./PostgresStatementRenderer.ts";
|
|
19
|
-
import { columnTypes } from "./columnTypes.ts";
|
|
20
|
-
|
|
21
|
-
export { columnTypes };
|
|
22
|
-
|
|
23
|
-
const statements = new StatementTextRenderer(t => new PostgresStatementRenderer(t));
|
|
24
|
-
|
|
25
|
-
export class PostgresDriver implements IDriver {
|
|
26
|
-
readonly statementRenderer = statements;
|
|
27
|
-
readonly information: Information = {
|
|
28
|
-
descriptions: [
|
|
29
|
-
"PostgreSQL server driver.",
|
|
30
|
-
"Full connection, command, transaction, and repository support.",
|
|
31
|
-
],
|
|
32
|
-
overrides: [
|
|
33
|
-
"Overrides SelectInsertedIdStatement to SELECT lastval() AS {column}",
|
|
34
|
-
"Overrides CreateTableStatement identity to GENERATED BY DEFAULT AS IDENTITY",
|
|
35
|
-
"Overrides CreateTableStatement boolean defaults (0/1 → TRUE/FALSE)",
|
|
36
|
-
"Overrides CreateTableStatement type mapping (int→INTEGER, uuid→UUID, string→TEXT, bool→BOOLEAN, decimal→NUMERIC, float→DOUBLE PRECISION, datetime→TIMESTAMPTZ, binary→BYTEA)",
|
|
37
|
-
],
|
|
38
|
-
changeLogs: [],
|
|
39
|
-
};
|
|
40
|
-
rowTypeConverters: Record<string, TypeConverter<Cell, Cell>> = PostgresRowTypeConverters;
|
|
41
|
-
columnType = (name: string): string =>
|
|
42
|
-
columnTypes[name] ??
|
|
43
|
-
(() => {
|
|
44
|
-
throw new DatasourceError(`Unknown postgres type "${name}"`);
|
|
45
|
-
})();
|
|
46
|
-
connection = (options?: DatasourceOptions): IConnection =>
|
|
47
|
-
PostgresConnection.from(options);
|
|
48
|
-
command = (connection: IConnection): ICommand =>
|
|
49
|
-
new PostgresCommand(connection as PostgresConnection, statements);
|
|
50
|
-
transaction = (
|
|
51
|
-
connection: IConnection,
|
|
52
|
-
isolation: IsolationLevel = "readCommitted",
|
|
53
|
-
): ITransaction =>
|
|
54
|
-
new PostgresTransaction(connection as PostgresConnection, isolation);
|
|
55
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
BulkUpdateStatement,
|
|
3
|
-
CreateTableStatement,
|
|
4
|
-
SelectInsertedIdStatement,
|
|
5
|
-
SelectInsertedIdStatementTextRenderer,
|
|
6
|
-
StatementRenderer,
|
|
7
|
-
type StatementTextRenderer,
|
|
8
|
-
} from "@deterministic-code/datasources";
|
|
9
|
-
import { PostgresBulkUpdateStatementTextRenderer } from "./PostgresBulkUpdateStatementTextRenderer.ts";
|
|
10
|
-
import { PostgresCreateTableStatementRenderer } from "./PostgresCreateTableStatementRenderer.ts";
|
|
11
|
-
|
|
12
|
-
class PostgresSelectInsertedIdStatementTextRenderer extends SelectInsertedIdStatementTextRenderer {
|
|
13
|
-
override render(statement: SelectInsertedIdStatement): string {
|
|
14
|
-
return `SELECT lastval() AS ${statement.column}`;
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export class PostgresStatementRenderer extends StatementRenderer {
|
|
19
|
-
constructor(text: StatementTextRenderer) {
|
|
20
|
-
super(text);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
protected override visitSelectInsertedId(inserted: SelectInsertedIdStatement): string {
|
|
24
|
-
return new PostgresSelectInsertedIdStatementTextRenderer().render(inserted);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
protected override visitCreateTable(create: CreateTableStatement): string {
|
|
28
|
-
return new PostgresCreateTableStatementRenderer().render(create);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
protected override visitBulkUpdate(update: BulkUpdateStatement): string {
|
|
32
|
-
return new PostgresBulkUpdateStatementTextRenderer().render(update);
|
|
33
|
-
}
|
|
34
|
-
}
|
package/src/bind.ts
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { parametersToRecord, type Cell, type Parameter } from "@deterministic-code/datasources";
|
|
2
|
-
import { isBase64 } from "./converters/BinaryConverter.ts";
|
|
3
|
-
import { isIsoDate } from "./converters/DateTimeConverter.ts";
|
|
4
|
-
import { reverse } from "./converters/PostgresRowTypeConverters.ts";
|
|
5
|
-
import type { Scalar, Wire } from "./scalar.ts";
|
|
6
|
-
|
|
7
|
-
const NAME = /\$([A-Za-z_][A-Za-z0-9_]*)/g;
|
|
8
|
-
|
|
9
|
-
const quoteMixedCase = (sql: string): string =>
|
|
10
|
-
sql.replace(/\$[A-Za-z_][A-Za-z0-9_]*|'[^']*'|"[^"]*"|`[^`]*`|\b[A-Za-z_][A-Za-z0-9_]*\b/g, (token) =>
|
|
11
|
-
token.startsWith("$") || token.startsWith("'") || token.startsWith("\"") || token.startsWith("`")
|
|
12
|
-
|| !/[A-Z]/.test(token) || !/[a-z]/.test(token)
|
|
13
|
-
? token
|
|
14
|
-
: `"${token}"`,
|
|
15
|
-
);
|
|
16
|
-
|
|
17
|
-
const wire = (value: Scalar): Wire =>
|
|
18
|
-
typeof value !== "string"
|
|
19
|
-
? value
|
|
20
|
-
: isIsoDate(value)
|
|
21
|
-
? new Date(value)
|
|
22
|
-
: isBase64(value)
|
|
23
|
-
? Uint8Array.from(Buffer.from(value, "base64"))
|
|
24
|
-
: value;
|
|
25
|
-
|
|
26
|
-
export const toPostgres = (
|
|
27
|
-
sql: string,
|
|
28
|
-
params?: Record<string, Scalar>,
|
|
29
|
-
): { text: string; values: Wire[] } => {
|
|
30
|
-
const names: string[] = [];
|
|
31
|
-
const text = quoteMixedCase(sql).replace(NAME, (_match, name: string) => {
|
|
32
|
-
let index = names.indexOf(name);
|
|
33
|
-
if (index < 0) {
|
|
34
|
-
names.push(name);
|
|
35
|
-
index = names.length - 1;
|
|
36
|
-
}
|
|
37
|
-
return `$${index + 1}`;
|
|
38
|
-
});
|
|
39
|
-
return { text, values: names.map((name) => wire(params?.[name] ?? null)) };
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
export const bindParameters = (
|
|
43
|
-
parameters?: Parameter[] | null,
|
|
44
|
-
): Record<string, Scalar> => {
|
|
45
|
-
const record = parametersToRecord(parameters);
|
|
46
|
-
const bound: Record<string, Scalar> = {};
|
|
47
|
-
for (const [name, value] of Object.entries(record))
|
|
48
|
-
bound[name] = reverse(value as Cell) as Scalar;
|
|
49
|
-
return bound;
|
|
50
|
-
};
|
package/src/columnTypes.ts
DELETED