drizzle-orm
Advanced tools
Comparing version 0.36.4-166fb8d to 0.36.4-3c69a1f
@@ -0,5 +1,5 @@ | ||
import type * as V1 from "./_relations.js"; | ||
import type { AnyColumn } from "./column.js"; | ||
import { Column } from "./column.js"; | ||
import { entityKind } from "./entity.js"; | ||
import type { Relation } from "./relations.js"; | ||
import type { View } from "./sql/sql.js"; | ||
@@ -21,3 +21,3 @@ import { SQL } from "./sql/sql.js"; | ||
} | ||
export declare class RelationTableAliasProxyHandler<T extends Relation> implements ProxyHandler<T> { | ||
export declare class RelationTableAliasProxyHandler<T extends V1.Relation> implements ProxyHandler<T> { | ||
private alias; | ||
@@ -29,5 +29,5 @@ static readonly [entityKind]: string; | ||
export declare function aliasedTable<T extends Table>(table: T, tableAlias: string): T; | ||
export declare function aliasedRelation<T extends Relation>(relation: T, tableAlias: string): T; | ||
export declare function aliasedRelation<T extends V1.Relation>(relation: T, tableAlias: string): T; | ||
export declare function aliasedTableColumn<T extends AnyColumn>(column: T, tableAlias: string): T; | ||
export declare function mapColumnsInAliasedSQLToAlias(query: SQL.Aliased, alias: string): SQL.Aliased; | ||
export declare function mapColumnsInSQLToAlias(query: SQL, alias: string): SQL; |
@@ -8,2 +8,3 @@ import { RDSDataClient, type RDSDataClientConfig } from '@aws-sdk/client-rds-data'; | ||
import type { PgRaw } from "../../pg-core/query-builders/raw.js"; | ||
import type { AnyRelations, EmptyRelations } from "../../relations.js"; | ||
import { type SQL, type SQLWrapper } from "../../sql/sql.js"; | ||
@@ -18,3 +19,3 @@ import type { DrizzleConfig, UpdateSet } from "../../utils.js"; | ||
} | ||
export interface DrizzleAwsDataApiPgConfig<TSchema extends Record<string, unknown> = Record<string, never>> extends DrizzleConfig<TSchema> { | ||
export interface DrizzleAwsDataApiPgConfig<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations> extends DrizzleConfig<TSchema, TRelations> { | ||
database: string; | ||
@@ -24,3 +25,3 @@ resourceArn: string; | ||
} | ||
export declare class AwsDataApiPgDatabase<TSchema extends Record<string, unknown> = Record<string, never>> extends PgDatabase<AwsDataApiPgQueryResultHKT, TSchema> { | ||
export declare class AwsDataApiPgDatabase<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations> extends PgDatabase<AwsDataApiPgQueryResultHKT, TSchema, TRelations> { | ||
static readonly [entityKind]: string; | ||
@@ -35,18 +36,18 @@ execute<TRow extends Record<string, unknown> = Record<string, unknown>>(query: SQLWrapper | string): PgRaw<AwsDataApiPgQueryResult<TRow>>; | ||
} | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TClient extends AwsDataApiClient = RDSDataClient>(...params: [ | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations, TClient extends AwsDataApiClient = RDSDataClient>(...params: [ | ||
TClient, | ||
DrizzleAwsDataApiPgConfig<TSchema> | ||
DrizzleAwsDataApiPgConfig<TSchema, TRelations> | ||
] | [ | ||
((DrizzleConfig<TSchema> & { | ||
((DrizzleConfig<TSchema, TRelations> & { | ||
connection: RDSDataClientConfig & Omit<DrizzleAwsDataApiPgConfig, keyof DrizzleConfig>; | ||
}) | (DrizzleAwsDataApiPgConfig<TSchema> & { | ||
}) | (DrizzleAwsDataApiPgConfig<TSchema, TRelations> & { | ||
client: TClient; | ||
})) | ||
]): AwsDataApiPgDatabase<TSchema> & { | ||
]): AwsDataApiPgDatabase<TSchema, TRelations> & { | ||
$client: TClient; | ||
}; | ||
export declare namespace drizzle { | ||
function mock<TSchema extends Record<string, unknown> = Record<string, never>>(config: DrizzleAwsDataApiPgConfig<TSchema>): AwsDataApiPgDatabase<TSchema> & { | ||
function mock<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations>(config: DrizzleAwsDataApiPgConfig<TSchema, TRelations>): AwsDataApiPgDatabase<TSchema, TRelations> & { | ||
$client: '$client is not available on drizzle.mock()'; | ||
}; | ||
} |
import { RDSDataClient } from "@aws-sdk/client-rds-data"; | ||
import * as V1 from "../../_relations.js"; | ||
import { entityKind, is } from "../../entity.js"; | ||
@@ -7,6 +8,2 @@ import { DefaultLogger } from "../../logger.js"; | ||
import { PgArray } from "../../pg-core/index.js"; | ||
import { | ||
createTableRelationsHelpers, | ||
extractTablesRelationalConfig | ||
} from "../../relations.js"; | ||
import { Param, sql } from "../../sql/sql.js"; | ||
@@ -61,5 +58,5 @@ import { Table } from "../../table.js"; | ||
if (config.schema) { | ||
const tablesConfig = extractTablesRelationalConfig( | ||
const tablesConfig = V1.extractTablesRelationalConfig( | ||
config.schema, | ||
createTableRelationsHelpers | ||
V1.createTableRelationsHelpers | ||
); | ||
@@ -72,4 +69,8 @@ schema = { | ||
} | ||
const session = new AwsDataApiSession(client, dialect, schema, { ...config, logger }, void 0); | ||
const db = new AwsDataApiPgDatabase(dialect, session, schema); | ||
const relations = config.relations; | ||
const session = new AwsDataApiSession(client, dialect, relations, schema, { | ||
...config, | ||
logger | ||
}, void 0); | ||
const db = new AwsDataApiPgDatabase(dialect, session, relations, schema); | ||
db.$client = client; | ||
@@ -76,0 +77,0 @@ return db; |
import type { MigrationConfig } from "../../migrator.js"; | ||
import type { AnyRelations } from "../../relations.js"; | ||
import type { AwsDataApiPgDatabase } from "./driver.js"; | ||
export declare function migrate<TSchema extends Record<string, unknown>>(db: AwsDataApiPgDatabase<TSchema>, config: MigrationConfig): Promise<void>; | ||
export declare function migrate<TSchema extends Record<string, unknown>, TRelations extends AnyRelations>(db: AwsDataApiPgDatabase<TSchema, TRelations>, config: MigrationConfig): Promise<void>; |
import type { ExecuteStatementCommandOutput, RDSDataClient } from '@aws-sdk/client-rds-data'; | ||
import type * as V1 from "../../_relations.js"; | ||
import { entityKind } from "../../entity.js"; | ||
@@ -6,3 +7,3 @@ import type { Logger } from "../../logger.js"; | ||
import type { SelectedFieldsOrdered } from "../../pg-core/query-builders/select.types.js"; | ||
import type { RelationalSchemaConfig, TablesRelationalConfig } from "../../relations.js"; | ||
import type { AnyRelations, TablesRelationalConfig } from "../../relations.js"; | ||
import { type QueryTypingsValue, type QueryWithTypings, type SQL } from "../../sql/sql.js"; | ||
@@ -12,3 +13,3 @@ export type AwsDataApiClient = RDSDataClient; | ||
values: AwsDataApiPgQueryResult<unknown[]>; | ||
}> extends PgPreparedQuery<T> { | ||
}, TIsRqbV2 extends boolean = false> extends PgPreparedQuery<T> { | ||
private client; | ||
@@ -21,2 +22,3 @@ private params; | ||
private customResultMapper?; | ||
private isRqbV2Query?; | ||
static readonly [entityKind]: string; | ||
@@ -26,4 +28,5 @@ private rawQuery; | ||
/** @internal */ | ||
transactionId: string | undefined, _isResponseInArrayMode: boolean, customResultMapper?: ((rows: unknown[][]) => T["execute"]) | undefined); | ||
transactionId: string | undefined, _isResponseInArrayMode: boolean, customResultMapper?: ((rows: TIsRqbV2 extends true ? Record<string, unknown>[] : unknown[][]) => T["execute"]) | undefined, isRqbV2Query?: TIsRqbV2 | undefined); | ||
execute(placeholderValues?: Record<string, unknown> | undefined): Promise<T['execute']>; | ||
private executeRqbV2; | ||
all(placeholderValues?: Record<string, unknown> | undefined): Promise<T['all']>; | ||
@@ -38,3 +41,4 @@ values(placeholderValues?: Record<string, unknown>): Promise<T['values']>; | ||
} | ||
export declare class AwsDataApiSession<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends PgSession<AwsDataApiPgQueryResultHKT, TFullSchema, TSchema> { | ||
export declare class AwsDataApiSession<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends PgSession<AwsDataApiPgQueryResultHKT, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
private relations; | ||
private schema; | ||
@@ -45,3 +49,3 @@ private options; | ||
/** @internal */ | ||
client: AwsDataApiClient, dialect: PgDialect, schema: RelationalSchemaConfig<TSchema> | undefined, options: AwsDataApiSessionOptions, | ||
client: AwsDataApiClient, dialect: PgDialect, relations: AnyRelations | undefined, schema: V1.RelationalSchemaConfig<TSchema> | undefined, options: AwsDataApiSessionOptions, | ||
/** @internal */ | ||
@@ -54,8 +58,9 @@ transactionId: string | undefined); | ||
}>(query: QueryWithTypings, fields: SelectedFieldsOrdered | undefined, name: string | undefined, isResponseInArrayMode: boolean, customResultMapper?: (rows: unknown[][]) => T['execute'], transactionId?: string): AwsDataApiPreparedQuery<T>; | ||
prepareRelationalQuery<T extends PreparedQueryConfig = PreparedQueryConfig>(query: QueryWithTypings, fields: SelectedFieldsOrdered | undefined, name: string | undefined, customResultMapper: (rows: Record<string, unknown>[]) => T['execute'], transactionId?: string): PgPreparedQuery<T>; | ||
execute<T>(query: SQL): Promise<T>; | ||
transaction<T>(transaction: (tx: AwsDataApiTransaction<TFullSchema, TSchema>) => Promise<T>, config?: PgTransactionConfig | undefined): Promise<T>; | ||
transaction<T>(transaction: (tx: AwsDataApiTransaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => Promise<T>, config?: PgTransactionConfig | undefined): Promise<T>; | ||
} | ||
export declare class AwsDataApiTransaction<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends PgTransaction<AwsDataApiPgQueryResultHKT, TFullSchema, TSchema> { | ||
export declare class AwsDataApiTransaction<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends PgTransaction<AwsDataApiPgQueryResultHKT, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
static readonly [entityKind]: string; | ||
transaction<T>(transaction: (tx: AwsDataApiTransaction<TFullSchema, TSchema>) => Promise<T>): Promise<T>; | ||
transaction<T>(transaction: (tx: AwsDataApiTransaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => Promise<T>): Promise<T>; | ||
} | ||
@@ -62,0 +67,0 @@ export type AwsDataApiPgQueryResult<T> = ExecuteStatementCommandOutput & { |
@@ -17,3 +17,3 @@ import { | ||
class AwsDataApiPreparedQuery extends PgPreparedQuery { | ||
constructor(client, queryString, params, typings, options, fields, transactionId, _isResponseInArrayMode, customResultMapper) { | ||
constructor(client, queryString, params, typings, options, fields, transactionId, _isResponseInArrayMode, customResultMapper, isRqbV2Query) { | ||
super({ sql: queryString, params }); | ||
@@ -28,2 +28,3 @@ this.client = client; | ||
this.customResultMapper = customResultMapper; | ||
this.isRqbV2Query = isRqbV2Query; | ||
this.rawQuery = new ExecuteStatementCommand({ | ||
@@ -42,2 +43,4 @@ sql: queryString, | ||
async execute(placeholderValues = {}) { | ||
if (this.isRqbV2Query) | ||
return this.executeRqbV2(placeholderValues); | ||
const { fields, joinsNotNullableMap, customResultMapper } = this; | ||
@@ -72,2 +75,34 @@ const result = await this.values(placeholderValues); | ||
} | ||
async executeRqbV2(placeholderValues = {}) { | ||
const { customResultMapper } = this; | ||
const result = await this.values(placeholderValues); | ||
const { columnMetadata, rows } = result; | ||
if (!columnMetadata) { | ||
return customResultMapper( | ||
rows | ||
); | ||
} | ||
const mappedRows = rows.map((sourceRow) => { | ||
const row = {}; | ||
for (const [index, value] of sourceRow.entries()) { | ||
const metadata = columnMetadata[index]; | ||
if (!metadata) { | ||
throw new Error( | ||
`Unexpected state: no column metadata found for index ${index}. Please report this issue on GitHub: https://github.com/drizzle-team/drizzle-orm/issues/new/choose` | ||
); | ||
} | ||
if (!metadata.name) { | ||
throw new Error( | ||
`Unexpected state: no column name for index ${index} found in the column metadata. Please report this issue on GitHub: https://github.com/drizzle-team/drizzle-orm/issues/new/choose` | ||
); | ||
} | ||
row[metadata.name] = value; | ||
} | ||
return row; | ||
}); | ||
Object.assign(result, { rows: mappedRows }); | ||
return customResultMapper( | ||
mappedRows | ||
); | ||
} | ||
async all(placeholderValues) { | ||
@@ -113,5 +148,6 @@ const result = await this.execute(placeholderValues); | ||
class AwsDataApiSession extends PgSession { | ||
constructor(client, dialect, schema, options, transactionId) { | ||
constructor(client, dialect, relations, schema, options, transactionId) { | ||
super(dialect); | ||
this.client = client; | ||
this.relations = relations; | ||
this.schema = schema; | ||
@@ -142,2 +178,16 @@ this.options = options; | ||
} | ||
prepareRelationalQuery(query, fields, name, customResultMapper, transactionId) { | ||
return new AwsDataApiPreparedQuery( | ||
this.client, | ||
query.sql, | ||
query.params, | ||
query.typings ?? [], | ||
this.options, | ||
fields, | ||
transactionId ?? this.transactionId, | ||
false, | ||
customResultMapper, | ||
true | ||
); | ||
} | ||
execute(query) { | ||
@@ -155,4 +205,16 @@ return this.prepareQuery( | ||
const { transactionId } = await this.client.send(new BeginTransactionCommand(this.rawQuery)); | ||
const session = new AwsDataApiSession(this.client, this.dialect, this.schema, this.options, transactionId); | ||
const tx = new AwsDataApiTransaction(this.dialect, session, this.schema); | ||
const session = new AwsDataApiSession( | ||
this.client, | ||
this.dialect, | ||
this.relations, | ||
this.schema, | ||
this.options, | ||
transactionId | ||
); | ||
const tx = new AwsDataApiTransaction( | ||
this.dialect, | ||
session, | ||
this.relations, | ||
this.schema | ||
); | ||
if (config) { | ||
@@ -178,2 +240,3 @@ await tx.setTransaction(config); | ||
this.session, | ||
this.relations, | ||
this.schema, | ||
@@ -180,0 +243,0 @@ this.nestedIndex + 1 |
import { type Database, type Options, type RunResult } from 'better-sqlite3'; | ||
import { entityKind } from "../entity.js"; | ||
import type { AnyRelations, EmptyRelations } from "../relations.js"; | ||
import { BaseSQLiteDatabase } from "../sqlite-core/db.js"; | ||
@@ -8,12 +9,12 @@ import { type DrizzleConfig } from "../utils.js"; | ||
} & Options) | string | undefined; | ||
export declare class BetterSQLite3Database<TSchema extends Record<string, unknown> = Record<string, never>> extends BaseSQLiteDatabase<'sync', RunResult, TSchema> { | ||
export declare class BetterSQLite3Database<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations> extends BaseSQLiteDatabase<'sync', RunResult, TSchema, TRelations> { | ||
static readonly [entityKind]: string; | ||
} | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(...params: [] | [ | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations>(...params: [] | [ | ||
Database | string | ||
] | [ | ||
Database | string, | ||
DrizzleConfig<TSchema> | ||
DrizzleConfig<TSchema, TRelations> | ||
] | [ | ||
(DrizzleConfig<TSchema> & ({ | ||
(DrizzleConfig<TSchema, TRelations> & ({ | ||
connection?: DrizzleBetterSQLite3DatabaseConfig; | ||
@@ -23,9 +24,9 @@ } | { | ||
})) | ||
]): BetterSQLite3Database<TSchema> & { | ||
]): BetterSQLite3Database<TSchema, TRelations> & { | ||
$client: Database; | ||
}; | ||
export declare namespace drizzle { | ||
function mock<TSchema extends Record<string, unknown> = Record<string, never>>(config?: DrizzleConfig<TSchema>): BetterSQLite3Database<TSchema> & { | ||
function mock<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations>(config?: DrizzleConfig<TSchema, TRelations>): BetterSQLite3Database<TSchema, TRelations> & { | ||
$client: '$client is not available on drizzle.mock()'; | ||
}; | ||
} |
import Client from "better-sqlite3"; | ||
import * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
import { DefaultLogger } from "../logger.js"; | ||
import { | ||
createTableRelationsHelpers, | ||
extractTablesRelationalConfig | ||
} from "../relations.js"; | ||
import { BaseSQLiteDatabase } from "../sqlite-core/db.js"; | ||
@@ -25,5 +22,5 @@ import { SQLiteSyncDialect } from "../sqlite-core/dialect.js"; | ||
if (config.schema) { | ||
const tablesConfig = extractTablesRelationalConfig( | ||
const tablesConfig = V1.extractTablesRelationalConfig( | ||
config.schema, | ||
createTableRelationsHelpers | ||
V1.createTableRelationsHelpers | ||
); | ||
@@ -36,4 +33,11 @@ schema = { | ||
} | ||
const session = new BetterSQLiteSession(client, dialect, schema, { logger }); | ||
const db = new BetterSQLite3Database("sync", dialect, session, schema); | ||
const relations = config.relations; | ||
const session = new BetterSQLiteSession(client, dialect, relations, schema, { logger }); | ||
const db = new BetterSQLite3Database( | ||
"sync", | ||
dialect, | ||
session, | ||
relations, | ||
schema | ||
); | ||
db.$client = client; | ||
@@ -40,0 +44,0 @@ return db; |
import type { MigrationConfig } from "../migrator.js"; | ||
import type { AnyRelations } from "../relations.js"; | ||
import type { BetterSQLite3Database } from "./driver.js"; | ||
export declare function migrate<TSchema extends Record<string, unknown>>(db: BetterSQLite3Database<TSchema>, config: MigrationConfig): void; | ||
export declare function migrate<TSchema extends Record<string, unknown>, TRelations extends AnyRelations>(db: BetterSQLite3Database<TSchema, TRelations>, config: MigrationConfig): void; |
import type { Database, RunResult, Statement } from 'better-sqlite3'; | ||
import type * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
import type { Logger } from "../logger.js"; | ||
import type { RelationalSchemaConfig, TablesRelationalConfig } from "../relations.js"; | ||
import type { AnyRelations, TablesRelationalConfig } from "../relations.js"; | ||
import { type Query } from "../sql/sql.js"; | ||
@@ -14,16 +15,18 @@ import type { SQLiteSyncDialect } from "../sqlite-core/dialect.js"; | ||
type PreparedQueryConfig = Omit<PreparedQueryConfigBase, 'statement' | 'run'>; | ||
export declare class BetterSQLiteSession<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends SQLiteSession<'sync', RunResult, TFullSchema, TSchema> { | ||
export declare class BetterSQLiteSession<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends SQLiteSession<'sync', RunResult, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
private client; | ||
private relations; | ||
private schema; | ||
static readonly [entityKind]: string; | ||
private logger; | ||
constructor(client: Database, dialect: SQLiteSyncDialect, schema: RelationalSchemaConfig<TSchema> | undefined, options?: BetterSQLiteSessionOptions); | ||
constructor(client: Database, dialect: SQLiteSyncDialect, relations: AnyRelations | undefined, schema: V1.RelationalSchemaConfig<TSchema> | undefined, options?: BetterSQLiteSessionOptions); | ||
prepareQuery<T extends Omit<PreparedQueryConfig, 'run'>>(query: Query, fields: SelectedFieldsOrdered | undefined, executeMethod: SQLiteExecuteMethod, isResponseInArrayMode: boolean, customResultMapper?: (rows: unknown[][]) => unknown): PreparedQuery<T>; | ||
transaction<T>(transaction: (tx: BetterSQLiteTransaction<TFullSchema, TSchema>) => T, config?: SQLiteTransactionConfig): T; | ||
prepareRelationalQuery<T extends Omit<PreparedQueryConfig, 'run'>>(query: Query, fields: SelectedFieldsOrdered | undefined, executeMethod: SQLiteExecuteMethod, customResultMapper: (rows: Record<string, unknown>[]) => unknown): PreparedQuery<T, true>; | ||
transaction<T>(transaction: (tx: BetterSQLiteTransaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => T, config?: SQLiteTransactionConfig): T; | ||
} | ||
export declare class BetterSQLiteTransaction<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends SQLiteTransaction<'sync', RunResult, TFullSchema, TSchema> { | ||
export declare class BetterSQLiteTransaction<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends SQLiteTransaction<'sync', RunResult, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
static readonly [entityKind]: string; | ||
transaction<T>(transaction: (tx: BetterSQLiteTransaction<TFullSchema, TSchema>) => T): T; | ||
transaction<T>(transaction: (tx: BetterSQLiteTransaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => T): T; | ||
} | ||
export declare class PreparedQuery<T extends PreparedQueryConfig = PreparedQueryConfig> extends PreparedQueryBase<{ | ||
export declare class PreparedQuery<T extends PreparedQueryConfig = PreparedQueryConfig, TIsRqbV2 extends boolean = false> extends PreparedQueryBase<{ | ||
type: 'sync'; | ||
@@ -41,9 +44,12 @@ run: RunResult; | ||
private customResultMapper?; | ||
private isRqbV2Query?; | ||
static readonly [entityKind]: string; | ||
constructor(stmt: Statement, query: Query, logger: Logger, fields: SelectedFieldsOrdered | undefined, executeMethod: SQLiteExecuteMethod, _isResponseInArrayMode: boolean, customResultMapper?: ((rows: unknown[][]) => unknown) | undefined); | ||
constructor(stmt: Statement, query: Query, logger: Logger, fields: SelectedFieldsOrdered | undefined, executeMethod: SQLiteExecuteMethod, _isResponseInArrayMode: boolean, customResultMapper?: ((rows: TIsRqbV2 extends true ? Record<string, unknown>[] : unknown[][]) => unknown) | undefined, isRqbV2Query?: TIsRqbV2 | undefined); | ||
run(placeholderValues?: Record<string, unknown>): RunResult; | ||
all(placeholderValues?: Record<string, unknown>): T['all']; | ||
get(placeholderValues?: Record<string, unknown>): T['get']; | ||
private allRqbV2; | ||
private getRqbV2; | ||
values(placeholderValues?: Record<string, unknown>): T['values']; | ||
} | ||
export {}; |
@@ -11,5 +11,6 @@ import { entityKind } from "../entity.js"; | ||
class BetterSQLiteSession extends SQLiteSession { | ||
constructor(client, dialect, schema, options = {}) { | ||
constructor(client, dialect, relations, schema, options = {}) { | ||
super(dialect); | ||
this.client = client; | ||
this.relations = relations; | ||
this.schema = schema; | ||
@@ -32,4 +33,17 @@ this.logger = options.logger ?? new NoopLogger(); | ||
} | ||
prepareRelationalQuery(query, fields, executeMethod, customResultMapper) { | ||
const stmt = this.client.prepare(query.sql); | ||
return new PreparedQuery( | ||
stmt, | ||
query, | ||
this.logger, | ||
fields, | ||
executeMethod, | ||
false, | ||
customResultMapper, | ||
true | ||
); | ||
} | ||
transaction(transaction, config = {}) { | ||
const tx = new BetterSQLiteTransaction("sync", this.dialect, this, this.schema); | ||
const tx = new BetterSQLiteTransaction("sync", this.dialect, this, this.relations, this.schema); | ||
const nativeTx = this.client.transaction(transaction); | ||
@@ -43,3 +57,10 @@ return nativeTx[config.behavior ?? "deferred"](tx); | ||
const savepointName = `sp${this.nestedIndex}`; | ||
const tx = new BetterSQLiteTransaction("sync", this.dialect, this.session, this.schema, this.nestedIndex + 1); | ||
const tx = new BetterSQLiteTransaction( | ||
"sync", | ||
this.dialect, | ||
this.session, | ||
this.relations, | ||
this.schema, | ||
this.nestedIndex + 1 | ||
); | ||
this.session.run(sql.raw(`savepoint ${savepointName}`)); | ||
@@ -57,3 +78,3 @@ try { | ||
class PreparedQuery extends PreparedQueryBase { | ||
constructor(stmt, query, logger, fields, executeMethod, _isResponseInArrayMode, customResultMapper) { | ||
constructor(stmt, query, logger, fields, executeMethod, _isResponseInArrayMode, customResultMapper, isRqbV2Query) { | ||
super("sync", executeMethod, query); | ||
@@ -65,2 +86,3 @@ this.stmt = stmt; | ||
this.customResultMapper = customResultMapper; | ||
this.isRqbV2Query = isRqbV2Query; | ||
} | ||
@@ -74,2 +96,4 @@ static [entityKind] = "BetterSQLitePreparedQuery"; | ||
all(placeholderValues) { | ||
if (this.isRqbV2Query) | ||
return this.allRqbV2(placeholderValues); | ||
const { fields, joinsNotNullableMap, query, logger, stmt, customResultMapper } = this; | ||
@@ -88,2 +112,4 @@ if (!fields && !customResultMapper) { | ||
get(placeholderValues) { | ||
if (this.isRqbV2Query) | ||
return this.getRqbV2(placeholderValues); | ||
const params = fillPlaceholders(this.query.params, placeholderValues ?? {}); | ||
@@ -104,2 +130,21 @@ this.logger.logQuery(this.query.sql, params); | ||
} | ||
allRqbV2(placeholderValues) { | ||
const { query, logger, stmt, customResultMapper } = this; | ||
const params = fillPlaceholders(query.params, placeholderValues ?? {}); | ||
logger.logQuery(query.sql, params); | ||
return customResultMapper( | ||
stmt.all(...params) | ||
); | ||
} | ||
getRqbV2(placeholderValues) { | ||
const params = fillPlaceholders(this.query.params, placeholderValues ?? {}); | ||
this.logger.logQuery(this.query.sql, params); | ||
const { stmt, customResultMapper } = this; | ||
const row = stmt.get(...params); | ||
if (row === void 0) | ||
return row; | ||
return customResultMapper( | ||
[row] | ||
); | ||
} | ||
values(placeholderValues) { | ||
@@ -106,0 +151,0 @@ const params = fillPlaceholders(this.query.params, placeholderValues ?? {}); |
import { Database } from 'bun:sqlite'; | ||
import { entityKind } from "../entity.js"; | ||
import type { AnyRelations, EmptyRelations } from "../relations.js"; | ||
import { BaseSQLiteDatabase } from "../sqlite-core/db.js"; | ||
import { type DrizzleConfig } from "../utils.js"; | ||
export declare class BunSQLiteDatabase<TSchema extends Record<string, unknown> = Record<string, never>> extends BaseSQLiteDatabase<'sync', void, TSchema> { | ||
export declare class BunSQLiteDatabase<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations> extends BaseSQLiteDatabase<'sync', void, TSchema, TRelations> { | ||
static readonly [entityKind]: string; | ||
@@ -31,9 +32,9 @@ } | ||
} & DrizzleBunSqliteDatabaseOptions) | string | undefined; | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TClient extends Database = Database>(...params: [] | [ | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations, TClient extends Database = Database>(...params: [] | [ | ||
TClient | string | ||
] | [ | ||
TClient | string, | ||
DrizzleConfig<TSchema> | ||
DrizzleConfig<TSchema, TRelations> | ||
] | [ | ||
(DrizzleConfig<TSchema> & ({ | ||
(DrizzleConfig<TSchema, TRelations> & ({ | ||
connection?: DrizzleBunSqliteDatabaseConfig; | ||
@@ -43,7 +44,7 @@ } | { | ||
})) | ||
]): BunSQLiteDatabase<TSchema> & { | ||
]): BunSQLiteDatabase<TSchema, TRelations> & { | ||
$client: TClient; | ||
}; | ||
export declare namespace drizzle { | ||
function mock<TSchema extends Record<string, unknown> = Record<string, never>>(config?: DrizzleConfig<TSchema>): BunSQLiteDatabase<TSchema> & { | ||
function mock<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations>(config?: DrizzleConfig<TSchema, TRelations>): BunSQLiteDatabase<TSchema, TRelations> & { | ||
$client: '$client is not available on drizzle.mock()'; | ||
@@ -50,0 +51,0 @@ }; |
import { Database } from "bun:sqlite"; | ||
import * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
import { DefaultLogger } from "../logger.js"; | ||
import { | ||
createTableRelationsHelpers, | ||
extractTablesRelationalConfig | ||
} from "../relations.js"; | ||
import { BaseSQLiteDatabase } from "../sqlite-core/db.js"; | ||
@@ -25,5 +22,5 @@ import { SQLiteSyncDialect } from "../sqlite-core/dialect.js"; | ||
if (config.schema) { | ||
const tablesConfig = extractTablesRelationalConfig( | ||
const tablesConfig = V1.extractTablesRelationalConfig( | ||
config.schema, | ||
createTableRelationsHelpers | ||
V1.createTableRelationsHelpers | ||
); | ||
@@ -36,4 +33,11 @@ schema = { | ||
} | ||
const session = new SQLiteBunSession(client, dialect, schema, { logger }); | ||
const db = new BunSQLiteDatabase("sync", dialect, session, schema); | ||
const relations = config.relations; | ||
const session = new SQLiteBunSession(client, dialect, relations, schema, { logger }); | ||
const db = new BunSQLiteDatabase( | ||
"sync", | ||
dialect, | ||
session, | ||
relations, | ||
schema | ||
); | ||
db.$client = client; | ||
@@ -40,0 +44,0 @@ return db; |
import type { MigrationConfig } from "../migrator.js"; | ||
import type { AnyRelations, EmptyRelations } from "../relations.js"; | ||
import type { BunSQLiteDatabase } from "./driver.js"; | ||
export declare function migrate<TSchema extends Record<string, unknown>>(db: BunSQLiteDatabase<TSchema>, config: MigrationConfig): void; | ||
export declare function migrate<TSchema extends Record<string, unknown>, TRelations extends AnyRelations = EmptyRelations>(db: BunSQLiteDatabase<TSchema, TRelations>, config: MigrationConfig): void; |
import type { Database, Statement as BunStatement } from 'bun:sqlite'; | ||
import type * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
import type { Logger } from "../logger.js"; | ||
import type { RelationalSchemaConfig, TablesRelationalConfig } from "../relations.js"; | ||
import type { AnyRelations, TablesRelationalConfig } from "../relations.js"; | ||
import { type Query } from "../sql/sql.js"; | ||
@@ -16,17 +17,19 @@ import type { SQLiteSyncDialect } from "../sqlite-core/dialect.js"; | ||
type Statement = BunStatement<any>; | ||
export declare class SQLiteBunSession<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends SQLiteSession<'sync', void, TFullSchema, TSchema> { | ||
export declare class SQLiteBunSession<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends SQLiteSession<'sync', void, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
private client; | ||
private relations; | ||
private schema; | ||
static readonly [entityKind]: string; | ||
private logger; | ||
constructor(client: Database, dialect: SQLiteSyncDialect, schema: RelationalSchemaConfig<TSchema> | undefined, options?: SQLiteBunSessionOptions); | ||
constructor(client: Database, dialect: SQLiteSyncDialect, relations: AnyRelations | undefined, schema: V1.RelationalSchemaConfig<TSchema> | undefined, options?: SQLiteBunSessionOptions); | ||
exec(query: string): void; | ||
prepareQuery<T extends Omit<PreparedQueryConfig, 'run'>>(query: Query, fields: SelectedFieldsOrdered | undefined, executeMethod: SQLiteExecuteMethod, isResponseInArrayMode: boolean, customResultMapper?: (rows: unknown[][]) => unknown): PreparedQuery<T>; | ||
transaction<T>(transaction: (tx: SQLiteBunTransaction<TFullSchema, TSchema>) => T, config?: SQLiteTransactionConfig): T; | ||
prepareRelationalQuery<T extends Omit<PreparedQueryConfig, 'run'>>(query: Query, fields: SelectedFieldsOrdered | undefined, executeMethod: SQLiteExecuteMethod, customResultMapper: (rows: Record<string, unknown>[]) => unknown): PreparedQuery<T, true>; | ||
transaction<T>(transaction: (tx: SQLiteBunTransaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => T, config?: SQLiteTransactionConfig): T; | ||
} | ||
export declare class SQLiteBunTransaction<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends SQLiteTransaction<'sync', void, TFullSchema, TSchema> { | ||
export declare class SQLiteBunTransaction<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends SQLiteTransaction<'sync', void, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
static readonly [entityKind]: string; | ||
transaction<T>(transaction: (tx: SQLiteBunTransaction<TFullSchema, TSchema>) => T): T; | ||
transaction<T>(transaction: (tx: SQLiteBunTransaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => T): T; | ||
} | ||
export declare class PreparedQuery<T extends PreparedQueryConfig = PreparedQueryConfig> extends PreparedQueryBase<{ | ||
export declare class PreparedQuery<T extends PreparedQueryConfig = PreparedQueryConfig, TIsRqbV2 extends boolean = false> extends PreparedQueryBase<{ | ||
type: 'sync'; | ||
@@ -44,9 +47,12 @@ run: void; | ||
private customResultMapper?; | ||
private isRqbV2Query?; | ||
static readonly [entityKind]: string; | ||
constructor(stmt: Statement, query: Query, logger: Logger, fields: SelectedFieldsOrdered | undefined, executeMethod: SQLiteExecuteMethod, _isResponseInArrayMode: boolean, customResultMapper?: ((rows: unknown[][]) => unknown) | undefined); | ||
constructor(stmt: Statement, query: Query, logger: Logger, fields: SelectedFieldsOrdered | undefined, executeMethod: SQLiteExecuteMethod, _isResponseInArrayMode: boolean, customResultMapper?: ((rows: TIsRqbV2 extends true ? Record<string, unknown>[] : unknown[][]) => unknown) | undefined, isRqbV2Query?: TIsRqbV2 | undefined); | ||
run(placeholderValues?: Record<string, unknown>): void; | ||
all(placeholderValues?: Record<string, unknown>): T['all']; | ||
get(placeholderValues?: Record<string, unknown>): T['get']; | ||
private allRqbV2; | ||
private getRqbV2; | ||
values(placeholderValues?: Record<string, unknown>): T['values']; | ||
} | ||
export {}; |
@@ -8,5 +8,6 @@ import { entityKind } from "../entity.js"; | ||
class SQLiteBunSession extends SQLiteSession { | ||
constructor(client, dialect, schema, options = {}) { | ||
constructor(client, dialect, relations, schema, options = {}) { | ||
super(dialect); | ||
this.client = client; | ||
this.relations = relations; | ||
this.schema = schema; | ||
@@ -32,4 +33,17 @@ this.logger = options.logger ?? new NoopLogger(); | ||
} | ||
prepareRelationalQuery(query, fields, executeMethod, customResultMapper) { | ||
const stmt = this.client.prepare(query.sql); | ||
return new PreparedQuery( | ||
stmt, | ||
query, | ||
this.logger, | ||
fields, | ||
executeMethod, | ||
false, | ||
customResultMapper, | ||
true | ||
); | ||
} | ||
transaction(transaction, config = {}) { | ||
const tx = new SQLiteBunTransaction("sync", this.dialect, this, this.schema); | ||
const tx = new SQLiteBunTransaction("sync", this.dialect, this, this.relations, this.schema); | ||
let result; | ||
@@ -47,3 +61,10 @@ const nativeTx = this.client.transaction(() => { | ||
const savepointName = `sp${this.nestedIndex}`; | ||
const tx = new SQLiteBunTransaction("sync", this.dialect, this.session, this.schema, this.nestedIndex + 1); | ||
const tx = new SQLiteBunTransaction( | ||
"sync", | ||
this.dialect, | ||
this.session, | ||
this.relations, | ||
this.schema, | ||
this.nestedIndex + 1 | ||
); | ||
this.session.run(sql.raw(`savepoint ${savepointName}`)); | ||
@@ -61,3 +82,3 @@ try { | ||
class PreparedQuery extends PreparedQueryBase { | ||
constructor(stmt, query, logger, fields, executeMethod, _isResponseInArrayMode, customResultMapper) { | ||
constructor(stmt, query, logger, fields, executeMethod, _isResponseInArrayMode, customResultMapper, isRqbV2Query) { | ||
super("sync", executeMethod, query); | ||
@@ -69,2 +90,3 @@ this.stmt = stmt; | ||
this.customResultMapper = customResultMapper; | ||
this.isRqbV2Query = isRqbV2Query; | ||
} | ||
@@ -78,2 +100,4 @@ static [entityKind] = "SQLiteBunPreparedQuery"; | ||
all(placeholderValues) { | ||
if (this.isRqbV2Query) | ||
return this.allRqbV2(placeholderValues); | ||
const { fields, query, logger, joinsNotNullableMap, stmt, customResultMapper } = this; | ||
@@ -92,2 +116,4 @@ if (!fields && !customResultMapper) { | ||
get(placeholderValues) { | ||
if (this.isRqbV2Query) | ||
return this.getRqbV2(placeholderValues); | ||
const params = fillPlaceholders(this.query.params, placeholderValues ?? {}); | ||
@@ -108,2 +134,21 @@ this.logger.logQuery(this.query.sql, params); | ||
} | ||
allRqbV2(placeholderValues) { | ||
const { query, logger, stmt, customResultMapper } = this; | ||
const params = fillPlaceholders(query.params, placeholderValues ?? {}); | ||
logger.logQuery(query.sql, params); | ||
return customResultMapper( | ||
stmt.all(...params) | ||
); | ||
} | ||
getRqbV2(placeholderValues) { | ||
const params = fillPlaceholders(this.query.params, placeholderValues ?? {}); | ||
this.logger.logQuery(this.query.sql, params); | ||
const { stmt, customResultMapper } = this; | ||
const row = stmt.get(...params); | ||
if (row === void 0) | ||
return row; | ||
return customResultMapper( | ||
[row] | ||
); | ||
} | ||
values(placeholderValues) { | ||
@@ -110,0 +155,0 @@ const params = fillPlaceholders(this.query.params, placeholderValues ?? {}); |
import type { D1Database as MiniflareD1Database } from '@miniflare/d1'; | ||
import type { BatchItem, BatchResponse } from "../batch.js"; | ||
import { entityKind } from "../entity.js"; | ||
import type { AnyRelations, EmptyRelations } from "../relations.js"; | ||
import { BaseSQLiteDatabase } from "../sqlite-core/db.js"; | ||
import type { DrizzleConfig, IfNotImported } from "../utils.js"; | ||
export type AnyD1Database = IfNotImported<D1Database, MiniflareD1Database, D1Database | IfNotImported<MiniflareD1Database, never, MiniflareD1Database>>; | ||
export declare class DrizzleD1Database<TSchema extends Record<string, unknown> = Record<string, never>> extends BaseSQLiteDatabase<'async', D1Result, TSchema> { | ||
export declare class DrizzleD1Database<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations> extends BaseSQLiteDatabase<'async', D1Result, TSchema, TRelations> { | ||
static readonly [entityKind]: string; | ||
batch<U extends BatchItem<'sqlite'>, T extends Readonly<[U, ...U[]]>>(batch: T): Promise<BatchResponse<T>>; | ||
} | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TClient extends AnyD1Database = AnyD1Database>(client: TClient, config?: DrizzleConfig<TSchema>): DrizzleD1Database<TSchema> & { | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations, TClient extends AnyD1Database = AnyD1Database>(client: TClient, config?: DrizzleConfig<TSchema, TRelations>): DrizzleD1Database<TSchema, TRelations> & { | ||
$client: TClient; | ||
}; |
@@ -0,7 +1,4 @@ | ||
import * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
import { DefaultLogger } from "../logger.js"; | ||
import { | ||
createTableRelationsHelpers, | ||
extractTablesRelationalConfig | ||
} from "../relations.js"; | ||
import { BaseSQLiteDatabase } from "../sqlite-core/db.js"; | ||
@@ -26,5 +23,5 @@ import { SQLiteAsyncDialect } from "../sqlite-core/dialect.js"; | ||
if (config.schema) { | ||
const tablesConfig = extractTablesRelationalConfig( | ||
const tablesConfig = V1.extractTablesRelationalConfig( | ||
config.schema, | ||
createTableRelationsHelpers | ||
V1.createTableRelationsHelpers | ||
); | ||
@@ -37,4 +34,11 @@ schema = { | ||
} | ||
const session = new SQLiteD1Session(client, dialect, schema, { logger }); | ||
const db = new DrizzleD1Database("async", dialect, session, schema); | ||
const relations = config.relations; | ||
const session = new SQLiteD1Session(client, dialect, relations, schema, { logger }); | ||
const db = new DrizzleD1Database( | ||
"async", | ||
dialect, | ||
session, | ||
relations, | ||
schema | ||
); | ||
db.$client = client; | ||
@@ -41,0 +45,0 @@ return db; |
import type { MigrationConfig } from "../migrator.js"; | ||
import type { AnyRelations } from "../relations.js"; | ||
import type { DrizzleD1Database } from "./driver.js"; | ||
export declare function migrate<TSchema extends Record<string, unknown>>(db: DrizzleD1Database<TSchema>, config: MigrationConfig): Promise<void>; | ||
export declare function migrate<TSchema extends Record<string, unknown>, TRelations extends AnyRelations>(db: DrizzleD1Database<TSchema, TRelations>, config: MigrationConfig): Promise<void>; |
@@ -0,5 +1,6 @@ | ||
import type * as V1 from "../_relations.js"; | ||
import type { BatchItem } from "../batch.js"; | ||
import { entityKind } from "../entity.js"; | ||
import type { Logger } from "../logger.js"; | ||
import type { RelationalSchemaConfig, TablesRelationalConfig } from "../relations.js"; | ||
import type { AnyRelations, TablesRelationalConfig } from "../relations.js"; | ||
import { type Query } from "../sql/sql.js"; | ||
@@ -15,4 +16,5 @@ import type { SQLiteAsyncDialect } from "../sqlite-core/dialect.js"; | ||
type PreparedQueryConfig = Omit<PreparedQueryConfigBase, 'statement' | 'run'>; | ||
export declare class SQLiteD1Session<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends SQLiteSession<'async', D1Result, TFullSchema, TSchema> { | ||
export declare class SQLiteD1Session<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends SQLiteSession<'async', D1Result, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
private client; | ||
private relations; | ||
private schema; | ||
@@ -22,4 +24,5 @@ private options; | ||
private logger; | ||
constructor(client: D1Database, dialect: SQLiteAsyncDialect, schema: RelationalSchemaConfig<TSchema> | undefined, options?: SQLiteD1SessionOptions); | ||
constructor(client: D1Database, dialect: SQLiteAsyncDialect, relations: AnyRelations | undefined, schema: V1.RelationalSchemaConfig<TSchema> | undefined, options?: SQLiteD1SessionOptions); | ||
prepareQuery(query: Query, fields: SelectedFieldsOrdered | undefined, executeMethod: SQLiteExecuteMethod, isResponseInArrayMode: boolean, customResultMapper?: (rows: unknown[][]) => unknown): D1PreparedQuery; | ||
prepareRelationalQuery(query: Query, fields: SelectedFieldsOrdered | undefined, executeMethod: SQLiteExecuteMethod, customResultMapper?: (rows: Record<string, unknown>[]) => unknown): D1PreparedQuery<PreparedQueryConfig, true>; | ||
batch<T extends BatchItem<'sqlite'>[] | readonly BatchItem<'sqlite'>[]>(queries: T): Promise<unknown[]>; | ||
@@ -29,9 +32,9 @@ extractRawAllValueFromBatchResult(result: unknown): unknown; | ||
extractRawValuesValueFromBatchResult(result: unknown): unknown; | ||
transaction<T>(transaction: (tx: D1Transaction<TFullSchema, TSchema>) => T | Promise<T>, config?: SQLiteTransactionConfig): Promise<T>; | ||
transaction<T>(transaction: (tx: D1Transaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => T | Promise<T>, config?: SQLiteTransactionConfig): Promise<T>; | ||
} | ||
export declare class D1Transaction<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends SQLiteTransaction<'async', D1Result, TFullSchema, TSchema> { | ||
export declare class D1Transaction<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends SQLiteTransaction<'async', D1Result, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
static readonly [entityKind]: string; | ||
transaction<T>(transaction: (tx: D1Transaction<TFullSchema, TSchema>) => Promise<T>): Promise<T>; | ||
transaction<T>(transaction: (tx: D1Transaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => Promise<T>): Promise<T>; | ||
} | ||
export declare class D1PreparedQuery<T extends PreparedQueryConfig = PreparedQueryConfig> extends SQLitePreparedQuery<{ | ||
export declare class D1PreparedQuery<T extends PreparedQueryConfig = PreparedQueryConfig, TIsRqbV2 extends boolean = false> extends SQLitePreparedQuery<{ | ||
type: 'async'; | ||
@@ -46,8 +49,12 @@ run: D1Response; | ||
private _isResponseInArrayMode; | ||
private customResultMapper?; | ||
private isRqbV2Query?; | ||
static readonly [entityKind]: string; | ||
constructor(stmt: D1PreparedStatement, query: Query, logger: Logger, fields: SelectedFieldsOrdered | undefined, executeMethod: SQLiteExecuteMethod, _isResponseInArrayMode: boolean, customResultMapper?: (rows: unknown[][]) => unknown); | ||
constructor(stmt: D1PreparedStatement, query: Query, logger: Logger, fields: SelectedFieldsOrdered | undefined, executeMethod: SQLiteExecuteMethod, _isResponseInArrayMode: boolean, customResultMapper?: ((rows: TIsRqbV2 extends true ? Record<string, unknown>[] : unknown[][]) => unknown) | undefined, isRqbV2Query?: TIsRqbV2 | undefined); | ||
run(placeholderValues?: Record<string, unknown>): Promise<D1Response>; | ||
all(placeholderValues?: Record<string, unknown>): Promise<T['all']>; | ||
private allRqbV2; | ||
mapAllResult(rows: unknown, isFromBatch?: boolean): unknown; | ||
get(placeholderValues?: Record<string, unknown>): Promise<T['get']>; | ||
private getRqbV2; | ||
mapGetResult(result: unknown, isFromBatch?: boolean): unknown; | ||
@@ -54,0 +61,0 @@ values<T extends any[] = unknown[]>(placeholderValues?: Record<string, unknown>): Promise<T[]>; |
@@ -8,5 +8,6 @@ import { entityKind } from "../entity.js"; | ||
class SQLiteD1Session extends SQLiteSession { | ||
constructor(client, dialect, schema, options = {}) { | ||
constructor(client, dialect, relations, schema, options = {}) { | ||
super(dialect); | ||
this.client = client; | ||
this.relations = relations; | ||
this.schema = schema; | ||
@@ -30,2 +31,15 @@ this.options = options; | ||
} | ||
prepareRelationalQuery(query, fields, executeMethod, customResultMapper) { | ||
const stmt = this.client.prepare(query.sql); | ||
return new D1PreparedQuery( | ||
stmt, | ||
query, | ||
this.logger, | ||
fields, | ||
executeMethod, | ||
false, | ||
customResultMapper, | ||
true | ||
); | ||
} | ||
async batch(queries) { | ||
@@ -60,3 +74,3 @@ const preparedQueries = []; | ||
async transaction(transaction, config) { | ||
const tx = new D1Transaction("async", this.dialect, this, this.schema); | ||
const tx = new D1Transaction("async", this.dialect, this, this.relations, this.schema); | ||
await this.run(sql.raw(`begin${config?.behavior ? " " + config.behavior : ""}`)); | ||
@@ -77,3 +91,10 @@ try { | ||
const savepointName = `sp${this.nestedIndex}`; | ||
const tx = new D1Transaction("async", this.dialect, this.session, this.schema, this.nestedIndex + 1); | ||
const tx = new D1Transaction( | ||
"async", | ||
this.dialect, | ||
this.session, | ||
this.relations, | ||
this.schema, | ||
this.nestedIndex + 1 | ||
); | ||
await this.session.run(sql.raw(`savepoint ${savepointName}`)); | ||
@@ -99,3 +120,3 @@ try { | ||
class D1PreparedQuery extends SQLitePreparedQuery { | ||
constructor(stmt, query, logger, fields, executeMethod, _isResponseInArrayMode, customResultMapper) { | ||
constructor(stmt, query, logger, fields, executeMethod, _isResponseInArrayMode, customResultMapper, isRqbV2Query) { | ||
super("async", executeMethod, query); | ||
@@ -105,2 +126,3 @@ this.logger = logger; | ||
this.customResultMapper = customResultMapper; | ||
this.isRqbV2Query = isRqbV2Query; | ||
this.fields = fields; | ||
@@ -111,4 +133,2 @@ this.stmt = stmt; | ||
/** @internal */ | ||
customResultMapper; | ||
/** @internal */ | ||
fields; | ||
@@ -123,2 +143,4 @@ /** @internal */ | ||
async all(placeholderValues) { | ||
if (this.isRqbV2Query) | ||
return this.allRqbV2(placeholderValues); | ||
const { fields, query, logger, stmt, customResultMapper } = this; | ||
@@ -133,2 +155,10 @@ if (!fields && !customResultMapper) { | ||
} | ||
async allRqbV2(placeholderValues) { | ||
const { query, logger, stmt, customResultMapper } = this; | ||
const params = fillPlaceholders(query.params, placeholderValues ?? {}); | ||
logger.logQuery(query.sql, params); | ||
return stmt.bind(...params).all().then( | ||
({ results }) => customResultMapper(results) | ||
); | ||
} | ||
mapAllResult(rows, isFromBatch) { | ||
@@ -147,2 +177,4 @@ if (isFromBatch) { | ||
async get(placeholderValues) { | ||
if (this.isRqbV2Query) | ||
return this.getRqbV2(placeholderValues); | ||
const { fields, joinsNotNullableMap, query, logger, stmt, customResultMapper } = this; | ||
@@ -163,2 +195,12 @@ if (!fields && !customResultMapper) { | ||
} | ||
async getRqbV2(placeholderValues) { | ||
const { query, logger, stmt, customResultMapper } = this; | ||
const params = fillPlaceholders(query.params, placeholderValues ?? {}); | ||
logger.logQuery(query.sql, params); | ||
const { results: rows } = await stmt.bind(...params).all(); | ||
if (!rows[0]) { | ||
return void 0; | ||
} | ||
return customResultMapper(rows); | ||
} | ||
mapGetResult(result, isFromBatch) { | ||
@@ -165,0 +207,0 @@ if (isFromBatch) { |
import type { SQLiteDatabase, SQLiteRunResult } from 'expo-sqlite'; | ||
import { entityKind } from "../entity.js"; | ||
import type { AnyRelations, EmptyRelations } from "../relations.js"; | ||
import { BaseSQLiteDatabase } from "../sqlite-core/db.js"; | ||
import type { DrizzleConfig } from "../utils.js"; | ||
export declare class ExpoSQLiteDatabase<TSchema extends Record<string, unknown> = Record<string, never>> extends BaseSQLiteDatabase<'sync', SQLiteRunResult, TSchema> { | ||
export declare class ExpoSQLiteDatabase<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations> extends BaseSQLiteDatabase<'sync', SQLiteRunResult, TSchema, TRelations> { | ||
static readonly [entityKind]: string; | ||
} | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(client: SQLiteDatabase, config?: DrizzleConfig<TSchema>): ExpoSQLiteDatabase<TSchema> & { | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations>(client: SQLiteDatabase, config?: DrizzleConfig<TSchema, TRelations>): ExpoSQLiteDatabase<TSchema, TRelations> & { | ||
$client: SQLiteDatabase; | ||
}; |
@@ -0,7 +1,4 @@ | ||
import * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
import { DefaultLogger } from "../logger.js"; | ||
import { | ||
createTableRelationsHelpers, | ||
extractTablesRelationalConfig | ||
} from "../relations.js"; | ||
import { BaseSQLiteDatabase } from "../sqlite-core/db.js"; | ||
@@ -23,5 +20,5 @@ import { SQLiteSyncDialect } from "../sqlite-core/dialect.js"; | ||
if (config.schema) { | ||
const tablesConfig = extractTablesRelationalConfig( | ||
const tablesConfig = V1.extractTablesRelationalConfig( | ||
config.schema, | ||
createTableRelationsHelpers | ||
V1.createTableRelationsHelpers | ||
); | ||
@@ -34,4 +31,11 @@ schema = { | ||
} | ||
const session = new ExpoSQLiteSession(client, dialect, schema, { logger }); | ||
const db = new ExpoSQLiteDatabase("sync", dialect, session, schema); | ||
const relations = config.relations; | ||
const session = new ExpoSQLiteSession(client, dialect, relations, schema, { logger }); | ||
const db = new ExpoSQLiteDatabase( | ||
"sync", | ||
dialect, | ||
session, | ||
relations, | ||
schema | ||
); | ||
db.$client = client; | ||
@@ -38,0 +42,0 @@ return db; |
@@ -0,1 +1,2 @@ | ||
import type { AnyRelations, EmptyRelations } from "../relations.js"; | ||
import type { ExpoSQLiteDatabase } from "./driver.js"; | ||
@@ -13,3 +14,3 @@ interface MigrationConfig { | ||
} | ||
export declare function migrate<TSchema extends Record<string, unknown>>(db: ExpoSQLiteDatabase<TSchema>, config: MigrationConfig): Promise<void>; | ||
export declare function migrate<TSchema extends Record<string, unknown>, TRelations extends AnyRelations = EmptyRelations>(db: ExpoSQLiteDatabase<TSchema, TRelations>, config: MigrationConfig): Promise<void>; | ||
interface State { | ||
@@ -19,3 +20,3 @@ success: boolean; | ||
} | ||
export declare const useMigrations: (db: ExpoSQLiteDatabase<any>, migrations: { | ||
export declare const useMigrations: (db: ExpoSQLiteDatabase<any, any>, migrations: { | ||
journal: { | ||
@@ -22,0 +23,0 @@ entries: { |
import type { AnySQLiteSelect } from "../sqlite-core/index.js"; | ||
import * as V1 from "../sqlite-core/query-builders/_query.js"; | ||
import { SQLiteRelationalQuery } from "../sqlite-core/query-builders/query.js"; | ||
export declare const useLiveQuery: <T extends Pick<AnySQLiteSelect, "_" | "then"> | SQLiteRelationalQuery<"sync", unknown>>(query: T, deps?: unknown[]) => { | ||
export declare const useLiveQuery: <T extends Pick<AnySQLiteSelect, "_" | "then"> | SQLiteRelationalQuery<"sync", unknown> | V1.SQLiteRelationalQuery<"sync", unknown>>(query: T, deps?: unknown[]) => { | ||
readonly data: Awaited<T>; | ||
@@ -5,0 +6,0 @@ readonly error: Error | undefined; |
@@ -6,2 +6,3 @@ import { addDatabaseChangeListener } from "expo-sqlite"; | ||
import { getTableConfig, getViewConfig, SQLiteTable, SQLiteView } from "../sqlite-core/index.js"; | ||
import * as V1 from "../sqlite-core/query-builders/_query.js"; | ||
import { SQLiteRelationalQuery } from "../sqlite-core/query-builders/query.js"; | ||
@@ -11,3 +12,3 @@ import { Subquery } from "../subquery.js"; | ||
const [data, setData] = useState( | ||
is(query, SQLiteRelationalQuery) && query.mode === "first" ? void 0 : [] | ||
is(query, V1.SQLiteRelationalQuery) || is(query, SQLiteRelationalQuery) && query.mode === "first" ? void 0 : [] | ||
); | ||
@@ -17,3 +18,3 @@ const [error, setError] = useState(); | ||
useEffect(() => { | ||
const entity = is(query, SQLiteRelationalQuery) ? query.table : query.config.table; | ||
const entity = is(query, V1.SQLiteRelationalQuery) || is(query, SQLiteRelationalQuery) ? query.table : query.config.table; | ||
if (is(entity, Subquery) || is(entity, SQL)) { | ||
@@ -20,0 +21,0 @@ setError(new Error("Selecting from subqueries and SQL are not supported in useLiveQuery")); |
import type { SQLiteDatabase, SQLiteRunResult, SQLiteStatement } from 'expo-sqlite'; | ||
import type * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
import type { Logger } from "../logger.js"; | ||
import type { RelationalSchemaConfig, TablesRelationalConfig } from "../relations.js"; | ||
import type { AnyRelations, TablesRelationalConfig } from "../relations.js"; | ||
import { type Query } from "../sql/sql.js"; | ||
@@ -14,16 +15,18 @@ import type { SQLiteSyncDialect } from "../sqlite-core/dialect.js"; | ||
type PreparedQueryConfig = Omit<PreparedQueryConfigBase, 'statement' | 'run'>; | ||
export declare class ExpoSQLiteSession<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends SQLiteSession<'sync', SQLiteRunResult, TFullSchema, TSchema> { | ||
export declare class ExpoSQLiteSession<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends SQLiteSession<'sync', SQLiteRunResult, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
private client; | ||
private relations; | ||
private schema; | ||
static readonly [entityKind]: string; | ||
private logger; | ||
constructor(client: SQLiteDatabase, dialect: SQLiteSyncDialect, schema: RelationalSchemaConfig<TSchema> | undefined, options?: ExpoSQLiteSessionOptions); | ||
constructor(client: SQLiteDatabase, dialect: SQLiteSyncDialect, relations: AnyRelations | undefined, schema: V1.RelationalSchemaConfig<TSchema> | undefined, options?: ExpoSQLiteSessionOptions); | ||
prepareQuery<T extends Omit<PreparedQueryConfig, 'run'>>(query: Query, fields: SelectedFieldsOrdered | undefined, executeMethod: SQLiteExecuteMethod, isResponseInArrayMode: boolean, customResultMapper?: (rows: unknown[][]) => unknown): ExpoSQLitePreparedQuery<T>; | ||
transaction<T>(transaction: (tx: ExpoSQLiteTransaction<TFullSchema, TSchema>) => T, config?: SQLiteTransactionConfig): T; | ||
prepareRelationalQuery<T extends Omit<PreparedQueryConfig, 'run'>>(query: Query, fields: SelectedFieldsOrdered | undefined, executeMethod: SQLiteExecuteMethod, customResultMapper: (rows: Record<string, unknown>[]) => unknown): ExpoSQLitePreparedQuery<T, true>; | ||
transaction<T>(transaction: (tx: ExpoSQLiteTransaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => T, config?: SQLiteTransactionConfig): T; | ||
} | ||
export declare class ExpoSQLiteTransaction<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends SQLiteTransaction<'sync', SQLiteRunResult, TFullSchema, TSchema> { | ||
export declare class ExpoSQLiteTransaction<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends SQLiteTransaction<'sync', SQLiteRunResult, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
static readonly [entityKind]: string; | ||
transaction<T>(transaction: (tx: ExpoSQLiteTransaction<TFullSchema, TSchema>) => T): T; | ||
transaction<T>(transaction: (tx: ExpoSQLiteTransaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => T): T; | ||
} | ||
export declare class ExpoSQLitePreparedQuery<T extends PreparedQueryConfig = PreparedQueryConfig> extends SQLitePreparedQuery<{ | ||
export declare class ExpoSQLitePreparedQuery<T extends PreparedQueryConfig = PreparedQueryConfig, TIsRqbV2 extends boolean = false> extends SQLitePreparedQuery<{ | ||
type: 'sync'; | ||
@@ -41,9 +44,12 @@ run: SQLiteRunResult; | ||
private customResultMapper?; | ||
private isRqbV2Query?; | ||
static readonly [entityKind]: string; | ||
constructor(stmt: SQLiteStatement, query: Query, logger: Logger, fields: SelectedFieldsOrdered | undefined, executeMethod: SQLiteExecuteMethod, _isResponseInArrayMode: boolean, customResultMapper?: ((rows: unknown[][]) => unknown) | undefined); | ||
constructor(stmt: SQLiteStatement, query: Query, logger: Logger, fields: SelectedFieldsOrdered | undefined, executeMethod: SQLiteExecuteMethod, _isResponseInArrayMode: boolean, customResultMapper?: ((rows: TIsRqbV2 extends true ? Record<string, unknown>[] : unknown[][]) => unknown) | undefined, isRqbV2Query?: TIsRqbV2 | undefined); | ||
run(placeholderValues?: Record<string, unknown>): SQLiteRunResult; | ||
all(placeholderValues?: Record<string, unknown>): T['all']; | ||
private allRqbV2; | ||
get(placeholderValues?: Record<string, unknown>): T['get']; | ||
private getRqbV2; | ||
values(placeholderValues?: Record<string, unknown>): T['values']; | ||
} | ||
export {}; |
@@ -11,5 +11,6 @@ import { entityKind } from "../entity.js"; | ||
class ExpoSQLiteSession extends SQLiteSession { | ||
constructor(client, dialect, schema, options = {}) { | ||
constructor(client, dialect, relations, schema, options = {}) { | ||
super(dialect); | ||
this.client = client; | ||
this.relations = relations; | ||
this.schema = schema; | ||
@@ -32,4 +33,17 @@ this.logger = options.logger ?? new NoopLogger(); | ||
} | ||
prepareRelationalQuery(query, fields, executeMethod, customResultMapper) { | ||
const stmt = this.client.prepareSync(query.sql); | ||
return new ExpoSQLitePreparedQuery( | ||
stmt, | ||
query, | ||
this.logger, | ||
fields, | ||
executeMethod, | ||
false, | ||
customResultMapper, | ||
true | ||
); | ||
} | ||
transaction(transaction, config = {}) { | ||
const tx = new ExpoSQLiteTransaction("sync", this.dialect, this, this.schema); | ||
const tx = new ExpoSQLiteTransaction("sync", this.dialect, this, this.relations, this.schema); | ||
this.run(sql.raw(`begin${config?.behavior ? " " + config.behavior : ""}`)); | ||
@@ -50,3 +64,10 @@ try { | ||
const savepointName = `sp${this.nestedIndex}`; | ||
const tx = new ExpoSQLiteTransaction("sync", this.dialect, this.session, this.schema, this.nestedIndex + 1); | ||
const tx = new ExpoSQLiteTransaction( | ||
"sync", | ||
this.dialect, | ||
this.session, | ||
this.relations, | ||
this.schema, | ||
this.nestedIndex + 1 | ||
); | ||
this.session.run(sql.raw(`savepoint ${savepointName}`)); | ||
@@ -64,3 +85,3 @@ try { | ||
class ExpoSQLitePreparedQuery extends SQLitePreparedQuery { | ||
constructor(stmt, query, logger, fields, executeMethod, _isResponseInArrayMode, customResultMapper) { | ||
constructor(stmt, query, logger, fields, executeMethod, _isResponseInArrayMode, customResultMapper, isRqbV2Query) { | ||
super("sync", executeMethod, query); | ||
@@ -72,2 +93,3 @@ this.stmt = stmt; | ||
this.customResultMapper = customResultMapper; | ||
this.isRqbV2Query = isRqbV2Query; | ||
} | ||
@@ -85,2 +107,4 @@ static [entityKind] = "ExpoSQLitePreparedQuery"; | ||
all(placeholderValues) { | ||
if (this.isRqbV2Query) | ||
return this.allRqbV2(placeholderValues); | ||
const { fields, joinsNotNullableMap, query, logger, stmt, customResultMapper } = this; | ||
@@ -98,3 +122,12 @@ if (!fields && !customResultMapper) { | ||
} | ||
allRqbV2(placeholderValues) { | ||
const { query, logger, stmt, customResultMapper } = this; | ||
const params = fillPlaceholders(query.params, placeholderValues ?? {}); | ||
logger.logQuery(query.sql, params); | ||
const rows = stmt.executeSync(params).getAllSync(); | ||
return customResultMapper(rows); | ||
} | ||
get(placeholderValues) { | ||
if (this.isRqbV2Query) | ||
return this.getRqbV2(placeholderValues); | ||
const params = fillPlaceholders(this.query.params, placeholderValues ?? {}); | ||
@@ -116,2 +149,12 @@ this.logger.logQuery(this.query.sql, params); | ||
} | ||
getRqbV2(placeholderValues) { | ||
const params = fillPlaceholders(this.query.params, placeholderValues ?? {}); | ||
this.logger.logQuery(this.query.sql, params); | ||
const { stmt, customResultMapper } = this; | ||
const row = stmt.executeSync(params).getFirstSync(); | ||
if (!row) { | ||
return void 0; | ||
} | ||
return customResultMapper([row]); | ||
} | ||
values(placeholderValues) { | ||
@@ -118,0 +161,0 @@ const params = fillPlaceholders(this.query.params, placeholderValues ?? {}); |
import type { ResultSet } from '@libsql/client'; | ||
import type { BatchItem, BatchResponse } from "../batch.js"; | ||
import { entityKind } from "../entity.js"; | ||
import type { AnyRelations, EmptyRelations } from "../relations.js"; | ||
import { BaseSQLiteDatabase } from "../sqlite-core/db.js"; | ||
export declare class LibSQLDatabase<TSchema extends Record<string, unknown> = Record<string, never>> extends BaseSQLiteDatabase<'async', ResultSet, TSchema> { | ||
export declare class LibSQLDatabase<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations> extends BaseSQLiteDatabase<'async', ResultSet, TSchema, TRelations> { | ||
static readonly [entityKind]: string; | ||
batch<U extends BatchItem<'sqlite'>, T extends Readonly<[U, ...U[]]>>(batch: T): Promise<BatchResponse<T>>; | ||
} |
@@ -0,7 +1,4 @@ | ||
import * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
import { DefaultLogger } from "../logger.js"; | ||
import { | ||
createTableRelationsHelpers, | ||
extractTablesRelationalConfig | ||
} from "../relations.js"; | ||
import { BaseSQLiteDatabase } from "../sqlite-core/db.js"; | ||
@@ -26,5 +23,5 @@ import { SQLiteAsyncDialect } from "../sqlite-core/dialect.js"; | ||
if (config.schema) { | ||
const tablesConfig = extractTablesRelationalConfig( | ||
const tablesConfig = V1.extractTablesRelationalConfig( | ||
config.schema, | ||
createTableRelationsHelpers | ||
V1.createTableRelationsHelpers | ||
); | ||
@@ -37,4 +34,11 @@ schema = { | ||
} | ||
const session = new LibSQLSession(client, dialect, schema, { logger }, void 0); | ||
const db = new LibSQLDatabase("async", dialect, session, schema); | ||
const relations = config.relations; | ||
const session = new LibSQLSession(client, dialect, relations, schema, { logger }, void 0); | ||
const db = new LibSQLDatabase( | ||
"async", | ||
dialect, | ||
session, | ||
relations, | ||
schema | ||
); | ||
db.$client = client; | ||
@@ -41,0 +45,0 @@ return db; |
import { type Client, type Config } from '@libsql/client'; | ||
import type { AnyRelations, EmptyRelations } from "../relations.js"; | ||
import { type DrizzleConfig } from "../utils.js"; | ||
import { type LibSQLDatabase } from "./driver-core.js"; | ||
export { LibSQLDatabase } from "./driver-core.js"; | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TClient extends Client = Client>(...params: [ | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations, TClient extends Client = Client>(...params: [ | ||
TClient | string | ||
] | [ | ||
TClient | string, | ||
DrizzleConfig<TSchema> | ||
DrizzleConfig<TSchema, TRelations> | ||
] | [ | ||
(DrizzleConfig<TSchema> & ({ | ||
(DrizzleConfig<TSchema, TRelations> & ({ | ||
connection: string | Config; | ||
@@ -16,9 +17,9 @@ } | { | ||
})) | ||
]): LibSQLDatabase<TSchema> & { | ||
]): LibSQLDatabase<TSchema, TRelations> & { | ||
$client: TClient; | ||
}; | ||
export declare namespace drizzle { | ||
function mock<TSchema extends Record<string, unknown> = Record<string, never>>(config?: DrizzleConfig<TSchema>): LibSQLDatabase<TSchema> & { | ||
function mock<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations>(config?: DrizzleConfig<TSchema, TRelations>): LibSQLDatabase<TSchema, TRelations> & { | ||
$client: '$client is not available on drizzle.mock()'; | ||
}; | ||
} |
import { type Client, type Config } from '@libsql/client/http'; | ||
import type { AnyRelations, EmptyRelations } from "../../relations.js"; | ||
import { type DrizzleConfig } from "../../utils.js"; | ||
import { type LibSQLDatabase } from "../driver-core.js"; | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TClient extends Client = Client>(...params: [ | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations, TClient extends Client = Client>(...params: [ | ||
TClient | string | ||
] | [ | ||
TClient | string, | ||
DrizzleConfig<TSchema> | ||
DrizzleConfig<TSchema, TRelations> | ||
] | [ | ||
(DrizzleConfig<TSchema> & ({ | ||
(DrizzleConfig<TSchema, TRelations> & ({ | ||
connection: string | Config; | ||
@@ -15,9 +16,9 @@ } | { | ||
})) | ||
]): LibSQLDatabase<TSchema> & { | ||
]): LibSQLDatabase<TSchema, TRelations> & { | ||
$client: TClient; | ||
}; | ||
export declare namespace drizzle { | ||
function mock<TSchema extends Record<string, unknown> = Record<string, never>>(config?: DrizzleConfig<TSchema>): LibSQLDatabase<TSchema> & { | ||
function mock<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations>(config?: DrizzleConfig<TSchema, TRelations>): LibSQLDatabase<TSchema, TRelations> & { | ||
$client: '$client is not available on drizzle.mock()'; | ||
}; | ||
} |
import type { MigrationConfig } from "../migrator.js"; | ||
import type { AnyRelations } from "../relations.js"; | ||
import type { LibSQLDatabase } from "./driver.js"; | ||
export declare function migrate<TSchema extends Record<string, unknown>>(db: LibSQLDatabase<TSchema>, config: MigrationConfig): Promise<void>; | ||
export declare function migrate<TSchema extends Record<string, unknown>, TRelations extends AnyRelations>(db: LibSQLDatabase<TSchema, TRelations>, config: MigrationConfig): Promise<void>; |
import { type Client, type Config } from '@libsql/client/node'; | ||
import type { AnyRelations, EmptyRelations } from "../../relations.js"; | ||
import { type DrizzleConfig } from "../../utils.js"; | ||
import { type LibSQLDatabase } from "../driver-core.js"; | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TClient extends Client = Client>(...params: [ | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations, TClient extends Client = Client>(...params: [ | ||
TClient | string | ||
] | [ | ||
TClient | string, | ||
DrizzleConfig<TSchema> | ||
DrizzleConfig<TSchema, TRelations> | ||
] | [ | ||
(DrizzleConfig<TSchema> & ({ | ||
(DrizzleConfig<TSchema, TRelations> & ({ | ||
connection: string | Config; | ||
@@ -15,9 +16,9 @@ } | { | ||
})) | ||
]): LibSQLDatabase<TSchema> & { | ||
]): LibSQLDatabase<TSchema, TRelations> & { | ||
$client: TClient; | ||
}; | ||
export declare namespace drizzle { | ||
function mock<TSchema extends Record<string, unknown> = Record<string, never>>(config?: DrizzleConfig<TSchema>): LibSQLDatabase<TSchema> & { | ||
function mock<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations>(config?: DrizzleConfig<TSchema, TRelations>): LibSQLDatabase<TSchema, TRelations> & { | ||
$client: '$client is not available on drizzle.mock()'; | ||
}; | ||
} |
import type { Client, ResultSet, Transaction } from '@libsql/client'; | ||
import type * as V1 from "../_relations.js"; | ||
import type { BatchItem as BatchItem } from "../batch.js"; | ||
import { entityKind } from "../entity.js"; | ||
import type { Logger } from "../logger.js"; | ||
import type { RelationalSchemaConfig, TablesRelationalConfig } from "../relations.js"; | ||
import type { AnyRelations, TablesRelationalConfig } from "../relations.js"; | ||
import { type Query } from "../sql/sql.js"; | ||
@@ -16,4 +17,5 @@ import type { SQLiteAsyncDialect } from "../sqlite-core/dialect.js"; | ||
type PreparedQueryConfig = Omit<PreparedQueryConfigBase, 'statement' | 'run'>; | ||
export declare class LibSQLSession<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends SQLiteSession<'async', ResultSet, TFullSchema, TSchema> { | ||
export declare class LibSQLSession<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends SQLiteSession<'async', ResultSet, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
private client; | ||
private relations; | ||
private schema; | ||
@@ -24,7 +26,8 @@ private options; | ||
private logger; | ||
constructor(client: Client, dialect: SQLiteAsyncDialect, schema: RelationalSchemaConfig<TSchema> | undefined, options: LibSQLSessionOptions, tx: Transaction | undefined); | ||
constructor(client: Client, dialect: SQLiteAsyncDialect, relations: AnyRelations | undefined, schema: V1.RelationalSchemaConfig<TSchema> | undefined, options: LibSQLSessionOptions, tx: Transaction | undefined); | ||
prepareQuery<T extends Omit<PreparedQueryConfig, 'run'>>(query: Query, fields: SelectedFieldsOrdered | undefined, executeMethod: SQLiteExecuteMethod, isResponseInArrayMode: boolean, customResultMapper?: (rows: unknown[][]) => unknown): LibSQLPreparedQuery<T>; | ||
prepareRelationalQuery<T extends Omit<PreparedQueryConfig, 'run'>>(query: Query, fields: SelectedFieldsOrdered | undefined, executeMethod: SQLiteExecuteMethod, customResultMapper: (rows: Record<string, unknown>[]) => unknown): LibSQLPreparedQuery<T, true>; | ||
batch<T extends BatchItem<'sqlite'>[] | readonly BatchItem<'sqlite'>[]>(queries: T): Promise<unknown[]>; | ||
migrate<T extends BatchItem<'sqlite'>[] | readonly BatchItem<'sqlite'>[]>(queries: T): Promise<unknown[]>; | ||
transaction<T>(transaction: (db: LibSQLTransaction<TFullSchema, TSchema>) => T | Promise<T>, _config?: SQLiteTransactionConfig): Promise<T>; | ||
transaction<T>(transaction: (db: LibSQLTransaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => T | Promise<T>, _config?: SQLiteTransactionConfig): Promise<T>; | ||
extractRawAllValueFromBatchResult(result: unknown): unknown; | ||
@@ -34,7 +37,7 @@ extractRawGetValueFromBatchResult(result: unknown): unknown; | ||
} | ||
export declare class LibSQLTransaction<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends SQLiteTransaction<'async', ResultSet, TFullSchema, TSchema> { | ||
export declare class LibSQLTransaction<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends SQLiteTransaction<'async', ResultSet, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
static readonly [entityKind]: string; | ||
transaction<T>(transaction: (tx: LibSQLTransaction<TFullSchema, TSchema>) => Promise<T>): Promise<T>; | ||
transaction<T>(transaction: (tx: LibSQLTransaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => Promise<T>): Promise<T>; | ||
} | ||
export declare class LibSQLPreparedQuery<T extends PreparedQueryConfig = PreparedQueryConfig> extends SQLitePreparedQuery<{ | ||
export declare class LibSQLPreparedQuery<T extends PreparedQueryConfig = PreparedQueryConfig, TIsRqbV2 extends boolean = false> extends SQLitePreparedQuery<{ | ||
type: 'async'; | ||
@@ -51,10 +54,13 @@ run: ResultSet; | ||
private _isResponseInArrayMode; | ||
private customResultMapper?; | ||
private isRqbV2Query?; | ||
static readonly [entityKind]: string; | ||
constructor(client: Client, query: Query, logger: Logger, | ||
/** @internal */ fields: SelectedFieldsOrdered | undefined, tx: Transaction | undefined, executeMethod: SQLiteExecuteMethod, _isResponseInArrayMode: boolean, | ||
/** @internal */ customResultMapper?: ((rows: unknown[][], mapColumnValue?: (value: unknown) => unknown) => unknown) | undefined); | ||
/** @internal */ fields: SelectedFieldsOrdered | undefined, tx: Transaction | undefined, executeMethod: SQLiteExecuteMethod, _isResponseInArrayMode: boolean, customResultMapper?: ((rows: TIsRqbV2 extends true ? Record<string, unknown>[] : unknown[][], mapColumnValue?: (value: unknown) => unknown) => unknown) | undefined, isRqbV2Query?: TIsRqbV2 | undefined); | ||
run(placeholderValues?: Record<string, unknown>): Promise<ResultSet>; | ||
all(placeholderValues?: Record<string, unknown>): Promise<T['all']>; | ||
private allRqbV2; | ||
mapAllResult(rows: unknown, isFromBatch?: boolean): unknown; | ||
get(placeholderValues?: Record<string, unknown>): Promise<T['get']>; | ||
private getRqbV2; | ||
mapGetResult(rows: unknown, isFromBatch?: boolean): unknown; | ||
@@ -61,0 +67,0 @@ values(placeholderValues?: Record<string, unknown>): Promise<T['values']>; |
@@ -8,5 +8,6 @@ import { entityKind } from "../entity.js"; | ||
class LibSQLSession extends SQLiteSession { | ||
constructor(client, dialect, schema, options, tx) { | ||
constructor(client, dialect, relations, schema, options, tx) { | ||
super(dialect); | ||
this.client = client; | ||
this.relations = relations; | ||
this.schema = schema; | ||
@@ -31,2 +32,15 @@ this.options = options; | ||
} | ||
prepareRelationalQuery(query, fields, executeMethod, customResultMapper) { | ||
return new LibSQLPreparedQuery( | ||
this.client, | ||
query, | ||
this.logger, | ||
fields, | ||
this.tx, | ||
executeMethod, | ||
false, | ||
customResultMapper, | ||
true | ||
); | ||
} | ||
async batch(queries) { | ||
@@ -61,2 +75,3 @@ const preparedQueries = []; | ||
this.dialect, | ||
this.relations, | ||
this.schema, | ||
@@ -66,3 +81,9 @@ this.options, | ||
); | ||
const tx = new LibSQLTransaction("async", this.dialect, session, this.schema); | ||
const tx = new LibSQLTransaction( | ||
"async", | ||
this.dialect, | ||
session, | ||
this.relations, | ||
this.schema | ||
); | ||
try { | ||
@@ -91,3 +112,10 @@ const result = await transaction(tx); | ||
const savepointName = `sp${this.nestedIndex}`; | ||
const tx = new LibSQLTransaction("async", this.dialect, this.session, this.schema, this.nestedIndex + 1); | ||
const tx = new LibSQLTransaction( | ||
"async", | ||
this.dialect, | ||
this.session, | ||
this.relations, | ||
this.schema, | ||
this.nestedIndex + 1 | ||
); | ||
await this.session.run(sql.raw(`savepoint ${savepointName}`)); | ||
@@ -105,3 +133,3 @@ try { | ||
class LibSQLPreparedQuery extends SQLitePreparedQuery { | ||
constructor(client, query, logger, fields, tx, executeMethod, _isResponseInArrayMode, customResultMapper) { | ||
constructor(client, query, logger, fields, tx, executeMethod, _isResponseInArrayMode, customResultMapper, isRqbV2Query) { | ||
super("async", executeMethod, query); | ||
@@ -114,2 +142,3 @@ this.client = client; | ||
this.customResultMapper = customResultMapper; | ||
this.isRqbV2Query = isRqbV2Query; | ||
this.customResultMapper = customResultMapper; | ||
@@ -126,2 +155,4 @@ this.fields = fields; | ||
async all(placeholderValues) { | ||
if (this.isRqbV2Query) | ||
return this.allRqbV2(placeholderValues); | ||
const { fields, logger, query, tx, client, customResultMapper } = this; | ||
@@ -137,2 +168,12 @@ if (!fields && !customResultMapper) { | ||
} | ||
async allRqbV2(placeholderValues) { | ||
const { logger, query, tx, client, customResultMapper } = this; | ||
const params = fillPlaceholders(query.params, placeholderValues ?? {}); | ||
logger.logQuery(query.sql, params); | ||
const stmt = { sql: query.sql, args: params }; | ||
if (tx) | ||
return tx.execute(stmt); | ||
const rows = await client.execute(stmt).then(({ rows: rows2 }) => rows2.map((row) => normalizeRow(row))); | ||
return customResultMapper(rows, normalizeFieldValue); | ||
} | ||
mapAllResult(rows, isFromBatch) { | ||
@@ -157,2 +198,4 @@ if (isFromBatch) { | ||
async get(placeholderValues) { | ||
if (this.isRqbV2Query) | ||
return this.getRqbV2(placeholderValues); | ||
const { fields, logger, query, tx, client, customResultMapper } = this; | ||
@@ -168,2 +211,15 @@ if (!fields && !customResultMapper) { | ||
} | ||
async getRqbV2(placeholderValues) { | ||
const { logger, query, tx, client, customResultMapper } = this; | ||
const params = fillPlaceholders(query.params, placeholderValues ?? {}); | ||
logger.logQuery(query.sql, params); | ||
const stmt = { sql: query.sql, args: params }; | ||
if (tx) | ||
return tx.execute(stmt); | ||
const { rows } = await client.execute(stmt); | ||
const row = normalizeRow(rows[0]); | ||
if (!row) | ||
return; | ||
return customResultMapper([row], normalizeFieldValue); | ||
} | ||
mapGetResult(rows, isFromBatch) { | ||
@@ -170,0 +226,0 @@ if (isFromBatch) { |
import { type Client, type Config } from '@libsql/client/sqlite3'; | ||
import type { AnyRelations, EmptyRelations } from "../../relations.js"; | ||
import { type DrizzleConfig } from "../../utils.js"; | ||
import { type LibSQLDatabase } from "../driver-core.js"; | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TClient extends Client = Client>(...params: [ | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations, TClient extends Client = Client>(...params: [ | ||
TClient | string | ||
] | [ | ||
TClient | string, | ||
DrizzleConfig<TSchema> | ||
DrizzleConfig<TSchema, TRelations> | ||
] | [ | ||
(DrizzleConfig<TSchema> & ({ | ||
(DrizzleConfig<TSchema, TRelations> & ({ | ||
connection: string | Config; | ||
@@ -15,9 +16,9 @@ } | { | ||
})) | ||
]): LibSQLDatabase<TSchema> & { | ||
]): LibSQLDatabase<TSchema, TRelations> & { | ||
$client: TClient; | ||
}; | ||
export declare namespace drizzle { | ||
function mock<TSchema extends Record<string, unknown> = Record<string, never>>(config?: DrizzleConfig<TSchema>): LibSQLDatabase<TSchema> & { | ||
function mock<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations>(config?: DrizzleConfig<TSchema, TRelations>): LibSQLDatabase<TSchema, TRelations> & { | ||
$client: '$client is not available on drizzle.mock()'; | ||
}; | ||
} |
import { type Client, type Config } from '@libsql/client-wasm'; | ||
import type { AnyRelations, EmptyRelations } from "../../relations.js"; | ||
import { type DrizzleConfig } from "../../utils.js"; | ||
import { type LibSQLDatabase } from "../driver-core.js"; | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TClient extends Client = Client>(...params: [ | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations, TClient extends Client = Client>(...params: [ | ||
TClient | string | ||
] | [ | ||
TClient | string, | ||
DrizzleConfig<TSchema> | ||
DrizzleConfig<TSchema, TRelations> | ||
] | [ | ||
(DrizzleConfig<TSchema> & ({ | ||
(DrizzleConfig<TSchema, TRelations> & ({ | ||
connection: string | Config; | ||
@@ -15,9 +16,9 @@ } | { | ||
})) | ||
]): LibSQLDatabase<TSchema> & { | ||
]): LibSQLDatabase<TSchema, TRelations> & { | ||
$client: TClient; | ||
}; | ||
export declare namespace drizzle { | ||
function mock<TSchema extends Record<string, unknown> = Record<string, never>>(config?: DrizzleConfig<TSchema>): LibSQLDatabase<TSchema> & { | ||
function mock<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations>(config?: DrizzleConfig<TSchema, TRelations>): LibSQLDatabase<TSchema, TRelations> & { | ||
$client: '$client is not available on drizzle.mock()'; | ||
}; | ||
} |
import { type Client, type Config } from '@libsql/client/web'; | ||
import type { AnyRelations, EmptyRelations } from "../../relations.js"; | ||
import { type DrizzleConfig } from "../../utils.js"; | ||
import { type LibSQLDatabase } from "../driver-core.js"; | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TClient extends Client = Client>(...params: [ | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations, TClient extends Client = Client>(...params: [ | ||
TClient | string | ||
] | [ | ||
TClient | string, | ||
DrizzleConfig<TSchema> | ||
DrizzleConfig<TSchema, TRelations> | ||
] | [ | ||
(DrizzleConfig<TSchema> & ({ | ||
(DrizzleConfig<TSchema, TRelations> & ({ | ||
connection: string | Config; | ||
@@ -15,9 +16,9 @@ } | { | ||
})) | ||
]): LibSQLDatabase<TSchema> & { | ||
]): LibSQLDatabase<TSchema, TRelations> & { | ||
$client: TClient; | ||
}; | ||
export declare namespace drizzle { | ||
function mock<TSchema extends Record<string, unknown> = Record<string, never>>(config?: DrizzleConfig<TSchema>): LibSQLDatabase<TSchema> & { | ||
function mock<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations>(config?: DrizzleConfig<TSchema, TRelations>): LibSQLDatabase<TSchema, TRelations> & { | ||
$client: '$client is not available on drizzle.mock()'; | ||
}; | ||
} |
import { type Client, type Config } from '@libsql/client/ws'; | ||
import type { AnyRelations, EmptyRelations } from "../../relations.js"; | ||
import { type DrizzleConfig } from "../../utils.js"; | ||
import { type LibSQLDatabase } from "../driver-core.js"; | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TClient extends Client = Client>(...params: [ | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations, TClient extends Client = Client>(...params: [ | ||
TClient | string | ||
] | [ | ||
TClient | string, | ||
DrizzleConfig<TSchema> | ||
DrizzleConfig<TSchema, TRelations> | ||
] | [ | ||
(DrizzleConfig<TSchema> & ({ | ||
(DrizzleConfig<TSchema, TRelations> & ({ | ||
connection: string | Config; | ||
@@ -15,9 +16,9 @@ } | { | ||
})) | ||
]): LibSQLDatabase<TSchema> & { | ||
]): LibSQLDatabase<TSchema, TRelations> & { | ||
$client: TClient; | ||
}; | ||
export declare namespace drizzle { | ||
function mock<TSchema extends Record<string, unknown> = Record<string, never>>(config?: DrizzleConfig<TSchema>): LibSQLDatabase<TSchema> & { | ||
function mock<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations>(config?: DrizzleConfig<TSchema, TRelations>): LibSQLDatabase<TSchema, TRelations> & { | ||
$client: '$client is not available on drizzle.mock()'; | ||
}; | ||
} |
import type { ResultSetHeader } from 'mysql2/promise'; | ||
import type * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
import type { TypedQueryBuilder } from "../query-builders/query-builder.js"; | ||
import type { ExtractTablesWithRelations, RelationalSchemaConfig, TablesRelationalConfig } from "../relations.js"; | ||
import type { AnyRelations, EmptyRelations, ExtractTablesWithRelations, TablesRelationalConfig } from "../relations.js"; | ||
import { type ColumnsSelection, type SQL, type SQLWrapper } from "../sql/sql.js"; | ||
@@ -9,2 +10,3 @@ import { WithSubquery } from "../subquery.js"; | ||
import type { MySqlDialect } from "./dialect.js"; | ||
import { _RelationalQueryBuilder } from "./query-builders/_query.js"; | ||
import { MySqlCountBuilder } from "./query-builders/count.js"; | ||
@@ -18,3 +20,3 @@ import { MySqlDeleteBase, MySqlInsertBuilder, MySqlSelectBuilder, MySqlUpdateBuilder, QueryBuilder } from "./query-builders/index.js"; | ||
import type { MySqlViewBase } from "./view-base.js"; | ||
export declare class MySqlDatabase<TQueryResult extends MySqlQueryResultHKT, TPreparedQueryHKT extends PreparedQueryHKTBase, TFullSchema extends Record<string, unknown> = {}, TSchema extends TablesRelationalConfig = ExtractTablesWithRelations<TFullSchema>> { | ||
export declare class MySqlDatabase<TQueryResult extends MySqlQueryResultHKT, TPreparedQueryHKT extends PreparedQueryHKTBase, TFullSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations, TTablesConfig extends TablesRelationalConfig = ExtractTablesWithRelations<TRelations>, TSchema extends V1.TablesRelationalConfig = V1.ExtractTablesWithRelations<TFullSchema>> { | ||
protected readonly mode: Mode; | ||
@@ -25,7 +27,12 @@ static readonly [entityKind]: string; | ||
readonly fullSchema: TFullSchema; | ||
readonly relations: TRelations; | ||
readonly tableNamesMap: Record<string, string>; | ||
}; | ||
query: TFullSchema extends Record<string, never> ? DrizzleTypeError<'Seems like the schema generic is missing - did you forget to add it to your DB type?'> : { | ||
[K in keyof TSchema]: RelationalQueryBuilder<TPreparedQueryHKT, TSchema, TSchema[K]>; | ||
/** @deprecated */ | ||
_query: TFullSchema extends Record<string, never> ? DrizzleTypeError<'Seems like the schema generic is missing - did you forget to add it to your DB type?'> : { | ||
[K in keyof TSchema]: _RelationalQueryBuilder<TPreparedQueryHKT, TSchema, TSchema[K]>; | ||
}; | ||
query: { | ||
[K in keyof TRelations['tables']]: RelationalQueryBuilder<TPreparedQueryHKT, TTablesConfig, TTablesConfig[K]>; | ||
}; | ||
constructor( | ||
@@ -35,3 +42,3 @@ /** @internal */ | ||
/** @internal */ | ||
session: MySqlSession<any, any, any, any>, schema: RelationalSchemaConfig<TSchema> | undefined, mode: Mode); | ||
session: MySqlSession<any, any, any, any, any, any>, relations: AnyRelations | undefined, schema: V1.RelationalSchemaConfig<TSchema> | undefined, mode: Mode); | ||
/** | ||
@@ -72,3 +79,3 @@ * Creates a subquery that defines a temporary named result set as a CTE. | ||
}; | ||
$count(source: MySqlTable | MySqlViewBase | SQL | SQLWrapper, filters?: SQL<unknown>): MySqlCountBuilder<MySqlSession<any, any, any, any>>; | ||
$count(source: MySqlTable | MySqlViewBase | SQL | SQLWrapper, filters?: SQL<unknown>): MySqlCountBuilder<MySqlSession<any, any, any, any, any, any>>; | ||
/** | ||
@@ -234,3 +241,3 @@ * Incorporates a previously defined CTE (using `$with`) into the main query. | ||
} = ResultSetHeader>(query: SQLWrapper | string): Promise<MySqlQueryResultKind<TQueryResult, T>>; | ||
transaction<T>(transaction: (tx: MySqlTransaction<TQueryResult, TPreparedQueryHKT, TFullSchema, TSchema>, config?: MySqlTransactionConfig) => Promise<T>, config?: MySqlTransactionConfig): Promise<T>; | ||
transaction<T>(transaction: (tx: MySqlTransaction<TQueryResult, TPreparedQueryHKT, TFullSchema, TRelations, TTablesConfig, TSchema>, config?: MySqlTransactionConfig) => Promise<T>, config?: MySqlTransactionConfig): Promise<T>; | ||
} | ||
@@ -240,2 +247,2 @@ export type MySQLWithReplicas<Q> = Q & { | ||
}; | ||
export declare const withReplicas: <HKT extends MySqlQueryResultHKT, TPreparedQueryHKT extends PreparedQueryHKTBase, TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig, Q extends MySqlDatabase<HKT, TPreparedQueryHKT, TFullSchema, TSchema extends Record<string, unknown> ? ExtractTablesWithRelations<TFullSchema> : TSchema>>(primary: Q, replicas: [Q, ...Q[]], getReplica?: (replicas: Q[]) => Q) => MySQLWithReplicas<Q>; | ||
export declare const withReplicas: <HKT extends MySqlQueryResultHKT, TPreparedQueryHKT extends PreparedQueryHKTBase, TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig, Q extends MySqlDatabase<HKT, TPreparedQueryHKT, TFullSchema, TRelations, TTablesConfig, TSchema extends Record<string, unknown> ? V1.ExtractTablesWithRelations<TFullSchema> : TSchema>>(primary: Q, replicas: [Q, ...Q[]], getReplica?: (replicas: Q[]) => Q) => MySQLWithReplicas<Q>; |
@@ -5,2 +5,3 @@ import { entityKind } from "../entity.js"; | ||
import { WithSubquery } from "../subquery.js"; | ||
import { _RelationalQueryBuilder } from "./query-builders/_query.js"; | ||
import { MySqlCountBuilder } from "./query-builders/count.js"; | ||
@@ -16,19 +17,22 @@ import { | ||
class MySqlDatabase { | ||
constructor(dialect, session, schema, mode) { | ||
constructor(dialect, session, relations, schema, mode) { | ||
this.dialect = dialect; | ||
this.session = session; | ||
this.mode = mode; | ||
const rel = relations ?? {}; | ||
this._ = schema ? { | ||
schema: schema.schema, | ||
fullSchema: schema.fullSchema, | ||
tableNamesMap: schema.tableNamesMap | ||
tableNamesMap: schema.tableNamesMap, | ||
relations: rel | ||
} : { | ||
schema: void 0, | ||
fullSchema: {}, | ||
tableNamesMap: {} | ||
tableNamesMap: {}, | ||
relations: rel | ||
}; | ||
this.query = {}; | ||
this._query = {}; | ||
if (this._.schema) { | ||
for (const [tableName, columns] of Object.entries(this._.schema)) { | ||
this.query[tableName] = new RelationalQueryBuilder( | ||
this._query[tableName] = new _RelationalQueryBuilder( | ||
schema.fullSchema, | ||
@@ -45,4 +49,21 @@ this._.schema, | ||
} | ||
this.query = {}; | ||
if (relations) { | ||
for (const [tableName, relation] of Object.entries(relations.tablesConfig)) { | ||
this.query[tableName] = new RelationalQueryBuilder( | ||
relations.tables, | ||
relations.tablesConfig, | ||
relations.tableNamesMap, | ||
relation.table, | ||
relation, | ||
dialect, | ||
session | ||
); | ||
} | ||
} | ||
} | ||
static [entityKind] = "MySqlDatabase"; | ||
/** @deprecated */ | ||
_query; | ||
// TO-DO: Figure out how to pass DrizzleTypeError without breaking withReplicas | ||
query; | ||
@@ -250,4 +271,4 @@ /** | ||
with: $with, | ||
get query() { | ||
return getReplica(replicas).query; | ||
get _query() { | ||
return getReplica(replicas)._query; | ||
} | ||
@@ -254,0 +275,0 @@ }; |
@@ -0,4 +1,5 @@ | ||
import * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
import type { MigrationConfig, MigrationMeta } from "../migrator.js"; | ||
import { type BuildRelationalQueryResult, type DBQueryConfig, type Relation, type TableRelationalConfig, type TablesRelationalConfig } from "../relations.js"; | ||
import type { BuildRelationalQueryResult, DBQueryConfig, TableRelationalConfig, TablesRelationalConfig } from "../relations.js"; | ||
import { SQL } from "../sql/sql.js"; | ||
@@ -53,15 +54,31 @@ import type { QueryWithTypings } from "../sql/sql.js"; | ||
sqlToQuery(sql: SQL, invokeSource?: 'indexes' | undefined): QueryWithTypings; | ||
buildRelationalQuery({ fullSchema, schema, tableNamesMap, table, tableConfig, queryConfig: config, tableAlias, nestedQueryRelation, joinOn, }: { | ||
/** @deprecated */ | ||
_buildRelationalQuery({ fullSchema, schema, tableNamesMap, table, tableConfig, queryConfig: config, tableAlias, nestedQueryRelation, joinOn, }: { | ||
fullSchema: Record<string, unknown>; | ||
schema: TablesRelationalConfig; | ||
schema: V1.TablesRelationalConfig; | ||
tableNamesMap: Record<string, string>; | ||
table: MySqlTable; | ||
tableConfig: TableRelationalConfig; | ||
queryConfig: true | DBQueryConfig<'many', true>; | ||
tableConfig: V1.TableRelationalConfig; | ||
queryConfig: true | V1.DBQueryConfig<'many', true>; | ||
tableAlias: string; | ||
nestedQueryRelation?: Relation; | ||
nestedQueryRelation?: V1.Relation; | ||
joinOn?: SQL; | ||
}): BuildRelationalQueryResult<MySqlTable, MySqlColumn>; | ||
buildRelationalQueryWithoutLateralSubqueries({ fullSchema, schema, tableNamesMap, table, tableConfig, queryConfig: config, tableAlias, nestedQueryRelation, joinOn, }: { | ||
}): V1.BuildRelationalQueryResult<MySqlTable, MySqlColumn>; | ||
/** @deprecated */ | ||
_buildRelationalQueryWithoutLateralSubqueries({ fullSchema, schema, tableNamesMap, table, tableConfig, queryConfig: config, tableAlias, nestedQueryRelation, joinOn, }: { | ||
fullSchema: Record<string, unknown>; | ||
schema: V1.TablesRelationalConfig; | ||
tableNamesMap: Record<string, string>; | ||
table: MySqlTable; | ||
tableConfig: V1.TableRelationalConfig; | ||
queryConfig: true | V1.DBQueryConfig<'many', true>; | ||
tableAlias: string; | ||
nestedQueryRelation?: V1.Relation; | ||
joinOn?: SQL; | ||
}): V1.BuildRelationalQueryResult<MySqlTable, MySqlColumn>; | ||
private unwrapAllColumns; | ||
private getSelectedTableColumns; | ||
private buildColumns; | ||
buildRelationalQuery({ tables, schema, tableNamesMap, table, tableConfig, queryConfig: config, relationWhere, mode, }: { | ||
tables: Record<string, MySqlTable>; | ||
schema: TablesRelationalConfig; | ||
@@ -71,7 +88,6 @@ tableNamesMap: Record<string, string>; | ||
tableConfig: TableRelationalConfig; | ||
queryConfig: true | DBQueryConfig<'many', true>; | ||
tableAlias: string; | ||
nestedQueryRelation?: Relation; | ||
joinOn?: SQL; | ||
}): BuildRelationalQueryResult<MySqlTable, MySqlColumn>; | ||
queryConfig?: DBQueryConfig<'many'> | true; | ||
relationWhere?: SQL; | ||
mode: 'first' | 'many'; | ||
}): BuildRelationalQueryResult; | ||
} |
@@ -0,1 +1,2 @@ | ||
import * as V1 from "../_relations.js"; | ||
import { aliasedTable, aliasedTableColumn, mapColumnsInAliasedSQLToAlias, mapColumnsInSQLToAlias } from "../alias.js"; | ||
@@ -8,11 +9,12 @@ import { CasingCache } from "../casing.js"; | ||
import { | ||
getOperators, | ||
getOrderByOperators, | ||
Many, | ||
normalizeRelation, | ||
One | ||
AggregatedField, | ||
One, | ||
relationExtrasToSQL, | ||
relationFilterToSQL, | ||
relationsOrderToSQL, | ||
relationToSQL | ||
} from "../relations.js"; | ||
import { Param, SQL, sql, View } from "../sql/sql.js"; | ||
import { Subquery } from "../subquery.js"; | ||
import { getTableName, getTableUniqueName, Table } from "../table.js"; | ||
import { Columns, getTableName, getTableUniqueName, Table } from "../table.js"; | ||
import { orderSelectedFields } from "../utils.js"; | ||
@@ -373,3 +375,4 @@ import { ViewBaseConfig } from "../view-common.js"; | ||
} | ||
buildRelationalQuery({ | ||
/** @deprecated */ | ||
_buildRelationalQuery({ | ||
fullSchema, | ||
@@ -403,3 +406,3 @@ schema, | ||
if (config.where) { | ||
const whereSql = typeof config.where === "function" ? config.where(aliasedColumns, getOperators()) : config.where; | ||
const whereSql = typeof config.where === "function" ? config.where(aliasedColumns, V1.getOperators()) : config.where; | ||
where = whereSql && mapColumnsInSQLToAlias(whereSql, tableAlias); | ||
@@ -456,3 +459,3 @@ } | ||
} | ||
let orderByOrig = typeof config.orderBy === "function" ? config.orderBy(aliasedColumns, getOrderByOperators()) : config.orderBy ?? []; | ||
let orderByOrig = typeof config.orderBy === "function" ? config.orderBy(aliasedColumns, V1.getOrderByOperators()) : config.orderBy ?? []; | ||
if (!Array.isArray(orderByOrig)) { | ||
@@ -474,3 +477,3 @@ orderByOrig = [orderByOrig]; | ||
} of selectedRelations) { | ||
const normalizedRelation = normalizeRelation(schema, tableNamesMap, relation); | ||
const normalizedRelation = V1.normalizeRelation(schema, tableNamesMap, relation); | ||
const relationTableName = getTableUniqueName(relation.referencedTable); | ||
@@ -487,3 +490,3 @@ const relationTableTsName = tableNamesMap[relationTableName]; | ||
); | ||
const builtRelation = this.buildRelationalQuery({ | ||
const builtRelation = this._buildRelationalQuery({ | ||
fullSchema, | ||
@@ -494,3 +497,3 @@ schema, | ||
tableConfig: schema[relationTableTsName], | ||
queryConfig: is(relation, One) ? selectedRelationConfigValue === true ? { limit: 1 } : { ...selectedRelationConfigValue, limit: 1 } : selectedRelationConfigValue, | ||
queryConfig: is(relation, V1.One) ? selectedRelationConfigValue === true ? { limit: 1 } : { ...selectedRelationConfigValue, limit: 1 } : selectedRelationConfigValue, | ||
tableAlias: relationTableAlias, | ||
@@ -530,3 +533,3 @@ joinOn: joinOn2, | ||
)})`; | ||
if (is(nestedQueryRelation, Many)) { | ||
if (is(nestedQueryRelation, V1.Many)) { | ||
field = sql`coalesce(json_arrayagg(${field}), json_array())`; | ||
@@ -605,3 +608,4 @@ } | ||
} | ||
buildRelationalQueryWithoutLateralSubqueries({ | ||
/** @deprecated */ | ||
_buildRelationalQueryWithoutLateralSubqueries({ | ||
fullSchema, | ||
@@ -634,3 +638,3 @@ schema, | ||
if (config.where) { | ||
const whereSql = typeof config.where === "function" ? config.where(aliasedColumns, getOperators()) : config.where; | ||
const whereSql = typeof config.where === "function" ? config.where(aliasedColumns, V1.getOperators()) : config.where; | ||
where = whereSql && mapColumnsInSQLToAlias(whereSql, tableAlias); | ||
@@ -687,3 +691,3 @@ } | ||
} | ||
let orderByOrig = typeof config.orderBy === "function" ? config.orderBy(aliasedColumns, getOrderByOperators()) : config.orderBy ?? []; | ||
let orderByOrig = typeof config.orderBy === "function" ? config.orderBy(aliasedColumns, V1.getOrderByOperators()) : config.orderBy ?? []; | ||
if (!Array.isArray(orderByOrig)) { | ||
@@ -705,3 +709,3 @@ orderByOrig = [orderByOrig]; | ||
} of selectedRelations) { | ||
const normalizedRelation = normalizeRelation(schema, tableNamesMap, relation); | ||
const normalizedRelation = V1.normalizeRelation(schema, tableNamesMap, relation); | ||
const relationTableName = getTableUniqueName(relation.referencedTable); | ||
@@ -718,3 +722,3 @@ const relationTableTsName = tableNamesMap[relationTableName]; | ||
); | ||
const builtRelation = this.buildRelationalQueryWithoutLateralSubqueries({ | ||
const builtRelation = this._buildRelationalQueryWithoutLateralSubqueries({ | ||
fullSchema, | ||
@@ -725,3 +729,3 @@ schema, | ||
tableConfig: schema[relationTableTsName], | ||
queryConfig: is(relation, One) ? selectedRelationConfigValue === true ? { limit: 1 } : { ...selectedRelationConfigValue, limit: 1 } : selectedRelationConfigValue, | ||
queryConfig: is(relation, V1.One) ? selectedRelationConfigValue === true ? { limit: 1 } : { ...selectedRelationConfigValue, limit: 1 } : selectedRelationConfigValue, | ||
tableAlias: relationTableAlias, | ||
@@ -732,3 +736,3 @@ joinOn: joinOn2, | ||
let fieldSql = sql`(${builtRelation.sql})`; | ||
if (is(relation, Many)) { | ||
if (is(relation, V1.Many)) { | ||
fieldSql = sql`coalesce(${fieldSql}, json_array())`; | ||
@@ -761,3 +765,3 @@ } | ||
)})`; | ||
if (is(nestedQueryRelation, Many)) { | ||
if (is(nestedQueryRelation, V1.Many)) { | ||
field = sql`json_arrayagg(${field})`; | ||
@@ -834,2 +838,144 @@ } | ||
} | ||
unwrapAllColumns = (table, selection) => { | ||
return sql.join( | ||
Object.entries(table[Columns]).map(([k, v]) => { | ||
selection.push({ | ||
key: k, | ||
field: v | ||
}); | ||
return sql`${v} as ${sql.identifier(k)}`; | ||
}), | ||
sql`, ` | ||
); | ||
}; | ||
getSelectedTableColumns = (table, columns) => { | ||
const selectedColumns = []; | ||
if (!columns) { | ||
for (const [k, v] of Object.entries(table[Columns])) { | ||
selectedColumns.push({ | ||
column: v, | ||
tsName: k | ||
}); | ||
} | ||
return selectedColumns; | ||
} | ||
const entries = Object.entries(columns); | ||
let colSelectionMode; | ||
for (const [k, v] of entries) { | ||
if (colSelectionMode === void 0) | ||
colSelectionMode = v; | ||
else if (v !== void 0 && colSelectionMode !== v) { | ||
throw new Error("Columns cannot be both true and false at the same time"); | ||
} | ||
if (v) { | ||
selectedColumns.push({ | ||
column: table[Columns][k], | ||
tsName: k | ||
}); | ||
} | ||
} | ||
if (colSelectionMode === false) { | ||
for (const [k, v] of Object.entries(table[Columns])) { | ||
if (columns[k] === false) | ||
continue; | ||
selectedColumns.push({ | ||
column: v, | ||
tsName: k | ||
}); | ||
} | ||
} | ||
return selectedColumns; | ||
}; | ||
buildColumns = (table, selection, params) => params?.columns ? (() => { | ||
const columnIdentifiers = []; | ||
const selectedColumns = this.getSelectedTableColumns(table, params?.columns); | ||
for (const column of selectedColumns) { | ||
columnIdentifiers.push( | ||
sql`${table[column.tsName]} as ${sql.identifier(column.tsName)}` | ||
); | ||
} | ||
return columnIdentifiers.length ? sql.join(columnIdentifiers, sql`, `) : this.unwrapAllColumns(table, selection); | ||
})() : (() => { | ||
const columnIdentifiers = [this.unwrapAllColumns(table, selection)]; | ||
return sql.join(columnIdentifiers, sql`, `); | ||
})(); | ||
buildRelationalQuery({ | ||
tables, | ||
schema, | ||
tableNamesMap, | ||
table, | ||
tableConfig, | ||
queryConfig: config, | ||
relationWhere, | ||
mode | ||
}) { | ||
const selection = []; | ||
const isSingle = mode === "first"; | ||
const params = config === true ? void 0 : config; | ||
const limit = isSingle ? 1 : params?.limit; | ||
const offset = params?.offset; | ||
const columns = this.buildColumns(table, selection, params); | ||
const where = params?.where && relationWhere ? and(relationFilterToSQL(table, params.where), relationWhere) : params?.where ? relationFilterToSQL(table, params.where) : relationWhere; | ||
const order = params?.orderBy ? relationsOrderToSQL(table, params.orderBy) : void 0; | ||
const extras = params?.extras ? relationExtrasToSQL(table, params.extras) : void 0; | ||
if (extras) | ||
selection.push(...extras.selection); | ||
const selectionArr = [columns]; | ||
const joins = params ? (() => { | ||
const { with: joins2 } = params; | ||
if (!joins2) | ||
return; | ||
const withEntries = Object.entries(joins2).filter(([_, v]) => v); | ||
if (!withEntries.length) | ||
return; | ||
return sql.join( | ||
withEntries.map(([k, join]) => { | ||
selectionArr.push(sql`${sql.identifier(k)}.${sql.identifier("r")} as ${sql.identifier(k)}`); | ||
if (is(tableConfig.relations[k], AggregatedField)) { | ||
const relation2 = tableConfig.relations[k]; | ||
relation2.onTable(table); | ||
const query2 = relation2.getSQL(); | ||
selection.push({ | ||
key: k, | ||
field: relation2 | ||
}); | ||
return sql`, lateral(${query2}) as ${sql.identifier(k)}`; | ||
} | ||
const relation = tableConfig.relations[k]; | ||
const isSingle2 = is(relation, One); | ||
const targetTable = relation.targetTable; | ||
const relationFilter = relationToSQL(relation); | ||
const innerQuery = this.buildRelationalQuery({ | ||
table: targetTable, | ||
mode: isSingle2 ? "first" : "many", | ||
schema, | ||
queryConfig: join, | ||
tableConfig: schema[tableNamesMap[getTableUniqueName(targetTable)]], | ||
tableNamesMap, | ||
tables, | ||
relationWhere: relationFilter | ||
}); | ||
selection.push({ | ||
field: targetTable, | ||
key: k, | ||
selection: innerQuery.selection, | ||
isArray: !isSingle2 | ||
}); | ||
const jsonColumns = sql.join( | ||
innerQuery.selection.map((s) => sql`${sql.raw(this.escapeString(s.key))}, ${sql.identifier(s.key)}`), | ||
sql`, ` | ||
); | ||
return sql`, lateral(select ${isSingle2 ? sql`json_object(${jsonColumns}) as ${sql.identifier("r")}` : sql`coalesce(json_arrayagg(json_object(${jsonColumns})), json_array()) as ${sql.identifier("r")}`} from (${innerQuery.sql}) as ${sql.identifier("t")}) as ${sql.identifier(k)}`; | ||
}) | ||
); | ||
})() : void 0; | ||
if (extras?.sql) | ||
selectionArr.push(extras.sql); | ||
const selectionSet = sql.join(selectionArr, sql`, `); | ||
const query = sql`select ${selectionSet} from ${table}${sql`${joins}`.if(joins)}${sql` where ${where}`.if(where)}${sql` order by ${order}`.if(order)}${sql` limit ${limit}`.if(limit !== void 0)}${sql` offset ${offset}`.if(offset !== void 0)}`; | ||
return { | ||
sql: query, | ||
selection | ||
}; | ||
} | ||
} | ||
@@ -836,0 +982,0 @@ export { |
@@ -6,3 +6,3 @@ import { entityKind } from "../../entity.js"; | ||
import type { MySqlViewBase } from "../view-base.js"; | ||
export declare class MySqlCountBuilder<TSession extends MySqlSession<any, any, any>> extends SQL<number> implements Promise<number>, SQLWrapper { | ||
export declare class MySqlCountBuilder<TSession extends MySqlSession<any, any, any>> extends SQL<number> implements Promise<number>, SQLWrapper<number> { | ||
readonly params: { | ||
@@ -9,0 +9,0 @@ source: MySqlTable | MySqlViewBase | SQL | SQLWrapper; |
@@ -7,6 +7,6 @@ import { entityKind } from "../../entity.js"; | ||
import type { MySqlDialect } from "../dialect.js"; | ||
import type { Mode, MySqlPreparedQueryConfig, MySqlSession, PreparedQueryHKTBase, PreparedQueryKind } from "../session.js"; | ||
import type { MySqlPreparedQueryConfig, MySqlSession, PreparedQueryHKTBase, PreparedQueryKind } from "../session.js"; | ||
import type { MySqlTable } from "../table.js"; | ||
export declare class RelationalQueryBuilder<TPreparedQueryHKT extends PreparedQueryHKTBase, TSchema extends TablesRelationalConfig, TFields extends TableRelationalConfig> { | ||
private fullSchema; | ||
private tables; | ||
private schema; | ||
@@ -18,10 +18,9 @@ private tableNamesMap; | ||
private session; | ||
private mode; | ||
static readonly [entityKind]: string; | ||
constructor(fullSchema: Record<string, unknown>, schema: TSchema, tableNamesMap: Record<string, string>, table: MySqlTable, tableConfig: TableRelationalConfig, dialect: MySqlDialect, session: MySqlSession, mode: Mode); | ||
findMany<TConfig extends DBQueryConfig<'many', true, TSchema, TFields>>(config?: KnownKeysOnly<TConfig, DBQueryConfig<'many', true, TSchema, TFields>>): MySqlRelationalQuery<TPreparedQueryHKT, BuildQueryResult<TSchema, TFields, TConfig>[]>; | ||
findFirst<TSelection extends Omit<DBQueryConfig<'many', true, TSchema, TFields>, 'limit'>>(config?: KnownKeysOnly<TSelection, Omit<DBQueryConfig<'many', true, TSchema, TFields>, 'limit'>>): MySqlRelationalQuery<TPreparedQueryHKT, BuildQueryResult<TSchema, TFields, TSelection> | undefined>; | ||
constructor(tables: Record<string, MySqlTable>, schema: TSchema, tableNamesMap: Record<string, string>, table: MySqlTable, tableConfig: TableRelationalConfig, dialect: MySqlDialect, session: MySqlSession); | ||
findMany<TConfig extends DBQueryConfig<'many', TSchema, TFields>>(config?: KnownKeysOnly<TConfig, DBQueryConfig<'many', TSchema, TFields>>): MySqlRelationalQuery<TPreparedQueryHKT, BuildQueryResult<TSchema, TFields, TConfig>[]>; | ||
findFirst<TSelection extends DBQueryConfig<'one', TSchema, TFields>>(config?: KnownKeysOnly<TSelection, DBQueryConfig<'one', TSchema, TFields>>): MySqlRelationalQuery<TPreparedQueryHKT, BuildQueryResult<TSchema, TFields, TSelection> | undefined>; | ||
} | ||
export declare class MySqlRelationalQuery<TPreparedQueryHKT extends PreparedQueryHKTBase, TResult> extends QueryPromise<TResult> { | ||
private fullSchema; | ||
private tables; | ||
private schema; | ||
@@ -34,7 +33,6 @@ private tableNamesMap; | ||
private config; | ||
private queryMode; | ||
private mode?; | ||
private mode; | ||
static readonly [entityKind]: string; | ||
protected $brand: 'MySqlRelationalQuery'; | ||
constructor(fullSchema: Record<string, unknown>, schema: TablesRelationalConfig, tableNamesMap: Record<string, string>, table: MySqlTable, tableConfig: TableRelationalConfig, dialect: MySqlDialect, session: MySqlSession, config: DBQueryConfig<'many', true> | true, queryMode: 'many' | 'first', mode?: Mode | undefined); | ||
constructor(tables: Record<string, MySqlTable>, schema: TablesRelationalConfig, tableNamesMap: Record<string, string>, table: MySqlTable, tableConfig: TableRelationalConfig, dialect: MySqlDialect, session: MySqlSession, config: DBQueryConfig<'many' | 'one'> | true, mode: 'many' | 'first'); | ||
prepare(): PreparedQueryKind<TPreparedQueryHKT, MySqlPreparedQueryConfig & { | ||
@@ -41,0 +39,0 @@ execute: TResult; |
@@ -7,4 +7,4 @@ import { entityKind } from "../../entity.js"; | ||
class RelationalQueryBuilder { | ||
constructor(fullSchema, schema, tableNamesMap, table, tableConfig, dialect, session, mode) { | ||
this.fullSchema = fullSchema; | ||
constructor(tables, schema, tableNamesMap, table, tableConfig, dialect, session) { | ||
this.tables = tables; | ||
this.schema = schema; | ||
@@ -16,8 +16,7 @@ this.tableNamesMap = tableNamesMap; | ||
this.session = session; | ||
this.mode = mode; | ||
} | ||
static [entityKind] = "MySqlRelationalQueryBuilder"; | ||
static [entityKind] = "MySqlRelationalQueryBuilderV2"; | ||
findMany(config) { | ||
return new MySqlRelationalQuery( | ||
this.fullSchema, | ||
this.tables, | ||
this.schema, | ||
@@ -29,5 +28,4 @@ this.tableNamesMap, | ||
this.session, | ||
config ? config : {}, | ||
"many", | ||
this.mode | ||
config ?? true, | ||
"many" | ||
); | ||
@@ -37,3 +35,3 @@ } | ||
return new MySqlRelationalQuery( | ||
this.fullSchema, | ||
this.tables, | ||
this.schema, | ||
@@ -45,5 +43,4 @@ this.tableNamesMap, | ||
this.session, | ||
config ? { ...config, limit: 1 } : { limit: 1 }, | ||
"first", | ||
this.mode | ||
config ?? true, | ||
"first" | ||
); | ||
@@ -53,5 +50,5 @@ } | ||
class MySqlRelationalQuery extends QueryPromise { | ||
constructor(fullSchema, schema, tableNamesMap, table, tableConfig, dialect, session, config, queryMode, mode) { | ||
constructor(tables, schema, tableNamesMap, table, tableConfig, dialect, session, config, mode) { | ||
super(); | ||
this.fullSchema = fullSchema; | ||
this.tables = tables; | ||
this.schema = schema; | ||
@@ -64,14 +61,13 @@ this.tableNamesMap = tableNamesMap; | ||
this.config = config; | ||
this.queryMode = queryMode; | ||
this.mode = mode; | ||
} | ||
static [entityKind] = "MySqlRelationalQuery"; | ||
static [entityKind] = "MySqlRelationalQueryV2"; | ||
prepare() { | ||
const { query, builtQuery } = this._toSQL(); | ||
return this.session.prepareQuery( | ||
return this.session.prepareRelationalQuery( | ||
builtQuery, | ||
void 0, | ||
(rawRows) => { | ||
const rows = rawRows.map((row) => mapRelationalRow(this.schema, this.tableConfig, row, query.selection)); | ||
if (this.queryMode === "first") { | ||
const rows = rawRows.map((row) => mapRelationalRow(row, query.selection)); | ||
if (this.mode === "first") { | ||
return rows[0]; | ||
@@ -84,4 +80,3 @@ } | ||
_getQuery() { | ||
const query = this.mode === "planetscale" ? this.dialect.buildRelationalQueryWithoutLateralSubqueries({ | ||
fullSchema: this.fullSchema, | ||
return this.dialect.buildRelationalQuery({ | ||
schema: this.schema, | ||
@@ -92,13 +87,5 @@ tableNamesMap: this.tableNamesMap, | ||
queryConfig: this.config, | ||
tableAlias: this.tableConfig.tsName | ||
}) : this.dialect.buildRelationalQuery({ | ||
fullSchema: this.fullSchema, | ||
schema: this.schema, | ||
tableNamesMap: this.tableNamesMap, | ||
table: this.table, | ||
tableConfig: this.tableConfig, | ||
queryConfig: this.config, | ||
tableAlias: this.tableConfig.tsName | ||
tables: this.tables, | ||
mode: this.mode | ||
}); | ||
return query; | ||
} | ||
@@ -105,0 +92,0 @@ _toSQL() { |
@@ -0,3 +1,4 @@ | ||
import type * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
import type { RelationalSchemaConfig, TablesRelationalConfig } from "../relations.js"; | ||
import type { AnyRelations, EmptyRelations, ExtractTablesWithRelations, TablesRelationalConfig } from "../relations.js"; | ||
import { type Query, type SQL } from "../sql/sql.js"; | ||
@@ -44,3 +45,3 @@ import type { Assume, Equal } from "../utils.js"; | ||
} | ||
export declare abstract class MySqlSession<TQueryResult extends MySqlQueryResultHKT = MySqlQueryResultHKT, TPreparedQueryHKT extends PreparedQueryHKTBase = PreparedQueryHKTBase, TFullSchema extends Record<string, unknown> = Record<string, never>, TSchema extends TablesRelationalConfig = Record<string, never>> { | ||
export declare abstract class MySqlSession<TQueryResult extends MySqlQueryResultHKT = MySqlQueryResultHKT, TPreparedQueryHKT extends PreparedQueryHKTBase = PreparedQueryHKTBase, TFullSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations, TTablesConfig extends TablesRelationalConfig = ExtractTablesWithRelations<TRelations>, TSchema extends V1.TablesRelationalConfig = V1.ExtractTablesWithRelations<TFullSchema>> { | ||
protected dialect: MySqlDialect; | ||
@@ -50,17 +51,19 @@ static readonly [entityKind]: string; | ||
abstract prepareQuery<T extends MySqlPreparedQueryConfig, TPreparedQueryHKT extends MySqlPreparedQueryHKT>(query: Query, fields: SelectedFieldsOrdered | undefined, customResultMapper?: (rows: unknown[][]) => T['execute'], generatedIds?: Record<string, unknown>[], returningIds?: SelectedFieldsOrdered): PreparedQueryKind<TPreparedQueryHKT, T>; | ||
abstract prepareRelationalQuery<T extends MySqlPreparedQueryConfig, TPreparedQueryHKT extends MySqlPreparedQueryHKT>(query: Query, fields: SelectedFieldsOrdered | undefined, customResultMapper: (rows: Record<string, unknown>[]) => T['execute'], generatedIds?: Record<string, unknown>[], returningIds?: SelectedFieldsOrdered): PreparedQueryKind<TPreparedQueryHKT, T>; | ||
execute<T>(query: SQL): Promise<T>; | ||
abstract all<T = unknown>(query: SQL): Promise<T[]>; | ||
count(sql: SQL): Promise<number>; | ||
abstract transaction<T>(transaction: (tx: MySqlTransaction<TQueryResult, TPreparedQueryHKT, TFullSchema, TSchema>) => Promise<T>, config?: MySqlTransactionConfig): Promise<T>; | ||
abstract transaction<T>(transaction: (tx: MySqlTransaction<TQueryResult, TPreparedQueryHKT, TFullSchema, TRelations, TTablesConfig, TSchema>) => Promise<T>, config?: MySqlTransactionConfig): Promise<T>; | ||
protected getSetTransactionSQL(config: MySqlTransactionConfig): SQL | undefined; | ||
protected getStartTransactionSQL(config: MySqlTransactionConfig): SQL | undefined; | ||
} | ||
export declare abstract class MySqlTransaction<TQueryResult extends MySqlQueryResultHKT, TPreparedQueryHKT extends PreparedQueryHKTBase, TFullSchema extends Record<string, unknown> = Record<string, never>, TSchema extends TablesRelationalConfig = Record<string, never>> extends MySqlDatabase<TQueryResult, TPreparedQueryHKT, TFullSchema, TSchema> { | ||
protected schema: RelationalSchemaConfig<TSchema> | undefined; | ||
export declare abstract class MySqlTransaction<TQueryResult extends MySqlQueryResultHKT, TPreparedQueryHKT extends PreparedQueryHKTBase, TFullSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations, TTablesConfig extends TablesRelationalConfig = ExtractTablesWithRelations<TRelations>, TSchema extends V1.TablesRelationalConfig = V1.ExtractTablesWithRelations<TFullSchema>> extends MySqlDatabase<TQueryResult, TPreparedQueryHKT, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
protected relations: AnyRelations | undefined; | ||
protected schema: V1.RelationalSchemaConfig<TSchema> | undefined; | ||
protected readonly nestedIndex: number; | ||
static readonly [entityKind]: string; | ||
constructor(dialect: MySqlDialect, session: MySqlSession, schema: RelationalSchemaConfig<TSchema> | undefined, nestedIndex: number, mode: Mode); | ||
constructor(dialect: MySqlDialect, session: MySqlSession, relations: AnyRelations | undefined, schema: V1.RelationalSchemaConfig<TSchema> | undefined, nestedIndex: number, mode: Mode); | ||
rollback(): never; | ||
/** Nested transactions (aka savepoints) only work with InnoDB engine. */ | ||
abstract transaction<T>(transaction: (tx: MySqlTransaction<TQueryResult, TPreparedQueryHKT, TFullSchema, TSchema>) => Promise<T>): Promise<T>; | ||
abstract transaction<T>(transaction: (tx: MySqlTransaction<TQueryResult, TPreparedQueryHKT, TFullSchema, TRelations, TTablesConfig, TSchema>) => Promise<T>): Promise<T>; | ||
} | ||
@@ -67,0 +70,0 @@ export interface PreparedQueryHKTBase extends MySqlPreparedQueryHKT { |
@@ -46,4 +46,5 @@ import { entityKind } from "../entity.js"; | ||
class MySqlTransaction extends MySqlDatabase { | ||
constructor(dialect, session, schema, nestedIndex, mode) { | ||
super(dialect, session, schema, mode); | ||
constructor(dialect, session, relations, schema, nestedIndex, mode) { | ||
super(dialect, session, relations, schema, mode); | ||
this.relations = relations; | ||
this.schema = schema; | ||
@@ -50,0 +51,0 @@ this.nestedIndex = nestedIndex; |
import { entityKind } from "../entity.js"; | ||
import { MySqlDatabase } from "../mysql-core/db.js"; | ||
import type { AnyRelations, EmptyRelations } from "../relations.js"; | ||
import type { DrizzleConfig } from "../utils.js"; | ||
import { type MySqlRemotePreparedQueryHKT, type MySqlRemoteQueryResultHKT } from "./session.js"; | ||
export declare class MySqlRemoteDatabase<TSchema extends Record<string, unknown> = Record<string, never>> extends MySqlDatabase<MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT, TSchema> { | ||
export declare class MySqlRemoteDatabase<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations> extends MySqlDatabase<MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT, TSchema, TRelations> { | ||
static readonly [entityKind]: string; | ||
@@ -13,2 +14,2 @@ } | ||
}>; | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(callback: RemoteCallback, config?: DrizzleConfig<TSchema>): MySqlRemoteDatabase<TSchema>; | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations>(callback: RemoteCallback, config?: DrizzleConfig<TSchema>): MySqlRemoteDatabase<TSchema, TRelations>; |
@@ -0,1 +1,2 @@ | ||
import * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
@@ -5,6 +6,2 @@ import { DefaultLogger } from "../logger.js"; | ||
import { MySqlDialect } from "../mysql-core/dialect.js"; | ||
import { | ||
createTableRelationsHelpers, | ||
extractTablesRelationalConfig | ||
} from "../relations.js"; | ||
import { MySqlRemoteSession } from "./session.js"; | ||
@@ -24,5 +21,5 @@ class MySqlRemoteDatabase extends MySqlDatabase { | ||
if (config.schema) { | ||
const tablesConfig = extractTablesRelationalConfig( | ||
const tablesConfig = V1.extractTablesRelationalConfig( | ||
config.schema, | ||
createTableRelationsHelpers | ||
V1.createTableRelationsHelpers | ||
); | ||
@@ -35,4 +32,11 @@ schema = { | ||
} | ||
const session = new MySqlRemoteSession(callback, dialect, schema, { logger }); | ||
return new MySqlRemoteDatabase(dialect, session, schema, "default"); | ||
const relations = config.relations; | ||
const session = new MySqlRemoteSession(callback, dialect, relations, schema, { logger }); | ||
return new MySqlRemoteDatabase( | ||
dialect, | ||
session, | ||
relations, | ||
schema, | ||
"default" | ||
); | ||
} | ||
@@ -39,0 +43,0 @@ export { |
import type { MigrationConfig } from "../migrator.js"; | ||
import type { AnyRelations } from "../relations.js"; | ||
import type { MySqlRemoteDatabase } from "./driver.js"; | ||
export type ProxyMigrator = (migrationQueries: string[]) => Promise<void>; | ||
export declare function migrate<TSchema extends Record<string, unknown>>(db: MySqlRemoteDatabase<TSchema>, callback: ProxyMigrator, config: MigrationConfig): Promise<void>; | ||
export declare function migrate<TSchema extends Record<string, unknown>, TRelations extends AnyRelations>(db: MySqlRemoteDatabase<TSchema, TRelations>, callback: ProxyMigrator, config: MigrationConfig): Promise<void>; |
import type { FieldPacket, ResultSetHeader } from 'mysql2/promise'; | ||
import type * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
@@ -9,3 +10,3 @@ import type { Logger } from "../logger.js"; | ||
import { MySqlPreparedQuery as PreparedQueryBase, MySqlSession } from "../mysql-core/session.js"; | ||
import type { RelationalSchemaConfig, TablesRelationalConfig } from "../relations.js"; | ||
import type { AnyRelations, TablesRelationalConfig } from "../relations.js"; | ||
import type { Query, SQL } from "../sql/sql.js"; | ||
@@ -18,17 +19,19 @@ import { type Assume } from "../utils.js"; | ||
} | ||
export declare class MySqlRemoteSession<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends MySqlSession<MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT, TFullSchema, TSchema> { | ||
export declare class MySqlRemoteSession<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends MySqlSession<MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
private client; | ||
private relations; | ||
private schema; | ||
static readonly [entityKind]: string; | ||
private logger; | ||
constructor(client: RemoteCallback, dialect: MySqlDialect, schema: RelationalSchemaConfig<TSchema> | undefined, options: MySqlRemoteSessionOptions); | ||
constructor(client: RemoteCallback, dialect: MySqlDialect, relations: AnyRelations | undefined, schema: V1.RelationalSchemaConfig<TSchema> | undefined, options: MySqlRemoteSessionOptions); | ||
prepareQuery<T extends MySqlPreparedQueryConfig>(query: Query, fields: SelectedFieldsOrdered | undefined, customResultMapper?: (rows: unknown[][]) => T['execute'], generatedIds?: Record<string, unknown>[], returningIds?: SelectedFieldsOrdered): PreparedQueryKind<MySqlRemotePreparedQueryHKT, T>; | ||
prepareRelationalQuery<T extends MySqlPreparedQueryConfig>(query: Query, fields: SelectedFieldsOrdered | undefined, customResultMapper: (rows: Record<string, unknown>[]) => T['execute'], generatedIds?: Record<string, unknown>[], returningIds?: SelectedFieldsOrdered): PreparedQueryKind<MySqlRemotePreparedQueryHKT, T>; | ||
all<T = unknown>(query: SQL): Promise<T[]>; | ||
transaction<T>(_transaction: (tx: MySqlProxyTransaction<TFullSchema, TSchema>) => Promise<T>, _config?: MySqlTransactionConfig): Promise<T>; | ||
transaction<T>(_transaction: (tx: MySqlProxyTransaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => Promise<T>, _config?: MySqlTransactionConfig): Promise<T>; | ||
} | ||
export declare class MySqlProxyTransaction<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends MySqlTransaction<MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT, TFullSchema, TSchema> { | ||
export declare class MySqlProxyTransaction<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends MySqlTransaction<MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
static readonly [entityKind]: string; | ||
transaction<T>(_transaction: (tx: MySqlProxyTransaction<TFullSchema, TSchema>) => Promise<T>): Promise<T>; | ||
transaction<T>(_transaction: (tx: MySqlProxyTransaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => Promise<T>): Promise<T>; | ||
} | ||
export declare class PreparedQuery<T extends MySqlPreparedQueryConfig> extends PreparedQueryBase<T> { | ||
export declare class PreparedQuery<T extends MySqlPreparedQueryConfig, TIsRqbV2 extends boolean = false> extends PreparedQueryBase<T> { | ||
private client; | ||
@@ -42,5 +45,7 @@ private queryString; | ||
private returningIds?; | ||
private isRqbV2Query?; | ||
static readonly [entityKind]: string; | ||
constructor(client: RemoteCallback, queryString: string, params: unknown[], logger: Logger, fields: SelectedFieldsOrdered | undefined, customResultMapper?: ((rows: unknown[][]) => T["execute"]) | undefined, generatedIds?: Record<string, unknown>[] | undefined, returningIds?: SelectedFieldsOrdered | undefined); | ||
constructor(client: RemoteCallback, queryString: string, params: unknown[], logger: Logger, fields: SelectedFieldsOrdered | undefined, customResultMapper?: ((rows: TIsRqbV2 extends true ? Record<string, unknown>[] : unknown[][]) => T["execute"]) | undefined, generatedIds?: Record<string, unknown>[] | undefined, returningIds?: SelectedFieldsOrdered | undefined, isRqbV2Query?: TIsRqbV2 | undefined); | ||
execute(placeholderValues?: Record<string, unknown> | undefined): Promise<T['execute']>; | ||
private executeRqbV2; | ||
iterator(_placeholderValues?: Record<string, unknown>): AsyncGenerator<T['iterator']>; | ||
@@ -47,0 +52,0 @@ } |
@@ -9,5 +9,6 @@ import { Column } from "../column.js"; | ||
class MySqlRemoteSession extends MySqlSession { | ||
constructor(client, dialect, schema, options) { | ||
constructor(client, dialect, relations, schema, options) { | ||
super(dialect); | ||
this.client = client; | ||
this.relations = relations; | ||
this.schema = schema; | ||
@@ -30,2 +31,15 @@ this.logger = options.logger ?? new NoopLogger(); | ||
} | ||
prepareRelationalQuery(query, fields, customResultMapper, generatedIds, returningIds) { | ||
return new PreparedQuery( | ||
this.client, | ||
query.sql, | ||
query.params, | ||
this.logger, | ||
fields, | ||
customResultMapper, | ||
generatedIds, | ||
returningIds, | ||
true | ||
); | ||
} | ||
all(query) { | ||
@@ -47,3 +61,3 @@ const querySql = this.dialect.sqlToQuery(query); | ||
class PreparedQuery extends PreparedQueryBase { | ||
constructor(client, queryString, params, logger, fields, customResultMapper, generatedIds, returningIds) { | ||
constructor(client, queryString, params, logger, fields, customResultMapper, generatedIds, returningIds, isRqbV2Query) { | ||
super(); | ||
@@ -58,5 +72,8 @@ this.client = client; | ||
this.returningIds = returningIds; | ||
this.isRqbV2Query = isRqbV2Query; | ||
} | ||
static [entityKind] = "MySqlProxyPreparedQuery"; | ||
async execute(placeholderValues = {}) { | ||
if (this.isRqbV2Query) | ||
return this.executeRqbV2(placeholderValues); | ||
const params = fillPlaceholders(this.params, placeholderValues); | ||
@@ -96,2 +113,30 @@ const { fields, client, queryString, logger, joinsNotNullableMap, customResultMapper, returningIds, generatedIds } = this; | ||
} | ||
async executeRqbV2(placeholderValues = {}) { | ||
const params = fillPlaceholders(this.params, placeholderValues); | ||
const { client, queryString, logger, customResultMapper, returningIds, generatedIds } = this; | ||
logger.logQuery(queryString, params); | ||
const { rows } = await client(queryString, params, "execute"); | ||
const insertId = rows[0].insertId; | ||
const affectedRows = rows[0].affectedRows; | ||
if (returningIds) { | ||
const returningResponse = []; | ||
let j = 0; | ||
for (let i = insertId; i < insertId + affectedRows; i++) { | ||
for (const column of returningIds) { | ||
const key = returningIds[0].path[0]; | ||
if (is(column.field, Column)) { | ||
if (column.field.primary && column.field.autoIncrement) { | ||
returningResponse.push({ [key]: i }); | ||
} | ||
if (column.field.defaultFn && generatedIds) { | ||
returningResponse.push({ [key]: generatedIds[j][key] }); | ||
} | ||
} | ||
} | ||
j++; | ||
} | ||
return returningResponse; | ||
} | ||
return customResultMapper(rows); | ||
} | ||
iterator(_placeholderValues = {}) { | ||
@@ -98,0 +143,0 @@ throw new Error("Streaming is not supported by the MySql Proxy driver"); |
import { type Connection as CallbackConnection, type Pool as CallbackPool, type PoolOptions } from 'mysql2'; | ||
import type { Connection, Pool } from 'mysql2/promise'; | ||
import * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
@@ -8,3 +9,3 @@ import type { Logger } from "../logger.js"; | ||
import type { Mode } from "../mysql-core/session.js"; | ||
import { type RelationalSchemaConfig, type TablesRelationalConfig } from "../relations.js"; | ||
import type { AnyRelations, EmptyRelations, TablesRelationalConfig } from "../relations.js"; | ||
import { type DrizzleConfig } from "../utils.js"; | ||
@@ -22,9 +23,9 @@ import type { MySql2Client, MySql2PreparedQueryHKT, MySql2QueryResultHKT } from "./session.js"; | ||
constructor(client: MySql2Client, dialect: MySqlDialect, options?: MySqlDriverOptions); | ||
createSession(schema: RelationalSchemaConfig<TablesRelationalConfig> | undefined, mode: Mode): MySql2Session<Record<string, unknown>, TablesRelationalConfig>; | ||
createSession(relations: AnyRelations | undefined, schema: V1.RelationalSchemaConfig<V1.TablesRelationalConfig> | undefined, mode: Mode): MySql2Session<Record<string, unknown>, AnyRelations, TablesRelationalConfig, V1.TablesRelationalConfig>; | ||
} | ||
export { MySqlDatabase } from "../mysql-core/db.js"; | ||
export declare class MySql2Database<TSchema extends Record<string, unknown> = Record<string, never>> extends MySqlDatabase<MySql2QueryResultHKT, MySql2PreparedQueryHKT, TSchema> { | ||
export declare class MySql2Database<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations> extends MySqlDatabase<MySql2QueryResultHKT, MySql2PreparedQueryHKT, TSchema, TRelations> { | ||
static readonly [entityKind]: string; | ||
} | ||
export type MySql2DrizzleConfig<TSchema extends Record<string, unknown> = Record<string, never>> = Omit<DrizzleConfig<TSchema>, 'schema'> & ({ | ||
export type MySql2DrizzleConfig<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations> = Omit<DrizzleConfig<TSchema, TRelations>, 'schema'> & ({ | ||
schema: TSchema; | ||
@@ -37,9 +38,9 @@ mode: Mode; | ||
export type AnyMySql2Connection = Pool | Connection | CallbackPool | CallbackConnection; | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TClient extends AnyMySql2Connection = CallbackPool>(...params: [ | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations, TClient extends AnyMySql2Connection = CallbackPool>(...params: [ | ||
TClient | string | ||
] | [ | ||
TClient | string, | ||
MySql2DrizzleConfig<TSchema> | ||
MySql2DrizzleConfig<TSchema, TRelations> | ||
] | [ | ||
(MySql2DrizzleConfig<TSchema> & ({ | ||
(MySql2DrizzleConfig<TSchema, TRelations> & ({ | ||
connection: string | PoolOptions; | ||
@@ -49,9 +50,9 @@ } | { | ||
})) | ||
]): MySql2Database<TSchema> & { | ||
]): MySql2Database<TSchema, TRelations> & { | ||
$client: TClient; | ||
}; | ||
export declare namespace drizzle { | ||
function mock<TSchema extends Record<string, unknown> = Record<string, never>>(config?: MySql2DrizzleConfig<TSchema>): MySql2Database<TSchema> & { | ||
function mock<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations>(config?: MySql2DrizzleConfig<TSchema, TRelations>): MySql2Database<TSchema, TRelations> & { | ||
$client: '$client is not available on drizzle.mock()'; | ||
}; | ||
} |
import { createPool } from "mysql2"; | ||
import * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
@@ -6,6 +7,2 @@ import { DefaultLogger } from "../logger.js"; | ||
import { MySqlDialect } from "../mysql-core/dialect.js"; | ||
import { | ||
createTableRelationsHelpers, | ||
extractTablesRelationalConfig | ||
} from "../relations.js"; | ||
import { isConfig } from "../utils.js"; | ||
@@ -21,4 +18,4 @@ import { DrizzleError } from "../errors.js"; | ||
static [entityKind] = "MySql2Driver"; | ||
createSession(schema, mode) { | ||
return new MySql2Session(this.client, this.dialect, schema, { logger: this.options.logger, mode }); | ||
createSession(relations, schema, mode) { | ||
return new MySql2Session(this.client, this.dialect, relations, schema, { logger: this.options.logger, mode }); | ||
} | ||
@@ -46,5 +43,5 @@ } | ||
} | ||
const tablesConfig = extractTablesRelationalConfig( | ||
const tablesConfig = V1.extractTablesRelationalConfig( | ||
config.schema, | ||
createTableRelationsHelpers | ||
V1.createTableRelationsHelpers | ||
); | ||
@@ -58,5 +55,12 @@ schema = { | ||
const mode = config.mode ?? "default"; | ||
const relations = config.relations; | ||
const driver = new MySql2Driver(clientForInstance, dialect, { logger }); | ||
const session = driver.createSession(schema, mode); | ||
const db = new MySql2Database(dialect, session, schema, mode); | ||
const session = driver.createSession(relations, schema, mode); | ||
const db = new MySql2Database( | ||
dialect, | ||
session, | ||
relations, | ||
schema, | ||
mode | ||
); | ||
db.$client = client; | ||
@@ -63,0 +67,0 @@ return db; |
import type { MigrationConfig } from "../migrator.js"; | ||
import type { AnyRelations } from "../relations.js"; | ||
import type { MySql2Database } from "./driver.js"; | ||
export declare function migrate<TSchema extends Record<string, unknown>>(db: MySql2Database<TSchema>, config: MigrationConfig): Promise<void>; | ||
export declare function migrate<TSchema extends Record<string, unknown>, TRelations extends AnyRelations>(db: MySql2Database<TSchema, TRelations>, config: MigrationConfig): Promise<void>; |
import type { Connection, FieldPacket, OkPacket, Pool, ResultSetHeader, RowDataPacket } from 'mysql2/promise'; | ||
import type * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
@@ -7,3 +8,3 @@ import type { Logger } from "../logger.js"; | ||
import { type Mode, MySqlPreparedQuery, type MySqlPreparedQueryConfig, type MySqlPreparedQueryHKT, type MySqlQueryResultHKT, MySqlSession, MySqlTransaction, type MySqlTransactionConfig, type PreparedQueryKind } from "../mysql-core/session.js"; | ||
import type { RelationalSchemaConfig, TablesRelationalConfig } from "../relations.js"; | ||
import type { AnyRelations, TablesRelationalConfig } from "../relations.js"; | ||
import type { Query, SQL } from "../sql/sql.js"; | ||
@@ -15,3 +16,3 @@ import { type Assume } from "../utils.js"; | ||
export type MySqlQueryResult<T = any> = [T extends ResultSetHeader ? T : T[], FieldPacket[]]; | ||
export declare class MySql2PreparedQuery<T extends MySqlPreparedQueryConfig> extends MySqlPreparedQuery<T> { | ||
export declare class MySql2PreparedQuery<T extends MySqlPreparedQueryConfig, TIsRqbV2 extends boolean = false> extends MySqlPreparedQuery<T> { | ||
private client; | ||
@@ -24,7 +25,9 @@ private params; | ||
private returningIds?; | ||
private isRqbV2Query?; | ||
static readonly [entityKind]: string; | ||
private rawQuery; | ||
private query; | ||
constructor(client: MySql2Client, queryString: string, params: unknown[], logger: Logger, fields: SelectedFieldsOrdered | undefined, customResultMapper?: ((rows: unknown[][]) => T["execute"]) | undefined, generatedIds?: Record<string, unknown>[] | undefined, returningIds?: SelectedFieldsOrdered | undefined); | ||
constructor(client: MySql2Client, queryString: string, params: unknown[], logger: Logger, fields: SelectedFieldsOrdered | undefined, customResultMapper?: ((rows: TIsRqbV2 extends true ? Record<string, unknown>[] : unknown[][]) => T["execute"]) | undefined, generatedIds?: Record<string, unknown>[] | undefined, returningIds?: SelectedFieldsOrdered | undefined, isRqbV2Query?: TIsRqbV2 | undefined); | ||
execute(placeholderValues?: Record<string, unknown>): Promise<T['execute']>; | ||
private executeRqbV2; | ||
iterator(placeholderValues?: Record<string, unknown>): AsyncGenerator<T['execute'] extends any[] ? T['execute'][number] : T['execute']>; | ||
@@ -36,4 +39,5 @@ } | ||
} | ||
export declare class MySql2Session<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends MySqlSession<MySqlQueryResultHKT, MySql2PreparedQueryHKT, TFullSchema, TSchema> { | ||
export declare class MySql2Session<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends MySqlSession<MySqlQueryResultHKT, MySql2PreparedQueryHKT, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
private client; | ||
private relations; | ||
private schema; | ||
@@ -44,10 +48,11 @@ private options; | ||
private mode; | ||
constructor(client: MySql2Client, dialect: MySqlDialect, schema: RelationalSchemaConfig<TSchema> | undefined, options: MySql2SessionOptions); | ||
constructor(client: MySql2Client, dialect: MySqlDialect, relations: AnyRelations | undefined, schema: V1.RelationalSchemaConfig<TSchema> | undefined, options: MySql2SessionOptions); | ||
prepareQuery<T extends MySqlPreparedQueryConfig>(query: Query, fields: SelectedFieldsOrdered | undefined, customResultMapper?: (rows: unknown[][]) => T['execute'], generatedIds?: Record<string, unknown>[], returningIds?: SelectedFieldsOrdered): PreparedQueryKind<MySql2PreparedQueryHKT, T>; | ||
prepareRelationalQuery<T extends MySqlPreparedQueryConfig>(query: Query, fields: SelectedFieldsOrdered | undefined, customResultMapper: (rows: Record<string, unknown>[]) => T['execute'], generatedIds?: Record<string, unknown>[], returningIds?: SelectedFieldsOrdered): PreparedQueryKind<MySql2PreparedQueryHKT, T>; | ||
all<T = unknown>(query: SQL): Promise<T[]>; | ||
transaction<T>(transaction: (tx: MySql2Transaction<TFullSchema, TSchema>) => Promise<T>, config?: MySqlTransactionConfig): Promise<T>; | ||
transaction<T>(transaction: (tx: MySql2Transaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => Promise<T>, config?: MySqlTransactionConfig): Promise<T>; | ||
} | ||
export declare class MySql2Transaction<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends MySqlTransaction<MySql2QueryResultHKT, MySql2PreparedQueryHKT, TFullSchema, TSchema> { | ||
export declare class MySql2Transaction<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends MySqlTransaction<MySql2QueryResultHKT, MySql2PreparedQueryHKT, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
static readonly [entityKind]: string; | ||
transaction<T>(transaction: (tx: MySql2Transaction<TFullSchema, TSchema>) => Promise<T>): Promise<T>; | ||
transaction<T>(transaction: (tx: MySql2Transaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => Promise<T>): Promise<T>; | ||
} | ||
@@ -54,0 +59,0 @@ export interface MySql2QueryResultHKT extends MySqlQueryResultHKT { |
@@ -13,3 +13,3 @@ import { once } from "node:events"; | ||
class MySql2PreparedQuery extends MySqlPreparedQuery { | ||
constructor(client, queryString, params, logger, fields, customResultMapper, generatedIds, returningIds) { | ||
constructor(client, queryString, params, logger, fields, customResultMapper, generatedIds, returningIds, isRqbV2Query) { | ||
super(); | ||
@@ -23,2 +23,3 @@ this.client = client; | ||
this.returningIds = returningIds; | ||
this.isRqbV2Query = isRqbV2Query; | ||
this.rawQuery = { | ||
@@ -49,2 +50,4 @@ sql: queryString, | ||
async execute(placeholderValues = {}) { | ||
if (this.isRqbV2Query) | ||
return this.executeRqbV2(placeholderValues); | ||
const params = fillPlaceholders(this.params, placeholderValues); | ||
@@ -85,2 +88,31 @@ this.logger.logQuery(this.rawQuery.sql, params); | ||
} | ||
async executeRqbV2(placeholderValues = {}) { | ||
const params = fillPlaceholders(this.params, placeholderValues); | ||
this.logger.logQuery(this.rawQuery.sql, params); | ||
const { client, rawQuery, customResultMapper, returningIds, generatedIds } = this; | ||
const res = await client.query(rawQuery, params); | ||
const insertId = res[0].insertId; | ||
const affectedRows = res[0].affectedRows; | ||
if (returningIds) { | ||
const returningResponse = []; | ||
let j = 0; | ||
for (let i = insertId; i < insertId + affectedRows; i++) { | ||
for (const column of returningIds) { | ||
const key = returningIds[0].path[0]; | ||
if (is(column.field, Column)) { | ||
if (column.field.primary && column.field.autoIncrement) { | ||
returningResponse.push({ [key]: i }); | ||
} | ||
if (column.field.defaultFn && generatedIds) { | ||
returningResponse.push({ [key]: generatedIds[j][key] }); | ||
} | ||
} | ||
} | ||
j++; | ||
} | ||
return customResultMapper(returningResponse); | ||
} | ||
const rows = res[0]; | ||
return customResultMapper(rows); | ||
} | ||
async *iterator(placeholderValues = {}) { | ||
@@ -129,5 +161,6 @@ const params = fillPlaceholders(this.params, placeholderValues); | ||
class MySql2Session extends MySqlSession { | ||
constructor(client, dialect, schema, options) { | ||
constructor(client, dialect, relations, schema, options) { | ||
super(dialect); | ||
this.client = client; | ||
this.relations = relations; | ||
this.schema = schema; | ||
@@ -153,2 +186,15 @@ this.options = options; | ||
} | ||
prepareRelationalQuery(query, fields, customResultMapper, generatedIds, returningIds) { | ||
return new MySql2PreparedQuery( | ||
this.client, | ||
query.sql, | ||
query.params, | ||
this.logger, | ||
fields, | ||
customResultMapper, | ||
generatedIds, | ||
returningIds, | ||
true | ||
); | ||
} | ||
/** | ||
@@ -182,2 +228,3 @@ * @internal | ||
this.dialect, | ||
this.relations, | ||
this.schema, | ||
@@ -189,2 +236,3 @@ this.options | ||
session, | ||
this.relations, | ||
this.schema, | ||
@@ -225,2 +273,3 @@ 0, | ||
this.session, | ||
this.relations, | ||
this.schema, | ||
@@ -227,0 +276,0 @@ this.nestedIndex + 1, |
import type { HTTPTransactionOptions, NeonQueryFunction } from '@neondatabase/serverless'; | ||
import * as V1 from "../_relations.js"; | ||
import type { BatchItem, BatchResponse } from "../batch.js"; | ||
@@ -7,3 +8,3 @@ import { entityKind } from "../entity.js"; | ||
import { PgDialect } from "../pg-core/dialect.js"; | ||
import type { RelationalSchemaConfig, TablesRelationalConfig } from "../relations.js"; | ||
import type { AnyRelations, EmptyRelations, Relations, TablesRelationalConfig } from "../relations.js"; | ||
import { type DrizzleConfig } from "../utils.js"; | ||
@@ -20,17 +21,17 @@ import { type NeonHttpClient, type NeonHttpQueryResultHKT, NeonHttpSession } from "./session.js"; | ||
constructor(client: NeonHttpClient, dialect: PgDialect, options?: NeonDriverOptions); | ||
createSession(schema: RelationalSchemaConfig<TablesRelationalConfig> | undefined): NeonHttpSession<Record<string, unknown>, TablesRelationalConfig>; | ||
createSession(relations: Relations | undefined, schema: V1.RelationalSchemaConfig<V1.TablesRelationalConfig> | undefined): NeonHttpSession<Record<string, unknown>, EmptyRelations, TablesRelationalConfig, V1.TablesRelationalConfig>; | ||
initMappers(): void; | ||
} | ||
export declare class NeonHttpDatabase<TSchema extends Record<string, unknown> = Record<string, never>> extends PgDatabase<NeonHttpQueryResultHKT, TSchema> { | ||
export declare class NeonHttpDatabase<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations> extends PgDatabase<NeonHttpQueryResultHKT, TSchema, TRelations> { | ||
static readonly [entityKind]: string; | ||
$withAuth(token: string): Omit<this, Exclude<keyof this, '$count' | 'delete' | 'select' | 'selectDistinct' | 'selectDistinctOn' | 'update' | 'insert' | 'with' | 'query' | 'execute' | 'refreshMaterializedView'>>; | ||
$withAuth(token: string): Omit<this, Exclude<keyof this, '$count' | 'delete' | 'select' | 'selectDistinct' | 'selectDistinctOn' | 'update' | 'insert' | 'with' | '_query' | 'query' | 'execute' | 'refreshMaterializedView'>>; | ||
batch<U extends BatchItem<'pg'>, T extends Readonly<[U, ...U[]]>>(batch: T): Promise<BatchResponse<T>>; | ||
} | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TClient extends NeonQueryFunction<any, any> = NeonQueryFunction<false, false>>(...params: [ | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations, TClient extends NeonQueryFunction<any, any> = NeonQueryFunction<false, false>>(...params: [ | ||
TClient | string | ||
] | [ | ||
TClient | string, | ||
DrizzleConfig<TSchema> | ||
DrizzleConfig<TSchema, TRelations> | ||
] | [ | ||
(DrizzleConfig<TSchema> & ({ | ||
(DrizzleConfig<TSchema, TRelations> & ({ | ||
connection: string | ({ | ||
@@ -42,9 +43,9 @@ connectionString: string; | ||
})) | ||
]): NeonHttpDatabase<TSchema> & { | ||
]): NeonHttpDatabase<TSchema, TRelations> & { | ||
$client: TClient; | ||
}; | ||
export declare namespace drizzle { | ||
function mock<TSchema extends Record<string, unknown> = Record<string, never>>(config?: DrizzleConfig<TSchema>): NeonHttpDatabase<TSchema> & { | ||
function mock<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations>(config?: DrizzleConfig<TSchema, TRelations>): NeonHttpDatabase<TSchema, TRelations> & { | ||
$client: '$client is not available on drizzle.mock()'; | ||
}; | ||
} |
import { neon, types } from "@neondatabase/serverless"; | ||
import * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
@@ -6,3 +7,2 @@ import { DefaultLogger } from "../logger.js"; | ||
import { PgDialect } from "../pg-core/dialect.js"; | ||
import { createTableRelationsHelpers, extractTablesRelationalConfig } from "../relations.js"; | ||
import { isConfig } from "../utils.js"; | ||
@@ -18,4 +18,6 @@ import { NeonHttpSession } from "./session.js"; | ||
static [entityKind] = "NeonHttpDriver"; | ||
createSession(schema) { | ||
return new NeonHttpSession(this.client, this.dialect, schema, { logger: this.options.logger }); | ||
createSession(relations, schema) { | ||
return new NeonHttpSession(this.client, this.dialect, relations ?? {}, schema, { | ||
logger: this.options.logger | ||
}); | ||
} | ||
@@ -37,3 +39,3 @@ initMappers() { | ||
return wrap(element, token, cb); | ||
if (p === "query") | ||
if (p === "query" || p === "_query") | ||
return wrap(element, token, cb, true); | ||
@@ -77,5 +79,5 @@ return new Proxy(element, { | ||
if (config.schema) { | ||
const tablesConfig = extractTablesRelationalConfig( | ||
const tablesConfig = V1.extractTablesRelationalConfig( | ||
config.schema, | ||
createTableRelationsHelpers | ||
V1.createTableRelationsHelpers | ||
); | ||
@@ -88,7 +90,9 @@ schema = { | ||
} | ||
const relations = config.relations; | ||
const driver = new NeonHttpDriver(client, dialect, { logger }); | ||
const session = driver.createSession(schema); | ||
const session = driver.createSession(relations, schema); | ||
const db = new NeonHttpDatabase( | ||
dialect, | ||
session, | ||
relations, | ||
schema | ||
@@ -95,0 +99,0 @@ ); |
import type { MigrationConfig } from "../migrator.js"; | ||
import type { AnyRelations } from "../relations.js"; | ||
import type { NeonHttpDatabase } from "./driver.js"; | ||
@@ -11,2 +12,2 @@ /** | ||
*/ | ||
export declare function migrate<TSchema extends Record<string, unknown>>(db: NeonHttpDatabase<TSchema>, config: MigrationConfig): Promise<void>; | ||
export declare function migrate<TSchema extends Record<string, unknown>, TRelations extends AnyRelations>(db: NeonHttpDatabase<TSchema, TRelations>, config: MigrationConfig): Promise<void>; |
import type { FullQueryResults, NeonQueryFunction } from '@neondatabase/serverless'; | ||
import type * as V1 from "../_relations.js"; | ||
import type { BatchItem } from "../batch.js"; | ||
@@ -10,6 +11,6 @@ import { entityKind } from "../entity.js"; | ||
import { PgPreparedQuery as PgPreparedQuery, PgSession } from "../pg-core/session.js"; | ||
import type { RelationalSchemaConfig, TablesRelationalConfig } from "../relations.js"; | ||
import type { AnyRelations, TablesRelationalConfig } from "../relations.js"; | ||
import { type Query, type SQL } from "../sql/sql.js"; | ||
export type NeonHttpClient = NeonQueryFunction<any, any>; | ||
export declare class NeonHttpPreparedQuery<T extends PreparedQueryConfig> extends PgPreparedQuery<T> { | ||
export declare class NeonHttpPreparedQuery<T extends PreparedQueryConfig, TIsRqbV2 extends boolean = false> extends PgPreparedQuery<T> { | ||
private client; | ||
@@ -20,5 +21,7 @@ private logger; | ||
private customResultMapper?; | ||
private isRqbV2Query?; | ||
static readonly [entityKind]: string; | ||
constructor(client: NeonHttpClient, query: Query, logger: Logger, fields: SelectedFieldsOrdered | undefined, _isResponseInArrayMode: boolean, customResultMapper?: ((rows: unknown[][]) => T["execute"]) | undefined); | ||
constructor(client: NeonHttpClient, query: Query, logger: Logger, fields: SelectedFieldsOrdered | undefined, _isResponseInArrayMode: boolean, customResultMapper?: ((rows: TIsRqbV2 extends true ? Record<string, unknown>[] : unknown[][]) => T["execute"]) | undefined, isRqbV2Query?: TIsRqbV2 | undefined); | ||
execute(placeholderValues: Record<string, unknown> | undefined): Promise<T['execute']>; | ||
private executeRqbV2; | ||
mapResult(result: unknown): unknown; | ||
@@ -31,4 +34,5 @@ all(placeholderValues?: Record<string, unknown> | undefined): Promise<T['all']>; | ||
} | ||
export declare class NeonHttpSession<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends PgSession<NeonHttpQueryResultHKT, TFullSchema, TSchema> { | ||
export declare class NeonHttpSession<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends PgSession<NeonHttpQueryResultHKT, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
private client; | ||
private relations; | ||
private schema; | ||
@@ -38,4 +42,5 @@ private options; | ||
private logger; | ||
constructor(client: NeonHttpClient, dialect: PgDialect, schema: RelationalSchemaConfig<TSchema> | undefined, options?: NeonHttpSessionOptions); | ||
constructor(client: NeonHttpClient, dialect: PgDialect, relations: AnyRelations, schema: V1.RelationalSchemaConfig<TSchema> | undefined, options?: NeonHttpSessionOptions); | ||
prepareQuery<T extends PreparedQueryConfig = PreparedQueryConfig>(query: Query, fields: SelectedFieldsOrdered | undefined, name: string | undefined, isResponseInArrayMode: boolean, customResultMapper?: (rows: unknown[][]) => T['execute']): PgPreparedQuery<T>; | ||
prepareRelationalQuery<T extends PreparedQueryConfig = PreparedQueryConfig>(query: Query, fields: SelectedFieldsOrdered | undefined, name: string | undefined, customResultMapper: (rows: Record<string, unknown>[]) => T['execute']): PgPreparedQuery<T>; | ||
batch<U extends BatchItem<'pg'>, T extends Readonly<[U, ...U[]]>>(queries: T): Promise<any>; | ||
@@ -45,7 +50,7 @@ query(query: string, params: unknown[]): Promise<FullQueryResults<true>>; | ||
count(sql: SQL): Promise<number>; | ||
transaction<T>(_transaction: (tx: NeonTransaction<TFullSchema, TSchema>) => Promise<T>, _config?: PgTransactionConfig): Promise<T>; | ||
transaction<T>(_transaction: (tx: NeonTransaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => Promise<T>, _config?: PgTransactionConfig): Promise<T>; | ||
} | ||
export declare class NeonTransaction<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends PgTransaction<NeonHttpQueryResultHKT, TFullSchema, TSchema> { | ||
export declare class NeonTransaction<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends PgTransaction<NeonHttpQueryResultHKT, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
static readonly [entityKind]: string; | ||
transaction<T>(_transaction: (tx: NeonTransaction<TFullSchema, TSchema>) => Promise<T>): Promise<T>; | ||
transaction<T>(_transaction: (tx: NeonTransaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => Promise<T>): Promise<T>; | ||
} | ||
@@ -52,0 +57,0 @@ export type NeonHttpQueryResult<T> = Omit<FullQueryResults<false>, 'rows'> & { |
@@ -16,3 +16,3 @@ import { entityKind } from "../entity.js"; | ||
class NeonHttpPreparedQuery extends PgPreparedQuery { | ||
constructor(client, query, logger, fields, _isResponseInArrayMode, customResultMapper) { | ||
constructor(client, query, logger, fields, _isResponseInArrayMode, customResultMapper, isRqbV2Query) { | ||
super(query); | ||
@@ -24,2 +24,3 @@ this.client = client; | ||
this.customResultMapper = customResultMapper; | ||
this.isRqbV2Query = isRqbV2Query; | ||
} | ||
@@ -29,2 +30,4 @@ static [entityKind] = "NeonHttpPreparedQuery"; | ||
async execute(placeholderValues = {}, token = this.authToken) { | ||
if (this.isRqbV2Query) | ||
return this.executeRqbV2(placeholderValues, token); | ||
const params = fillPlaceholders(this.query.params, placeholderValues); | ||
@@ -53,2 +56,17 @@ this.logger.logQuery(this.query.sql, params); | ||
} | ||
async executeRqbV2(placeholderValues, token) { | ||
const params = fillPlaceholders(this.query.params, placeholderValues); | ||
this.logger.logQuery(this.query.sql, params); | ||
const { client, query, customResultMapper } = this; | ||
const result = await client( | ||
query.sql, | ||
params, | ||
token === void 0 ? rawQueryConfig : { | ||
...rawQueryConfig, | ||
authToken: token | ||
} | ||
); | ||
const rows = result.rows; | ||
return customResultMapper(rows); | ||
} | ||
mapResult(result) { | ||
@@ -88,5 +106,6 @@ if (!this.fields && !this.customResultMapper) { | ||
class NeonHttpSession extends PgSession { | ||
constructor(client, dialect, schema, options = {}) { | ||
constructor(client, dialect, relations, schema, options = {}) { | ||
super(dialect); | ||
this.client = client; | ||
this.relations = relations; | ||
this.schema = schema; | ||
@@ -108,2 +127,13 @@ this.options = options; | ||
} | ||
prepareRelationalQuery(query, fields, name, customResultMapper) { | ||
return new NeonHttpPreparedQuery( | ||
this.client, | ||
query, | ||
this.logger, | ||
fields, | ||
false, | ||
customResultMapper, | ||
true | ||
); | ||
} | ||
async batch(queries) { | ||
@@ -110,0 +140,0 @@ const preparedQueries = []; |
import { Pool, type PoolConfig } from '@neondatabase/serverless'; | ||
import * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
@@ -6,3 +7,3 @@ import type { Logger } from "../logger.js"; | ||
import { PgDialect } from "../pg-core/dialect.js"; | ||
import { type RelationalSchemaConfig, type TablesRelationalConfig } from "../relations.js"; | ||
import type { AnyRelations, EmptyRelations, TablesRelationalConfig } from "../relations.js"; | ||
import { type DrizzleConfig } from "../utils.js"; | ||
@@ -20,14 +21,14 @@ import type { NeonClient, NeonQueryResultHKT } from "./session.js"; | ||
constructor(client: NeonClient, dialect: PgDialect, options?: NeonDriverOptions); | ||
createSession(schema: RelationalSchemaConfig<TablesRelationalConfig> | undefined): NeonSession<Record<string, unknown>, TablesRelationalConfig>; | ||
createSession(relations: AnyRelations | undefined, schema: V1.RelationalSchemaConfig<V1.TablesRelationalConfig> | undefined): NeonSession<Record<string, unknown>, AnyRelations, TablesRelationalConfig, V1.TablesRelationalConfig>; | ||
} | ||
export declare class NeonDatabase<TSchema extends Record<string, unknown> = Record<string, never>> extends PgDatabase<NeonQueryResultHKT, TSchema> { | ||
export declare class NeonDatabase<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations> extends PgDatabase<NeonQueryResultHKT, TSchema, TRelations> { | ||
static readonly [entityKind]: string; | ||
} | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TClient extends NeonClient = Pool>(...params: [ | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations, TClient extends NeonClient = Pool>(...params: [ | ||
TClient | string | ||
] | [ | ||
TClient | string, | ||
DrizzleConfig<TSchema> | ||
DrizzleConfig<TSchema, TRelations> | ||
] | [ | ||
(DrizzleConfig<TSchema> & ({ | ||
(DrizzleConfig<TSchema, TRelations> & ({ | ||
connection: string | PoolConfig; | ||
@@ -39,9 +40,9 @@ } | { | ||
}) | ||
]): NeonDatabase<TSchema> & { | ||
]): NeonDatabase<TSchema, TRelations> & { | ||
$client: TClient; | ||
}; | ||
export declare namespace drizzle { | ||
function mock<TSchema extends Record<string, unknown> = Record<string, never>>(config?: DrizzleConfig<TSchema>): NeonDatabase<TSchema> & { | ||
function mock<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations>(config?: DrizzleConfig<TSchema, TRelations>): NeonDatabase<TSchema> & { | ||
$client: '$client is not available on drizzle.mock()'; | ||
}; | ||
} |
import { neonConfig, Pool } from "@neondatabase/serverless"; | ||
import * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
@@ -6,6 +7,2 @@ import { DefaultLogger } from "../logger.js"; | ||
import { PgDialect } from "../pg-core/dialect.js"; | ||
import { | ||
createTableRelationsHelpers, | ||
extractTablesRelationalConfig | ||
} from "../relations.js"; | ||
import { isConfig } from "../utils.js"; | ||
@@ -20,4 +17,4 @@ import { NeonSession } from "./session.js"; | ||
static [entityKind] = "NeonDriver"; | ||
createSession(schema) { | ||
return new NeonSession(this.client, this.dialect, schema, { logger: this.options.logger }); | ||
createSession(relations, schema) { | ||
return new NeonSession(this.client, this.dialect, relations, schema, { logger: this.options.logger }); | ||
} | ||
@@ -38,5 +35,5 @@ } | ||
if (config.schema) { | ||
const tablesConfig = extractTablesRelationalConfig( | ||
const tablesConfig = V1.extractTablesRelationalConfig( | ||
config.schema, | ||
createTableRelationsHelpers | ||
V1.createTableRelationsHelpers | ||
); | ||
@@ -49,5 +46,6 @@ schema = { | ||
} | ||
const relations = config.relations; | ||
const driver = new NeonDriver(client, dialect, { logger }); | ||
const session = driver.createSession(schema); | ||
const db = new NeonDatabase(dialect, session, schema); | ||
const session = driver.createSession(relations, schema); | ||
const db = new NeonDatabase(dialect, session, relations, schema); | ||
db.$client = client; | ||
@@ -54,0 +52,0 @@ return db; |
import type { MigrationConfig } from "../migrator.js"; | ||
import type { AnyRelations } from "../relations.js"; | ||
import type { NeonDatabase } from "./driver.js"; | ||
export declare function migrate<TSchema extends Record<string, unknown>>(db: NeonDatabase<TSchema>, config: MigrationConfig): Promise<void>; | ||
export declare function migrate<TSchema extends Record<string, unknown>, TRelations extends AnyRelations>(db: NeonDatabase<TSchema, TRelations>, config: MigrationConfig): Promise<void>; |
import { type Client, Pool, type PoolClient, type QueryResult, type QueryResultRow } from '@neondatabase/serverless'; | ||
import type * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
@@ -9,7 +10,7 @@ import type { Logger } from "../logger.js"; | ||
import { PgPreparedQuery, PgSession } from "../pg-core/session.js"; | ||
import type { RelationalSchemaConfig, TablesRelationalConfig } from "../relations.js"; | ||
import type { AnyRelations, TablesRelationalConfig } from "../relations.js"; | ||
import { type Query, type SQL } from "../sql/sql.js"; | ||
import { type Assume } from "../utils.js"; | ||
export type NeonClient = Pool | PoolClient | Client; | ||
export declare class NeonPreparedQuery<T extends PreparedQueryConfig> extends PgPreparedQuery<T> { | ||
export declare class NeonPreparedQuery<T extends PreparedQueryConfig, TIsRqbV2 extends boolean = false> extends PgPreparedQuery<T> { | ||
private client; | ||
@@ -21,7 +22,9 @@ private params; | ||
private customResultMapper?; | ||
private isRqbV2Query?; | ||
static readonly [entityKind]: string; | ||
private rawQueryConfig; | ||
private queryConfig; | ||
constructor(client: NeonClient, queryString: string, params: unknown[], logger: Logger, fields: SelectedFieldsOrdered | undefined, name: string | undefined, _isResponseInArrayMode: boolean, customResultMapper?: ((rows: unknown[][]) => T["execute"]) | undefined); | ||
constructor(client: NeonClient, queryString: string, params: unknown[], logger: Logger, fields: SelectedFieldsOrdered | undefined, name: string | undefined, _isResponseInArrayMode: boolean, customResultMapper?: ((rows: TIsRqbV2 extends true ? Record<string, unknown>[] : unknown[][]) => T["execute"]) | undefined, isRqbV2Query?: TIsRqbV2 | undefined); | ||
execute(placeholderValues?: Record<string, unknown> | undefined): Promise<T['execute']>; | ||
private executeRqbV2; | ||
all(placeholderValues?: Record<string, unknown> | undefined): Promise<T['all']>; | ||
@@ -33,4 +36,5 @@ values(placeholderValues?: Record<string, unknown> | undefined): Promise<T['values']>; | ||
} | ||
export declare class NeonSession<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends PgSession<NeonQueryResultHKT, TFullSchema, TSchema> { | ||
export declare class NeonSession<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends PgSession<NeonQueryResultHKT, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
private client; | ||
private relations; | ||
private schema; | ||
@@ -40,12 +44,13 @@ private options; | ||
private logger; | ||
constructor(client: NeonClient, dialect: PgDialect, schema: RelationalSchemaConfig<TSchema> | undefined, options?: NeonSessionOptions); | ||
constructor(client: NeonClient, dialect: PgDialect, relations: AnyRelations | undefined, schema: V1.RelationalSchemaConfig<TSchema> | undefined, options?: NeonSessionOptions); | ||
prepareQuery<T extends PreparedQueryConfig = PreparedQueryConfig>(query: Query, fields: SelectedFieldsOrdered | undefined, name: string | undefined, isResponseInArrayMode: boolean, customResultMapper?: (rows: unknown[][]) => T['execute']): PgPreparedQuery<T>; | ||
prepareRelationalQuery<T extends PreparedQueryConfig = PreparedQueryConfig>(query: Query, fields: SelectedFieldsOrdered | undefined, name: string | undefined, customResultMapper?: (rows: Record<string, unknown>[]) => T['execute']): PgPreparedQuery<T>; | ||
query(query: string, params: unknown[]): Promise<QueryResult>; | ||
queryObjects<T extends QueryResultRow>(query: string, params: unknown[]): Promise<QueryResult<T>>; | ||
count(sql: SQL): Promise<number>; | ||
transaction<T>(transaction: (tx: NeonTransaction<TFullSchema, TSchema>) => Promise<T>, config?: PgTransactionConfig): Promise<T>; | ||
transaction<T>(transaction: (tx: NeonTransaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => Promise<T>, config?: PgTransactionConfig): Promise<T>; | ||
} | ||
export declare class NeonTransaction<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends PgTransaction<NeonQueryResultHKT, TFullSchema, TSchema> { | ||
export declare class NeonTransaction<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends PgTransaction<NeonQueryResultHKT, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
static readonly [entityKind]: string; | ||
transaction<T>(transaction: (tx: NeonTransaction<TFullSchema, TSchema>) => Promise<T>): Promise<T>; | ||
transaction<T>(transaction: (tx: NeonTransaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => Promise<T>): Promise<T>; | ||
} | ||
@@ -52,0 +57,0 @@ export interface NeonQueryResultHKT extends PgQueryResultHKT { |
@@ -12,3 +12,3 @@ import { | ||
class NeonPreparedQuery extends PgPreparedQuery { | ||
constructor(client, queryString, params, logger, fields, name, _isResponseInArrayMode, customResultMapper) { | ||
constructor(client, queryString, params, logger, fields, name, _isResponseInArrayMode, customResultMapper, isRqbV2Query) { | ||
super({ sql: queryString, params }); | ||
@@ -21,2 +21,3 @@ this.client = client; | ||
this.customResultMapper = customResultMapper; | ||
this.isRqbV2Query = isRqbV2Query; | ||
this.rawQueryConfig = { | ||
@@ -72,2 +73,4 @@ name, | ||
async execute(placeholderValues = {}) { | ||
if (this.isRqbV2Query) | ||
return this.executeRqbV2(placeholderValues); | ||
const params = fillPlaceholders(this.params, placeholderValues); | ||
@@ -82,2 +85,9 @@ this.logger.logQuery(this.rawQueryConfig.text, params); | ||
} | ||
async executeRqbV2(placeholderValues = {}) { | ||
const params = fillPlaceholders(this.params, placeholderValues); | ||
this.logger.logQuery(this.rawQueryConfig.text, params); | ||
const { client, rawQueryConfig: rawQuery, customResultMapper } = this; | ||
const result = await client.query(rawQuery, params); | ||
return customResultMapper(result.rows); | ||
} | ||
all(placeholderValues = {}) { | ||
@@ -99,5 +109,6 @@ const params = fillPlaceholders(this.params, placeholderValues); | ||
class NeonSession extends PgSession { | ||
constructor(client, dialect, schema, options = {}) { | ||
constructor(client, dialect, relations, schema, options = {}) { | ||
super(dialect); | ||
this.client = client; | ||
this.relations = relations; | ||
this.schema = schema; | ||
@@ -121,2 +132,15 @@ this.options = options; | ||
} | ||
prepareRelationalQuery(query, fields, name, customResultMapper) { | ||
return new NeonPreparedQuery( | ||
this.client, | ||
query.sql, | ||
query.params, | ||
this.logger, | ||
fields, | ||
name, | ||
false, | ||
customResultMapper, | ||
true | ||
); | ||
} | ||
async query(query, params) { | ||
@@ -141,4 +165,9 @@ this.logger.logQuery(query, params); | ||
async transaction(transaction, config = {}) { | ||
const session = this.client instanceof Pool ? new NeonSession(await this.client.connect(), this.dialect, this.schema, this.options) : this; | ||
const tx = new NeonTransaction(this.dialect, session, this.schema); | ||
const session = this.client instanceof Pool ? new NeonSession(await this.client.connect(), this.dialect, this.relations, this.schema, this.options) : this; | ||
const tx = new NeonTransaction( | ||
this.dialect, | ||
session, | ||
this.relations, | ||
this.schema | ||
); | ||
await tx.execute(sql`begin ${tx.getTransactionConfigSQL(config)}`); | ||
@@ -163,3 +192,9 @@ try { | ||
const savepointName = `sp${this.nestedIndex + 1}`; | ||
const tx = new NeonTransaction(this.dialect, this.session, this.schema, this.nestedIndex + 1); | ||
const tx = new NeonTransaction( | ||
this.dialect, | ||
this.session, | ||
this.relations, | ||
this.schema, | ||
this.nestedIndex + 1 | ||
); | ||
await tx.execute(sql.raw(`savepoint ${savepointName}`)); | ||
@@ -166,0 +201,0 @@ try { |
import { type Pool, type PoolConfig } from 'pg'; | ||
import * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
@@ -6,3 +7,3 @@ import type { Logger } from "../logger.js"; | ||
import { PgDialect } from "../pg-core/dialect.js"; | ||
import { type RelationalSchemaConfig, type TablesRelationalConfig } from "../relations.js"; | ||
import type { AnyRelations, EmptyRelations, TablesRelationalConfig } from "../relations.js"; | ||
import { type DrizzleConfig } from "../utils.js"; | ||
@@ -20,14 +21,14 @@ import type { NodePgClient, NodePgQueryResultHKT } from "./session.js"; | ||
constructor(client: NodePgClient, dialect: PgDialect, options?: PgDriverOptions); | ||
createSession(schema: RelationalSchemaConfig<TablesRelationalConfig> | undefined): NodePgSession<Record<string, unknown>, TablesRelationalConfig>; | ||
createSession(relations: AnyRelations | undefined, schema: V1.RelationalSchemaConfig<V1.TablesRelationalConfig> | undefined): NodePgSession<Record<string, unknown>, AnyRelations, TablesRelationalConfig, V1.TablesRelationalConfig>; | ||
} | ||
export declare class NodePgDatabase<TSchema extends Record<string, unknown> = Record<string, never>> extends PgDatabase<NodePgQueryResultHKT, TSchema> { | ||
export declare class NodePgDatabase<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations> extends PgDatabase<NodePgQueryResultHKT, TSchema, TRelations> { | ||
static readonly [entityKind]: string; | ||
} | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TClient extends NodePgClient = Pool>(...params: [ | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations, TClient extends NodePgClient = Pool>(...params: [ | ||
TClient | string | ||
] | [ | ||
TClient | string, | ||
DrizzleConfig<TSchema> | ||
DrizzleConfig<TSchema, TRelations> | ||
] | [ | ||
(DrizzleConfig<TSchema> & ({ | ||
(DrizzleConfig<TSchema, TRelations> & ({ | ||
connection: string | PoolConfig; | ||
@@ -37,9 +38,9 @@ } | { | ||
})) | ||
]): NodePgDatabase<TSchema> & { | ||
]): NodePgDatabase<TSchema, TRelations> & { | ||
$client: TClient; | ||
}; | ||
export declare namespace drizzle { | ||
function mock<TSchema extends Record<string, unknown> = Record<string, never>>(config?: DrizzleConfig<TSchema>): NodePgDatabase<TSchema> & { | ||
function mock<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations>(config?: DrizzleConfig<TSchema, TRelations>): NodePgDatabase<TSchema, TRelations> & { | ||
$client: '$client is not available on drizzle.mock()'; | ||
}; | ||
} |
import pg from "pg"; | ||
import * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
@@ -6,6 +7,2 @@ import { DefaultLogger } from "../logger.js"; | ||
import { PgDialect } from "../pg-core/dialect.js"; | ||
import { | ||
createTableRelationsHelpers, | ||
extractTablesRelationalConfig | ||
} from "../relations.js"; | ||
import { isConfig } from "../utils.js"; | ||
@@ -20,4 +17,4 @@ import { NodePgSession } from "./session.js"; | ||
static [entityKind] = "NodePgDriver"; | ||
createSession(schema) { | ||
return new NodePgSession(this.client, this.dialect, schema, { logger: this.options.logger }); | ||
createSession(relations, schema) { | ||
return new NodePgSession(this.client, this.dialect, relations, schema, { logger: this.options.logger }); | ||
} | ||
@@ -38,5 +35,5 @@ } | ||
if (config.schema) { | ||
const tablesConfig = extractTablesRelationalConfig( | ||
const tablesConfig = V1.extractTablesRelationalConfig( | ||
config.schema, | ||
createTableRelationsHelpers | ||
V1.createTableRelationsHelpers | ||
); | ||
@@ -49,5 +46,11 @@ schema = { | ||
} | ||
const relations = config.relations; | ||
const driver = new NodePgDriver(client, dialect, { logger }); | ||
const session = driver.createSession(schema); | ||
const db = new NodePgDatabase(dialect, session, schema); | ||
const session = driver.createSession(relations, schema); | ||
const db = new NodePgDatabase( | ||
dialect, | ||
session, | ||
relations, | ||
schema | ||
); | ||
db.$client = client; | ||
@@ -54,0 +57,0 @@ return db; |
import type { MigrationConfig } from "../migrator.js"; | ||
import type { AnyRelations } from "../relations.js"; | ||
import type { NodePgDatabase } from "./driver.js"; | ||
export declare function migrate<TSchema extends Record<string, unknown>>(db: NodePgDatabase<TSchema>, config: MigrationConfig): Promise<void>; | ||
export declare function migrate<TSchema extends Record<string, unknown>, TRelations extends AnyRelations>(db: NodePgDatabase<TSchema, TRelations>, config: MigrationConfig): Promise<void>; |
import type { Client, PoolClient, QueryResult, QueryResultRow } from 'pg'; | ||
import pg from 'pg'; | ||
import type * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
@@ -10,7 +11,7 @@ import { type Logger } from "../logger.js"; | ||
import { PgPreparedQuery, PgSession } from "../pg-core/session.js"; | ||
import type { RelationalSchemaConfig, TablesRelationalConfig } from "../relations.js"; | ||
import type { AnyRelations, TablesRelationalConfig } from "../relations.js"; | ||
import { type Query, type SQL } from "../sql/sql.js"; | ||
import { type Assume } from "../utils.js"; | ||
export type NodePgClient = pg.Pool | PoolClient | Client; | ||
export declare class NodePgPreparedQuery<T extends PreparedQueryConfig> extends PgPreparedQuery<T> { | ||
export declare class NodePgPreparedQuery<T extends PreparedQueryConfig, TIsRqbV2 extends boolean = false> extends PgPreparedQuery<T> { | ||
private client; | ||
@@ -22,7 +23,9 @@ private params; | ||
private customResultMapper?; | ||
private isRqbV2Query?; | ||
static readonly [entityKind]: string; | ||
private rawQueryConfig; | ||
private queryConfig; | ||
constructor(client: NodePgClient, queryString: string, params: unknown[], logger: Logger, fields: SelectedFieldsOrdered | undefined, name: string | undefined, _isResponseInArrayMode: boolean, customResultMapper?: ((rows: unknown[][]) => T["execute"]) | undefined); | ||
constructor(client: NodePgClient, queryString: string, params: unknown[], logger: Logger, fields: SelectedFieldsOrdered | undefined, name: string | undefined, _isResponseInArrayMode: boolean, customResultMapper?: ((rows: TIsRqbV2 extends true ? Record<string, unknown>[] : unknown[][]) => T["execute"]) | undefined, isRqbV2Query?: TIsRqbV2 | undefined); | ||
execute(placeholderValues?: Record<string, unknown> | undefined): Promise<T['execute']>; | ||
private executeRqbV2; | ||
all(placeholderValues?: Record<string, unknown> | undefined): Promise<T['all']>; | ||
@@ -33,4 +36,5 @@ } | ||
} | ||
export declare class NodePgSession<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends PgSession<NodePgQueryResultHKT, TFullSchema, TSchema> { | ||
export declare class NodePgSession<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends PgSession<NodePgQueryResultHKT, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
private client; | ||
private relations; | ||
private schema; | ||
@@ -40,10 +44,11 @@ private options; | ||
private logger; | ||
constructor(client: NodePgClient, dialect: PgDialect, schema: RelationalSchemaConfig<TSchema> | undefined, options?: NodePgSessionOptions); | ||
constructor(client: NodePgClient, dialect: PgDialect, relations: AnyRelations | undefined, schema: V1.RelationalSchemaConfig<TSchema> | undefined, options?: NodePgSessionOptions); | ||
prepareQuery<T extends PreparedQueryConfig = PreparedQueryConfig>(query: Query, fields: SelectedFieldsOrdered | undefined, name: string | undefined, isResponseInArrayMode: boolean, customResultMapper?: (rows: unknown[][]) => T['execute']): PgPreparedQuery<T>; | ||
transaction<T>(transaction: (tx: NodePgTransaction<TFullSchema, TSchema>) => Promise<T>, config?: PgTransactionConfig | undefined): Promise<T>; | ||
prepareRelationalQuery<T extends PreparedQueryConfig = PreparedQueryConfig>(query: Query, fields: SelectedFieldsOrdered | undefined, name: string | undefined, customResultMapper?: (rows: Record<string, unknown>[]) => T['execute']): PgPreparedQuery<T>; | ||
transaction<T>(transaction: (tx: NodePgTransaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => Promise<T>, config?: PgTransactionConfig | undefined): Promise<T>; | ||
count(sql: SQL): Promise<number>; | ||
} | ||
export declare class NodePgTransaction<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends PgTransaction<NodePgQueryResultHKT, TFullSchema, TSchema> { | ||
export declare class NodePgTransaction<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends PgTransaction<NodePgQueryResultHKT, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
static readonly [entityKind]: string; | ||
transaction<T>(transaction: (tx: NodePgTransaction<TFullSchema, TSchema>) => Promise<T>): Promise<T>; | ||
transaction<T>(transaction: (tx: NodePgTransaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => Promise<T>): Promise<T>; | ||
} | ||
@@ -50,0 +55,0 @@ export interface NodePgQueryResultHKT extends PgQueryResultHKT { |
@@ -11,3 +11,3 @@ import pg from "pg"; | ||
class NodePgPreparedQuery extends PgPreparedQuery { | ||
constructor(client, queryString, params, logger, fields, name, _isResponseInArrayMode, customResultMapper) { | ||
constructor(client, queryString, params, logger, fields, name, _isResponseInArrayMode, customResultMapper, isRqbV2Query) { | ||
super({ sql: queryString, params }); | ||
@@ -20,2 +20,3 @@ this.client = client; | ||
this.customResultMapper = customResultMapper; | ||
this.isRqbV2Query = isRqbV2Query; | ||
this.rawQueryConfig = { | ||
@@ -71,2 +72,4 @@ name, | ||
async execute(placeholderValues = {}) { | ||
if (this.isRqbV2Query) | ||
return this.executeRqbV2(placeholderValues); | ||
return tracer.startActiveSpan("drizzle.execute", async () => { | ||
@@ -99,2 +102,20 @@ const params = fillPlaceholders(this.params, placeholderValues); | ||
} | ||
async executeRqbV2(placeholderValues = {}) { | ||
return tracer.startActiveSpan("drizzle.execute", async () => { | ||
const params = fillPlaceholders(this.params, placeholderValues); | ||
this.logger.logQuery(this.rawQueryConfig.text, params); | ||
const { rawQueryConfig: rawQuery, client, customResultMapper } = this; | ||
const result = await tracer.startActiveSpan("drizzle.driver.execute", (span) => { | ||
span?.setAttributes({ | ||
"drizzle.query.name": rawQuery.name, | ||
"drizzle.query.text": rawQuery.text, | ||
"drizzle.query.params": JSON.stringify(params) | ||
}); | ||
return client.query(rawQuery, params); | ||
}); | ||
return tracer.startActiveSpan("drizzle.mapResponse", () => { | ||
return customResultMapper(result.rows); | ||
}); | ||
}); | ||
} | ||
all(placeholderValues = {}) { | ||
@@ -120,5 +141,6 @@ return tracer.startActiveSpan("drizzle.execute", () => { | ||
class NodePgSession extends PgSession { | ||
constructor(client, dialect, schema, options = {}) { | ||
constructor(client, dialect, relations, schema, options = {}) { | ||
super(dialect); | ||
this.client = client; | ||
this.relations = relations; | ||
this.schema = schema; | ||
@@ -142,5 +164,23 @@ this.options = options; | ||
} | ||
prepareRelationalQuery(query, fields, name, customResultMapper) { | ||
return new NodePgPreparedQuery( | ||
this.client, | ||
query.sql, | ||
query.params, | ||
this.logger, | ||
fields, | ||
name, | ||
false, | ||
customResultMapper, | ||
true | ||
); | ||
} | ||
async transaction(transaction, config) { | ||
const session = this.client instanceof Pool ? new NodePgSession(await this.client.connect(), this.dialect, this.schema, this.options) : this; | ||
const tx = new NodePgTransaction(this.dialect, session, this.schema); | ||
const session = this.client instanceof Pool ? new NodePgSession(await this.client.connect(), this.dialect, this.relations, this.schema, this.options) : this; | ||
const tx = new NodePgTransaction( | ||
this.dialect, | ||
session, | ||
this.relations, | ||
this.schema | ||
); | ||
await tx.execute(sql`begin${config ? sql` ${tx.getTransactionConfigSQL(config)}` : void 0}`); | ||
@@ -174,2 +214,3 @@ try { | ||
this.session, | ||
this.relations, | ||
this.schema, | ||
@@ -176,0 +217,0 @@ this.nestedIndex + 1 |
import type { OPSQLiteConnection, QueryResult } from '@op-engineering/op-sqlite'; | ||
import { entityKind } from "../entity.js"; | ||
import type { AnyRelations, EmptyRelations } from "../relations.js"; | ||
import { BaseSQLiteDatabase } from "../sqlite-core/db.js"; | ||
import type { DrizzleConfig } from "../utils.js"; | ||
export declare class OPSQLiteDatabase<TSchema extends Record<string, unknown> = Record<string, never>> extends BaseSQLiteDatabase<'async', QueryResult, TSchema> { | ||
export declare class OPSQLiteDatabase<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations> extends BaseSQLiteDatabase<'async', QueryResult, TSchema, TRelations> { | ||
static readonly [entityKind]: string; | ||
} | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(client: OPSQLiteConnection, config?: DrizzleConfig<TSchema>): OPSQLiteDatabase<TSchema> & { | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations>(client: OPSQLiteConnection, config?: DrizzleConfig<TSchema, TRelations>): OPSQLiteDatabase<TSchema, TRelations> & { | ||
$client: OPSQLiteConnection; | ||
}; |
@@ -0,7 +1,4 @@ | ||
import * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
import { DefaultLogger } from "../logger.js"; | ||
import { | ||
createTableRelationsHelpers, | ||
extractTablesRelationalConfig | ||
} from "../relations.js"; | ||
import { BaseSQLiteDatabase } from "../sqlite-core/db.js"; | ||
@@ -23,5 +20,5 @@ import { SQLiteAsyncDialect } from "../sqlite-core/dialect.js"; | ||
if (config.schema) { | ||
const tablesConfig = extractTablesRelationalConfig( | ||
const tablesConfig = V1.extractTablesRelationalConfig( | ||
config.schema, | ||
createTableRelationsHelpers | ||
V1.createTableRelationsHelpers | ||
); | ||
@@ -34,4 +31,11 @@ schema = { | ||
} | ||
const session = new OPSQLiteSession(client, dialect, schema, { logger }); | ||
const db = new OPSQLiteDatabase("async", dialect, session, schema); | ||
const relations = config.relations; | ||
const session = new OPSQLiteSession(client, dialect, relations, schema, { logger }); | ||
const db = new OPSQLiteDatabase( | ||
"async", | ||
dialect, | ||
session, | ||
relations, | ||
schema | ||
); | ||
db.$client = client; | ||
@@ -38,0 +42,0 @@ return db; |
@@ -0,1 +1,2 @@ | ||
import type { AnyRelations } from "../relations.js"; | ||
import type { OPSQLiteDatabase } from "./driver.js"; | ||
@@ -13,3 +14,3 @@ interface MigrationConfig { | ||
} | ||
export declare function migrate<TSchema extends Record<string, unknown>>(db: OPSQLiteDatabase<TSchema>, config: MigrationConfig): Promise<void>; | ||
export declare function migrate<TSchema extends Record<string, unknown>, TRelations extends AnyRelations>(db: OPSQLiteDatabase<TSchema, TRelations>, config: MigrationConfig): Promise<void>; | ||
interface State { | ||
@@ -19,3 +20,3 @@ success: boolean; | ||
} | ||
export declare const useMigrations: (db: OPSQLiteDatabase<any>, migrations: { | ||
export declare const useMigrations: (db: OPSQLiteDatabase<any, any>, migrations: { | ||
journal: { | ||
@@ -22,0 +23,0 @@ entries: { |
import type { OPSQLiteConnection, QueryResult } from '@op-engineering/op-sqlite'; | ||
import type * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
import type { Logger } from "../logger.js"; | ||
import type { RelationalSchemaConfig, TablesRelationalConfig } from "../relations.js"; | ||
import type { AnyRelations, TablesRelationalConfig } from "../relations.js"; | ||
import { type Query } from "../sql/sql.js"; | ||
@@ -14,16 +15,18 @@ import type { SQLiteAsyncDialect } from "../sqlite-core/dialect.js"; | ||
type PreparedQueryConfig = Omit<PreparedQueryConfigBase, 'statement' | 'run'>; | ||
export declare class OPSQLiteSession<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends SQLiteSession<'async', QueryResult, TFullSchema, TSchema> { | ||
export declare class OPSQLiteSession<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends SQLiteSession<'async', QueryResult, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
private client; | ||
private relations; | ||
private schema; | ||
static readonly [entityKind]: string; | ||
private logger; | ||
constructor(client: OPSQLiteConnection, dialect: SQLiteAsyncDialect, schema: RelationalSchemaConfig<TSchema> | undefined, options?: OPSQLiteSessionOptions); | ||
constructor(client: OPSQLiteConnection, dialect: SQLiteAsyncDialect, relations: AnyRelations | undefined, schema: V1.RelationalSchemaConfig<TSchema> | undefined, options?: OPSQLiteSessionOptions); | ||
prepareQuery<T extends Omit<PreparedQueryConfig, 'run'>>(query: Query, fields: SelectedFieldsOrdered | undefined, executeMethod: SQLiteExecuteMethod, isResponseInArrayMode: boolean, customResultMapper?: (rows: unknown[][]) => unknown): OPSQLitePreparedQuery<T>; | ||
transaction<T>(transaction: (tx: OPSQLiteTransaction<TFullSchema, TSchema>) => T, config?: SQLiteTransactionConfig): T; | ||
prepareRelationalQuery<T extends Omit<PreparedQueryConfig, 'run'>>(query: Query, fields: SelectedFieldsOrdered | undefined, executeMethod: SQLiteExecuteMethod, customResultMapper: (rows: Record<string, unknown>[]) => unknown): OPSQLitePreparedQuery<T, true>; | ||
transaction<T>(transaction: (tx: OPSQLiteTransaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => T, config?: SQLiteTransactionConfig): T; | ||
} | ||
export declare class OPSQLiteTransaction<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends SQLiteTransaction<'async', QueryResult, TFullSchema, TSchema> { | ||
export declare class OPSQLiteTransaction<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends SQLiteTransaction<'async', QueryResult, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
static readonly [entityKind]: string; | ||
transaction<T>(transaction: (tx: OPSQLiteTransaction<TFullSchema, TSchema>) => T): T; | ||
transaction<T>(transaction: (tx: OPSQLiteTransaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => T): T; | ||
} | ||
export declare class OPSQLitePreparedQuery<T extends PreparedQueryConfig = PreparedQueryConfig> extends SQLitePreparedQuery<{ | ||
export declare class OPSQLitePreparedQuery<T extends PreparedQueryConfig = PreparedQueryConfig, TIsRqbV2 extends boolean = false> extends SQLitePreparedQuery<{ | ||
type: 'async'; | ||
@@ -41,9 +44,12 @@ run: QueryResult; | ||
private customResultMapper?; | ||
private isRqbV2Query?; | ||
static readonly [entityKind]: string; | ||
constructor(client: OPSQLiteConnection, query: Query, logger: Logger, fields: SelectedFieldsOrdered | undefined, executeMethod: SQLiteExecuteMethod, _isResponseInArrayMode: boolean, customResultMapper?: ((rows: unknown[][]) => unknown) | undefined); | ||
constructor(client: OPSQLiteConnection, query: Query, logger: Logger, fields: SelectedFieldsOrdered | undefined, executeMethod: SQLiteExecuteMethod, _isResponseInArrayMode: boolean, customResultMapper?: ((rows: TIsRqbV2 extends true ? Record<string, unknown>[] : unknown[][]) => unknown) | undefined, isRqbV2Query?: TIsRqbV2 | undefined); | ||
run(placeholderValues?: Record<string, unknown>): Promise<QueryResult>; | ||
all(placeholderValues?: Record<string, unknown>): Promise<T['all']>; | ||
private allRqbV2; | ||
get(placeholderValues?: Record<string, unknown>): Promise<T['get']>; | ||
private getRqbV2; | ||
values(placeholderValues?: Record<string, unknown>): Promise<T['values']>; | ||
} | ||
export {}; |
@@ -11,5 +11,6 @@ import { entityKind } from "../entity.js"; | ||
class OPSQLiteSession extends SQLiteSession { | ||
constructor(client, dialect, schema, options = {}) { | ||
constructor(client, dialect, relations, schema, options = {}) { | ||
super(dialect); | ||
this.client = client; | ||
this.relations = relations; | ||
this.schema = schema; | ||
@@ -31,4 +32,16 @@ this.logger = options.logger ?? new NoopLogger(); | ||
} | ||
prepareRelationalQuery(query, fields, executeMethod, customResultMapper) { | ||
return new OPSQLitePreparedQuery( | ||
this.client, | ||
query, | ||
this.logger, | ||
fields, | ||
executeMethod, | ||
false, | ||
customResultMapper, | ||
true | ||
); | ||
} | ||
transaction(transaction, config = {}) { | ||
const tx = new OPSQLiteTransaction("async", this.dialect, this, this.schema); | ||
const tx = new OPSQLiteTransaction("async", this.dialect, this, this.relations, this.schema); | ||
this.run(sql.raw(`begin${config?.behavior ? " " + config.behavior : ""}`)); | ||
@@ -49,3 +62,10 @@ try { | ||
const savepointName = `sp${this.nestedIndex}`; | ||
const tx = new OPSQLiteTransaction("async", this.dialect, this.session, this.schema, this.nestedIndex + 1); | ||
const tx = new OPSQLiteTransaction( | ||
"async", | ||
this.dialect, | ||
this.session, | ||
this.relations, | ||
this.schema, | ||
this.nestedIndex + 1 | ||
); | ||
this.session.run(sql.raw(`savepoint ${savepointName}`)); | ||
@@ -63,3 +83,3 @@ try { | ||
class OPSQLitePreparedQuery extends SQLitePreparedQuery { | ||
constructor(client, query, logger, fields, executeMethod, _isResponseInArrayMode, customResultMapper) { | ||
constructor(client, query, logger, fields, executeMethod, _isResponseInArrayMode, customResultMapper, isRqbV2Query) { | ||
super("sync", executeMethod, query); | ||
@@ -71,2 +91,3 @@ this.client = client; | ||
this.customResultMapper = customResultMapper; | ||
this.isRqbV2Query = isRqbV2Query; | ||
} | ||
@@ -80,2 +101,4 @@ static [entityKind] = "OPSQLitePreparedQuery"; | ||
async all(placeholderValues) { | ||
if (this.isRqbV2Query) | ||
return this.allRqbV2(placeholderValues); | ||
const { fields, joinsNotNullableMap, query, logger, customResultMapper, client } = this; | ||
@@ -93,3 +116,12 @@ if (!fields && !customResultMapper) { | ||
} | ||
async allRqbV2(placeholderValues) { | ||
const { query, logger, customResultMapper, client } = this; | ||
const params = fillPlaceholders(query.params, placeholderValues ?? {}); | ||
logger.logQuery(query.sql, params); | ||
const rows = client.execute(query.sql, params).rows?._array || []; | ||
return customResultMapper(rows); | ||
} | ||
async get(placeholderValues) { | ||
if (this.isRqbV2Query) | ||
return this.getRqbV2(placeholderValues); | ||
const { fields, joinsNotNullableMap, customResultMapper, query, logger, client } = this; | ||
@@ -112,2 +144,13 @@ const params = fillPlaceholders(query.params, placeholderValues ?? {}); | ||
} | ||
async getRqbV2(placeholderValues) { | ||
const { customResultMapper, query, logger, client } = this; | ||
const params = fillPlaceholders(query.params, placeholderValues ?? {}); | ||
logger.logQuery(query.sql, params); | ||
const rows = client.execute(query.sql, params).rows?._array || []; | ||
const row = rows[0]; | ||
if (!row) { | ||
return void 0; | ||
} | ||
return customResultMapper([row]); | ||
} | ||
values(placeholderValues) { | ||
@@ -114,0 +157,0 @@ const params = fillPlaceholders(this.query.params, placeholderValues ?? {}); |
@@ -0,1 +1,2 @@ | ||
import type * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
@@ -7,3 +8,3 @@ import type { PgDialect } from "./dialect.js"; | ||
import type { TypedQueryBuilder } from "../query-builders/query-builder.js"; | ||
import type { ExtractTablesWithRelations, RelationalSchemaConfig, TablesRelationalConfig } from "../relations.js"; | ||
import type { AnyRelations, EmptyRelations, ExtractTablesWithRelations, TablesRelationalConfig } from "../relations.js"; | ||
import { type ColumnsSelection, type SQL, type SQLWrapper } from "../sql/sql.js"; | ||
@@ -13,2 +14,3 @@ import { WithSubquery } from "../subquery.js"; | ||
import type { PgColumn } from "./columns/index.js"; | ||
import { _RelationalQueryBuilder } from "./query-builders/_query.js"; | ||
import { PgCountBuilder } from "./query-builders/count.js"; | ||
@@ -22,3 +24,3 @@ import { RelationalQueryBuilder } from "./query-builders/query.js"; | ||
import type { PgMaterializedView } from "./view.js"; | ||
export declare class PgDatabase<TQueryResult extends PgQueryResultHKT, TFullSchema extends Record<string, unknown> = Record<string, never>, TSchema extends TablesRelationalConfig = ExtractTablesWithRelations<TFullSchema>> { | ||
export declare class PgDatabase<TQueryResult extends PgQueryResultHKT, TFullSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations, TTablesConfig extends TablesRelationalConfig = ExtractTablesWithRelations<TRelations>, TSchema extends V1.TablesRelationalConfig = V1.ExtractTablesWithRelations<TFullSchema>> { | ||
static readonly [entityKind]: string; | ||
@@ -29,7 +31,12 @@ readonly _: { | ||
readonly tableNamesMap: Record<string, string>; | ||
readonly session: PgSession<TQueryResult, TFullSchema, TSchema>; | ||
readonly relations: TRelations; | ||
readonly session: PgSession<TQueryResult, TFullSchema, TRelations, TTablesConfig, TSchema>; | ||
}; | ||
query: TFullSchema extends Record<string, never> ? DrizzleTypeError<'Seems like the schema generic is missing - did you forget to add it to your DB type?'> : { | ||
[K in keyof TSchema]: RelationalQueryBuilder<TSchema, TSchema[K]>; | ||
/** @deprecated */ | ||
_query: TFullSchema extends Record<string, never> ? DrizzleTypeError<'Seems like the schema generic is missing - did you forget to add it to your DB type?'> : { | ||
[K in keyof TSchema]: _RelationalQueryBuilder<TSchema, TSchema[K]>; | ||
}; | ||
query: { | ||
[K in keyof TRelations['tables']]: RelationalQueryBuilder<TTablesConfig, TTablesConfig[K]>; | ||
}; | ||
constructor( | ||
@@ -39,3 +46,3 @@ /** @internal */ | ||
/** @internal */ | ||
session: PgSession<any, any, any>, schema: RelationalSchemaConfig<TSchema> | undefined); | ||
session: PgSession<any, any, any, any, any>, relations: AnyRelations | undefined, schema: V1.RelationalSchemaConfig<TSchema> | undefined); | ||
/** | ||
@@ -76,3 +83,3 @@ * Creates a subquery that defines a temporary named result set as a CTE. | ||
}; | ||
$count(source: PgTable | PgViewBase | SQL | SQLWrapper, filters?: SQL<unknown>): PgCountBuilder<PgSession<any, any, any>>; | ||
$count(source: PgTable | PgViewBase | SQL | SQLWrapper, filters?: SQL<unknown>): PgCountBuilder<PgSession<any, any, any, any, any>>; | ||
/** | ||
@@ -286,3 +293,3 @@ * Incorporates a previously defined CTE (using `$with`) into the main query. | ||
execute<TRow extends Record<string, unknown> = Record<string, unknown>>(query: SQLWrapper | string): PgRaw<PgQueryResultKind<TQueryResult, TRow>>; | ||
transaction<T>(transaction: (tx: PgTransaction<TQueryResult, TFullSchema, TSchema>) => Promise<T>, config?: PgTransactionConfig): Promise<T>; | ||
transaction<T>(transaction: (tx: PgTransaction<TQueryResult, TFullSchema, TRelations, TTablesConfig, TSchema>) => Promise<T>, config?: PgTransactionConfig): Promise<T>; | ||
} | ||
@@ -292,2 +299,2 @@ export type PgWithReplicas<Q> = Q & { | ||
}; | ||
export declare const withReplicas: <HKT extends PgQueryResultHKT, TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig, Q extends PgDatabase<HKT, TFullSchema, TSchema extends Record<string, unknown> ? ExtractTablesWithRelations<TFullSchema> : TSchema>>(primary: Q, replicas: [Q, ...Q[]], getReplica?: (replicas: Q[]) => Q) => PgWithReplicas<Q>; | ||
export declare const withReplicas: <HKT extends PgQueryResultHKT, TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig, Q extends PgDatabase<HKT, TFullSchema, TRelations, TTablesConfig, TSchema extends Record<string, unknown> ? V1.ExtractTablesWithRelations<TFullSchema> : TSchema>>(primary: Q, replicas: [Q, ...Q[]], getReplica?: (replicas: Q[]) => Q) => PgWithReplicas<Q>; |
@@ -12,2 +12,3 @@ import { entityKind } from "../entity.js"; | ||
import { WithSubquery } from "../subquery.js"; | ||
import { _RelationalQueryBuilder } from "./query-builders/_query.js"; | ||
import { PgCountBuilder } from "./query-builders/count.js"; | ||
@@ -18,5 +19,6 @@ import { RelationalQueryBuilder } from "./query-builders/query.js"; | ||
class PgDatabase { | ||
constructor(dialect, session, schema) { | ||
constructor(dialect, session, relations, schema) { | ||
this.dialect = dialect; | ||
this.session = session; | ||
const rel = relations ?? {}; | ||
this._ = schema ? { | ||
@@ -26,2 +28,3 @@ schema: schema.schema, | ||
tableNamesMap: schema.tableNamesMap, | ||
relations: rel, | ||
session | ||
@@ -32,8 +35,9 @@ } : { | ||
tableNamesMap: {}, | ||
relations: rel, | ||
session | ||
}; | ||
this.query = {}; | ||
this._query = {}; | ||
if (this._.schema) { | ||
for (const [tableName, columns] of Object.entries(this._.schema)) { | ||
this.query[tableName] = new RelationalQueryBuilder( | ||
this._query[tableName] = new _RelationalQueryBuilder( | ||
schema.fullSchema, | ||
@@ -49,4 +53,21 @@ this._.schema, | ||
} | ||
this.query = {}; | ||
if (relations) { | ||
for (const [tableName, relation] of Object.entries(relations.tablesConfig)) { | ||
this.query[tableName] = new RelationalQueryBuilder( | ||
relations.tables, | ||
relations.tablesConfig, | ||
relations.tableNamesMap, | ||
relation.table, | ||
relation, | ||
dialect, | ||
session | ||
); | ||
} | ||
} | ||
} | ||
static [entityKind] = "PgDatabase"; | ||
/** @deprecated */ | ||
_query; | ||
// TO-DO: Figure out how to pass DrizzleTypeError without breaking withReplicas | ||
query; | ||
@@ -288,3 +309,6 @@ /** | ||
transaction(transaction, config) { | ||
return this.session.transaction(transaction, config); | ||
return this.session.transaction( | ||
transaction, | ||
config | ||
); | ||
} | ||
@@ -316,4 +340,4 @@ } | ||
with: $with, | ||
get query() { | ||
return getReplica(replicas).query; | ||
get _query() { | ||
return getReplica(replicas)._query; | ||
} | ||
@@ -320,0 +344,0 @@ }; |
@@ -0,1 +1,2 @@ | ||
import * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
@@ -7,3 +8,3 @@ import type { MigrationConfig, MigrationMeta } from "../migrator.js"; | ||
import { PgTable } from "./table.js"; | ||
import { type BuildRelationalQueryResult, type DBQueryConfig, type Relation, type TableRelationalConfig, type TablesRelationalConfig } from "../relations.js"; | ||
import { type BuildRelationalQueryResult, type DBQueryConfig, type TableRelationalConfig, type TablesRelationalConfig } from "../relations.js"; | ||
import { type DriverValueEncoder, type QueryTypingsValue, type QueryWithTypings, SQL } from "../sql/sql.js"; | ||
@@ -55,4 +56,18 @@ import { type Casing, type UpdateSet } from "../utils.js"; | ||
sqlToQuery(sql: SQL, invokeSource?: 'indexes' | undefined): QueryWithTypings; | ||
buildRelationalQueryWithoutPK({ fullSchema, schema, tableNamesMap, table, tableConfig, queryConfig: config, tableAlias, nestedQueryRelation, joinOn, }: { | ||
/** @deprecated */ | ||
_buildRelationalQuery({ fullSchema, schema, tableNamesMap, table, tableConfig, queryConfig: config, tableAlias, nestedQueryRelation, joinOn, }: { | ||
fullSchema: Record<string, unknown>; | ||
schema: V1.TablesRelationalConfig; | ||
tableNamesMap: Record<string, string>; | ||
table: PgTable; | ||
tableConfig: V1.TableRelationalConfig; | ||
queryConfig: true | V1.DBQueryConfig<'many', true>; | ||
tableAlias: string; | ||
nestedQueryRelation?: V1.Relation; | ||
joinOn?: SQL; | ||
}): V1.BuildRelationalQueryResult<PgTable, PgColumn>; | ||
private unwrapAllColumns; | ||
private buildColumns; | ||
buildRelationalQuery({ tables, schema, tableNamesMap, table, tableConfig, queryConfig: config, relationWhere, mode, }: { | ||
tables: Record<string, PgTable>; | ||
schema: TablesRelationalConfig; | ||
@@ -62,7 +77,6 @@ tableNamesMap: Record<string, string>; | ||
tableConfig: TableRelationalConfig; | ||
queryConfig: true | DBQueryConfig<'many', true>; | ||
tableAlias: string; | ||
nestedQueryRelation?: Relation; | ||
joinOn?: SQL; | ||
}): BuildRelationalQueryResult<PgTable, PgColumn>; | ||
queryConfig?: DBQueryConfig<'many'> | true; | ||
relationWhere?: SQL; | ||
mode: 'first' | 'many'; | ||
}): BuildRelationalQueryResult; | ||
} |
@@ -0,1 +1,2 @@ | ||
import * as V1 from "../_relations.js"; | ||
import { aliasedTable, aliasedTableColumn, mapColumnsInAliasedSQLToAlias, mapColumnsInSQLToAlias } from "../alias.js"; | ||
@@ -20,7 +21,8 @@ import { CasingCache } from "../casing.js"; | ||
import { | ||
getOperators, | ||
getOrderByOperators, | ||
Many, | ||
normalizeRelation, | ||
One | ||
AggregatedField, | ||
One, | ||
relationExtrasToSQL, | ||
relationFilterToSQL, | ||
relationsOrderToSQL, | ||
relationToSQL | ||
} from "../relations.js"; | ||
@@ -34,3 +36,3 @@ import { and, eq, View } from "../sql/index.js"; | ||
import { Subquery } from "../subquery.js"; | ||
import { getTableName, getTableUniqueName, Table } from "../table.js"; | ||
import { Columns, getTableName, getTableUniqueName, Table } from "../table.js"; | ||
import { orderSelectedFields } from "../utils.js"; | ||
@@ -429,484 +431,4 @@ import { ViewBaseConfig } from "../view-common.js"; | ||
} | ||
// buildRelationalQueryWithPK({ | ||
// fullSchema, | ||
// schema, | ||
// tableNamesMap, | ||
// table, | ||
// tableConfig, | ||
// queryConfig: config, | ||
// tableAlias, | ||
// isRoot = false, | ||
// joinOn, | ||
// }: { | ||
// fullSchema: Record<string, unknown>; | ||
// schema: TablesRelationalConfig; | ||
// tableNamesMap: Record<string, string>; | ||
// table: PgTable; | ||
// tableConfig: TableRelationalConfig; | ||
// queryConfig: true | DBQueryConfig<'many', true>; | ||
// tableAlias: string; | ||
// isRoot?: boolean; | ||
// joinOn?: SQL; | ||
// }): BuildRelationalQueryResult<PgTable, PgColumn> { | ||
// // For { "<relation>": true }, return a table with selection of all columns | ||
// if (config === true) { | ||
// const selectionEntries = Object.entries(tableConfig.columns); | ||
// const selection: BuildRelationalQueryResult<PgTable, PgColumn>['selection'] = selectionEntries.map(( | ||
// [key, value], | ||
// ) => ({ | ||
// dbKey: value.name, | ||
// tsKey: key, | ||
// field: value as PgColumn, | ||
// relationTableTsKey: undefined, | ||
// isJson: false, | ||
// selection: [], | ||
// })); | ||
// return { | ||
// tableTsKey: tableConfig.tsName, | ||
// sql: table, | ||
// selection, | ||
// }; | ||
// } | ||
// // let selection: BuildRelationalQueryResult<PgTable, PgColumn>['selection'] = []; | ||
// // let selectionForBuild = selection; | ||
// const aliasedColumns = Object.fromEntries( | ||
// Object.entries(tableConfig.columns).map(([key, value]) => [key, aliasedTableColumn(value, tableAlias)]), | ||
// ); | ||
// const aliasedRelations = Object.fromEntries( | ||
// Object.entries(tableConfig.relations).map(([key, value]) => [key, aliasedRelation(value, tableAlias)]), | ||
// ); | ||
// const aliasedFields = Object.assign({}, aliasedColumns, aliasedRelations); | ||
// let where, hasUserDefinedWhere; | ||
// if (config.where) { | ||
// const whereSql = typeof config.where === 'function' ? config.where(aliasedFields, operators) : config.where; | ||
// where = whereSql && mapColumnsInSQLToAlias(whereSql, tableAlias); | ||
// hasUserDefinedWhere = !!where; | ||
// } | ||
// where = and(joinOn, where); | ||
// // const fieldsSelection: { tsKey: string; value: PgColumn | SQL.Aliased; isExtra?: boolean }[] = []; | ||
// let joins: Join[] = []; | ||
// let selectedColumns: string[] = []; | ||
// // Figure out which columns to select | ||
// if (config.columns) { | ||
// let isIncludeMode = false; | ||
// for (const [field, value] of Object.entries(config.columns)) { | ||
// if (value === undefined) { | ||
// continue; | ||
// } | ||
// if (field in tableConfig.columns) { | ||
// if (!isIncludeMode && value === true) { | ||
// isIncludeMode = true; | ||
// } | ||
// selectedColumns.push(field); | ||
// } | ||
// } | ||
// if (selectedColumns.length > 0) { | ||
// selectedColumns = isIncludeMode | ||
// ? selectedColumns.filter((c) => config.columns?.[c] === true) | ||
// : Object.keys(tableConfig.columns).filter((key) => !selectedColumns.includes(key)); | ||
// } | ||
// } else { | ||
// // Select all columns if selection is not specified | ||
// selectedColumns = Object.keys(tableConfig.columns); | ||
// } | ||
// // for (const field of selectedColumns) { | ||
// // const column = tableConfig.columns[field]! as PgColumn; | ||
// // fieldsSelection.push({ tsKey: field, value: column }); | ||
// // } | ||
// let initiallySelectedRelations: { | ||
// tsKey: string; | ||
// queryConfig: true | DBQueryConfig<'many', false>; | ||
// relation: Relation; | ||
// }[] = []; | ||
// // let selectedRelations: BuildRelationalQueryResult<PgTable, PgColumn>['selection'] = []; | ||
// // Figure out which relations to select | ||
// if (config.with) { | ||
// initiallySelectedRelations = Object.entries(config.with) | ||
// .filter((entry): entry is [typeof entry[0], NonNullable<typeof entry[1]>] => !!entry[1]) | ||
// .map(([tsKey, queryConfig]) => ({ tsKey, queryConfig, relation: tableConfig.relations[tsKey]! })); | ||
// } | ||
// const manyRelations = initiallySelectedRelations.filter((r) => | ||
// is(r.relation, Many) | ||
// && (schema[tableNamesMap[r.relation.referencedTable[Table.Symbol.Name]]!]?.primaryKey.length ?? 0) > 0 | ||
// ); | ||
// // If this is the last Many relation (or there are no Many relations), we are on the innermost subquery level | ||
// const isInnermostQuery = manyRelations.length < 2; | ||
// const selectedExtras: { | ||
// tsKey: string; | ||
// value: SQL.Aliased; | ||
// }[] = []; | ||
// // Figure out which extras to select | ||
// if (isInnermostQuery && config.extras) { | ||
// const extras = typeof config.extras === 'function' | ||
// ? config.extras(aliasedFields, { sql }) | ||
// : config.extras; | ||
// for (const [tsKey, value] of Object.entries(extras)) { | ||
// selectedExtras.push({ | ||
// tsKey, | ||
// value: mapColumnsInAliasedSQLToAlias(value, tableAlias), | ||
// }); | ||
// } | ||
// } | ||
// // Transform `fieldsSelection` into `selection` | ||
// // `fieldsSelection` shouldn't be used after this point | ||
// // for (const { tsKey, value, isExtra } of fieldsSelection) { | ||
// // selection.push({ | ||
// // dbKey: is(value, SQL.Aliased) ? value.fieldAlias : tableConfig.columns[tsKey]!.name, | ||
// // tsKey, | ||
// // field: is(value, Column) ? aliasedTableColumn(value, tableAlias) : value, | ||
// // relationTableTsKey: undefined, | ||
// // isJson: false, | ||
// // isExtra, | ||
// // selection: [], | ||
// // }); | ||
// // } | ||
// let orderByOrig = typeof config.orderBy === 'function' | ||
// ? config.orderBy(aliasedFields, orderByOperators) | ||
// : config.orderBy ?? []; | ||
// if (!Array.isArray(orderByOrig)) { | ||
// orderByOrig = [orderByOrig]; | ||
// } | ||
// const orderBy = orderByOrig.map((orderByValue) => { | ||
// if (is(orderByValue, Column)) { | ||
// return aliasedTableColumn(orderByValue, tableAlias) as PgColumn; | ||
// } | ||
// return mapColumnsInSQLToAlias(orderByValue, tableAlias); | ||
// }); | ||
// const limit = isInnermostQuery ? config.limit : undefined; | ||
// const offset = isInnermostQuery ? config.offset : undefined; | ||
// // For non-root queries without additional config except columns, return a table with selection | ||
// if ( | ||
// !isRoot | ||
// && initiallySelectedRelations.length === 0 | ||
// && selectedExtras.length === 0 | ||
// && !where | ||
// && orderBy.length === 0 | ||
// && limit === undefined | ||
// && offset === undefined | ||
// ) { | ||
// return { | ||
// tableTsKey: tableConfig.tsName, | ||
// sql: table, | ||
// selection: selectedColumns.map((key) => ({ | ||
// dbKey: tableConfig.columns[key]!.name, | ||
// tsKey: key, | ||
// field: tableConfig.columns[key] as PgColumn, | ||
// relationTableTsKey: undefined, | ||
// isJson: false, | ||
// selection: [], | ||
// })), | ||
// }; | ||
// } | ||
// const selectedRelationsWithoutPK: | ||
// // Process all relations without primary keys, because they need to be joined differently and will all be on the same query level | ||
// for ( | ||
// const { | ||
// tsKey: selectedRelationTsKey, | ||
// queryConfig: selectedRelationConfigValue, | ||
// relation, | ||
// } of initiallySelectedRelations | ||
// ) { | ||
// const normalizedRelation = normalizeRelation(schema, tableNamesMap, relation); | ||
// const relationTableName = relation.referencedTable[Table.Symbol.Name]; | ||
// const relationTableTsName = tableNamesMap[relationTableName]!; | ||
// const relationTable = schema[relationTableTsName]!; | ||
// if (relationTable.primaryKey.length > 0) { | ||
// continue; | ||
// } | ||
// const relationTableAlias = `${tableAlias}_${selectedRelationTsKey}`; | ||
// const joinOn = and( | ||
// ...normalizedRelation.fields.map((field, i) => | ||
// eq( | ||
// aliasedTableColumn(normalizedRelation.references[i]!, relationTableAlias), | ||
// aliasedTableColumn(field, tableAlias), | ||
// ) | ||
// ), | ||
// ); | ||
// const builtRelation = this.buildRelationalQueryWithoutPK({ | ||
// fullSchema, | ||
// schema, | ||
// tableNamesMap, | ||
// table: fullSchema[relationTableTsName] as PgTable, | ||
// tableConfig: schema[relationTableTsName]!, | ||
// queryConfig: selectedRelationConfigValue, | ||
// tableAlias: relationTableAlias, | ||
// joinOn, | ||
// nestedQueryRelation: relation, | ||
// }); | ||
// const field = sql`${sql.identifier(relationTableAlias)}.${sql.identifier('data')}`.as(selectedRelationTsKey); | ||
// joins.push({ | ||
// on: sql`true`, | ||
// table: new Subquery(builtRelation.sql as SQL, {}, relationTableAlias), | ||
// alias: relationTableAlias, | ||
// joinType: 'left', | ||
// lateral: true, | ||
// }); | ||
// selectedRelations.push({ | ||
// dbKey: selectedRelationTsKey, | ||
// tsKey: selectedRelationTsKey, | ||
// field, | ||
// relationTableTsKey: relationTableTsName, | ||
// isJson: true, | ||
// selection: builtRelation.selection, | ||
// }); | ||
// } | ||
// const oneRelations = initiallySelectedRelations.filter((r): r is typeof r & { relation: One } => | ||
// is(r.relation, One) | ||
// ); | ||
// // Process all One relations with PKs, because they can all be joined on the same level | ||
// for ( | ||
// const { | ||
// tsKey: selectedRelationTsKey, | ||
// queryConfig: selectedRelationConfigValue, | ||
// relation, | ||
// } of oneRelations | ||
// ) { | ||
// const normalizedRelation = normalizeRelation(schema, tableNamesMap, relation); | ||
// const relationTableName = relation.referencedTable[Table.Symbol.Name]; | ||
// const relationTableTsName = tableNamesMap[relationTableName]!; | ||
// const relationTableAlias = `${tableAlias}_${selectedRelationTsKey}`; | ||
// const relationTable = schema[relationTableTsName]!; | ||
// if (relationTable.primaryKey.length === 0) { | ||
// continue; | ||
// } | ||
// const joinOn = and( | ||
// ...normalizedRelation.fields.map((field, i) => | ||
// eq( | ||
// aliasedTableColumn(normalizedRelation.references[i]!, relationTableAlias), | ||
// aliasedTableColumn(field, tableAlias), | ||
// ) | ||
// ), | ||
// ); | ||
// const builtRelation = this.buildRelationalQueryWithPK({ | ||
// fullSchema, | ||
// schema, | ||
// tableNamesMap, | ||
// table: fullSchema[relationTableTsName] as PgTable, | ||
// tableConfig: schema[relationTableTsName]!, | ||
// queryConfig: selectedRelationConfigValue, | ||
// tableAlias: relationTableAlias, | ||
// joinOn, | ||
// }); | ||
// const field = sql`case when ${sql.identifier(relationTableAlias)} is null then null else json_build_array(${ | ||
// sql.join( | ||
// builtRelation.selection.map(({ field }) => | ||
// is(field, SQL.Aliased) | ||
// ? sql`${sql.identifier(relationTableAlias)}.${sql.identifier(field.fieldAlias)}` | ||
// : is(field, Column) | ||
// ? aliasedTableColumn(field, relationTableAlias) | ||
// : field | ||
// ), | ||
// sql`, `, | ||
// ) | ||
// }) end`.as(selectedRelationTsKey); | ||
// const isLateralJoin = is(builtRelation.sql, SQL); | ||
// joins.push({ | ||
// on: isLateralJoin ? sql`true` : joinOn, | ||
// table: is(builtRelation.sql, SQL) | ||
// ? new Subquery(builtRelation.sql, {}, relationTableAlias) | ||
// : aliasedTable(builtRelation.sql, relationTableAlias), | ||
// alias: relationTableAlias, | ||
// joinType: 'left', | ||
// lateral: is(builtRelation.sql, SQL), | ||
// }); | ||
// selectedRelations.push({ | ||
// dbKey: selectedRelationTsKey, | ||
// tsKey: selectedRelationTsKey, | ||
// field, | ||
// relationTableTsKey: relationTableTsName, | ||
// isJson: true, | ||
// selection: builtRelation.selection, | ||
// }); | ||
// } | ||
// let distinct: PgSelectConfig['distinct']; | ||
// let tableFrom: PgTable | Subquery = table; | ||
// // Process first Many relation - each one requires a nested subquery | ||
// const manyRelation = manyRelations[0]; | ||
// if (manyRelation) { | ||
// const { | ||
// tsKey: selectedRelationTsKey, | ||
// queryConfig: selectedRelationQueryConfig, | ||
// relation, | ||
// } = manyRelation; | ||
// distinct = { | ||
// on: tableConfig.primaryKey.map((c) => aliasedTableColumn(c as PgColumn, tableAlias)), | ||
// }; | ||
// const normalizedRelation = normalizeRelation(schema, tableNamesMap, relation); | ||
// const relationTableName = relation.referencedTable[Table.Symbol.Name]; | ||
// const relationTableTsName = tableNamesMap[relationTableName]!; | ||
// const relationTableAlias = `${tableAlias}_${selectedRelationTsKey}`; | ||
// const joinOn = and( | ||
// ...normalizedRelation.fields.map((field, i) => | ||
// eq( | ||
// aliasedTableColumn(normalizedRelation.references[i]!, relationTableAlias), | ||
// aliasedTableColumn(field, tableAlias), | ||
// ) | ||
// ), | ||
// ); | ||
// const builtRelationJoin = this.buildRelationalQueryWithPK({ | ||
// fullSchema, | ||
// schema, | ||
// tableNamesMap, | ||
// table: fullSchema[relationTableTsName] as PgTable, | ||
// tableConfig: schema[relationTableTsName]!, | ||
// queryConfig: selectedRelationQueryConfig, | ||
// tableAlias: relationTableAlias, | ||
// joinOn, | ||
// }); | ||
// const builtRelationSelectionField = sql`case when ${ | ||
// sql.identifier(relationTableAlias) | ||
// } is null then '[]' else json_agg(json_build_array(${ | ||
// sql.join( | ||
// builtRelationJoin.selection.map(({ field }) => | ||
// is(field, SQL.Aliased) | ||
// ? sql`${sql.identifier(relationTableAlias)}.${sql.identifier(field.fieldAlias)}` | ||
// : is(field, Column) | ||
// ? aliasedTableColumn(field, relationTableAlias) | ||
// : field | ||
// ), | ||
// sql`, `, | ||
// ) | ||
// })) over (partition by ${sql.join(distinct.on, sql`, `)}) end`.as(selectedRelationTsKey); | ||
// const isLateralJoin = is(builtRelationJoin.sql, SQL); | ||
// joins.push({ | ||
// on: isLateralJoin ? sql`true` : joinOn, | ||
// table: isLateralJoin | ||
// ? new Subquery(builtRelationJoin.sql as SQL, {}, relationTableAlias) | ||
// : aliasedTable(builtRelationJoin.sql as PgTable, relationTableAlias), | ||
// alias: relationTableAlias, | ||
// joinType: 'left', | ||
// lateral: isLateralJoin, | ||
// }); | ||
// // Build the "from" subquery with the remaining Many relations | ||
// const builtTableFrom = this.buildRelationalQueryWithPK({ | ||
// fullSchema, | ||
// schema, | ||
// tableNamesMap, | ||
// table, | ||
// tableConfig, | ||
// queryConfig: { | ||
// ...config, | ||
// where: undefined, | ||
// orderBy: undefined, | ||
// limit: undefined, | ||
// offset: undefined, | ||
// with: manyRelations.slice(1).reduce<NonNullable<typeof config['with']>>( | ||
// (result, { tsKey, queryConfig: configValue }) => { | ||
// result[tsKey] = configValue; | ||
// return result; | ||
// }, | ||
// {}, | ||
// ), | ||
// }, | ||
// tableAlias, | ||
// }); | ||
// selectedRelations.push({ | ||
// dbKey: selectedRelationTsKey, | ||
// tsKey: selectedRelationTsKey, | ||
// field: builtRelationSelectionField, | ||
// relationTableTsKey: relationTableTsName, | ||
// isJson: true, | ||
// selection: builtRelationJoin.selection, | ||
// }); | ||
// // selection = builtTableFrom.selection.map((item) => | ||
// // is(item.field, SQL.Aliased) | ||
// // ? { ...item, field: sql`${sql.identifier(tableAlias)}.${sql.identifier(item.field.fieldAlias)}` } | ||
// // : item | ||
// // ); | ||
// // selectionForBuild = [{ | ||
// // dbKey: '*', | ||
// // tsKey: '*', | ||
// // field: sql`${sql.identifier(tableAlias)}.*`, | ||
// // selection: [], | ||
// // isJson: false, | ||
// // relationTableTsKey: undefined, | ||
// // }]; | ||
// // const newSelectionItem: (typeof selection)[number] = { | ||
// // dbKey: selectedRelationTsKey, | ||
// // tsKey: selectedRelationTsKey, | ||
// // field, | ||
// // relationTableTsKey: relationTableTsName, | ||
// // isJson: true, | ||
// // selection: builtRelationJoin.selection, | ||
// // }; | ||
// // selection.push(newSelectionItem); | ||
// // selectionForBuild.push(newSelectionItem); | ||
// tableFrom = is(builtTableFrom.sql, PgTable) | ||
// ? builtTableFrom.sql | ||
// : new Subquery(builtTableFrom.sql, {}, tableAlias); | ||
// } | ||
// if (selectedColumns.length === 0 && selectedRelations.length === 0 && selectedExtras.length === 0) { | ||
// throw new DrizzleError(`No fields selected for table "${tableConfig.tsName}" ("${tableAlias}")`); | ||
// } | ||
// let selection: BuildRelationalQueryResult<PgTable, PgColumn>['selection']; | ||
// function prepareSelectedColumns() { | ||
// return selectedColumns.map((key) => ({ | ||
// dbKey: tableConfig.columns[key]!.name, | ||
// tsKey: key, | ||
// field: tableConfig.columns[key] as PgColumn, | ||
// relationTableTsKey: undefined, | ||
// isJson: false, | ||
// selection: [], | ||
// })); | ||
// } | ||
// function prepareSelectedExtras() { | ||
// return selectedExtras.map((item) => ({ | ||
// dbKey: item.value.fieldAlias, | ||
// tsKey: item.tsKey, | ||
// field: item.value, | ||
// relationTableTsKey: undefined, | ||
// isJson: false, | ||
// selection: [], | ||
// })); | ||
// } | ||
// if (isRoot) { | ||
// selection = [ | ||
// ...prepareSelectedColumns(), | ||
// ...prepareSelectedExtras(), | ||
// ]; | ||
// } | ||
// if (hasUserDefinedWhere || orderBy.length > 0) { | ||
// tableFrom = new Subquery( | ||
// this.buildSelectQuery({ | ||
// table: is(tableFrom, PgTable) ? aliasedTable(tableFrom, tableAlias) : tableFrom, | ||
// fields: {}, | ||
// fieldsFlat: selectionForBuild.map(({ field }) => ({ | ||
// path: [], | ||
// field: is(field, Column) ? aliasedTableColumn(field, tableAlias) : field, | ||
// })), | ||
// joins, | ||
// distinct, | ||
// }), | ||
// {}, | ||
// tableAlias, | ||
// ); | ||
// selectionForBuild = selection.map((item) => | ||
// is(item.field, SQL.Aliased) | ||
// ? { ...item, field: sql`${sql.identifier(tableAlias)}.${sql.identifier(item.field.fieldAlias)}` } | ||
// : item | ||
// ); | ||
// joins = []; | ||
// distinct = undefined; | ||
// } | ||
// const result = this.buildSelectQuery({ | ||
// table: is(tableFrom, PgTable) ? aliasedTable(tableFrom, tableAlias) : tableFrom, | ||
// fields: {}, | ||
// fieldsFlat: selectionForBuild.map(({ field }) => ({ | ||
// path: [], | ||
// field: is(field, Column) ? aliasedTableColumn(field, tableAlias) : field, | ||
// })), | ||
// where, | ||
// limit, | ||
// offset, | ||
// joins, | ||
// orderBy, | ||
// distinct, | ||
// }); | ||
// return { | ||
// tableTsKey: tableConfig.tsName, | ||
// sql: result, | ||
// selection, | ||
// }; | ||
// } | ||
buildRelationalQueryWithoutPK({ | ||
/** @deprecated */ | ||
_buildRelationalQuery({ | ||
fullSchema, | ||
@@ -940,3 +462,3 @@ schema, | ||
if (config.where) { | ||
const whereSql = typeof config.where === "function" ? config.where(aliasedColumns, getOperators()) : config.where; | ||
const whereSql = typeof config.where === "function" ? config.where(aliasedColumns, V1.getOperators()) : config.where; | ||
where = whereSql && mapColumnsInSQLToAlias(whereSql, tableAlias); | ||
@@ -993,3 +515,3 @@ } | ||
} | ||
let orderByOrig = typeof config.orderBy === "function" ? config.orderBy(aliasedColumns, getOrderByOperators()) : config.orderBy ?? []; | ||
let orderByOrig = typeof config.orderBy === "function" ? config.orderBy(aliasedColumns, V1.getOrderByOperators()) : config.orderBy ?? []; | ||
if (!Array.isArray(orderByOrig)) { | ||
@@ -1011,3 +533,3 @@ orderByOrig = [orderByOrig]; | ||
} of selectedRelations) { | ||
const normalizedRelation = normalizeRelation(schema, tableNamesMap, relation); | ||
const normalizedRelation = V1.normalizeRelation(schema, tableNamesMap, relation); | ||
const relationTableName = getTableUniqueName(relation.referencedTable); | ||
@@ -1024,3 +546,3 @@ const relationTableTsName = tableNamesMap[relationTableName]; | ||
); | ||
const builtRelation = this.buildRelationalQueryWithoutPK({ | ||
const builtRelation = this._buildRelationalQuery({ | ||
fullSchema, | ||
@@ -1031,3 +553,3 @@ schema, | ||
tableConfig: schema[relationTableTsName], | ||
queryConfig: is(relation, One) ? selectedRelationConfigValue === true ? { limit: 1 } : { ...selectedRelationConfigValue, limit: 1 } : selectedRelationConfigValue, | ||
queryConfig: is(relation, V1.One) ? selectedRelationConfigValue === true ? { limit: 1 } : { ...selectedRelationConfigValue, limit: 1 } : selectedRelationConfigValue, | ||
tableAlias: relationTableAlias, | ||
@@ -1067,3 +589,3 @@ joinOn: joinOn2, | ||
)})`; | ||
if (is(nestedQueryRelation, Many)) { | ||
if (is(nestedQueryRelation, V1.Many)) { | ||
field = sql`coalesce(json_agg(${field}${orderBy.length > 0 ? sql` order by ${sql.join(orderBy, sql`, `)}` : void 0}), '[]'::json)`; | ||
@@ -1137,2 +659,129 @@ } | ||
} | ||
unwrapAllColumns = (table, selection) => { | ||
return sql.join( | ||
Object.entries(table[Columns]).map(([k, v]) => { | ||
selection.push({ | ||
key: k, | ||
field: v | ||
}); | ||
return sql`${v} as ${sql.identifier(k)}`; | ||
}), | ||
sql`, ` | ||
); | ||
}; | ||
buildColumns = (table, tableConfig, selection, config) => config?.columns ? (() => { | ||
const entries = Object.entries(config.columns); | ||
const columnIdentifiers = []; | ||
let colSelectionMode; | ||
for (const [k, v] of entries) { | ||
if (colSelectionMode === void 0) | ||
colSelectionMode = v; | ||
else if (v !== void 0 && colSelectionMode !== v) { | ||
throw new Error("Columns cannot be both true and false at the same time"); | ||
} | ||
if (v) { | ||
columnIdentifiers.push( | ||
sql`${table[Columns][k]} as ${sql.identifier(k)}` | ||
); | ||
selection.push({ | ||
key: k, | ||
field: table[Columns][k] | ||
}); | ||
} | ||
} | ||
if (colSelectionMode === false) { | ||
for (const [k, v] of Object.entries(table[Columns])) { | ||
if (config.columns[k] === false) | ||
continue; | ||
columnIdentifiers.push(sql`${v} as ${sql.identifier(k)}`); | ||
selection.push({ | ||
key: k, | ||
field: v | ||
}); | ||
} | ||
} | ||
return columnIdentifiers.length ? sql.join(columnIdentifiers, sql`, `) : this.unwrapAllColumns(table, selection); | ||
})() : (() => { | ||
const columnIdentifiers = [this.unwrapAllColumns(table, selection)]; | ||
return sql.join(columnIdentifiers, sql`, `); | ||
})(); | ||
buildRelationalQuery({ | ||
tables, | ||
schema, | ||
tableNamesMap, | ||
table, | ||
tableConfig, | ||
queryConfig: config, | ||
relationWhere, | ||
mode | ||
}) { | ||
const selection = []; | ||
const isSingle = mode === "first"; | ||
const params = config === true ? void 0 : config; | ||
const limit = isSingle ? 1 : params?.limit; | ||
const offset = params?.offset; | ||
const where = params?.where && relationWhere ? and(relationFilterToSQL(table, params.where), relationWhere) : params?.where ? relationFilterToSQL(table, params.where) : relationWhere; | ||
const order = params?.orderBy ? relationsOrderToSQL(table, params.orderBy) : void 0; | ||
const columns = this.buildColumns(table, tableConfig, selection, params); | ||
const extras = params?.extras ? relationExtrasToSQL(table, params.extras) : void 0; | ||
if (extras) | ||
selection.push(...extras.selection); | ||
const selectionArr = [columns]; | ||
const joins = params ? (() => { | ||
const { with: joins2 } = params; | ||
if (!joins2) | ||
return; | ||
const withEntries = Object.entries(joins2).filter(([_, v]) => v); | ||
if (!withEntries.length) | ||
return; | ||
return sql.join( | ||
withEntries.map(([k, join]) => { | ||
if (is(tableConfig.relations[k], AggregatedField)) { | ||
const relation2 = tableConfig.relations[k]; | ||
relation2.onTable(table); | ||
const query2 = relation2.getSQL(); | ||
selection.push({ | ||
key: k, | ||
field: relation2 | ||
}); | ||
selectionArr.push(sql`${sql.identifier(k)}.${sql.identifier("r")} as ${sql.identifier(k)}`); | ||
return sql`left join lateral(${query2}) as ${sql.identifier(k)} on true`; | ||
} | ||
const relation = tableConfig.relations[k]; | ||
const isSingle2 = is(relation, One); | ||
const targetTable = relation.targetTable; | ||
const relationFilter = relationToSQL(relation); | ||
selectionArr.push( | ||
isSingle2 ? sql`${sql.identifier(k)}.${sql.identifier("r")} as ${sql.identifier(k)}` : sql`coalesce(${sql.identifier(k)}.${sql.identifier("r")}, '[]') as ${sql.identifier(k)}` | ||
); | ||
const innerQuery = this.buildRelationalQuery({ | ||
table: targetTable, | ||
mode: isSingle2 ? "first" : "many", | ||
schema, | ||
queryConfig: join, | ||
tableConfig: schema[tableNamesMap[getTableUniqueName(targetTable)]], | ||
tableNamesMap, | ||
tables, | ||
relationWhere: relationFilter | ||
}); | ||
selection.push({ | ||
field: targetTable, | ||
key: k, | ||
selection: innerQuery.selection, | ||
isArray: !isSingle2 | ||
}); | ||
return sql`left join lateral(select ${isSingle2 ? sql`row_to_json(${sql.identifier("t")}.*) ${sql.identifier("r")}` : sql`json_agg(row_to_json(${sql.identifier("t")}.*)) ${sql.identifier("r")}`} from (${innerQuery.sql}) as ${sql.identifier("t")}) as ${sql.identifier(k)} on true`; | ||
}), | ||
sql` ` | ||
); | ||
})() : void 0; | ||
if (extras?.sql) | ||
selectionArr.push(extras.sql); | ||
const selectionSet = sql.join(selectionArr.filter((e) => e !== void 0), sql`, `); | ||
const query = sql`select ${selectionSet} from ${table}${sql` ${joins}`.if(joins)}${sql` where ${where}`.if(where)}${sql` order by ${order}`.if(order)}${sql` limit ${limit}`.if(limit !== void 0)}${sql` offset ${offset}`.if(offset !== void 0)}`; | ||
return { | ||
sql: query, | ||
selection | ||
}; | ||
} | ||
} | ||
@@ -1139,0 +788,0 @@ export { |
@@ -5,3 +5,3 @@ import { entityKind } from "../../entity.js"; | ||
import type { PgTable } from "../table.js"; | ||
export declare class PgCountBuilder<TSession extends PgSession<any, any, any>> extends SQL<number> implements Promise<number>, SQLWrapper { | ||
export declare class PgCountBuilder<TSession extends PgSession<any, any, any>> extends SQL<number> implements Promise<number>, SQLWrapper<number> { | ||
readonly params: { | ||
@@ -8,0 +8,0 @@ source: PgTable | SQL | SQLWrapper; |
@@ -11,3 +11,3 @@ import { entityKind } from "../../entity.js"; | ||
export declare class RelationalQueryBuilder<TSchema extends TablesRelationalConfig, TFields extends TableRelationalConfig> { | ||
private fullSchema; | ||
private tables; | ||
private schema; | ||
@@ -20,8 +20,8 @@ private tableNamesMap; | ||
static readonly [entityKind]: string; | ||
constructor(fullSchema: Record<string, unknown>, schema: TSchema, tableNamesMap: Record<string, string>, table: PgTable, tableConfig: TableRelationalConfig, dialect: PgDialect, session: PgSession); | ||
findMany<TConfig extends DBQueryConfig<'many', true, TSchema, TFields>>(config?: KnownKeysOnly<TConfig, DBQueryConfig<'many', true, TSchema, TFields>>): PgRelationalQuery<BuildQueryResult<TSchema, TFields, TConfig>[]>; | ||
findFirst<TSelection extends Omit<DBQueryConfig<'many', true, TSchema, TFields>, 'limit'>>(config?: KnownKeysOnly<TSelection, Omit<DBQueryConfig<'many', true, TSchema, TFields>, 'limit'>>): PgRelationalQuery<BuildQueryResult<TSchema, TFields, TSelection> | undefined>; | ||
constructor(tables: Record<string, PgTable>, schema: TSchema, tableNamesMap: Record<string, string>, table: PgTable, tableConfig: TableRelationalConfig, dialect: PgDialect, session: PgSession); | ||
findMany<TConfig extends DBQueryConfig<'many', TSchema, TFields>>(config?: KnownKeysOnly<TConfig, DBQueryConfig<'many', TSchema, TFields>>): PgRelationalQuery<BuildQueryResult<TSchema, TFields, TConfig>[]>; | ||
findFirst<TConfig extends DBQueryConfig<'one', TSchema, TFields>>(config?: KnownKeysOnly<TConfig, DBQueryConfig<'one', TSchema, TFields>>): PgRelationalQuery<BuildQueryResult<TSchema, TFields, TConfig> | undefined>; | ||
} | ||
export declare class PgRelationalQuery<TResult> extends QueryPromise<TResult> implements RunnableQuery<TResult, 'pg'>, SQLWrapper { | ||
private fullSchema; | ||
private tables; | ||
private schema; | ||
@@ -40,3 +40,3 @@ private tableNamesMap; | ||
}; | ||
constructor(fullSchema: Record<string, unknown>, schema: TablesRelationalConfig, tableNamesMap: Record<string, string>, table: PgTable, tableConfig: TableRelationalConfig, dialect: PgDialect, session: PgSession, config: DBQueryConfig<'many', true> | true, mode: 'many' | 'first'); | ||
constructor(tables: Record<string, PgTable>, schema: TablesRelationalConfig, tableNamesMap: Record<string, string>, table: PgTable, tableConfig: TableRelationalConfig, dialect: PgDialect, session: PgSession, config: DBQueryConfig<'many' | 'one'> | true, mode: 'many' | 'first'); | ||
prepare(name: string): PgPreparedQuery<PreparedQueryConfig & { | ||
@@ -43,0 +43,0 @@ execute: TResult; |
@@ -8,4 +8,4 @@ import { entityKind } from "../../entity.js"; | ||
class RelationalQueryBuilder { | ||
constructor(fullSchema, schema, tableNamesMap, table, tableConfig, dialect, session) { | ||
this.fullSchema = fullSchema; | ||
constructor(tables, schema, tableNamesMap, table, tableConfig, dialect, session) { | ||
this.tables = tables; | ||
this.schema = schema; | ||
@@ -18,6 +18,6 @@ this.tableNamesMap = tableNamesMap; | ||
} | ||
static [entityKind] = "PgRelationalQueryBuilder"; | ||
static [entityKind] = "PgRelationalQueryBuilderV2"; | ||
findMany(config) { | ||
return new PgRelationalQuery( | ||
this.fullSchema, | ||
this.tables, | ||
this.schema, | ||
@@ -29,3 +29,3 @@ this.tableNamesMap, | ||
this.session, | ||
config ? config : {}, | ||
config ?? true, | ||
"many" | ||
@@ -36,3 +36,3 @@ ); | ||
return new PgRelationalQuery( | ||
this.fullSchema, | ||
this.tables, | ||
this.schema, | ||
@@ -44,3 +44,3 @@ this.tableNamesMap, | ||
this.session, | ||
config ? { ...config, limit: 1 } : { limit: 1 }, | ||
config ?? true, | ||
"first" | ||
@@ -51,5 +51,5 @@ ); | ||
class PgRelationalQuery extends QueryPromise { | ||
constructor(fullSchema, schema, tableNamesMap, table, tableConfig, dialect, session, config, mode) { | ||
constructor(tables, schema, tableNamesMap, table, tableConfig, dialect, session, config, mode) { | ||
super(); | ||
this.fullSchema = fullSchema; | ||
this.tables = tables; | ||
this.schema = schema; | ||
@@ -64,3 +64,3 @@ this.tableNamesMap = tableNamesMap; | ||
} | ||
static [entityKind] = "PgRelationalQuery"; | ||
static [entityKind] = "PgRelationalQueryV2"; | ||
/** @internal */ | ||
@@ -70,11 +70,8 @@ _prepare(name) { | ||
const { query, builtQuery } = this._toSQL(); | ||
return this.session.prepareQuery( | ||
return this.session.prepareRelationalQuery( | ||
builtQuery, | ||
void 0, | ||
name, | ||
true, | ||
(rawRows, mapColumnValue) => { | ||
const rows = rawRows.map( | ||
(row) => mapRelationalRow(this.schema, this.tableConfig, row, query.selection, mapColumnValue) | ||
); | ||
const rows = rawRows.map((row) => mapRelationalRow(row, query.selection, mapColumnValue)); | ||
if (this.mode === "first") { | ||
@@ -92,4 +89,3 @@ return rows[0]; | ||
_getQuery() { | ||
return this.dialect.buildRelationalQueryWithoutPK({ | ||
fullSchema: this.fullSchema, | ||
return this.dialect.buildRelationalQuery({ | ||
schema: this.schema, | ||
@@ -100,3 +96,4 @@ tableNamesMap: this.tableNamesMap, | ||
queryConfig: this.config, | ||
tableAlias: this.tableConfig.tsName | ||
tables: this.tables, | ||
mode: this.mode | ||
}); | ||
@@ -103,0 +100,0 @@ } |
@@ -0,3 +1,4 @@ | ||
import type * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
import type { TablesRelationalConfig } from "../relations.js"; | ||
import type { AnyRelations, EmptyRelations, ExtractTablesWithRelations, TablesRelationalConfig } from "../relations.js"; | ||
import type { PreparedQuery } from "../session.js"; | ||
@@ -27,3 +28,3 @@ import { type Query, type SQL } from "../sql/index.js"; | ||
} | ||
export declare abstract class PgSession<TQueryResult extends PgQueryResultHKT = PgQueryResultHKT, TFullSchema extends Record<string, unknown> = Record<string, never>, TSchema extends TablesRelationalConfig = Record<string, never>> { | ||
export declare abstract class PgSession<TQueryResult extends PgQueryResultHKT = PgQueryResultHKT, TFullSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations, TTablesConfig extends TablesRelationalConfig = ExtractTablesWithRelations<TRelations>, TSchema extends V1.TablesRelationalConfig = V1.ExtractTablesWithRelations<TFullSchema>> { | ||
protected dialect: PgDialect; | ||
@@ -33,8 +34,10 @@ static readonly [entityKind]: string; | ||
abstract prepareQuery<T extends PreparedQueryConfig = PreparedQueryConfig>(query: Query, fields: SelectedFieldsOrdered | undefined, name: string | undefined, isResponseInArrayMode: boolean, customResultMapper?: (rows: unknown[][], mapColumnValue?: (value: unknown) => unknown) => T['execute']): PgPreparedQuery<T>; | ||
abstract prepareRelationalQuery<T extends PreparedQueryConfig = PreparedQueryConfig>(query: Query, fields: SelectedFieldsOrdered | undefined, name: string | undefined, customResultMapper: (rows: Record<string, unknown>[], mapColumnValue?: (value: unknown) => unknown) => T['execute']): PgPreparedQuery<T>; | ||
execute<T>(query: SQL): Promise<T>; | ||
all<T = unknown>(query: SQL): Promise<T[]>; | ||
count(sql: SQL): Promise<number>; | ||
abstract transaction<T>(transaction: (tx: PgTransaction<TQueryResult, TFullSchema, TSchema>) => Promise<T>, config?: PgTransactionConfig): Promise<T>; | ||
abstract transaction<T>(transaction: (tx: PgTransaction<TQueryResult, TFullSchema, TRelations, TTablesConfig, TSchema>) => Promise<T>, config?: PgTransactionConfig): Promise<T>; | ||
} | ||
export declare abstract class PgTransaction<TQueryResult extends PgQueryResultHKT, TFullSchema extends Record<string, unknown> = Record<string, never>, TSchema extends TablesRelationalConfig = Record<string, never>> extends PgDatabase<TQueryResult, TFullSchema, TSchema> { | ||
export declare abstract class PgTransaction<TQueryResult extends PgQueryResultHKT, TFullSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations, TTablesConfig extends TablesRelationalConfig = ExtractTablesWithRelations<TRelations>, TSchema extends V1.TablesRelationalConfig = V1.ExtractTablesWithRelations<TFullSchema>> extends PgDatabase<TQueryResult, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
protected relations: AnyRelations | undefined; | ||
protected schema: { | ||
@@ -47,3 +50,3 @@ fullSchema: Record<string, unknown>; | ||
static readonly [entityKind]: string; | ||
constructor(dialect: PgDialect, session: PgSession<any, any, any>, schema: { | ||
constructor(dialect: PgDialect, session: PgSession<any, any, any, any, any>, relations: AnyRelations | undefined, schema: { | ||
fullSchema: Record<string, unknown>; | ||
@@ -55,3 +58,3 @@ schema: TSchema; | ||
setTransaction(config: PgTransactionConfig): Promise<void>; | ||
abstract transaction<T>(transaction: (tx: PgTransaction<TQueryResult, TFullSchema, TSchema>) => Promise<T>): Promise<T>; | ||
abstract transaction<T>(transaction: (tx: PgTransaction<TQueryResult, TFullSchema, TRelations, TTablesConfig, TSchema>) => Promise<T>): Promise<T>; | ||
} | ||
@@ -58,0 +61,0 @@ export interface PgQueryResultHKT { |
@@ -62,4 +62,5 @@ import { entityKind } from "../entity.js"; | ||
class PgTransaction extends PgDatabase { | ||
constructor(dialect, session, schema, nestedIndex = 0) { | ||
super(dialect, session, schema); | ||
constructor(dialect, session, relations, schema, nestedIndex = 0) { | ||
super(dialect, session, relations, schema); | ||
this.relations = relations; | ||
this.schema = schema; | ||
@@ -66,0 +67,0 @@ this.nestedIndex = nestedIndex; |
import { entityKind } from "../entity.js"; | ||
import { PgDatabase } from "../pg-core/db.js"; | ||
import { PgDialect } from "../pg-core/dialect.js"; | ||
import type { AnyRelations, EmptyRelations } from "../relations.js"; | ||
import type { DrizzleConfig } from "../utils.js"; | ||
import { type PgRemoteQueryResultHKT } from "./session.js"; | ||
export declare class PgRemoteDatabase<TSchema extends Record<string, unknown> = Record<string, never>> extends PgDatabase<PgRemoteQueryResultHKT, TSchema> { | ||
export declare class PgRemoteDatabase<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations> extends PgDatabase<PgRemoteQueryResultHKT, TSchema, TRelations> { | ||
static readonly [entityKind]: string; | ||
@@ -12,2 +13,2 @@ } | ||
}>; | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(callback: RemoteCallback, config?: DrizzleConfig<TSchema>, _dialect?: () => PgDialect): PgRemoteDatabase<TSchema>; | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations>(callback: RemoteCallback, config?: DrizzleConfig<TSchema, TRelations>, _dialect?: () => PgDialect): PgRemoteDatabase<TSchema, TRelations>; |
@@ -0,1 +1,2 @@ | ||
import * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
@@ -5,6 +6,2 @@ import { DefaultLogger } from "../logger.js"; | ||
import { PgDialect } from "../pg-core/dialect.js"; | ||
import { | ||
createTableRelationsHelpers, | ||
extractTablesRelationalConfig | ||
} from "../relations.js"; | ||
import { PgRemoteSession } from "./session.js"; | ||
@@ -24,5 +21,5 @@ class PgRemoteDatabase extends PgDatabase { | ||
if (config.schema) { | ||
const tablesConfig = extractTablesRelationalConfig( | ||
const tablesConfig = V1.extractTablesRelationalConfig( | ||
config.schema, | ||
createTableRelationsHelpers | ||
V1.createTableRelationsHelpers | ||
); | ||
@@ -35,4 +32,10 @@ schema = { | ||
} | ||
const session = new PgRemoteSession(callback, dialect, schema, { logger }); | ||
return new PgRemoteDatabase(dialect, session, schema); | ||
const relations = config.relations; | ||
const session = new PgRemoteSession(callback, dialect, relations, schema, { logger }); | ||
return new PgRemoteDatabase( | ||
dialect, | ||
session, | ||
relations, | ||
schema | ||
); | ||
} | ||
@@ -39,0 +42,0 @@ export { |
import type { MigrationConfig } from "../migrator.js"; | ||
import type { AnyRelations } from "../relations.js"; | ||
import type { PgRemoteDatabase } from "./driver.js"; | ||
export type ProxyMigrator = (migrationQueries: string[]) => Promise<void>; | ||
export declare function migrate<TSchema extends Record<string, unknown>>(db: PgRemoteDatabase<TSchema>, callback: ProxyMigrator, config: MigrationConfig): Promise<void>; | ||
export declare function migrate<TSchema extends Record<string, unknown>, TRelations extends AnyRelations>(db: PgRemoteDatabase<TSchema, TRelations>, callback: ProxyMigrator, config: MigrationConfig): Promise<void>; |
@@ -0,1 +1,2 @@ | ||
import type * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
@@ -8,3 +9,3 @@ import type { Logger } from "../logger.js"; | ||
import { PgPreparedQuery as PreparedQueryBase, PgSession } from "../pg-core/session.js"; | ||
import type { RelationalSchemaConfig, TablesRelationalConfig } from "../relations.js"; | ||
import type { AnyRelations, TablesRelationalConfig } from "../relations.js"; | ||
import type { QueryWithTypings } from "../sql/sql.js"; | ||
@@ -16,16 +17,18 @@ import { type Assume } from "../utils.js"; | ||
} | ||
export declare class PgRemoteSession<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends PgSession<PgRemoteQueryResultHKT, TFullSchema, TSchema> { | ||
export declare class PgRemoteSession<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends PgSession<PgRemoteQueryResultHKT, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
private client; | ||
private relations; | ||
private schema; | ||
static readonly [entityKind]: string; | ||
private logger; | ||
constructor(client: RemoteCallback, dialect: PgDialect, schema: RelationalSchemaConfig<TSchema> | undefined, options?: PgRemoteSessionOptions); | ||
constructor(client: RemoteCallback, dialect: PgDialect, relations: AnyRelations | undefined, schema: V1.RelationalSchemaConfig<TSchema> | undefined, options?: PgRemoteSessionOptions); | ||
prepareQuery<T extends PreparedQueryConfig>(query: QueryWithTypings, fields: SelectedFieldsOrdered | undefined, name: string | undefined, isResponseInArrayMode: boolean, customResultMapper?: (rows: unknown[][]) => T['execute']): PreparedQuery<T>; | ||
transaction<T>(_transaction: (tx: PgProxyTransaction<TFullSchema, TSchema>) => Promise<T>, _config?: PgTransactionConfig): Promise<T>; | ||
prepareRelationalQuery<T extends PreparedQueryConfig>(query: QueryWithTypings, fields: SelectedFieldsOrdered | undefined, name: string | undefined, customResultMapper?: (rows: Record<string, unknown>[]) => T['execute']): PreparedQuery<T, true>; | ||
transaction<T>(_transaction: (tx: PgProxyTransaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => Promise<T>, _config?: PgTransactionConfig): Promise<T>; | ||
} | ||
export declare class PgProxyTransaction<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends PgTransaction<PgRemoteQueryResultHKT, TFullSchema, TSchema> { | ||
export declare class PgProxyTransaction<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends PgTransaction<PgRemoteQueryResultHKT, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
static readonly [entityKind]: string; | ||
transaction<T>(_transaction: (tx: PgProxyTransaction<TFullSchema, TSchema>) => Promise<T>): Promise<T>; | ||
transaction<T>(_transaction: (tx: PgProxyTransaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => Promise<T>): Promise<T>; | ||
} | ||
export declare class PreparedQuery<T extends PreparedQueryConfig> extends PreparedQueryBase<T> { | ||
export declare class PreparedQuery<T extends PreparedQueryConfig, TIsRqbV2 extends boolean = false> extends PreparedQueryBase<T> { | ||
private client; | ||
@@ -39,5 +42,7 @@ private queryString; | ||
private customResultMapper?; | ||
private isRqbV2Query?; | ||
static readonly [entityKind]: string; | ||
constructor(client: RemoteCallback, queryString: string, params: unknown[], typings: any[] | undefined, logger: Logger, fields: SelectedFieldsOrdered | undefined, _isResponseInArrayMode: boolean, customResultMapper?: ((rows: unknown[][]) => T["execute"]) | undefined); | ||
constructor(client: RemoteCallback, queryString: string, params: unknown[], typings: any[] | undefined, logger: Logger, fields: SelectedFieldsOrdered | undefined, _isResponseInArrayMode: boolean, customResultMapper?: ((rows: TIsRqbV2 extends true ? Record<string, unknown>[] : unknown[][]) => T["execute"]) | undefined, isRqbV2Query?: TIsRqbV2 | undefined); | ||
execute(placeholderValues?: Record<string, unknown> | undefined): Promise<T['execute']>; | ||
private executeRqbV2; | ||
all(): Promise<void>; | ||
@@ -44,0 +49,0 @@ } |
@@ -9,5 +9,6 @@ import { entityKind } from "../entity.js"; | ||
class PgRemoteSession extends PgSession { | ||
constructor(client, dialect, schema, options = {}) { | ||
constructor(client, dialect, relations, schema, options = {}) { | ||
super(dialect); | ||
this.client = client; | ||
this.relations = relations; | ||
this.schema = schema; | ||
@@ -30,2 +31,15 @@ this.logger = options.logger ?? new NoopLogger(); | ||
} | ||
prepareRelationalQuery(query, fields, name, customResultMapper) { | ||
return new PreparedQuery( | ||
this.client, | ||
query.sql, | ||
query.params, | ||
query.typings, | ||
this.logger, | ||
fields, | ||
false, | ||
customResultMapper, | ||
true | ||
); | ||
} | ||
async transaction(_transaction, _config) { | ||
@@ -42,3 +56,3 @@ throw new Error("Transactions are not supported by the Postgres Proxy driver"); | ||
class PreparedQuery extends PreparedQueryBase { | ||
constructor(client, queryString, params, typings, logger, fields, _isResponseInArrayMode, customResultMapper) { | ||
constructor(client, queryString, params, typings, logger, fields, _isResponseInArrayMode, customResultMapper, isRqbV2Query) { | ||
super({ sql: queryString, params }); | ||
@@ -53,5 +67,8 @@ this.client = client; | ||
this.customResultMapper = customResultMapper; | ||
this.isRqbV2Query = isRqbV2Query; | ||
} | ||
static [entityKind] = "PgProxyPreparedQuery"; | ||
async execute(placeholderValues = {}) { | ||
if (this.isRqbV2Query) | ||
return this.executeRqbV2(placeholderValues); | ||
return tracer.startActiveSpan("drizzle.execute", async (span) => { | ||
@@ -84,2 +101,20 @@ const params = fillPlaceholders(this.params, placeholderValues); | ||
} | ||
async executeRqbV2(placeholderValues = {}) { | ||
return tracer.startActiveSpan("drizzle.execute", async (span) => { | ||
const params = fillPlaceholders(this.params, placeholderValues); | ||
const { client, queryString, customResultMapper, logger, typings } = this; | ||
span?.setAttributes({ | ||
"drizzle.query.text": queryString, | ||
"drizzle.query.params": JSON.stringify(params) | ||
}); | ||
logger.logQuery(queryString, params); | ||
const rows = await tracer.startActiveSpan("drizzle.driver.execute", async () => { | ||
const { rows: rows2 } = await client(queryString, params, "execute", typings); | ||
return rows2; | ||
}); | ||
return tracer.startActiveSpan("drizzle.mapResponse", () => { | ||
return customResultMapper(rows); | ||
}); | ||
}); | ||
} | ||
async all() { | ||
@@ -86,0 +121,0 @@ } |
import { PGlite, type PGliteOptions } from '@electric-sql/pglite'; | ||
import * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
@@ -6,3 +7,3 @@ import type { Logger } from "../logger.js"; | ||
import { PgDialect } from "../pg-core/dialect.js"; | ||
import { type RelationalSchemaConfig, type TablesRelationalConfig } from "../relations.js"; | ||
import type { AnyRelations, EmptyRelations, TablesRelationalConfig } from "../relations.js"; | ||
import { type DrizzleConfig } from "../utils.js"; | ||
@@ -20,14 +21,14 @@ import type { PgliteClient, PgliteQueryResultHKT } from "./session.js"; | ||
constructor(client: PgliteClient, dialect: PgDialect, options?: PgDriverOptions); | ||
createSession(schema: RelationalSchemaConfig<TablesRelationalConfig> | undefined): PgliteSession<Record<string, unknown>, TablesRelationalConfig>; | ||
createSession(relations: AnyRelations | undefined, schema: V1.RelationalSchemaConfig<V1.TablesRelationalConfig> | undefined): PgliteSession<Record<string, unknown>, AnyRelations, TablesRelationalConfig, V1.TablesRelationalConfig>; | ||
} | ||
export declare class PgliteDatabase<TSchema extends Record<string, unknown> = Record<string, never>> extends PgDatabase<PgliteQueryResultHKT, TSchema> { | ||
export declare class PgliteDatabase<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations> extends PgDatabase<PgliteQueryResultHKT, TSchema, TRelations> { | ||
static readonly [entityKind]: string; | ||
} | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TClient extends PGlite = PGlite>(...params: [] | [ | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations, TClient extends PGlite = PGlite>(...params: [] | [ | ||
TClient | string | ||
] | [ | ||
TClient | string, | ||
DrizzleConfig<TSchema> | ||
DrizzleConfig<TSchema, TRelations> | ||
] | [ | ||
(DrizzleConfig<TSchema> & ({ | ||
(DrizzleConfig<TSchema, TRelations> & ({ | ||
connection?: (PGliteOptions & { | ||
@@ -39,9 +40,9 @@ dataDir?: string; | ||
})) | ||
]): PgliteDatabase<TSchema> & { | ||
]): PgliteDatabase<TSchema, TRelations> & { | ||
$client: TClient; | ||
}; | ||
export declare namespace drizzle { | ||
function mock<TSchema extends Record<string, unknown> = Record<string, never>>(config?: DrizzleConfig<TSchema>): PgliteDatabase<TSchema> & { | ||
function mock<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations>(config?: DrizzleConfig<TSchema, TRelations>): PgliteDatabase<TSchema, TRelations> & { | ||
$client: '$client is not available on drizzle.mock()'; | ||
}; | ||
} |
import { PGlite } from "@electric-sql/pglite"; | ||
import * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
@@ -6,6 +7,2 @@ import { DefaultLogger } from "../logger.js"; | ||
import { PgDialect } from "../pg-core/dialect.js"; | ||
import { | ||
createTableRelationsHelpers, | ||
extractTablesRelationalConfig | ||
} from "../relations.js"; | ||
import { isConfig } from "../utils.js"; | ||
@@ -20,4 +17,4 @@ import { PgliteSession } from "./session.js"; | ||
static [entityKind] = "PgliteDriver"; | ||
createSession(schema) { | ||
return new PgliteSession(this.client, this.dialect, schema, { logger: this.options.logger }); | ||
createSession(relations, schema) { | ||
return new PgliteSession(this.client, this.dialect, relations, schema, { logger: this.options.logger }); | ||
} | ||
@@ -38,5 +35,5 @@ } | ||
if (config.schema) { | ||
const tablesConfig = extractTablesRelationalConfig( | ||
const tablesConfig = V1.extractTablesRelationalConfig( | ||
config.schema, | ||
createTableRelationsHelpers | ||
V1.createTableRelationsHelpers | ||
); | ||
@@ -49,5 +46,11 @@ schema = { | ||
} | ||
const relations = config.relations; | ||
const driver = new PgliteDriver(client, dialect, { logger }); | ||
const session = driver.createSession(schema); | ||
const db = new PgliteDatabase(dialect, session, schema); | ||
const session = driver.createSession(relations, schema); | ||
const db = new PgliteDatabase( | ||
dialect, | ||
session, | ||
relations, | ||
schema | ||
); | ||
db.$client = client; | ||
@@ -54,0 +57,0 @@ return db; |
import type { MigrationConfig } from "../migrator.js"; | ||
import type { AnyRelations } from "../relations.js"; | ||
import type { PgliteDatabase } from "./driver.js"; | ||
export declare function migrate<TSchema extends Record<string, unknown>>(db: PgliteDatabase<TSchema>, config: MigrationConfig): Promise<void>; | ||
export declare function migrate<TSchema extends Record<string, unknown>, TRelations extends AnyRelations>(db: PgliteDatabase<TSchema, TRelations>, config: MigrationConfig): Promise<void>; |
import type { PGlite, Results, Row, Transaction } from '@electric-sql/pglite'; | ||
import type * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
@@ -9,7 +10,7 @@ import { type Logger } from "../logger.js"; | ||
import { PgPreparedQuery, PgSession } from "../pg-core/session.js"; | ||
import type { RelationalSchemaConfig, TablesRelationalConfig } from "../relations.js"; | ||
import { type Query, type SQL } from "../sql/sql.js"; | ||
import { type Assume } from "../utils.js"; | ||
import type { AnyRelations, TablesRelationalConfig } from "../relations.js"; | ||
export type PgliteClient = PGlite; | ||
export declare class PglitePreparedQuery<T extends PreparedQueryConfig> extends PgPreparedQuery<T> { | ||
export declare class PglitePreparedQuery<T extends PreparedQueryConfig, TIsRqbV2 extends boolean = false> extends PgPreparedQuery<T> { | ||
private client; | ||
@@ -22,7 +23,9 @@ private queryString; | ||
private customResultMapper?; | ||
private isRqbV2Query?; | ||
static readonly [entityKind]: string; | ||
private rawQueryConfig; | ||
private queryConfig; | ||
constructor(client: PgliteClient | Transaction, queryString: string, params: unknown[], logger: Logger, fields: SelectedFieldsOrdered | undefined, name: string | undefined, _isResponseInArrayMode: boolean, customResultMapper?: ((rows: unknown[][]) => T["execute"]) | undefined); | ||
constructor(client: PgliteClient | Transaction, queryString: string, params: unknown[], logger: Logger, fields: SelectedFieldsOrdered | undefined, name: string | undefined, _isResponseInArrayMode: boolean, customResultMapper?: ((rows: TIsRqbV2 extends true ? Record<string, unknown>[] : unknown[][]) => T["execute"]) | undefined, isRqbV2Query?: TIsRqbV2 | undefined); | ||
execute(placeholderValues?: Record<string, unknown> | undefined): Promise<T['execute']>; | ||
private executeRqbV2; | ||
all(placeholderValues?: Record<string, unknown> | undefined): Promise<T['all']>; | ||
@@ -33,4 +36,5 @@ } | ||
} | ||
export declare class PgliteSession<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends PgSession<PgliteQueryResultHKT, TFullSchema, TSchema> { | ||
export declare class PgliteSession<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends PgSession<PgliteQueryResultHKT, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
private client; | ||
private relations; | ||
private schema; | ||
@@ -40,10 +44,11 @@ private options; | ||
private logger; | ||
constructor(client: PgliteClient | Transaction, dialect: PgDialect, schema: RelationalSchemaConfig<TSchema> | undefined, options?: PgliteSessionOptions); | ||
constructor(client: PgliteClient | Transaction, dialect: PgDialect, relations: AnyRelations | undefined, schema: V1.RelationalSchemaConfig<TSchema> | undefined, options?: PgliteSessionOptions); | ||
prepareQuery<T extends PreparedQueryConfig = PreparedQueryConfig>(query: Query, fields: SelectedFieldsOrdered | undefined, name: string | undefined, isResponseInArrayMode: boolean, customResultMapper?: (rows: unknown[][]) => T['execute']): PgPreparedQuery<T>; | ||
transaction<T>(transaction: (tx: PgliteTransaction<TFullSchema, TSchema>) => Promise<T>, config?: PgTransactionConfig | undefined): Promise<T>; | ||
prepareRelationalQuery<T extends PreparedQueryConfig = PreparedQueryConfig>(query: Query, fields: SelectedFieldsOrdered | undefined, name: string | undefined, customResultMapper: (rows: Record<string, unknown>[]) => T['execute']): PgPreparedQuery<T>; | ||
transaction<T>(transaction: (tx: PgliteTransaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => Promise<T>, config?: PgTransactionConfig | undefined): Promise<T>; | ||
count(sql: SQL): Promise<number>; | ||
} | ||
export declare class PgliteTransaction<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends PgTransaction<PgliteQueryResultHKT, TFullSchema, TSchema> { | ||
export declare class PgliteTransaction<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends PgTransaction<PgliteQueryResultHKT, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
static readonly [entityKind]: string; | ||
transaction<T>(transaction: (tx: PgliteTransaction<TFullSchema, TSchema>) => Promise<T>): Promise<T>; | ||
transaction<T>(transaction: (tx: PgliteTransaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => Promise<T>): Promise<T>; | ||
} | ||
@@ -50,0 +55,0 @@ export interface PgliteQueryResultHKT extends PgQueryResultHKT { |
@@ -9,3 +9,3 @@ import { entityKind } from "../entity.js"; | ||
class PglitePreparedQuery extends PgPreparedQuery { | ||
constructor(client, queryString, params, logger, fields, name, _isResponseInArrayMode, customResultMapper) { | ||
constructor(client, queryString, params, logger, fields, name, _isResponseInArrayMode, customResultMapper, isRqbV2Query) { | ||
super({ sql: queryString, params }); | ||
@@ -19,2 +19,3 @@ this.client = client; | ||
this.customResultMapper = customResultMapper; | ||
this.isRqbV2Query = isRqbV2Query; | ||
this.rawQueryConfig = { | ||
@@ -43,2 +44,4 @@ rowMode: "object", | ||
async execute(placeholderValues = {}) { | ||
if (this.isRqbV2Query) | ||
return this.executeRqbV2(placeholderValues); | ||
const params = fillPlaceholders(this.params, placeholderValues); | ||
@@ -53,2 +56,9 @@ this.logger.logQuery(this.queryString, params); | ||
} | ||
async executeRqbV2(placeholderValues = {}) { | ||
const params = fillPlaceholders(this.params, placeholderValues); | ||
this.logger.logQuery(this.queryString, params); | ||
const { rawQueryConfig, client, customResultMapper, queryString } = this; | ||
const result = await client.query(queryString, params, rawQueryConfig); | ||
return customResultMapper(result.rows); | ||
} | ||
all(placeholderValues = {}) { | ||
@@ -65,5 +75,6 @@ const params = fillPlaceholders(this.params, placeholderValues); | ||
class PgliteSession extends PgSession { | ||
constructor(client, dialect, schema, options = {}) { | ||
constructor(client, dialect, relations, schema, options = {}) { | ||
super(dialect); | ||
this.client = client; | ||
this.relations = relations; | ||
this.schema = schema; | ||
@@ -87,2 +98,15 @@ this.options = options; | ||
} | ||
prepareRelationalQuery(query, fields, name, customResultMapper) { | ||
return new PglitePreparedQuery( | ||
this.client, | ||
query.sql, | ||
query.params, | ||
this.logger, | ||
fields, | ||
name, | ||
false, | ||
customResultMapper, | ||
true | ||
); | ||
} | ||
async transaction(transaction, config) { | ||
@@ -93,6 +117,12 @@ return this.client.transaction(async (client) => { | ||
this.dialect, | ||
this.relations, | ||
this.schema, | ||
this.options | ||
); | ||
const tx = new PgliteTransaction(this.dialect, session, this.schema); | ||
const tx = new PgliteTransaction( | ||
this.dialect, | ||
session, | ||
this.relations, | ||
this.schema | ||
); | ||
if (config) { | ||
@@ -118,2 +148,3 @@ await tx.setTransaction(config); | ||
this.session, | ||
this.relations, | ||
this.schema, | ||
@@ -120,0 +151,0 @@ this.nestedIndex + 1 |
@@ -6,2 +6,3 @@ import type { Config } from '@planetscale/database'; | ||
import { MySqlDatabase } from "../mysql-core/db.js"; | ||
import type { AnyRelations, EmptyRelations } from "../relations.js"; | ||
import { type DrizzleConfig } from "../utils.js"; | ||
@@ -12,12 +13,12 @@ import type { PlanetScalePreparedQueryHKT, PlanetscaleQueryResultHKT } from "./session.js"; | ||
} | ||
export declare class PlanetScaleDatabase<TSchema extends Record<string, unknown> = Record<string, never>> extends MySqlDatabase<PlanetscaleQueryResultHKT, PlanetScalePreparedQueryHKT, TSchema> { | ||
export declare class PlanetScaleDatabase<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations> extends MySqlDatabase<PlanetscaleQueryResultHKT, PlanetScalePreparedQueryHKT, TSchema, TRelations> { | ||
static readonly [entityKind]: string; | ||
} | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TClient extends Client = Client>(...params: [ | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations, TClient extends Client = Client>(...params: [ | ||
TClient | string | ||
] | [ | ||
TClient | string, | ||
DrizzleConfig<TSchema> | ||
DrizzleConfig<TSchema, TRelations> | ||
] | [ | ||
(DrizzleConfig<TSchema> & ({ | ||
(DrizzleConfig<TSchema, TRelations> & ({ | ||
connection: string | Config; | ||
@@ -27,9 +28,9 @@ } | { | ||
})) | ||
]): PlanetScaleDatabase<TSchema> & { | ||
]): PlanetScaleDatabase<TSchema, TRelations> & { | ||
$client: TClient; | ||
}; | ||
export declare namespace drizzle { | ||
function mock<TSchema extends Record<string, unknown> = Record<string, never>>(config?: DrizzleConfig<TSchema>): PlanetScaleDatabase<TSchema> & { | ||
function mock<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations>(config?: DrizzleConfig<TSchema, TRelations>): PlanetScaleDatabase<TSchema, TRelations> & { | ||
$client: '$client is not available on drizzle.mock()'; | ||
}; | ||
} |
import { Client } from "@planetscale/database"; | ||
import * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
@@ -6,6 +7,2 @@ import { DefaultLogger } from "../logger.js"; | ||
import { MySqlDialect } from "../mysql-core/dialect.js"; | ||
import { | ||
createTableRelationsHelpers, | ||
extractTablesRelationalConfig | ||
} from "../relations.js"; | ||
import { isConfig } from "../utils.js"; | ||
@@ -40,5 +37,5 @@ import { PlanetscaleSession } from "./session.js"; | ||
if (config.schema) { | ||
const tablesConfig = extractTablesRelationalConfig( | ||
const tablesConfig = V1.extractTablesRelationalConfig( | ||
config.schema, | ||
createTableRelationsHelpers | ||
V1.createTableRelationsHelpers | ||
); | ||
@@ -51,4 +48,11 @@ schema = { | ||
} | ||
const session = new PlanetscaleSession(client, dialect, void 0, schema, { logger }); | ||
const db = new PlanetScaleDatabase(dialect, session, schema, "planetscale"); | ||
const relations = config.relations; | ||
const session = new PlanetscaleSession(client, dialect, void 0, relations, schema, { logger }); | ||
const db = new PlanetScaleDatabase( | ||
dialect, | ||
session, | ||
relations, | ||
schema, | ||
"planetscale" | ||
); | ||
db.$client = client; | ||
@@ -55,0 +59,0 @@ return db; |
import type { MigrationConfig } from "../migrator.js"; | ||
import type { AnyRelations } from "../relations.js"; | ||
import type { PlanetScaleDatabase } from "./driver.js"; | ||
export declare function migrate<TSchema extends Record<string, unknown>>(db: PlanetScaleDatabase<TSchema>, config: MigrationConfig): Promise<void>; | ||
export declare function migrate<TSchema extends Record<string, unknown>, TRelations extends AnyRelations>(db: PlanetScaleDatabase<TSchema, TRelations>, config: MigrationConfig): Promise<void>; |
import type { Client, Connection, ExecutedQuery, Transaction } from '@planetscale/database'; | ||
import type * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
@@ -7,6 +8,6 @@ import type { Logger } from "../logger.js"; | ||
import { MySqlPreparedQuery, type MySqlPreparedQueryConfig, type MySqlPreparedQueryHKT, type MySqlQueryResultHKT, MySqlSession, MySqlTransaction } from "../mysql-core/session.js"; | ||
import type { RelationalSchemaConfig, TablesRelationalConfig } from "../relations.js"; | ||
import type { AnyRelations, TablesRelationalConfig } from "../relations.js"; | ||
import { type Query, type SQL } from "../sql/sql.js"; | ||
import { type Assume } from "../utils.js"; | ||
export declare class PlanetScalePreparedQuery<T extends MySqlPreparedQueryConfig> extends MySqlPreparedQuery<T> { | ||
export declare class PlanetScalePreparedQuery<T extends MySqlPreparedQueryConfig, TIsRqbV2 extends boolean = false> extends MySqlPreparedQuery<T> { | ||
private client; | ||
@@ -20,7 +21,9 @@ private queryString; | ||
private returningIds?; | ||
private isRqbV2Query?; | ||
static readonly [entityKind]: string; | ||
private rawQuery; | ||
private query; | ||
constructor(client: Client | Transaction | Connection, queryString: string, params: unknown[], logger: Logger, fields: SelectedFieldsOrdered | undefined, customResultMapper?: ((rows: unknown[][]) => T["execute"]) | undefined, generatedIds?: Record<string, unknown>[] | undefined, returningIds?: SelectedFieldsOrdered | undefined); | ||
constructor(client: Client | Transaction | Connection, queryString: string, params: unknown[], logger: Logger, fields: SelectedFieldsOrdered | undefined, customResultMapper?: ((rows: TIsRqbV2 extends true ? Record<string, unknown>[] : unknown[][]) => T["execute"]) | undefined, generatedIds?: Record<string, unknown>[] | undefined, returningIds?: SelectedFieldsOrdered | undefined, isRqbV2Query?: TIsRqbV2 | undefined); | ||
execute(placeholderValues?: Record<string, unknown> | undefined): Promise<T['execute']>; | ||
private executeRqbV2; | ||
iterator(_placeholderValues?: Record<string, unknown>): AsyncGenerator<T['iterator']>; | ||
@@ -31,4 +34,5 @@ } | ||
} | ||
export declare class PlanetscaleSession<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends MySqlSession<MySqlQueryResultHKT, PlanetScalePreparedQueryHKT, TFullSchema, TSchema> { | ||
export declare class PlanetscaleSession<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends MySqlSession<MySqlQueryResultHKT, PlanetScalePreparedQueryHKT, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
private baseClient; | ||
private relations; | ||
private schema; | ||
@@ -39,4 +43,5 @@ private options; | ||
private client; | ||
constructor(baseClient: Client | Connection, dialect: MySqlDialect, tx: Transaction | undefined, schema: RelationalSchemaConfig<TSchema> | undefined, options?: PlanetscaleSessionOptions); | ||
constructor(baseClient: Client | Connection, dialect: MySqlDialect, tx: Transaction | undefined, relations: AnyRelations | undefined, schema: V1.RelationalSchemaConfig<TSchema> | undefined, options?: PlanetscaleSessionOptions); | ||
prepareQuery<T extends MySqlPreparedQueryConfig = MySqlPreparedQueryConfig>(query: Query, fields: SelectedFieldsOrdered | undefined, customResultMapper?: (rows: unknown[][]) => T['execute'], generatedIds?: Record<string, unknown>[], returningIds?: SelectedFieldsOrdered): MySqlPreparedQuery<T>; | ||
prepareRelationalQuery<T extends MySqlPreparedQueryConfig = MySqlPreparedQueryConfig>(query: Query, fields: SelectedFieldsOrdered | undefined, customResultMapper: (rows: Record<string, unknown>[]) => T['execute'], generatedIds?: Record<string, unknown>[], returningIds?: SelectedFieldsOrdered): MySqlPreparedQuery<T>; | ||
query(query: string, params: unknown[]): Promise<ExecutedQuery>; | ||
@@ -46,8 +51,8 @@ queryObjects(query: string, params: unknown[]): Promise<ExecutedQuery>; | ||
count(sql: SQL): Promise<number>; | ||
transaction<T>(transaction: (tx: PlanetScaleTransaction<TFullSchema, TSchema>) => Promise<T>): Promise<T>; | ||
transaction<T>(transaction: (tx: PlanetScaleTransaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => Promise<T>): Promise<T>; | ||
} | ||
export declare class PlanetScaleTransaction<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends MySqlTransaction<PlanetscaleQueryResultHKT, PlanetScalePreparedQueryHKT, TFullSchema, TSchema> { | ||
export declare class PlanetScaleTransaction<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends MySqlTransaction<PlanetscaleQueryResultHKT, PlanetScalePreparedQueryHKT, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
static readonly [entityKind]: string; | ||
constructor(dialect: MySqlDialect, session: MySqlSession, schema: RelationalSchemaConfig<TSchema> | undefined, nestedIndex?: number); | ||
transaction<T>(transaction: (tx: PlanetScaleTransaction<TFullSchema, TSchema>) => Promise<T>): Promise<T>; | ||
constructor(dialect: MySqlDialect, session: MySqlSession, relations: AnyRelations | undefined, schema: V1.RelationalSchemaConfig<TSchema> | undefined, nestedIndex?: number); | ||
transaction<T>(transaction: (tx: PlanetScaleTransaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => Promise<T>): Promise<T>; | ||
} | ||
@@ -54,0 +59,0 @@ export interface PlanetscaleQueryResultHKT extends MySqlQueryResultHKT { |
@@ -12,3 +12,3 @@ import { Column } from "../column.js"; | ||
class PlanetScalePreparedQuery extends MySqlPreparedQuery { | ||
constructor(client, queryString, params, logger, fields, customResultMapper, generatedIds, returningIds) { | ||
constructor(client, queryString, params, logger, fields, customResultMapper, generatedIds, returningIds, isRqbV2Query) { | ||
super(); | ||
@@ -23,2 +23,3 @@ this.client = client; | ||
this.returningIds = returningIds; | ||
this.isRqbV2Query = isRqbV2Query; | ||
} | ||
@@ -29,2 +30,4 @@ static [entityKind] = "PlanetScalePreparedQuery"; | ||
async execute(placeholderValues = {}) { | ||
if (this.isRqbV2Query) | ||
return this.executeRqbV2(placeholderValues); | ||
const params = fillPlaceholders(this.params, placeholderValues); | ||
@@ -74,2 +77,39 @@ this.logger.logQuery(this.queryString, params); | ||
} | ||
async executeRqbV2(placeholderValues = {}) { | ||
const params = fillPlaceholders(this.params, placeholderValues); | ||
this.logger.logQuery(this.queryString, params); | ||
const { | ||
client, | ||
queryString, | ||
rawQuery, | ||
customResultMapper, | ||
returningIds, | ||
generatedIds | ||
} = this; | ||
const res = await client.execute(queryString, params, rawQuery); | ||
const insertId = Number.parseFloat(res.insertId); | ||
const affectedRows = res.rowsAffected; | ||
if (returningIds) { | ||
const returningResponse = []; | ||
let j = 0; | ||
for (let i = insertId; i < insertId + affectedRows; i++) { | ||
for (const column of returningIds) { | ||
const key = returningIds[0].path[0]; | ||
if (is(column.field, Column)) { | ||
if (column.field.primary && column.field.autoIncrement) { | ||
returningResponse.push({ [key]: i }); | ||
} | ||
if (column.field.defaultFn && generatedIds) { | ||
returningResponse.push({ [key]: generatedIds[j][key] }); | ||
} | ||
} | ||
} | ||
j++; | ||
} | ||
return customResultMapper(returningResponse); | ||
} | ||
return customResultMapper( | ||
res.rows | ||
); | ||
} | ||
iterator(_placeholderValues) { | ||
@@ -80,5 +120,6 @@ throw new Error("Streaming is not supported by the PlanetScale Serverless driver"); | ||
class PlanetscaleSession extends MySqlSession { | ||
constructor(baseClient, dialect, tx, schema, options = {}) { | ||
constructor(baseClient, dialect, tx, relations, schema, options = {}) { | ||
super(dialect); | ||
this.baseClient = baseClient; | ||
this.relations = relations; | ||
this.schema = schema; | ||
@@ -104,2 +145,15 @@ this.options = options; | ||
} | ||
prepareRelationalQuery(query, fields, customResultMapper, generatedIds, returningIds) { | ||
return new PlanetScalePreparedQuery( | ||
this.client, | ||
query.sql, | ||
query.params, | ||
this.logger, | ||
fields, | ||
customResultMapper, | ||
generatedIds, | ||
returningIds, | ||
true | ||
); | ||
} | ||
async query(query, params) { | ||
@@ -125,6 +179,14 @@ this.logger.logQuery(query, params); | ||
return this.baseClient.transaction((pstx) => { | ||
const session = new PlanetscaleSession(this.baseClient, this.dialect, pstx, this.schema, this.options); | ||
const session = new PlanetscaleSession( | ||
this.baseClient, | ||
this.dialect, | ||
pstx, | ||
this.relations, | ||
this.schema, | ||
this.options | ||
); | ||
const tx = new PlanetScaleTransaction( | ||
this.dialect, | ||
session, | ||
this.relations, | ||
this.schema | ||
@@ -138,4 +200,4 @@ ); | ||
static [entityKind] = "PlanetScaleTransaction"; | ||
constructor(dialect, session, schema, nestedIndex = 0) { | ||
super(dialect, session, schema, nestedIndex, "planetscale"); | ||
constructor(dialect, session, relations, schema, nestedIndex = 0) { | ||
super(dialect, session, relations, schema, nestedIndex, "planetscale"); | ||
} | ||
@@ -147,2 +209,3 @@ async transaction(transaction) { | ||
this.session, | ||
this.relations, | ||
this.schema, | ||
@@ -149,0 +212,0 @@ this.nestedIndex + 1 |
import { type Options, type PostgresType, type Sql } from 'postgres'; | ||
import { entityKind } from "../entity.js"; | ||
import { PgDatabase } from "../pg-core/db.js"; | ||
import type { AnyRelations, EmptyRelations } from "../relations.js"; | ||
import { type DrizzleConfig } from "../utils.js"; | ||
import type { PostgresJsQueryResultHKT } from "./session.js"; | ||
export declare class PostgresJsDatabase<TSchema extends Record<string, unknown> = Record<string, never>> extends PgDatabase<PostgresJsQueryResultHKT, TSchema> { | ||
export declare class PostgresJsDatabase<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations> extends PgDatabase<PostgresJsQueryResultHKT, TSchema, TRelations> { | ||
static readonly [entityKind]: string; | ||
} | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TClient extends Sql = Sql>(...params: [ | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations, TClient extends Sql = Sql>(...params: [ | ||
TClient | string | ||
] | [ | ||
TClient | string, | ||
DrizzleConfig<TSchema> | ||
DrizzleConfig<TSchema, TRelations> | ||
] | [ | ||
(DrizzleConfig<TSchema> & ({ | ||
(DrizzleConfig<TSchema, TRelations> & ({ | ||
connection: string | ({ | ||
@@ -22,9 +23,9 @@ url?: string; | ||
})) | ||
]): PostgresJsDatabase<TSchema> & { | ||
]): PostgresJsDatabase<TSchema, TRelations> & { | ||
$client: TClient; | ||
}; | ||
export declare namespace drizzle { | ||
function mock<TSchema extends Record<string, unknown> = Record<string, never>>(config?: DrizzleConfig<TSchema>): PostgresJsDatabase<TSchema> & { | ||
function mock<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations>(config?: DrizzleConfig<TSchema, TRelations>): PostgresJsDatabase<TSchema> & { | ||
$client: '$client is not available on drizzle.mock()'; | ||
}; | ||
} |
import pgClient from "postgres"; | ||
import * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
@@ -6,6 +7,2 @@ import { DefaultLogger } from "../logger.js"; | ||
import { PgDialect } from "../pg-core/dialect.js"; | ||
import { | ||
createTableRelationsHelpers, | ||
extractTablesRelationalConfig | ||
} from "../relations.js"; | ||
import { isConfig } from "../utils.js"; | ||
@@ -33,5 +30,5 @@ import { PostgresJsSession } from "./session.js"; | ||
if (config.schema) { | ||
const tablesConfig = extractTablesRelationalConfig( | ||
const tablesConfig = V1.extractTablesRelationalConfig( | ||
config.schema, | ||
createTableRelationsHelpers | ||
V1.createTableRelationsHelpers | ||
); | ||
@@ -44,4 +41,5 @@ schema = { | ||
} | ||
const session = new PostgresJsSession(client, dialect, schema, { logger }); | ||
const db = new PostgresJsDatabase(dialect, session, schema); | ||
const relations = config.relations; | ||
const session = new PostgresJsSession(client, dialect, relations, schema, { logger }); | ||
const db = new PostgresJsDatabase(dialect, session, relations, schema); | ||
db.$client = client; | ||
@@ -71,3 +69,8 @@ return db; | ||
function mock(config) { | ||
return construct({}, config); | ||
return construct({ | ||
options: { | ||
parsers: {}, | ||
serializers: {} | ||
} | ||
}, config); | ||
} | ||
@@ -74,0 +77,0 @@ drizzle2.mock = mock; |
import type { MigrationConfig } from "../migrator.js"; | ||
import type { AnyRelations } from "../relations.js"; | ||
import type { PostgresJsDatabase } from "./driver.js"; | ||
export declare function migrate<TSchema extends Record<string, unknown>>(db: PostgresJsDatabase<TSchema>, config: MigrationConfig): Promise<void>; | ||
export declare function migrate<TSchema extends Record<string, unknown>, TRelations extends AnyRelations>(db: PostgresJsDatabase<TSchema, TRelations>, config: MigrationConfig): Promise<void>; |
import type { Row, RowList, Sql, TransactionSql } from 'postgres'; | ||
import type * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
@@ -9,6 +10,6 @@ import type { Logger } from "../logger.js"; | ||
import { PgPreparedQuery, PgSession } from "../pg-core/session.js"; | ||
import type { RelationalSchemaConfig, TablesRelationalConfig } from "../relations.js"; | ||
import type { AnyRelations, TablesRelationalConfig } from "../relations.js"; | ||
import { type Query } from "../sql/sql.js"; | ||
import { type Assume } from "../utils.js"; | ||
export declare class PostgresJsPreparedQuery<T extends PreparedQueryConfig> extends PgPreparedQuery<T> { | ||
export declare class PostgresJsPreparedQuery<T extends PreparedQueryConfig, TIsRqbV2 extends boolean = false> extends PgPreparedQuery<T> { | ||
private client; | ||
@@ -21,5 +22,7 @@ private queryString; | ||
private customResultMapper?; | ||
private isRqbV2Query?; | ||
static readonly [entityKind]: string; | ||
constructor(client: Sql, queryString: string, params: unknown[], logger: Logger, fields: SelectedFieldsOrdered | undefined, _isResponseInArrayMode: boolean, customResultMapper?: ((rows: unknown[][]) => T["execute"]) | undefined); | ||
constructor(client: Sql, queryString: string, params: unknown[], logger: Logger, fields: SelectedFieldsOrdered | undefined, _isResponseInArrayMode: boolean, customResultMapper?: ((rows: TIsRqbV2 extends true ? Record<string, unknown>[] : unknown[][]) => T["execute"]) | undefined, isRqbV2Query?: TIsRqbV2 | undefined); | ||
execute(placeholderValues?: Record<string, unknown> | undefined): Promise<T['execute']>; | ||
private executeRqbV2; | ||
all(placeholderValues?: Record<string, unknown> | undefined): Promise<T['all']>; | ||
@@ -30,21 +33,24 @@ } | ||
} | ||
export declare class PostgresJsSession<TSQL extends Sql, TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends PgSession<PostgresJsQueryResultHKT, TFullSchema, TSchema> { | ||
export declare class PostgresJsSession<TSQL extends Sql, TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends PgSession<PostgresJsQueryResultHKT, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
client: TSQL; | ||
private relations; | ||
private schema; | ||
static readonly [entityKind]: string; | ||
logger: Logger; | ||
constructor(client: TSQL, dialect: PgDialect, schema: RelationalSchemaConfig<TSchema> | undefined, | ||
constructor(client: TSQL, dialect: PgDialect, relations: AnyRelations | undefined, schema: V1.RelationalSchemaConfig<TSchema> | undefined, | ||
/** @internal */ | ||
options?: PostgresJsSessionOptions); | ||
prepareQuery<T extends PreparedQueryConfig = PreparedQueryConfig>(query: Query, fields: SelectedFieldsOrdered | undefined, name: string | undefined, isResponseInArrayMode: boolean, customResultMapper?: (rows: unknown[][]) => T['execute']): PgPreparedQuery<T>; | ||
prepareRelationalQuery<T extends PreparedQueryConfig = PreparedQueryConfig>(query: Query, fields: SelectedFieldsOrdered | undefined, name: string | undefined, customResultMapper: (rows: Record<string, unknown>[]) => T['execute']): PgPreparedQuery<T>; | ||
query(query: string, params: unknown[]): Promise<RowList<Row[]>>; | ||
queryObjects<T extends Row>(query: string, params: unknown[]): Promise<RowList<T[]>>; | ||
transaction<T>(transaction: (tx: PostgresJsTransaction<TFullSchema, TSchema>) => Promise<T>, config?: PgTransactionConfig): Promise<T>; | ||
transaction<T>(transaction: (tx: PostgresJsTransaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => Promise<T>, config?: PgTransactionConfig): Promise<T>; | ||
} | ||
export declare class PostgresJsTransaction<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends PgTransaction<PostgresJsQueryResultHKT, TFullSchema, TSchema> { | ||
export declare class PostgresJsTransaction<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends PgTransaction<PostgresJsQueryResultHKT, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
protected relations: AnyRelations | undefined; | ||
static readonly [entityKind]: string; | ||
constructor(dialect: PgDialect, | ||
/** @internal */ | ||
session: PostgresJsSession<TransactionSql, TFullSchema, TSchema>, schema: RelationalSchemaConfig<TSchema> | undefined, nestedIndex?: number); | ||
transaction<T>(transaction: (tx: PostgresJsTransaction<TFullSchema, TSchema>) => Promise<T>): Promise<T>; | ||
session: PostgresJsSession<TransactionSql, TFullSchema, TRelations, TTablesConfig, TSchema>, schema: V1.RelationalSchemaConfig<TSchema> | undefined, relations: AnyRelations | undefined, nestedIndex?: number); | ||
transaction<T>(transaction: (tx: PostgresJsTransaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => Promise<T>): Promise<T>; | ||
} | ||
@@ -51,0 +57,0 @@ export interface PostgresJsQueryResultHKT extends PgQueryResultHKT { |
@@ -9,3 +9,3 @@ import { entityKind } from "../entity.js"; | ||
class PostgresJsPreparedQuery extends PgPreparedQuery { | ||
constructor(client, queryString, params, logger, fields, _isResponseInArrayMode, customResultMapper) { | ||
constructor(client, queryString, params, logger, fields, _isResponseInArrayMode, customResultMapper, isRqbV2Query) { | ||
super({ sql: queryString, params }); | ||
@@ -19,5 +19,8 @@ this.client = client; | ||
this.customResultMapper = customResultMapper; | ||
this.isRqbV2Query = isRqbV2Query; | ||
} | ||
static [entityKind] = "PostgresJsPreparedQuery"; | ||
async execute(placeholderValues = {}) { | ||
if (this.isRqbV2Query) | ||
return this.executeRqbV2(placeholderValues); | ||
return tracer.startActiveSpan("drizzle.execute", async (span) => { | ||
@@ -48,2 +51,23 @@ const params = fillPlaceholders(this.params, placeholderValues); | ||
} | ||
async executeRqbV2(placeholderValues = {}) { | ||
return tracer.startActiveSpan("drizzle.execute", async (span) => { | ||
const params = fillPlaceholders(this.params, placeholderValues); | ||
span?.setAttributes({ | ||
"drizzle.query.text": this.queryString, | ||
"drizzle.query.params": JSON.stringify(params) | ||
}); | ||
this.logger.logQuery(this.queryString, params); | ||
const { queryString: query, client, customResultMapper } = this; | ||
const rows = await tracer.startActiveSpan("drizzle.driver.execute", () => { | ||
span?.setAttributes({ | ||
"drizzle.query.text": query, | ||
"drizzle.query.params": JSON.stringify(params) | ||
}); | ||
return client.unsafe(query, params); | ||
}); | ||
return tracer.startActiveSpan("drizzle.mapResponse", () => { | ||
return customResultMapper(rows); | ||
}); | ||
}); | ||
} | ||
all(placeholderValues = {}) { | ||
@@ -72,5 +96,6 @@ return tracer.startActiveSpan("drizzle.execute", async (span) => { | ||
class PostgresJsSession extends PgSession { | ||
constructor(client, dialect, schema, options = {}) { | ||
constructor(client, dialect, relations, schema, options = {}) { | ||
super(dialect); | ||
this.client = client; | ||
this.relations = relations; | ||
this.schema = schema; | ||
@@ -93,2 +118,14 @@ this.options = options; | ||
} | ||
prepareRelationalQuery(query, fields, name, customResultMapper) { | ||
return new PostgresJsPreparedQuery( | ||
this.client, | ||
query.sql, | ||
query.params, | ||
this.logger, | ||
fields, | ||
false, | ||
customResultMapper, | ||
true | ||
); | ||
} | ||
query(query, params) { | ||
@@ -106,6 +143,7 @@ this.logger.logQuery(query, params); | ||
this.dialect, | ||
this.relations, | ||
this.schema, | ||
this.options | ||
); | ||
const tx = new PostgresJsTransaction(this.dialect, session, this.schema); | ||
const tx = new PostgresJsTransaction(this.dialect, session, this.schema, this.relations); | ||
if (config) { | ||
@@ -119,5 +157,6 @@ await tx.setTransaction(config); | ||
class PostgresJsTransaction extends PgTransaction { | ||
constructor(dialect, session, schema, nestedIndex = 0) { | ||
super(dialect, session, schema, nestedIndex); | ||
constructor(dialect, session, schema, relations, nestedIndex = 0) { | ||
super(dialect, session, relations, schema, nestedIndex); | ||
this.session = session; | ||
this.relations = relations; | ||
} | ||
@@ -130,6 +169,12 @@ static [entityKind] = "PostgresJsTransaction"; | ||
this.dialect, | ||
this.relations, | ||
this.schema, | ||
this.session.options | ||
); | ||
const tx = new PostgresJsTransaction(this.dialect, session, this.schema); | ||
const tx = new PostgresJsTransaction( | ||
this.dialect, | ||
session, | ||
this.schema, | ||
this.relations | ||
); | ||
return transaction(tx); | ||
@@ -136,0 +181,0 @@ }); |
@@ -10,3 +10,3 @@ import { Prisma } from "@prisma/client"; | ||
const dialect = new MySqlDialect(); | ||
super(dialect, new PrismaMySqlSession(dialect, client, { logger }), void 0, "default"); | ||
super(dialect, new PrismaMySqlSession(dialect, client, { logger }), void 0, void 0, "default"); | ||
} | ||
@@ -13,0 +13,0 @@ } |
@@ -6,2 +6,3 @@ import type { PrismaClient } from '@prisma/client/extension'; | ||
import { MySqlPreparedQuery, MySqlSession } from "../../mysql-core/index.js"; | ||
import type { EmptyRelations, ExtractTablesWithRelations } from "../../relations.js"; | ||
import type { Query, SQL } from "../../sql/sql.js"; | ||
@@ -32,3 +33,4 @@ import type { Assume } from "../../utils.js"; | ||
prepareQuery<T extends MySqlPreparedQueryConfig = MySqlPreparedQueryConfig>(query: Query): MySqlPreparedQuery<T>; | ||
transaction<T>(_transaction: (tx: MySqlTransaction<PrismaMySqlQueryResultHKT, PrismaMySqlPreparedQueryHKT, Record<string, never>, Record<string, never>>) => Promise<T>, _config?: MySqlTransactionConfig): Promise<T>; | ||
prepareRelationalQuery<T extends MySqlPreparedQueryConfig = MySqlPreparedQueryConfig>(): MySqlPreparedQuery<T>; | ||
transaction<T>(_transaction: (tx: MySqlTransaction<PrismaMySqlQueryResultHKT, PrismaMySqlPreparedQueryHKT, Record<string, never>, EmptyRelations, ExtractTablesWithRelations<EmptyRelations>, Record<string, never>>) => Promise<T>, _config?: MySqlTransactionConfig): Promise<T>; | ||
} | ||
@@ -35,0 +37,0 @@ export interface PrismaMySqlQueryResultHKT extends MySqlQueryResultHKT { |
@@ -40,2 +40,5 @@ import { entityKind } from "../../entity.js"; | ||
} | ||
prepareRelationalQuery() { | ||
throw new Error("Method not implemented"); | ||
} | ||
transaction(_transaction, _config) { | ||
@@ -42,0 +45,0 @@ throw new Error("Method not implemented."); |
@@ -10,3 +10,3 @@ import { Prisma } from "@prisma/client"; | ||
const dialect = new PgDialect(); | ||
super(dialect, new PrismaPgSession(dialect, client, { logger }), void 0); | ||
super(dialect, new PrismaPgSession(dialect, client, { logger }), void 0, void 0); | ||
} | ||
@@ -13,0 +13,0 @@ } |
@@ -6,2 +6,3 @@ import type { PrismaClient } from '@prisma/client/extension'; | ||
import { PgPreparedQuery, PgSession } from "../../pg-core/index.js"; | ||
import type { EmptyRelations, ExtractTablesWithRelations } from "../../relations.js"; | ||
import type { Query, SQL } from "../../sql/sql.js"; | ||
@@ -30,3 +31,4 @@ export declare class PrismaPgPreparedQuery<T> extends PgPreparedQuery<PreparedQueryConfig & { | ||
prepareQuery<T extends PreparedQueryConfig = PreparedQueryConfig>(query: Query): PgPreparedQuery<T>; | ||
transaction<T>(_transaction: (tx: PgTransaction<PgQueryResultHKT, Record<string, never>, Record<string, never>>) => Promise<T>, _config?: PgTransactionConfig): Promise<T>; | ||
prepareRelationalQuery<T extends PreparedQueryConfig = PreparedQueryConfig>(): PgPreparedQuery<T>; | ||
transaction<T>(_transaction: (tx: PgTransaction<PgQueryResultHKT, Record<string, never>, EmptyRelations, ExtractTablesWithRelations<EmptyRelations>, Record<string, never>>) => Promise<T>, _config?: PgTransactionConfig): Promise<T>; | ||
} | ||
@@ -33,0 +35,0 @@ export interface PrismaPgQueryResultHKT extends PgQueryResultHKT { |
@@ -39,2 +39,5 @@ import { entityKind } from "../../entity.js"; | ||
} | ||
prepareRelationalQuery() { | ||
throw new Error("Method not implemented."); | ||
} | ||
transaction(_transaction, _config) { | ||
@@ -41,0 +44,0 @@ throw new Error("Method not implemented."); |
@@ -18,3 +18,3 @@ import { Prisma } from "@prisma/client"; | ||
client: { | ||
$drizzle: new BaseSQLiteDatabase("async", dialect, session, void 0) | ||
$drizzle: new BaseSQLiteDatabase("async", dialect, session, void 0, void 0) | ||
} | ||
@@ -21,0 +21,0 @@ }); |
import type { PrismaClient } from '@prisma/client/extension'; | ||
import { entityKind } from "../../entity.js"; | ||
import { type Logger } from "../../logger.js"; | ||
import type { EmptyRelations, ExtractTablesWithRelations } from "../../relations.js"; | ||
import type { Query } from "../../sql/sql.js"; | ||
@@ -29,3 +30,3 @@ import type { PreparedQueryConfig as PreparedQueryConfigBase, SelectedFieldsOrdered, SQLiteAsyncDialect, SQLiteExecuteMethod, SQLiteTransaction, SQLiteTransactionConfig } from "../../sqlite-core/index.js"; | ||
} | ||
export declare class PrismaSQLiteSession extends SQLiteSession<'async', unknown, Record<string, never>, Record<string, never>> { | ||
export declare class PrismaSQLiteSession extends SQLiteSession<'async', unknown, Record<string, never>, EmptyRelations, ExtractTablesWithRelations<EmptyRelations>, Record<string, never>> { | ||
private readonly prisma; | ||
@@ -36,4 +37,5 @@ static readonly [entityKind]: string; | ||
prepareQuery<T extends Omit<PreparedQueryConfig, 'run'>>(query: Query, fields: SelectedFieldsOrdered | undefined, executeMethod: SQLiteExecuteMethod): PrismaSQLitePreparedQuery<T>; | ||
transaction<T>(_transaction: (tx: SQLiteTransaction<'async', unknown, Record<string, never>, Record<string, never>>) => Promise<T>, _config?: SQLiteTransactionConfig): Promise<T>; | ||
prepareRelationalQuery<T extends Omit<PreparedQueryConfig, 'run'>>(): PrismaSQLitePreparedQuery<T>; | ||
transaction<T>(_transaction: (tx: SQLiteTransaction<'async', unknown, Record<string, never>, EmptyRelations, ExtractTablesWithRelations<EmptyRelations>, Record<string, never>>) => Promise<T>, _config?: SQLiteTransactionConfig): Promise<T>; | ||
} | ||
export {}; |
@@ -43,2 +43,5 @@ import { entityKind } from "../../entity.js"; | ||
} | ||
prepareRelationalQuery() { | ||
throw new Error("Method not implemented."); | ||
} | ||
transaction(_transaction, _config) { | ||
@@ -45,0 +48,0 @@ throw new Error("Method not implemented."); |
@@ -5,61 +5,71 @@ import { type AnyTable, type InferModelFromColumns, Table } from "./table.js"; | ||
import { and, asc, between, desc, exists, ilike, inArray, isNotNull, isNull, like, not, notBetween, notExists, notIlike, notInArray, notLike, or } from "./sql/expressions/index.js"; | ||
import { type Placeholder, SQL, sql } from "./sql/sql.js"; | ||
import type { Assume, ColumnsWithTable, Equal, Simplify, ValueOrArray } from "./utils.js"; | ||
export declare abstract class Relation<TTableName extends string = string> { | ||
readonly sourceTable: Table; | ||
readonly referencedTable: AnyTable<{ | ||
name: TTableName; | ||
import { type Placeholder, SQL, sql, type SQLWrapper } from "./sql/sql.js"; | ||
import { type Assume, type Equal, type Simplify, type ValueOrArray, type Writable } from "./utils.js"; | ||
export declare class Relations<TSchema extends Record<string, unknown> = Record<string, unknown>, TTables extends Record<string, Table> = Record<string, Table>, TConfig extends RelationsBuilderConfig<TTables> = RelationsBuilderConfig<TTables>> { | ||
readonly schema: TSchema; | ||
readonly tables: TTables; | ||
readonly config: TConfig; | ||
static readonly [entityKind]: string; | ||
readonly $brand: 'Relations'; | ||
/** table DB name -> schema table key */ | ||
readonly tableNamesMap: Record<string, string>; | ||
readonly tablesConfig: TablesRelationalConfig; | ||
constructor(schema: TSchema, tables: TTables, config: TConfig); | ||
} | ||
export type EmptyRelations = Relations<Record<string, never>, Record<string, never>, Record<string, never>>; | ||
export type AnyRelations = Relations<Record<string, any>, Record<string, any>, Record<string, any>>; | ||
export declare abstract class Relation<TSourceTableName extends string = string, TTargetTableName extends string = string> { | ||
readonly targetTable: AnyTable<{ | ||
name: TTargetTableName; | ||
}>; | ||
readonly relationName: string | undefined; | ||
static readonly [entityKind]: string; | ||
readonly $brand: 'Relation'; | ||
readonly referencedTableName: TTableName; | ||
fieldName: string; | ||
constructor(sourceTable: Table, referencedTable: AnyTable<{ | ||
name: TTableName; | ||
}>, relationName: string | undefined); | ||
abstract withFieldName(fieldName: string): Relation<TTableName>; | ||
} | ||
export declare class Relations<TTableName extends string = string, TConfig extends Record<string, Relation> = Record<string, Relation>> { | ||
readonly table: AnyTable<{ | ||
name: TTableName; | ||
sourceColumns: AnyColumn<{ | ||
tableName: TSourceTableName; | ||
}>[]; | ||
targetColumns: AnyColumn<{ | ||
tableName: TTargetTableName; | ||
}>[]; | ||
alias: string | undefined; | ||
where: RelationsFilter<Record<string, Column>> | undefined; | ||
sourceTable: AnyTable<{ | ||
name: TSourceTableName; | ||
}>; | ||
readonly config: (helpers: TableRelationsHelpers<TTableName>) => TConfig; | ||
static readonly [entityKind]: string; | ||
readonly $brand: 'Relations'; | ||
constructor(table: AnyTable<{ | ||
name: TTableName; | ||
}>, config: (helpers: TableRelationsHelpers<TTableName>) => TConfig); | ||
constructor(targetTable: AnyTable<{ | ||
name: TTargetTableName; | ||
}>); | ||
} | ||
export declare class One<TTableName extends string = string, TIsNullable extends boolean = boolean> extends Relation<TTableName> { | ||
readonly config: RelationConfig<TTableName, string, AnyColumn<{ | ||
tableName: TTableName; | ||
}>[]> | undefined; | ||
readonly isNullable: TIsNullable; | ||
export declare class One<TSourceTableName extends string, TTargetTableName extends string, TOptional extends boolean = boolean> extends Relation<TSourceTableName, TTargetTableName> { | ||
static readonly [entityKind]: string; | ||
protected $relationBrand: 'One'; | ||
constructor(sourceTable: Table, referencedTable: AnyTable<{ | ||
name: TTableName; | ||
}>, config: RelationConfig<TTableName, string, AnyColumn<{ | ||
tableName: TTableName; | ||
}>[]> | undefined, isNullable: TIsNullable); | ||
withFieldName(fieldName: string): One<TTableName>; | ||
readonly optional: TOptional; | ||
constructor(targetTable: AnyTable<{ | ||
name: TTargetTableName; | ||
}>, config: AnyOneConfig | undefined); | ||
} | ||
export declare class Many<TTableName extends string> extends Relation<TTableName> { | ||
readonly config: { | ||
relationName: string; | ||
} | undefined; | ||
export declare class Many<TSourceTableName extends string, TTargetTableName extends string> extends Relation<TSourceTableName, TTargetTableName> { | ||
readonly config: AnyManyConfig | undefined; | ||
static readonly [entityKind]: string; | ||
protected $relationBrand: 'Many'; | ||
constructor(sourceTable: Table, referencedTable: AnyTable<{ | ||
name: TTableName; | ||
}>, config: { | ||
relationName: string; | ||
} | undefined); | ||
withFieldName(fieldName: string): Many<TTableName>; | ||
constructor(targetTable: AnyTable<{ | ||
name: TTargetTableName; | ||
}>, config: AnyManyConfig | undefined); | ||
} | ||
export type TableRelationsKeysOnly<TSchema extends Record<string, unknown>, TTableName extends string, K extends keyof TSchema> = TSchema[K] extends Relations<TTableName> ? K : never; | ||
export type ExtractTableRelationsFromSchema<TSchema extends Record<string, unknown>, TTableName extends string> = ExtractObjectValues<{ | ||
[K in keyof TSchema as TableRelationsKeysOnly<TSchema, TTableName, K>]: TSchema[K] extends Relations<TTableName, infer TConfig> ? TConfig : never; | ||
}>; | ||
export declare abstract class AggregatedField<T = unknown> implements SQLWrapper<T> { | ||
static readonly [entityKind]: string; | ||
readonly $brand: 'AggregatedField'; | ||
readonly _: { | ||
readonly data: T; | ||
}; | ||
protected table: Table | undefined; | ||
onTable(table: Table): this; | ||
abstract getSQL(): SQL<T>; | ||
} | ||
export declare class Count extends AggregatedField<number> { | ||
static readonly [entityKind]: string; | ||
protected $aggregatedFieldBrand: 'Count'; | ||
private query; | ||
getSQL(): SQL<number>; | ||
} | ||
export type ExtractObjectValues<T> = T[keyof T]; | ||
@@ -69,3 +79,3 @@ export type ExtractRelationsFromTableExtraConfigSchema<TConfig extends unknown[]> = ExtractObjectValues<{ | ||
}>; | ||
export declare function getOperators(): { | ||
export declare const operators: { | ||
and: typeof and; | ||
@@ -94,3 +104,8 @@ between: typeof between; | ||
}; | ||
export type Operators = ReturnType<typeof getOperators>; | ||
export type Operators = typeof operators; | ||
export declare const orderByOperators: { | ||
sql: typeof sql; | ||
asc: typeof asc; | ||
desc: typeof desc; | ||
}; | ||
export declare function getOrderByOperators(): { | ||
@@ -102,33 +117,41 @@ sql: typeof sql; | ||
export type OrderByOperators = ReturnType<typeof getOrderByOperators>; | ||
export type FindTableByDBName<TSchema extends TablesRelationalConfig, TTableName extends string> = ExtractObjectValues<{ | ||
[K in keyof TSchema as TSchema[K]['dbName'] extends TTableName ? K : never]: TSchema[K]; | ||
export type FindTableByDBNameRelationalConfig<TSchema extends TablesRelationalConfig, TTableName extends string> = ExtractObjectValues<{ | ||
[K in keyof TSchema as TSchema[K]['table']['_']['name'] extends TTableName ? K : never]: TSchema[K]; | ||
}>; | ||
export type DBQueryConfig<TRelationType extends 'one' | 'many' = 'one' | 'many', TIsRoot extends boolean = boolean, TSchema extends TablesRelationalConfig = TablesRelationalConfig, TTableConfig extends TableRelationalConfig = TableRelationalConfig> = { | ||
export type FindTableByDBNameTablesRecord<TSchema extends Record<string, Table>, TTableName extends string> = ExtractObjectValues<{ | ||
[K in keyof TSchema as TSchema[K]['_']['name'] extends TTableName ? K : never]: TSchema[K]; | ||
}>; | ||
export type FindTableInRelationsConfig<TSchema extends TablesRelationalConfig, TTargetTable extends Table, TTableName extends string = TTargetTable['_']['name'], TSchemaName extends string | undefined = TTargetTable['_']['schema'] extends undefined ? undefined : TTargetTable['_']['schema']> = ExtractObjectValues<{ | ||
[K in keyof TSchema as TSchema[K]['dbName'] extends TTableName ? TSchema[K]['schema'] extends undefined ? TSchemaName extends undefined ? K : never : TSchemaName extends TSchema[K]['schema'] ? K : never : never]: TSchema[K]; | ||
}>; | ||
export type SQLOperator = { | ||
sql: Operators['sql']; | ||
}; | ||
export type DBQueryConfig<TRelationType extends 'one' | 'many' = 'one' | 'many', TSchema extends TablesRelationalConfig = TablesRelationalConfig, TTableConfig extends TableRelationalConfig = TableRelationalConfig> = { | ||
config?: TTableConfig['relations']; | ||
columns?: { | ||
[K in keyof TTableConfig['columns']]?: boolean; | ||
[K in keyof TTableConfig['columns']]?: true; | ||
} | { | ||
[K in keyof TTableConfig['columns']]?: false; | ||
}; | ||
with?: { | ||
[K in keyof TTableConfig['relations']]?: true | DBQueryConfig<TTableConfig['relations'][K] extends One ? 'one' : 'many', false, TSchema, FindTableByDBName<TSchema, TTableConfig['relations'][K]['referencedTableName']>>; | ||
[K in keyof TTableConfig['relations']]?: true | (TTableConfig['relations'][K] extends Relation ? DBQueryConfig<TTableConfig['relations'][K] extends One<string, string> ? 'one' : 'many', TSchema, FindTableInRelationsConfig<TSchema, TTableConfig['relations'][K]['targetTable']>> : never); | ||
}; | ||
extras?: Record<string, SQL.Aliased> | ((fields: Simplify<[ | ||
extras?: Record<string, SQLWrapper> | ((fields: Simplify<[ | ||
TTableConfig['columns'] | ||
] extends [never] ? {} : TTableConfig['columns']>, operators: { | ||
sql: Operators['sql']; | ||
}) => Record<string, SQL.Aliased>); | ||
} & (TRelationType extends 'many' ? { | ||
where?: SQL | undefined | ((fields: Simplify<[ | ||
TTableConfig['columns'] | ||
] extends [never] ? {} : TTableConfig['columns']>, operators: Operators) => SQL | undefined); | ||
] extends [never] ? {} : TTableConfig['columns']>, operators: SQLOperator) => Record<string, SQLWrapper>); | ||
offset?: number | Placeholder; | ||
where?: RelationsFilter<TTableConfig['columns']>; | ||
orderBy?: ValueOrArray<AnyColumn | SQL> | ((fields: Simplify<[ | ||
TTableConfig['columns'] | ||
] extends [never] ? {} : TTableConfig['columns']>, operators: OrderByOperators) => ValueOrArray<AnyColumn | SQL>); | ||
} & (TRelationType extends 'many' ? { | ||
limit?: number | Placeholder; | ||
} & (TIsRoot extends true ? { | ||
offset?: number | Placeholder; | ||
} : {}) : {}); | ||
} : {}); | ||
export interface TableRelationalConfig { | ||
table: Table; | ||
tsName: string; | ||
dbName: string; | ||
columns: Record<string, Column>; | ||
relations: Record<string, Relation>; | ||
relations: Record<string, RelationsBuilderEntry>; | ||
primaryKey: AnyColumn[]; | ||
@@ -138,19 +161,24 @@ schema?: string; | ||
export type TablesRelationalConfig = Record<string, TableRelationalConfig>; | ||
export interface RelationalSchemaConfig<TSchema extends TablesRelationalConfig> { | ||
fullSchema: Record<string, unknown>; | ||
schema: TSchema; | ||
export interface RelationalSchemaConfig<TTablesConfig extends TablesRelationalConfig> { | ||
tables: Record<string, Table>; | ||
tablesConfig: TTablesConfig; | ||
tableNamesMap: Record<string, string>; | ||
} | ||
export type ExtractTablesWithRelations<TSchema extends Record<string, unknown>> = { | ||
[K in keyof TSchema as TSchema[K] extends Table ? K : never]: TSchema[K] extends Table ? { | ||
type NonUndefinedRecord<TRecord extends Record<string, any>> = { | ||
[K in keyof TRecord as K extends undefined ? never : K]: TRecord[K]; | ||
}; | ||
export type ExtractTablesWithRelations<TRelations extends Relations, TTables extends Record<string, Table> = TRelations['tables']> = { | ||
[K in keyof TTables]: { | ||
table: TTables[K]; | ||
tsName: K & string; | ||
dbName: TSchema[K]['_']['name']; | ||
columns: TSchema[K]['_']['columns']; | ||
relations: ExtractTableRelationsFromSchema<TSchema, TSchema[K]['_']['name']>; | ||
dbName: TTables[K]['_']['name']; | ||
columns: TTables[K]['_']['columns']; | ||
relations: K extends keyof TRelations['config'] ? TRelations['config'][K] extends Record<string, any> ? NonUndefinedRecord<TRelations['config'][K]> : Record<string, never> : Record<string, never>; | ||
primaryKey: AnyColumn[]; | ||
} : never; | ||
schema: TTables[K]['_']['schema']; | ||
}; | ||
}; | ||
export type ReturnTypeOrValue<T> = T extends (...args: any[]) => infer R ? R : T; | ||
export type BuildRelationResult<TSchema extends TablesRelationalConfig, TInclude, TRelations extends Record<string, Relation>> = { | ||
[K in NonUndefinedKeysOnly<TInclude> & keyof TRelations]: TRelations[K] extends infer TRel extends Relation ? BuildQueryResult<TSchema, FindTableByDBName<TSchema, TRel['referencedTableName']>, Assume<TInclude[K], true | Record<string, unknown>>> extends infer TResult ? TRel extends One ? TResult | (Equal<TRel['isNullable'], false> extends true ? null : never) : TResult[] : never : never; | ||
export type BuildRelationResult<TConfig extends TablesRelationalConfig, TInclude, TRelations extends Record<string, RelationsBuilderEntry>> = { | ||
[K in NonUndefinedKeysOnly<TInclude> & keyof TRelations]: TRelations[K] extends infer TRel extends Relation ? BuildQueryResult<TConfig, FindTableInRelationsConfig<TConfig, TRel['targetTable']>, Assume<TInclude[K], true | Record<string, unknown>>> extends infer TResult ? TRel extends One<string, string> ? TResult | (Equal<TRel['optional'], true> extends true ? null : never) : TResult[] : never : TRelations[K] extends AggregatedField<infer TData> ? TData : never; | ||
}; | ||
@@ -165,26 +193,4 @@ export type NonUndefinedKeysOnly<T> = ExtractObjectValues<{ | ||
}> : InferModelFromColumns<TTableConfig['columns']>) & (TFullSelection['extras'] extends Record<string, unknown> | ((...args: any[]) => Record<string, unknown>) ? { | ||
[K in NonUndefinedKeysOnly<ReturnTypeOrValue<TFullSelection['extras']>>]: Assume<ReturnTypeOrValue<TFullSelection['extras']>[K], SQL.Aliased>['_']['type']; | ||
[K in NonUndefinedKeysOnly<ReturnTypeOrValue<TFullSelection['extras']>>]: Assume<ReturnTypeOrValue<TFullSelection['extras']>[K], SQL>['_']['type']; | ||
} : {}) & (TFullSelection['with'] extends Record<string, unknown> ? BuildRelationResult<TSchema, TFullSelection['with'], TTableConfig['relations']> : {})> : never; | ||
export interface RelationConfig<TTableName extends string, TForeignTableName extends string, TColumns extends AnyColumn<{ | ||
tableName: TTableName; | ||
}>[]> { | ||
relationName?: string; | ||
fields: TColumns; | ||
references: ColumnsWithTable<TTableName, TForeignTableName, TColumns>; | ||
} | ||
export declare function extractTablesRelationalConfig<TTables extends TablesRelationalConfig>(schema: Record<string, unknown>, configHelpers: (table: Table) => any): { | ||
tables: TTables; | ||
tableNamesMap: Record<string, string>; | ||
}; | ||
export declare function relations<TTableName extends string, TRelations extends Record<string, Relation<any>>>(table: AnyTable<{ | ||
name: TTableName; | ||
}>, relations: (helpers: TableRelationsHelpers<TTableName>) => TRelations): Relations<TTableName, TRelations>; | ||
export declare function createOne<TTableName extends string>(sourceTable: Table): <TForeignTable extends Table, TColumns extends [AnyColumn<{ | ||
tableName: TTableName; | ||
}>, ...AnyColumn<{ | ||
tableName: TTableName; | ||
}>[]]>(table: TForeignTable, config?: RelationConfig<TTableName, TForeignTable["_"]["name"], TColumns>) => One<TForeignTable["_"]["name"], Equal<TColumns[number]["_"]["notNull"], true>>; | ||
export declare function createMany(sourceTable: Table): <TForeignTable extends Table>(referencedTable: TForeignTable, config?: { | ||
relationName: string; | ||
}) => Many<TForeignTable["_"]["name"]>; | ||
export interface NormalizedRelation { | ||
@@ -194,29 +200,162 @@ fields: AnyColumn[]; | ||
} | ||
export declare function normalizeRelation(schema: TablesRelationalConfig, tableNamesMap: Record<string, string>, relation: Relation): NormalizedRelation; | ||
export declare function createTableRelationsHelpers<TTableName extends string>(sourceTable: AnyTable<{ | ||
name: TTableName; | ||
}>): { | ||
one: <TForeignTable extends Table, TColumns extends [AnyColumn<{ | ||
export interface BuildRelationalQueryResult { | ||
selection: { | ||
key: string; | ||
field: Column | Table | SQL | SQL.Aliased | SQLWrapper | AggregatedField; | ||
isArray?: boolean; | ||
selection?: BuildRelationalQueryResult['selection']; | ||
}[]; | ||
sql: SQL; | ||
} | ||
export declare function mapRelationalRow(row: Record<string, unknown>, buildQueryResultSelection: BuildRelationalQueryResult['selection'], mapColumnValue?: (value: unknown) => unknown, | ||
/** Needed for SQLite as it returns JSON values as strings */ | ||
parseJson?: boolean): Record<string, unknown>; | ||
export declare class RelationsBuilderTable<TTableName extends string = string> implements SQLWrapper { | ||
static readonly [entityKind]: string; | ||
readonly _: { | ||
readonly name: TTableName; | ||
readonly table: AnyTable<{ | ||
name: TTableName; | ||
}>; | ||
}; | ||
constructor(table: AnyTable<{ | ||
name: TTableName; | ||
}>); | ||
getSQL(): SQL; | ||
} | ||
export type RelationsBuilderColumnConfig<TTableName extends string = string, TData = unknown> = { | ||
readonly tableName: TTableName; | ||
readonly data: TData; | ||
readonly column: AnyColumn<{ | ||
tableName: TTableName; | ||
}>, ...AnyColumn<{ | ||
}>; | ||
through?: RelationsBuilderColumnBase; | ||
}; | ||
export type RelationsBuilderColumnBase<TTableName extends string = string, TData = unknown> = { | ||
_: RelationsBuilderColumnConfig<TTableName, TData>; | ||
} & SQLWrapper; | ||
export declare class RelationsBuilderColumn<TTableName extends string = string, TData = unknown> implements SQLWrapper, RelationsBuilderColumnBase<TTableName, TData> { | ||
static readonly [entityKind]: string; | ||
readonly _: { | ||
readonly tableName: TTableName; | ||
readonly data: TData; | ||
readonly column: AnyColumn<{ | ||
tableName: TTableName; | ||
}>; | ||
through?: RelationsBuilderColumnBase; | ||
}; | ||
constructor(column: AnyColumn<{ | ||
tableName: TTableName; | ||
}>[]]>(table: TForeignTable, config?: RelationConfig<TTableName, TForeignTable["_"]["name"], TColumns> | undefined) => One<TForeignTable["_"]["name"], Equal<TColumns[number]["_"]["notNull"], true>>; | ||
many: <TForeignTable extends Table>(referencedTable: TForeignTable, config?: { | ||
relationName: string; | ||
}) => Many<TForeignTable["_"]["name"]>; | ||
}>); | ||
through(column: RelationsBuilderColumnBase<string, TData>): Omit<this, 'through'>; | ||
getSQL(): SQL; | ||
} | ||
export type RelationFieldsFilterInternals<T> = { | ||
eq?: T; | ||
ne?: T; | ||
gt?: T; | ||
gte?: T; | ||
lt?: T; | ||
lte?: T; | ||
in?: T[]; | ||
notIn?: T[]; | ||
like?: string; | ||
ilike?: string; | ||
notLike?: string; | ||
notIlike?: string; | ||
isNull?: true; | ||
isNotNull?: true; | ||
$not?: RelationsFieldFilter<T>; | ||
$or?: RelationsFieldFilter<T>[]; | ||
}; | ||
export type TableRelationsHelpers<TTableName extends string> = ReturnType<typeof createTableRelationsHelpers<TTableName>>; | ||
export interface BuildRelationalQueryResult<TTable extends Table = Table, TColumn extends Column = Column> { | ||
tableTsKey: string; | ||
export type RelationsFieldFilter<T> = T | RelationFieldsFilterInternals<T>; | ||
export type RelationsFilter<TColumns extends Record<string, Column>> = { | ||
[K in keyof TColumns]?: RelationsFieldFilter<TColumns[K]['_']['data']>; | ||
} & { | ||
$or?: RelationsFilter<TColumns>[]; | ||
$not?: RelationsFilter<TColumns>[]; | ||
$raw?: (operators: Operators) => SQL; | ||
}; | ||
export interface OneConfig<TSchema extends Record<string, Table>, TSourceColumns extends Readonly<[RelationsBuilderColumnBase, ...RelationsBuilderColumnBase[]]> | Readonly<RelationsBuilderColumnBase>, TTargetTableName extends string, TOptional extends boolean> { | ||
from?: TSourceColumns | Writable<TSourceColumns>; | ||
to?: TSourceColumns extends [RelationsBuilderColumnBase, ...RelationsBuilderColumnBase[]] ? { | ||
[K in keyof TSourceColumns]: RelationsBuilderColumnBase<TTargetTableName>; | ||
} : RelationsBuilderColumnBase<TTargetTableName>; | ||
where?: TSourceColumns extends [RelationsBuilderColumnBase, ...RelationsBuilderColumnBase[]] ? RelationsFilter<FindTableByDBNameTablesRecord<TSchema, TSourceColumns[number]['_']['tableName']>['_']['columns']> : RelationsFilter<FindTableByDBNameTablesRecord<TSchema, Assume<TSourceColumns, RelationsBuilderColumnBase>['_']['tableName']>['_']['columns']>; | ||
optional?: TOptional; | ||
alias?: string; | ||
} | ||
export type AnyOneConfig = OneConfig<Record<string, Table>, Readonly<[RelationsBuilderColumnBase, ...RelationsBuilderColumnBase[]] | RelationsBuilderColumnBase<string, unknown>>, string, boolean>; | ||
export interface ManyConfig<TSchema extends Record<string, Table>, TSourceColumns extends Readonly<[RelationsBuilderColumnBase, ...RelationsBuilderColumnBase[]]> | Readonly<RelationsBuilderColumnBase>, TTargetTableName extends string> { | ||
from?: TSourceColumns; | ||
to?: TSourceColumns extends [RelationsBuilderColumnBase, ...RelationsBuilderColumnBase[]] ? { | ||
[K in keyof TSourceColumns]: RelationsBuilderColumnBase<TTargetTableName>; | ||
} : RelationsBuilderColumnBase<TTargetTableName>; | ||
where?: TSourceColumns extends [RelationsBuilderColumnBase, ...RelationsBuilderColumnBase[]] ? RelationsFilter<FindTableByDBNameTablesRecord<TSchema, TSourceColumns[number]['_']['tableName']>['_']['columns']> : RelationsFilter<FindTableByDBNameTablesRecord<TSchema, Assume<TSourceColumns, RelationsBuilderColumnBase>['_']['tableName']>['_']['columns']>; | ||
alias?: string; | ||
} | ||
export type AnyManyConfig = ManyConfig<Record<string, Table>, Readonly<[RelationsBuilderColumnBase, ...RelationsBuilderColumnBase[]]> | Readonly<RelationsBuilderColumnBase>, string>; | ||
export interface OneFn<TTables extends Record<string, Table>, TTargetTableName extends string> { | ||
<TSourceColumns extends Readonly<[RelationsBuilderColumnBase, ...RelationsBuilderColumnBase[]]> | RelationsBuilderColumnBase = any, TOptional extends boolean = false>(config?: OneConfig<TTables, TSourceColumns, TTargetTableName, TOptional>): One<TSourceColumns extends [RelationsBuilderColumnBase, ...RelationsBuilderColumnBase[]] ? TSourceColumns[number]['_']['tableName'] : Assume<TSourceColumns, RelationsBuilderColumnBase>['_']['tableName'], TTargetTableName, TOptional>; | ||
} | ||
export interface ManyFn<TTables extends Record<string, Table>, TTargetTableName extends string> { | ||
<TSourceColumns extends Readonly<[RelationsBuilderColumnBase, ...RelationsBuilderColumnBase[]]> | RelationsBuilderColumnBase = any>(config?: ManyConfig<TTables, TSourceColumns, TTargetTableName>): Many<TSourceColumns extends [RelationsBuilderColumnBase, ...RelationsBuilderColumnBase[]] ? TSourceColumns[number]['_']['tableName'] : Assume<TSourceColumns, RelationsBuilderColumnBase>['_']['tableName'], TTargetTableName>; | ||
} | ||
export declare class RelationsHelperStatic<TTables extends Record<string, Table>> { | ||
static readonly [entityKind]: string; | ||
readonly $brand: 'RelationsHelperStatic'; | ||
readonly _: { | ||
readonly tables: TTables; | ||
}; | ||
constructor(tables: TTables); | ||
one: { | ||
[K in keyof TTables]: OneFn<TTables, TTables[K]['_']['name']>; | ||
}; | ||
many: { | ||
[K in keyof TTables]: ManyFn<TTables, TTables[K]['_']['name']>; | ||
}; | ||
aggs: { | ||
count(): Count; | ||
}; | ||
} | ||
export type RelationsBuilder<TSchema extends Record<string, Table>> = { | ||
[TTableName in keyof TSchema & string]: { | ||
[TColumnName in keyof TSchema[TTableName]['_']['columns']]: RelationsBuilderColumn<TSchema[TTableName]['_']['name'], TSchema[TTableName]['_']['columns'][TColumnName]['_']['data']>; | ||
} & RelationsBuilderTable<TTableName>; | ||
} & RelationsHelperStatic<TSchema>; | ||
export type RelationsBuilderConfig<TTables extends Record<string, Table>> = { | ||
[TTableName in keyof TTables & string]?: Record<string, RelationsBuilderEntry<TTables, TTableName>>; | ||
}; | ||
export type RelationsBuilderEntry<TTables extends Record<string, Table> = Record<string, Table>, TSourceTableName extends string = string> = Relation<TTables[TSourceTableName]['_']['name'], TTables[keyof TTables & string]['_']['name']> | AggregatedField<any>; | ||
export type ExtractTablesFromSchema<TSchema extends Record<string, unknown>> = { | ||
[K in keyof TSchema as TSchema[K] extends Table ? K : never]: TSchema[K] extends Table ? TSchema[K] : never; | ||
}; | ||
export declare function createRelationsHelper<TSchema extends Record<string, unknown>, TTables extends Record<string, Table>>(schema: TSchema): RelationsBuilder<TTables>; | ||
export declare function defineRelations<TSchema extends Record<string, unknown>, TConfig extends RelationsBuilderConfig<TTables>, TTables extends Record<string, Table> = ExtractTablesFromSchema<TSchema>>(schema: TSchema, relations: (helpers: RelationsBuilder<TTables>) => TConfig): Relations<TSchema, TTables, TConfig>; | ||
export type WithContainer<TRelatedTables extends Record<string, Table>> = { | ||
with?: { | ||
[K in keyof TRelatedTables]?: boolean | DBQueryConfig; | ||
}; | ||
}; | ||
export type ColumnWithTSName = { | ||
column: Column; | ||
tsName: string; | ||
}; | ||
export type RelationsOrder<TColumns extends Record<string, Column>> = { | ||
[K in keyof TColumns]?: 'asc' | 'desc'; | ||
}; | ||
export type OrderBy = ValueOrArray<AnyColumn | SQL> | ((fields: Record<string, Column>, operators: OrderByOperators) => ValueOrArray<AnyColumn | SQL>); | ||
export type Extras = Record<string, SQL> | ((fields: Record<string, Column>, operators: SQLOperator) => Record<string, SQL>); | ||
export declare function relationFilterToSQL(table: Table, filter: RelationsFilter<Record<string, Column>>): SQL | undefined; | ||
export declare function relationsOrderToSQL(table: Table, orders: ValueOrArray<AnyColumn | SQL> | ((fields: Record<string, Column>, operators: OrderByOperators) => ValueOrArray<AnyColumn | SQL>)): SQL | undefined; | ||
export declare function relationExtrasToSQL(table: Table, extras: Record<string, SQLWrapper> | ((columns: Record<string, Column>, operators: SQLOperator) => Record<string, SQLWrapper>)): { | ||
sql: SQL<unknown> | undefined; | ||
selection: { | ||
dbKey: string; | ||
tsKey: string; | ||
field: TColumn | SQL | SQL.Aliased; | ||
relationTableTsKey: string | undefined; | ||
isJson: boolean; | ||
isExtra?: boolean; | ||
selection: BuildRelationalQueryResult<TTable>['selection']; | ||
key: string; | ||
field: Column | Table | SQL | SQL.Aliased | SQLWrapper | AggregatedField; | ||
isArray?: boolean; | ||
selection?: BuildRelationalQueryResult["selection"]; | ||
}[]; | ||
sql: TTable | SQL; | ||
} | ||
export declare function mapRelationalRow(tablesConfig: TablesRelationalConfig, tableConfig: TableRelationalConfig, row: unknown[], buildQueryResultSelection: BuildRelationalQueryResult['selection'], mapColumnValue?: (value: unknown) => unknown): Record<string, unknown>; | ||
}; | ||
export declare function relationToSQL(relation: Relation): SQL | undefined; | ||
export {}; |
693
relations.js
import { getTableUniqueName, Table } from "./table.js"; | ||
import { Columns, getTableName } from "./table.js"; | ||
import { Column } from "./column.js"; | ||
@@ -31,273 +32,485 @@ import { entityKind, is } from "./entity.js"; | ||
import { SQL, sql } from "./sql/sql.js"; | ||
import { getTableColumns } from "./utils.js"; | ||
class Relations { | ||
constructor(schema, tables, config) { | ||
this.schema = schema; | ||
this.tables = tables; | ||
this.config = config; | ||
for (const [tsName, table] of Object.entries(tables)) { | ||
this.tableNamesMap[getTableUniqueName(table)] = tsName; | ||
const tableConfig = this.tablesConfig[tsName] = { | ||
table, | ||
tsName, | ||
dbName: table[Table.Symbol.Name], | ||
schema: table[Table.Symbol.Schema], | ||
columns: table[Table.Symbol.Columns], | ||
relations: config[tsName] || {}, | ||
primaryKey: [] | ||
}; | ||
for (const column of Object.values(table[Table.Symbol.Columns])) { | ||
if (column.primary) { | ||
tableConfig.primaryKey.push(column); | ||
} | ||
} | ||
const extraConfig = table[Table.Symbol.ExtraConfigBuilder]?.(table); | ||
if (extraConfig) { | ||
for (const configEntry of Object.values(extraConfig)) { | ||
if (is(configEntry, PrimaryKeyBuilder)) { | ||
tableConfig.primaryKey.push(...configEntry.columns); | ||
} | ||
} | ||
} | ||
} | ||
for (const tableConfig of Object.values(this.tablesConfig)) { | ||
for (const [relationFieldName, relation] of Object.entries(tableConfig.relations)) { | ||
if (!is(relation, Relation)) { | ||
continue; | ||
} | ||
relation.sourceTable = tableConfig.table; | ||
relation.fieldName = relationFieldName; | ||
} | ||
} | ||
for (const tableConfig of Object.values(this.tablesConfig)) { | ||
for (const [relationFieldName, relation] of Object.entries(tableConfig.relations)) { | ||
const relationPrintName = `relations -> ${tableConfig.tsName}.${relationFieldName}`; | ||
if (!is(relation, Relation)) { | ||
continue; | ||
} | ||
if (typeof relation.alias === "string" && !relation.alias) { | ||
throw new Error(`${relationPrintName}: "alias" cannot be an empty string - omit it if you don't need it`); | ||
} | ||
if (relation.sourceColumns?.length === 0) { | ||
throw new Error(`${relationPrintName}: "from" cannot be an empty array`); | ||
} | ||
if (relation.targetColumns?.length === 0) { | ||
throw new Error(`${relationPrintName}: "to" cannot be an empty array`); | ||
} | ||
if (relation.sourceColumns && relation.targetColumns) { | ||
if (relation.sourceColumns.length !== relation.targetColumns.length) { | ||
throw new Error( | ||
`${relationPrintName}: "from" and "to" arrays must have the same length` | ||
); | ||
} | ||
continue; | ||
} | ||
if (relation.sourceColumns || relation.targetColumns) { | ||
throw new Error( | ||
`${relationPrintName}: relation must have either both "from" and "to" defined, or none of them` | ||
); | ||
} | ||
let reverseRelation; | ||
const targetTableTsName = this.tableNamesMap[getTableUniqueName(relation.targetTable)]; | ||
if (!targetTableTsName) { | ||
throw new Error( | ||
`Table "${getTableUniqueName(relation.targetTable)}" not found in provided TS schema` | ||
); | ||
} | ||
const reverseTableConfig = this.tablesConfig[targetTableTsName]; | ||
if (!reverseTableConfig) { | ||
throw new Error( | ||
`${relationPrintName}: not enough data provided to build the relation - "from"/"to" are not defined, and no reverse relations of table "${targetTableTsName}" were found"` | ||
); | ||
} | ||
if (relation.alias) { | ||
const reverseRelations = Object.values(reverseTableConfig.relations).filter( | ||
(it) => is(it, Relation) && it.alias === relation.alias | ||
); | ||
if (reverseRelations.length > 1) { | ||
throw new Error( | ||
`${relationPrintName}: not enough data provided to build the relation - "from"/"to" are not defined, and multiple relations with alias "${relation.alias}" found in table "${targetTableTsName}": ${reverseRelations.map((it) => `"${it.fieldName}"`).join(", ")}` | ||
); | ||
} | ||
reverseRelation = reverseRelations[0]; | ||
if (!reverseRelation) { | ||
throw new Error( | ||
`${relationPrintName}: not enough data provided to build the relation - "from"/"to" are not defined, and there is no reverse relation of table "${targetTableTsName}" with alias "${relation.alias}"` | ||
); | ||
} | ||
} else { | ||
const reverseRelations = Object.values(reverseTableConfig.relations).filter( | ||
(it) => is(it, Relation) && it.targetTable === relation.sourceTable && !it.alias | ||
); | ||
if (reverseRelations.length > 1) { | ||
throw new Error( | ||
`${relationPrintName}: not enough data provided to build the relation - "from"/"to" are not defined, and multiple relations between "${targetTableTsName}" and "${getTableUniqueName(relation.sourceTable)}" were found. | ||
Hint: you can specify "alias" on both sides of the relation with the same value` | ||
); | ||
} | ||
reverseRelation = reverseRelations[0]; | ||
if (!reverseRelation) { | ||
throw new Error( | ||
`${relationPrintName}: not enough data provided to build the relation - "from"/"to" are not defined, and no reverse relation of table "${targetTableTsName}" with target table "${getTableUniqueName(relation.sourceTable)}" was found` | ||
); | ||
} | ||
} | ||
if (!reverseRelation.sourceColumns || !reverseRelation.targetColumns) { | ||
throw new Error( | ||
`${relationPrintName}: not enough data provided to build the relation - "from"/"to" are not defined, and reverse relation "${targetTableTsName}.${reverseRelation.fieldName}" does not have "from"/"to" defined` | ||
); | ||
} | ||
relation.sourceColumns = reverseRelation.targetColumns; | ||
relation.targetColumns = reverseRelation.sourceColumns; | ||
relation.where = reverseRelation.where; | ||
} | ||
} | ||
} | ||
static [entityKind] = "RelationsV2"; | ||
/** table DB name -> schema table key */ | ||
tableNamesMap = {}; | ||
tablesConfig = {}; | ||
} | ||
class Relation { | ||
constructor(sourceTable, referencedTable, relationName) { | ||
this.sourceTable = sourceTable; | ||
this.referencedTable = referencedTable; | ||
this.relationName = relationName; | ||
this.referencedTableName = referencedTable[Table.Symbol.Name]; | ||
constructor(targetTable) { | ||
this.targetTable = targetTable; | ||
} | ||
static [entityKind] = "Relation"; | ||
referencedTableName; | ||
fieldName; | ||
sourceColumns; | ||
targetColumns; | ||
alias; | ||
where; | ||
sourceTable; | ||
} | ||
class Relations { | ||
constructor(table, config) { | ||
this.table = table; | ||
this.config = config; | ||
} | ||
static [entityKind] = "Relations"; | ||
} | ||
class One extends Relation { | ||
constructor(sourceTable, referencedTable, config, isNullable) { | ||
super(sourceTable, referencedTable, config?.relationName); | ||
this.config = config; | ||
this.isNullable = isNullable; | ||
} | ||
static [entityKind] = "One"; | ||
withFieldName(fieldName) { | ||
const relation = new One( | ||
this.sourceTable, | ||
this.referencedTable, | ||
this.config, | ||
this.isNullable | ||
); | ||
relation.fieldName = fieldName; | ||
return relation; | ||
optional; | ||
constructor(targetTable, config) { | ||
super(targetTable); | ||
this.alias = config?.alias; | ||
this.where = config?.where; | ||
if (config?.from) { | ||
this.sourceColumns = Array.isArray(config.from) ? config.from.map((it) => it._.column) : [config.from._.column]; | ||
} | ||
if (config?.to) { | ||
this.targetColumns = Array.isArray(config.to) ? config.to.map((it) => it._.column) : [config.to._.column]; | ||
} | ||
this.optional = config?.optional ?? false; | ||
} | ||
} | ||
class Many extends Relation { | ||
constructor(sourceTable, referencedTable, config) { | ||
super(sourceTable, referencedTable, config?.relationName); | ||
constructor(targetTable, config) { | ||
super(targetTable); | ||
this.config = config; | ||
this.alias = config?.alias; | ||
this.where = config?.where; | ||
if (config?.from) { | ||
this.sourceColumns = Array.isArray(config.from) ? config.from.map((it) => it._.column) : [config.from._.column]; | ||
} | ||
if (config?.to) { | ||
this.targetColumns = Array.isArray(config.to) ? config.to.map((it) => it._.column) : [config.to._.column]; | ||
} | ||
} | ||
static [entityKind] = "Many"; | ||
withFieldName(fieldName) { | ||
const relation = new Many( | ||
this.sourceTable, | ||
this.referencedTable, | ||
this.config | ||
); | ||
relation.fieldName = fieldName; | ||
return relation; | ||
} | ||
class AggregatedField { | ||
static [entityKind] = "AggregatedField"; | ||
table; | ||
onTable(table) { | ||
this.table = table; | ||
return this; | ||
} | ||
} | ||
function getOperators() { | ||
return { | ||
and, | ||
between, | ||
eq, | ||
exists, | ||
gt, | ||
gte, | ||
ilike, | ||
inArray, | ||
isNull, | ||
isNotNull, | ||
like, | ||
lt, | ||
lte, | ||
ne, | ||
not, | ||
notBetween, | ||
notExists, | ||
notLike, | ||
notIlike, | ||
notInArray, | ||
or, | ||
sql | ||
}; | ||
class Count extends AggregatedField { | ||
static [entityKind] = "AggregatedFieldCount"; | ||
query; | ||
getSQL() { | ||
if (!this.query) { | ||
if (!this.table) | ||
throw new Error("Table must be set before building aggregate field"); | ||
this.query = sql`select count(*) as ${sql.identifier("r")} from ${this.table}`.mapWith(Number); | ||
} | ||
return this.query; | ||
} | ||
} | ||
const operators = { | ||
and, | ||
between, | ||
eq, | ||
exists, | ||
gt, | ||
gte, | ||
ilike, | ||
inArray, | ||
isNull, | ||
isNotNull, | ||
like, | ||
lt, | ||
lte, | ||
ne, | ||
not, | ||
notBetween, | ||
notExists, | ||
notLike, | ||
notIlike, | ||
notInArray, | ||
or, | ||
sql | ||
}; | ||
const orderByOperators = { | ||
sql, | ||
asc, | ||
desc | ||
}; | ||
function getOrderByOperators() { | ||
return { | ||
sql, | ||
asc, | ||
desc | ||
}; | ||
return orderByOperators; | ||
} | ||
function extractTablesRelationalConfig(schema, configHelpers) { | ||
if (Object.keys(schema).length === 1 && "default" in schema && !is(schema["default"], Table)) { | ||
schema = schema["default"]; | ||
} | ||
const tableNamesMap = {}; | ||
const relationsBuffer = {}; | ||
const tablesConfig = {}; | ||
for (const [key, value] of Object.entries(schema)) { | ||
if (is(value, Table)) { | ||
const dbName = getTableUniqueName(value); | ||
const bufferedRelations = relationsBuffer[dbName]; | ||
tableNamesMap[dbName] = key; | ||
tablesConfig[key] = { | ||
tsName: key, | ||
dbName: value[Table.Symbol.Name], | ||
schema: value[Table.Symbol.Schema], | ||
columns: value[Table.Symbol.Columns], | ||
relations: bufferedRelations?.relations ?? {}, | ||
primaryKey: bufferedRelations?.primaryKey ?? [] | ||
}; | ||
for (const column of Object.values( | ||
value[Table.Symbol.Columns] | ||
)) { | ||
if (column.primary) { | ||
tablesConfig[key].primaryKey.push(column); | ||
function mapRelationalRow(row, buildQueryResultSelection, mapColumnValue = (value) => value, parseJson = false) { | ||
for (const selectionItem of buildQueryResultSelection) { | ||
const field = selectionItem.field; | ||
if (is(field, Table)) { | ||
if (row[selectionItem.key] === null) | ||
continue; | ||
if (parseJson) | ||
row[selectionItem.key] = JSON.parse(row[selectionItem.key]); | ||
if (selectionItem.isArray) { | ||
for (const item of row[selectionItem.key]) { | ||
mapRelationalRow(item, selectionItem.selection, mapColumnValue); | ||
} | ||
continue; | ||
} | ||
const extraConfig = value[Table.Symbol.ExtraConfigBuilder]?.(value[Table.Symbol.ExtraConfigColumns]); | ||
if (extraConfig) { | ||
for (const configEntry of Object.values(extraConfig)) { | ||
if (is(configEntry, PrimaryKeyBuilder)) { | ||
tablesConfig[key].primaryKey.push(...configEntry.columns); | ||
} | ||
} | ||
} | ||
} else if (is(value, Relations)) { | ||
const dbName = getTableUniqueName(value.table); | ||
const tableName = tableNamesMap[dbName]; | ||
const relations2 = value.config( | ||
configHelpers(value.table) | ||
mapRelationalRow( | ||
row[selectionItem.key], | ||
selectionItem.selection, | ||
mapColumnValue | ||
); | ||
let primaryKey; | ||
for (const [relationName, relation] of Object.entries(relations2)) { | ||
if (tableName) { | ||
const tableConfig = tablesConfig[tableName]; | ||
tableConfig.relations[relationName] = relation; | ||
if (primaryKey) { | ||
tableConfig.primaryKey.push(...primaryKey); | ||
} | ||
} else { | ||
if (!(dbName in relationsBuffer)) { | ||
relationsBuffer[dbName] = { | ||
relations: {}, | ||
primaryKey | ||
}; | ||
} | ||
relationsBuffer[dbName].relations[relationName] = relation; | ||
} | ||
} | ||
continue; | ||
} | ||
const value = mapColumnValue(row[selectionItem.key]); | ||
if (value === null) | ||
continue; | ||
let decoder; | ||
if (is(field, Column)) { | ||
decoder = field; | ||
} else if (is(field, SQL)) { | ||
decoder = field.decoder; | ||
} else if (is(field, SQL.Aliased)) { | ||
decoder = field.sql.decoder; | ||
} else { | ||
decoder = field.getSQL().decoder; | ||
} | ||
row[selectionItem.key] = decoder.mapFromDriverValue(value); | ||
} | ||
return { tables: tablesConfig, tableNamesMap }; | ||
return row; | ||
} | ||
function relations(table, relations2) { | ||
return new Relations( | ||
table, | ||
(helpers) => Object.fromEntries( | ||
Object.entries(relations2(helpers)).map(([key, value]) => [ | ||
key, | ||
value.withFieldName(key) | ||
]) | ||
) | ||
); | ||
} | ||
function createOne(sourceTable) { | ||
return function one(table, config) { | ||
return new One( | ||
sourceTable, | ||
table, | ||
config, | ||
config?.fields.reduce((res, f) => res && f.notNull, true) ?? false | ||
); | ||
}; | ||
} | ||
function createMany(sourceTable) { | ||
return function many(referencedTable, config) { | ||
return new Many(sourceTable, referencedTable, config); | ||
}; | ||
} | ||
function normalizeRelation(schema, tableNamesMap, relation) { | ||
if (is(relation, One) && relation.config) { | ||
return { | ||
fields: relation.config.fields, | ||
references: relation.config.references | ||
class RelationsBuilderTable { | ||
static [entityKind] = "RelationsBuilderTable"; | ||
_; | ||
constructor(table) { | ||
this._ = { | ||
name: getTableName(table), | ||
table | ||
}; | ||
} | ||
const referencedTableTsName = tableNamesMap[getTableUniqueName(relation.referencedTable)]; | ||
if (!referencedTableTsName) { | ||
throw new Error( | ||
`Table "${relation.referencedTable[Table.Symbol.Name]}" not found in schema` | ||
); | ||
getSQL() { | ||
return this._.table.getSQL(); | ||
} | ||
const referencedTableConfig = schema[referencedTableTsName]; | ||
if (!referencedTableConfig) { | ||
throw new Error(`Table "${referencedTableTsName}" not found in schema`); | ||
} | ||
class RelationsBuilderColumn { | ||
static [entityKind] = "RelationsBuilderColumn"; | ||
_; | ||
constructor(column) { | ||
this._ = { | ||
tableName: getTableName(column.table), | ||
data: void 0, | ||
column | ||
}; | ||
} | ||
const sourceTable = relation.sourceTable; | ||
const sourceTableTsName = tableNamesMap[getTableUniqueName(sourceTable)]; | ||
if (!sourceTableTsName) { | ||
throw new Error( | ||
`Table "${sourceTable[Table.Symbol.Name]}" not found in schema` | ||
); | ||
through(column) { | ||
this._.through = column; | ||
return this; | ||
} | ||
const reverseRelations = []; | ||
for (const referencedTableRelation of Object.values( | ||
referencedTableConfig.relations | ||
)) { | ||
if (relation.relationName && relation !== referencedTableRelation && referencedTableRelation.relationName === relation.relationName || !relation.relationName && referencedTableRelation.referencedTable === relation.sourceTable) { | ||
reverseRelations.push(referencedTableRelation); | ||
} | ||
getSQL() { | ||
return this._.column.getSQL(); | ||
} | ||
if (reverseRelations.length > 1) { | ||
throw relation.relationName ? new Error( | ||
`There are multiple relations with name "${relation.relationName}" in table "${referencedTableTsName}"` | ||
) : new Error( | ||
`There are multiple relations between "${referencedTableTsName}" and "${relation.sourceTable[Table.Symbol.Name]}". Please specify relation name` | ||
); | ||
} | ||
if (reverseRelations[0] && is(reverseRelations[0], One) && reverseRelations[0].config) { | ||
return { | ||
fields: reverseRelations[0].config.references, | ||
references: reverseRelations[0].config.fields | ||
} | ||
class RelationsHelperStatic { | ||
static [entityKind] = "RelationsHelperStatic"; | ||
_; | ||
constructor(tables) { | ||
this._ = { | ||
tables | ||
}; | ||
const one = {}; | ||
const many = {}; | ||
for (const [tableName, table] of Object.entries(tables)) { | ||
one[tableName] = (config) => { | ||
return new One(table, config); | ||
}; | ||
many[tableName] = (config) => { | ||
return new Many(table, config); | ||
}; | ||
} | ||
this.one = one; | ||
this.many = many; | ||
} | ||
throw new Error( | ||
`There is not enough information to infer relation "${sourceTableTsName}.${relation.fieldName}"` | ||
one; | ||
many; | ||
aggs = { | ||
count() { | ||
return new Count(); | ||
} | ||
}; | ||
} | ||
function createRelationsHelper(schema) { | ||
const schemaTables = Object.fromEntries( | ||
Object.entries(schema).filter((e) => is(e[1], Table)) | ||
); | ||
const helperStatic = new RelationsHelperStatic(schemaTables); | ||
const tables = Object.entries(schema).reduce((acc, [key, value]) => { | ||
if (is(value, Table)) { | ||
const rTable = new RelationsBuilderTable(value); | ||
const columns = Object.entries(getTableColumns(value)).reduce( | ||
(acc2, [key2, column]) => { | ||
const rbColumn = new RelationsBuilderColumn(column); | ||
acc2[key2] = rbColumn; | ||
return acc2; | ||
}, | ||
{} | ||
); | ||
acc[key] = Object.assign(rTable, columns); | ||
} | ||
return acc; | ||
}, {}); | ||
return Object.assign(helperStatic, tables); | ||
} | ||
function createTableRelationsHelpers(sourceTable) { | ||
return { | ||
one: createOne(sourceTable), | ||
many: createMany(sourceTable) | ||
}; | ||
function defineRelations(schema, relations) { | ||
return new Relations( | ||
schema, | ||
schema, | ||
relations(createRelationsHelper(schema)) | ||
); | ||
} | ||
function mapRelationalRow(tablesConfig, tableConfig, row, buildQueryResultSelection, mapColumnValue = (value) => value) { | ||
const result = {}; | ||
for (const [ | ||
selectionItemIndex, | ||
selectionItem | ||
] of buildQueryResultSelection.entries()) { | ||
if (selectionItem.isJson) { | ||
const relation = tableConfig.relations[selectionItem.tsKey]; | ||
const rawSubRows = row[selectionItemIndex]; | ||
const subRows = typeof rawSubRows === "string" ? JSON.parse(rawSubRows) : rawSubRows; | ||
result[selectionItem.tsKey] = is(relation, One) ? subRows && mapRelationalRow( | ||
tablesConfig, | ||
tablesConfig[selectionItem.relationTableTsKey], | ||
subRows, | ||
selectionItem.selection, | ||
mapColumnValue | ||
) : subRows.map( | ||
(subRow) => mapRelationalRow( | ||
tablesConfig, | ||
tablesConfig[selectionItem.relationTableTsKey], | ||
subRow, | ||
selectionItem.selection, | ||
mapColumnValue | ||
) | ||
); | ||
} else { | ||
const value = mapColumnValue(row[selectionItemIndex]); | ||
const field = selectionItem.field; | ||
let decoder; | ||
if (is(field, Column)) { | ||
decoder = field; | ||
} else if (is(field, SQL)) { | ||
decoder = field.decoder; | ||
} else { | ||
decoder = field.sql.decoder; | ||
function relationsFieldFilterToSQL(column, filter) { | ||
if (typeof filter !== "object") | ||
return eq(column, filter); | ||
const entries = Object.entries(filter); | ||
if (!entries.length) | ||
return void 0; | ||
const parts = []; | ||
for (const [target, value] of entries) { | ||
if (value === void 0) | ||
continue; | ||
switch (target) { | ||
case "$not": { | ||
const res = relationsFieldFilterToSQL(column, value); | ||
if (!res) | ||
continue; | ||
parts.push(not(res)); | ||
continue; | ||
} | ||
result[selectionItem.tsKey] = value === null ? null : decoder.mapFromDriverValue(value); | ||
case "$or": { | ||
if (!value.length) | ||
continue; | ||
parts.push( | ||
or( | ||
...value.map((subFilter) => relationsFieldFilterToSQL(column, subFilter)) | ||
) | ||
); | ||
continue; | ||
} | ||
default: { | ||
parts.push( | ||
operators[target]( | ||
column, | ||
value | ||
) | ||
); | ||
continue; | ||
} | ||
} | ||
} | ||
return result; | ||
if (!parts.length) | ||
return void 0; | ||
return and(...parts); | ||
} | ||
function relationFilterToSQL(table, filter) { | ||
const entries = Object.entries(filter); | ||
if (!entries.length) | ||
return void 0; | ||
const parts = []; | ||
for (const [target, value] of entries) { | ||
if (value === void 0) | ||
continue; | ||
switch (target) { | ||
case "$raw": { | ||
if (value) | ||
parts.push(value(operators)); | ||
continue; | ||
} | ||
case "$or": { | ||
if (!value?.length) | ||
continue; | ||
parts.push( | ||
or( | ||
...value.map( | ||
(subFilter) => relationFilterToSQL(table, subFilter) | ||
) | ||
) | ||
); | ||
continue; | ||
} | ||
case "$not": { | ||
if (!value?.length) | ||
continue; | ||
parts.push( | ||
not( | ||
and( | ||
...value.map( | ||
(subFilter) => relationFilterToSQL(table, subFilter) | ||
) | ||
) | ||
) | ||
); | ||
continue; | ||
} | ||
default: { | ||
const colFilter = relationsFieldFilterToSQL( | ||
table[target], | ||
value | ||
); | ||
if (colFilter) | ||
parts.push(colFilter); | ||
continue; | ||
} | ||
} | ||
} | ||
return and(...parts); | ||
} | ||
function relationsOrderToSQL(table, orders) { | ||
const data = typeof orders === "function" ? orders(table[Columns], orderByOperators) : orders; | ||
return is(data, SQL) ? data : Array.isArray(data) ? data.length ? sql.join(data.map((o) => is(o, SQL) ? o : asc(o)), sql`, `) : void 0 : asc(data); | ||
} | ||
function relationExtrasToSQL(table, extras) { | ||
const subqueries = []; | ||
const selection = []; | ||
for (const [key, extra] of Object.entries( | ||
typeof extras === "function" ? extras(table[Columns], { sql: operators.sql }) : extras | ||
)) { | ||
if (!extra) | ||
continue; | ||
const query = sql`(${extra.getSQL()}) as ${sql.identifier(key)}`; | ||
query.decoder = extra.getSQL().decoder; | ||
subqueries.push(query); | ||
selection.push({ | ||
key, | ||
field: query | ||
}); | ||
} | ||
return { | ||
sql: subqueries.length ? sql.join(subqueries, sql`, `) : void 0, | ||
selection | ||
}; | ||
} | ||
function relationToSQL(relation) { | ||
const table = relation.sourceTable; | ||
const columnWhere = relation.sourceColumns.map((s, i) => { | ||
const t = relation.targetColumns[i]; | ||
return eq(s, t); | ||
}); | ||
const targetWhere = relation.where ? and(...columnWhere, relationFilterToSQL(table, relation.where)) : and(...columnWhere); | ||
return targetWhere; | ||
} | ||
export { | ||
AggregatedField, | ||
Count, | ||
Many, | ||
@@ -307,12 +520,16 @@ One, | ||
Relations, | ||
createMany, | ||
createOne, | ||
createTableRelationsHelpers, | ||
extractTablesRelationalConfig, | ||
getOperators, | ||
RelationsBuilderColumn, | ||
RelationsBuilderTable, | ||
RelationsHelperStatic, | ||
createRelationsHelper, | ||
defineRelations, | ||
getOrderByOperators, | ||
mapRelationalRow, | ||
normalizeRelation, | ||
relations | ||
operators, | ||
orderByOperators, | ||
relationExtrasToSQL, | ||
relationFilterToSQL, | ||
relationToSQL, | ||
relationsOrderToSQL | ||
}; | ||
//# sourceMappingURL=relations.js.map |
import type { Database } from 'sql.js'; | ||
import type { AnyRelations, EmptyRelations } from "../relations.js"; | ||
import { BaseSQLiteDatabase } from "../sqlite-core/db.js"; | ||
import type { DrizzleConfig } from "../utils.js"; | ||
export type SQLJsDatabase<TSchema extends Record<string, unknown> = Record<string, never>> = BaseSQLiteDatabase<'sync', void, TSchema>; | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(client: Database, config?: DrizzleConfig<TSchema>): SQLJsDatabase<TSchema>; | ||
export type SQLJsDatabase<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations> = BaseSQLiteDatabase<'sync', void, TSchema, TRelations>; | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations>(client: Database, config?: DrizzleConfig<TSchema>): SQLJsDatabase<TSchema, TRelations>; |
@@ -0,6 +1,3 @@ | ||
import * as V1 from "../_relations.js"; | ||
import { DefaultLogger } from "../logger.js"; | ||
import { | ||
createTableRelationsHelpers, | ||
extractTablesRelationalConfig | ||
} from "../relations.js"; | ||
import { BaseSQLiteDatabase } from "../sqlite-core/db.js"; | ||
@@ -19,5 +16,5 @@ import { SQLiteSyncDialect } from "../sqlite-core/dialect.js"; | ||
if (config.schema) { | ||
const tablesConfig = extractTablesRelationalConfig( | ||
const tablesConfig = V1.extractTablesRelationalConfig( | ||
config.schema, | ||
createTableRelationsHelpers | ||
V1.createTableRelationsHelpers | ||
); | ||
@@ -30,4 +27,5 @@ schema = { | ||
} | ||
const session = new SQLJsSession(client, dialect, schema, { logger }); | ||
return new BaseSQLiteDatabase("sync", dialect, session, schema); | ||
const relations = config.relations; | ||
const session = new SQLJsSession(client, dialect, relations, schema, { logger }); | ||
return new BaseSQLiteDatabase("sync", dialect, session, relations, schema); | ||
} | ||
@@ -34,0 +32,0 @@ export { |
import type { MigrationConfig } from "../migrator.js"; | ||
import type { AnyRelations, EmptyRelations } from "../relations.js"; | ||
import type { SQLJsDatabase } from "./driver.js"; | ||
export declare function migrate<TSchema extends Record<string, unknown>>(db: SQLJsDatabase<TSchema>, config: MigrationConfig): void; | ||
export declare function migrate<TSchema extends Record<string, unknown>, TRelations extends AnyRelations = EmptyRelations>(db: SQLJsDatabase<TSchema, TRelations>, config: MigrationConfig): void; |
import type { Database, Statement } from 'sql.js'; | ||
import type * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
import type { Logger } from "../logger.js"; | ||
import type { RelationalSchemaConfig, TablesRelationalConfig } from "../relations.js"; | ||
import type { AnyRelations, TablesRelationalConfig } from "../relations.js"; | ||
import { type Query } from "../sql/sql.js"; | ||
@@ -15,17 +16,19 @@ import type { SQLiteSyncDialect } from "../sqlite-core/dialect.js"; | ||
type PreparedQueryConfig = Omit<PreparedQueryConfigBase, 'statement' | 'run'>; | ||
export declare class SQLJsSession<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends SQLiteSession<'sync', void, TFullSchema, TSchema> { | ||
export declare class SQLJsSession<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends SQLiteSession<'sync', void, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
private client; | ||
private relations; | ||
private schema; | ||
static readonly [entityKind]: string; | ||
private logger; | ||
constructor(client: Database, dialect: SQLiteSyncDialect, schema: RelationalSchemaConfig<TSchema> | undefined, options?: SQLJsSessionOptions); | ||
constructor(client: Database, dialect: SQLiteSyncDialect, relations: AnyRelations | undefined, schema: V1.RelationalSchemaConfig<TSchema> | undefined, options?: SQLJsSessionOptions); | ||
prepareQuery<T extends Omit<PreparedQueryConfig, 'run'>>(query: Query, fields: SelectedFieldsOrdered | undefined, executeMethod: SQLiteExecuteMethod, isResponseInArrayMode: boolean): PreparedQuery<T>; | ||
prepareOneTimeQuery<T extends Omit<PreparedQueryConfig, 'run'>>(query: Query, fields: SelectedFieldsOrdered | undefined, executeMethod: SQLiteExecuteMethod, isResponseInArrayMode: boolean, customResultMapper?: (rows: unknown[][]) => unknown): PreparedQuery<T>; | ||
transaction<T>(transaction: (tx: SQLJsTransaction<TFullSchema, TSchema>) => T, config?: SQLiteTransactionConfig): T; | ||
prepareRelationalQuery<T extends Omit<PreparedQueryConfig, 'run'>>(query: Query, fields: SelectedFieldsOrdered | undefined, executeMethod: SQLiteExecuteMethod, customResultMapper: (rows: Record<string, unknown>[]) => unknown): PreparedQuery<T, true>; | ||
transaction<T>(transaction: (tx: SQLJsTransaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => T, config?: SQLiteTransactionConfig): T; | ||
} | ||
export declare class SQLJsTransaction<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends SQLiteTransaction<'sync', void, TFullSchema, TSchema> { | ||
export declare class SQLJsTransaction<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends SQLiteTransaction<'sync', void, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
static readonly [entityKind]: string; | ||
transaction<T>(transaction: (tx: SQLJsTransaction<TFullSchema, TSchema>) => T): T; | ||
transaction<T>(transaction: (tx: SQLJsTransaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => T): T; | ||
} | ||
export declare class PreparedQuery<T extends PreparedQueryConfig = PreparedQueryConfig> extends PreparedQueryBase<{ | ||
export declare class PreparedQuery<T extends PreparedQueryConfig = PreparedQueryConfig, TIsRqbV2 extends boolean = false> extends PreparedQueryBase<{ | ||
type: 'sync'; | ||
@@ -44,7 +47,10 @@ run: void; | ||
private isOneTimeQuery; | ||
private isRqbV2Query?; | ||
static readonly [entityKind]: string; | ||
constructor(stmt: Statement, query: Query, logger: Logger, fields: SelectedFieldsOrdered | undefined, executeMethod: SQLiteExecuteMethod, _isResponseInArrayMode: boolean, customResultMapper?: ((rows: unknown[][], mapColumnValue?: (value: unknown) => unknown) => unknown) | undefined, isOneTimeQuery?: boolean); | ||
constructor(stmt: Statement, query: Query, logger: Logger, fields: SelectedFieldsOrdered | undefined, executeMethod: SQLiteExecuteMethod, _isResponseInArrayMode: boolean, customResultMapper?: ((rows: TIsRqbV2 extends true ? Record<string, unknown>[] : unknown[][], mapColumnValue?: (value: unknown) => unknown) => unknown) | undefined, isOneTimeQuery?: boolean, isRqbV2Query?: TIsRqbV2 | undefined); | ||
run(placeholderValues?: Record<string, unknown>): void; | ||
all(placeholderValues?: Record<string, unknown>): T['all']; | ||
private allRqbV2; | ||
get(placeholderValues?: Record<string, unknown>): T['get']; | ||
private getRqbV2; | ||
values(placeholderValues?: Record<string, unknown>): T['values']; | ||
@@ -51,0 +57,0 @@ free(): boolean; |
@@ -8,5 +8,6 @@ import { entityKind } from "../entity.js"; | ||
class SQLJsSession extends SQLiteSession { | ||
constructor(client, dialect, schema, options = {}) { | ||
constructor(client, dialect, relations, schema, options = {}) { | ||
super(dialect); | ||
this.client = client; | ||
this.relations = relations; | ||
this.schema = schema; | ||
@@ -34,4 +35,18 @@ this.logger = options.logger ?? new NoopLogger(); | ||
} | ||
prepareRelationalQuery(query, fields, executeMethod, customResultMapper) { | ||
const stmt = this.client.prepare(query.sql); | ||
return new PreparedQuery( | ||
stmt, | ||
query, | ||
this.logger, | ||
fields, | ||
executeMethod, | ||
false, | ||
customResultMapper, | ||
false, | ||
true | ||
); | ||
} | ||
transaction(transaction, config = {}) { | ||
const tx = new SQLJsTransaction("sync", this.dialect, this, this.schema); | ||
const tx = new SQLJsTransaction("sync", this.dialect, this, this.relations, this.schema); | ||
this.run(sql.raw(`begin${config.behavior ? ` ${config.behavior}` : ""}`)); | ||
@@ -52,3 +67,10 @@ try { | ||
const savepointName = `sp${this.nestedIndex + 1}`; | ||
const tx = new SQLJsTransaction("sync", this.dialect, this.session, this.schema, this.nestedIndex + 1); | ||
const tx = new SQLJsTransaction( | ||
"sync", | ||
this.dialect, | ||
this.session, | ||
this.relations, | ||
this.schema, | ||
this.nestedIndex + 1 | ||
); | ||
tx.run(sql.raw(`savepoint ${savepointName}`)); | ||
@@ -66,3 +88,3 @@ try { | ||
class PreparedQuery extends PreparedQueryBase { | ||
constructor(stmt, query, logger, fields, executeMethod, _isResponseInArrayMode, customResultMapper, isOneTimeQuery = false) { | ||
constructor(stmt, query, logger, fields, executeMethod, _isResponseInArrayMode, customResultMapper, isOneTimeQuery = false, isRqbV2Query) { | ||
super("sync", executeMethod, query); | ||
@@ -75,2 +97,3 @@ this.stmt = stmt; | ||
this.isOneTimeQuery = isOneTimeQuery; | ||
this.isRqbV2Query = isRqbV2Query; | ||
} | ||
@@ -88,2 +111,4 @@ static [entityKind] = "SQLJsPreparedQuery"; | ||
all(placeholderValues) { | ||
if (this.isRqbV2Query) | ||
return this.allRqbV2(placeholderValues); | ||
const { fields, joinsNotNullableMap, logger, query, stmt, isOneTimeQuery, customResultMapper } = this; | ||
@@ -109,3 +134,19 @@ if (!fields && !customResultMapper) { | ||
} | ||
allRqbV2(placeholderValues) { | ||
const { logger, query, stmt, isOneTimeQuery, customResultMapper } = this; | ||
const params = fillPlaceholders(query.params, placeholderValues ?? {}); | ||
logger.logQuery(query.sql, params); | ||
stmt.bind(params); | ||
const rows = []; | ||
while (stmt.step()) { | ||
rows.push(stmt.getAsObject()); | ||
} | ||
if (isOneTimeQuery) { | ||
this.free(); | ||
} | ||
return customResultMapper(rows, normalizeFieldValue); | ||
} | ||
get(placeholderValues) { | ||
if (this.isRqbV2Query) | ||
return this.getRqbV2(placeholderValues); | ||
const params = fillPlaceholders(this.query.params, placeholderValues ?? {}); | ||
@@ -133,2 +174,15 @@ this.logger.logQuery(this.query.sql, params); | ||
} | ||
getRqbV2(placeholderValues) { | ||
const params = fillPlaceholders(this.query.params, placeholderValues ?? {}); | ||
this.logger.logQuery(this.query.sql, params); | ||
const { stmt, isOneTimeQuery, customResultMapper } = this; | ||
const row = stmt.getAsObject(params); | ||
if (isOneTimeQuery) { | ||
this.free(); | ||
} | ||
if (!row) { | ||
return void 0; | ||
} | ||
return customResultMapper([row], normalizeFieldValue); | ||
} | ||
values(placeholderValues) { | ||
@@ -135,0 +189,0 @@ const params = fillPlaceholders(this.query.params, placeholderValues ?? {}); |
@@ -48,4 +48,4 @@ import type { CasingCache } from "../casing.js"; | ||
*/ | ||
export interface SQLWrapper { | ||
getSQL(): SQL; | ||
export interface SQLWrapper<T = unknown> { | ||
getSQL(): SQL<T>; | ||
shouldOmitSQLParens?(): boolean; | ||
@@ -60,3 +60,3 @@ } | ||
} | ||
export declare class SQL<T = unknown> implements SQLWrapper { | ||
export declare class SQL<T = unknown> implements SQLWrapper<T> { | ||
readonly queryChunks: SQLChunk[]; | ||
@@ -74,3 +74,3 @@ static readonly [entityKind]: string; | ||
private mapInlineParam; | ||
getSQL(): SQL; | ||
getSQL(): SQL<T>; | ||
as(alias: string): SQL.Aliased<T>; | ||
@@ -77,0 +77,0 @@ /** |
@@ -0,4 +1,5 @@ | ||
import type * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
import type { TypedQueryBuilder } from "../query-builders/query-builder.js"; | ||
import type { ExtractTablesWithRelations, RelationalSchemaConfig, TablesRelationalConfig } from "../relations.js"; | ||
import type { AnyRelations, EmptyRelations, ExtractTablesWithRelations, TablesRelationalConfig } from "../relations.js"; | ||
import { type ColumnsSelection, type SQL, type SQLWrapper } from "../sql/sql.js"; | ||
@@ -11,2 +12,3 @@ import type { SQLiteAsyncDialect, SQLiteSyncDialect } from "./dialect.js"; | ||
import type { DrizzleTypeError } from "../utils.js"; | ||
import { _RelationalQueryBuilder } from "./query-builders/_query.js"; | ||
import { SQLiteCountBuilder } from "./query-builders/count.js"; | ||
@@ -17,3 +19,3 @@ import { RelationalQueryBuilder } from "./query-builders/query.js"; | ||
import type { SQLiteViewBase } from "./view-base.js"; | ||
export declare class BaseSQLiteDatabase<TResultKind extends 'sync' | 'async', TRunResult, TFullSchema extends Record<string, unknown> = Record<string, never>, TSchema extends TablesRelationalConfig = ExtractTablesWithRelations<TFullSchema>> { | ||
export declare class BaseSQLiteDatabase<TResultKind extends 'sync' | 'async', TRunResult, TFullSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations, TTablesConfig extends TablesRelationalConfig = ExtractTablesWithRelations<TRelations>, TSchema extends V1.TablesRelationalConfig = V1.ExtractTablesWithRelations<TFullSchema>> { | ||
private resultKind; | ||
@@ -25,6 +27,11 @@ static readonly [entityKind]: string; | ||
readonly tableNamesMap: Record<string, string>; | ||
readonly relations: TRelations; | ||
}; | ||
query: TFullSchema extends Record<string, never> ? DrizzleTypeError<'Seems like the schema generic is missing - did you forget to add it to your DB type?'> : { | ||
[K in keyof TSchema]: RelationalQueryBuilder<TResultKind, TFullSchema, TSchema, TSchema[K]>; | ||
/** @deprecated */ | ||
_query: TFullSchema extends Record<string, never> ? DrizzleTypeError<'Seems like the schema generic is missing - did you forget to add it to your DB type?'> : { | ||
[K in keyof TSchema]: _RelationalQueryBuilder<TResultKind, TFullSchema, TSchema, TSchema[K]>; | ||
}; | ||
query: { | ||
[K in keyof TRelations['tables']]: RelationalQueryBuilder<TResultKind, TTablesConfig, TTablesConfig[K]>; | ||
}; | ||
constructor(resultKind: TResultKind, | ||
@@ -37,3 +44,3 @@ /** @internal */ | ||
/** @internal */ | ||
session: SQLiteSession<TResultKind, TRunResult, TFullSchema, TSchema>, schema: RelationalSchemaConfig<TSchema> | undefined); | ||
session: SQLiteSession<TResultKind, TRunResult, TFullSchema, TRelations, TTablesConfig, TSchema>, relations: AnyRelations | undefined, _schema: V1.RelationalSchemaConfig<TSchema> | undefined); | ||
/** | ||
@@ -74,3 +81,3 @@ * Creates a subquery that defines a temporary named result set as a CTE. | ||
}; | ||
$count(source: SQLiteTable | SQLiteViewBase | SQL | SQLWrapper, filters?: SQL<unknown>): SQLiteCountBuilder<SQLiteSession<TResultKind, TRunResult, TFullSchema, TSchema>>; | ||
$count(source: SQLiteTable | SQLiteViewBase | SQL | SQLWrapper, filters?: SQL<unknown>): SQLiteCountBuilder<SQLiteSession<TResultKind, TRunResult, TFullSchema, TRelations, TTablesConfig, TSchema>>; | ||
/** | ||
@@ -255,3 +262,3 @@ * Incorporates a previously defined CTE (using `$with`) into the main query. | ||
values<T extends unknown[] = unknown[]>(query: SQLWrapper | string): DBResult<TResultKind, T[]>; | ||
transaction<T>(transaction: (tx: SQLiteTransaction<TResultKind, TRunResult, TFullSchema, TSchema>) => Result<TResultKind, T>, config?: SQLiteTransactionConfig): Result<TResultKind, T>; | ||
transaction<T>(transaction: (tx: SQLiteTransaction<TResultKind, TRunResult, TFullSchema, TRelations, TTablesConfig, TSchema>) => Result<TResultKind, T>, config?: SQLiteTransactionConfig): Result<TResultKind, T>; | ||
} | ||
@@ -261,2 +268,2 @@ export type SQLiteWithReplicas<Q> = Q & { | ||
}; | ||
export declare const withReplicas: <TResultKind extends "sync" | "async", TRunResult, TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig, Q extends BaseSQLiteDatabase<TResultKind, TRunResult, TFullSchema, TSchema extends Record<string, unknown> ? ExtractTablesWithRelations<TFullSchema> : TSchema>>(primary: Q, replicas: [Q, ...Q[]], getReplica?: (replicas: Q[]) => Q) => SQLiteWithReplicas<Q>; | ||
export declare const withReplicas: <TResultKind extends "sync" | "async", TRunResult, TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig, Q extends BaseSQLiteDatabase<TResultKind, TRunResult, TFullSchema, TRelations, TTablesConfig, TSchema extends Record<string, unknown> ? V1.ExtractTablesWithRelations<TFullSchema> : TSchema>>(primary: Q, replicas: [Q, ...Q[]], getReplica?: (replicas: Q[]) => Q) => SQLiteWithReplicas<Q>; |
@@ -12,2 +12,3 @@ import { entityKind } from "../entity.js"; | ||
import { WithSubquery } from "../subquery.js"; | ||
import { _RelationalQueryBuilder } from "./query-builders/_query.js"; | ||
import { SQLiteCountBuilder } from "./query-builders/count.js"; | ||
@@ -17,25 +18,28 @@ import { RelationalQueryBuilder } from "./query-builders/query.js"; | ||
class BaseSQLiteDatabase { | ||
constructor(resultKind, dialect, session, schema) { | ||
constructor(resultKind, dialect, session, relations, _schema) { | ||
this.resultKind = resultKind; | ||
this.dialect = dialect; | ||
this.session = session; | ||
this._ = schema ? { | ||
schema: schema.schema, | ||
fullSchema: schema.fullSchema, | ||
tableNamesMap: schema.tableNamesMap | ||
const rel = relations ?? {}; | ||
this._ = _schema ? { | ||
schema: _schema.schema, | ||
fullSchema: _schema.fullSchema, | ||
tableNamesMap: _schema.tableNamesMap, | ||
relations: rel | ||
} : { | ||
schema: void 0, | ||
fullSchema: {}, | ||
tableNamesMap: {} | ||
tableNamesMap: {}, | ||
relations: rel | ||
}; | ||
this.query = {}; | ||
const query = this.query; | ||
this._query = {}; | ||
const query = this._query; | ||
if (this._.schema) { | ||
for (const [tableName, columns] of Object.entries(this._.schema)) { | ||
query[tableName] = new RelationalQueryBuilder( | ||
query[tableName] = new _RelationalQueryBuilder( | ||
resultKind, | ||
schema.fullSchema, | ||
_schema.fullSchema, | ||
this._.schema, | ||
this._.tableNamesMap, | ||
schema.fullSchema[tableName], | ||
_schema.fullSchema[tableName], | ||
columns, | ||
@@ -47,4 +51,21 @@ dialect, | ||
} | ||
this.query = {}; | ||
if (relations) { | ||
for (const [tableName, relation] of Object.entries(relations.tablesConfig)) { | ||
this.query[tableName] = new RelationalQueryBuilder( | ||
relations.tables, | ||
relations.tablesConfig, | ||
relations.tableNamesMap, | ||
relation.table, | ||
relation, | ||
dialect, | ||
session | ||
); | ||
} | ||
} | ||
} | ||
static [entityKind] = "BaseSQLiteDatabase"; | ||
/** @deprecated */ | ||
_query; | ||
// TO-DO: Figure out how to pass DrizzleTypeError without breaking withReplicas | ||
query; | ||
@@ -326,4 +347,4 @@ /** | ||
with: $with, | ||
get query() { | ||
return getReplica(replicas).query; | ||
get _query() { | ||
return getReplica(replicas)._query; | ||
} | ||
@@ -330,0 +351,0 @@ }; |
@@ -0,4 +1,5 @@ | ||
import * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
import type { MigrationConfig, MigrationMeta } from "../migrator.js"; | ||
import { type BuildRelationalQueryResult, type DBQueryConfig, type Relation, type TableRelationalConfig, type TablesRelationalConfig } from "../relations.js"; | ||
import { type AnyRelations, type BuildRelationalQueryResult, type DBQueryConfig, type TableRelationalConfig, type TablesRelationalConfig } from "../relations.js"; | ||
import { type QueryWithTypings, SQL } from "../sql/sql.js"; | ||
@@ -48,4 +49,19 @@ import { SQLiteColumn } from "./columns/index.js"; | ||
sqlToQuery(sql: SQL, invokeSource?: 'indexes' | undefined): QueryWithTypings; | ||
buildRelationalQuery({ fullSchema, schema, tableNamesMap, table, tableConfig, queryConfig: config, tableAlias, nestedQueryRelation, joinOn, }: { | ||
/** @deprecated */ | ||
_buildRelationalQuery({ fullSchema, schema, tableNamesMap, table, tableConfig, queryConfig: config, tableAlias, nestedQueryRelation, joinOn, }: { | ||
fullSchema: Record<string, unknown>; | ||
schema: V1.TablesRelationalConfig; | ||
tableNamesMap: Record<string, string>; | ||
table: SQLiteTable; | ||
tableConfig: V1.TableRelationalConfig; | ||
queryConfig: true | V1.DBQueryConfig<'many', true>; | ||
tableAlias: string; | ||
nestedQueryRelation?: V1.Relation; | ||
joinOn?: SQL; | ||
}): V1.BuildRelationalQueryResult<SQLiteTable, SQLiteColumn>; | ||
private unwrapAllColumns; | ||
private getSelectedTableColumns; | ||
private buildColumns; | ||
buildRelationalQuery({ tables, schema, tableNamesMap, table, tableConfig, queryConfig: config, relationWhere, mode, isNested, }: { | ||
tables: Record<string, SQLiteTable>; | ||
schema: TablesRelationalConfig; | ||
@@ -55,15 +71,15 @@ tableNamesMap: Record<string, string>; | ||
tableConfig: TableRelationalConfig; | ||
queryConfig: true | DBQueryConfig<'many', true>; | ||
tableAlias: string; | ||
nestedQueryRelation?: Relation; | ||
joinOn?: SQL; | ||
}): BuildRelationalQueryResult<SQLiteTable, SQLiteColumn>; | ||
queryConfig?: DBQueryConfig<'many'> | true; | ||
relationWhere?: SQL; | ||
mode: 'first' | 'many'; | ||
isNested?: boolean; | ||
}): BuildRelationalQueryResult; | ||
} | ||
export declare class SQLiteSyncDialect extends SQLiteDialect { | ||
static readonly [entityKind]: string; | ||
migrate(migrations: MigrationMeta[], session: SQLiteSession<'sync', unknown, Record<string, unknown>, TablesRelationalConfig>, config?: string | MigrationConfig): void; | ||
migrate(migrations: MigrationMeta[], session: SQLiteSession<'sync', unknown, Record<string, unknown>, AnyRelations, TablesRelationalConfig, V1.TablesRelationalConfig>, config?: string | MigrationConfig): void; | ||
} | ||
export declare class SQLiteAsyncDialect extends SQLiteDialect { | ||
static readonly [entityKind]: string; | ||
migrate(migrations: MigrationMeta[], session: SQLiteSession<'async', any, any, any>, config?: string | MigrationConfig): Promise<void>; | ||
migrate(migrations: MigrationMeta[], session: SQLiteSession<'async', unknown, Record<string, unknown>, AnyRelations, TablesRelationalConfig, V1.TablesRelationalConfig>, config?: string | MigrationConfig): Promise<void>; | ||
} |
@@ -0,1 +1,2 @@ | ||
import * as V1 from "../_relations.js"; | ||
import { aliasedTable, aliasedTableColumn, mapColumnsInAliasedSQLToAlias, mapColumnsInSQLToAlias } from "../alias.js"; | ||
@@ -7,7 +8,8 @@ import { CasingCache } from "../casing.js"; | ||
import { | ||
getOperators, | ||
getOrderByOperators, | ||
Many, | ||
normalizeRelation, | ||
One | ||
AggregatedField, | ||
One, | ||
relationExtrasToSQL, | ||
relationFilterToSQL, | ||
relationsOrderToSQL, | ||
relationToSQL | ||
} from "../relations.js"; | ||
@@ -19,3 +21,3 @@ import { and, eq } from "../sql/index.js"; | ||
import { Subquery } from "../subquery.js"; | ||
import { getTableName, getTableUniqueName, Table } from "../table.js"; | ||
import { Columns, getTableName, getTableUniqueName, Table } from "../table.js"; | ||
import { orderSelectedFields } from "../utils.js"; | ||
@@ -348,3 +350,4 @@ import { ViewBaseConfig } from "../view-common.js"; | ||
} | ||
buildRelationalQuery({ | ||
/** @deprecated */ | ||
_buildRelationalQuery({ | ||
fullSchema, | ||
@@ -378,3 +381,3 @@ schema, | ||
if (config.where) { | ||
const whereSql = typeof config.where === "function" ? config.where(aliasedColumns, getOperators()) : config.where; | ||
const whereSql = typeof config.where === "function" ? config.where(aliasedColumns, V1.getOperators()) : config.where; | ||
where = whereSql && mapColumnsInSQLToAlias(whereSql, tableAlias); | ||
@@ -431,3 +434,3 @@ } | ||
} | ||
let orderByOrig = typeof config.orderBy === "function" ? config.orderBy(aliasedColumns, getOrderByOperators()) : config.orderBy ?? []; | ||
let orderByOrig = typeof config.orderBy === "function" ? config.orderBy(aliasedColumns, V1.getOrderByOperators()) : config.orderBy ?? []; | ||
if (!Array.isArray(orderByOrig)) { | ||
@@ -449,3 +452,3 @@ orderByOrig = [orderByOrig]; | ||
} of selectedRelations) { | ||
const normalizedRelation = normalizeRelation(schema, tableNamesMap, relation); | ||
const normalizedRelation = V1.normalizeRelation(schema, tableNamesMap, relation); | ||
const relationTableName = getTableUniqueName(relation.referencedTable); | ||
@@ -462,3 +465,3 @@ const relationTableTsName = tableNamesMap[relationTableName]; | ||
); | ||
const builtRelation = this.buildRelationalQuery({ | ||
const builtRelation = this._buildRelationalQuery({ | ||
fullSchema, | ||
@@ -469,3 +472,3 @@ schema, | ||
tableConfig: schema[relationTableTsName], | ||
queryConfig: is(relation, One) ? selectedRelationConfigValue === true ? { limit: 1 } : { ...selectedRelationConfigValue, limit: 1 } : selectedRelationConfigValue, | ||
queryConfig: is(relation, V1.One) ? selectedRelationConfigValue === true ? { limit: 1 } : { ...selectedRelationConfigValue, limit: 1 } : selectedRelationConfigValue, | ||
tableAlias: relationTableAlias, | ||
@@ -500,3 +503,3 @@ joinOn: joinOn2, | ||
)})`; | ||
if (is(nestedQueryRelation, Many)) { | ||
if (is(nestedQueryRelation, V1.Many)) { | ||
field = sql`coalesce(json_group_array(${field}), json_array())`; | ||
@@ -572,2 +575,147 @@ } | ||
} | ||
unwrapAllColumns = (table, selection) => { | ||
return sql.join( | ||
Object.entries(table[Columns]).map(([k, v]) => { | ||
selection.push({ | ||
key: k, | ||
field: v | ||
}); | ||
return sql`${v} as ${sql.identifier(k)}`; | ||
}), | ||
sql`, ` | ||
); | ||
}; | ||
getSelectedTableColumns = (table, columns) => { | ||
const selectedColumns = []; | ||
if (!columns) { | ||
for (const [k, v] of Object.entries(table[Columns])) { | ||
selectedColumns.push({ | ||
column: v, | ||
tsName: k | ||
}); | ||
} | ||
return selectedColumns; | ||
} | ||
const entries = Object.entries(columns); | ||
let colSelectionMode; | ||
for (const [k, v] of entries) { | ||
if (colSelectionMode === void 0) | ||
colSelectionMode = v; | ||
else if (v !== void 0 && colSelectionMode !== v) { | ||
throw new Error("Columns cannot be both true and false at the same time"); | ||
} | ||
if (v) { | ||
selectedColumns.push({ | ||
column: table[Columns][k], | ||
tsName: k | ||
}); | ||
} | ||
} | ||
if (colSelectionMode === false) { | ||
for (const [k, v] of Object.entries(table[Columns])) { | ||
if (columns[k] === false) | ||
continue; | ||
selectedColumns.push({ | ||
column: v, | ||
tsName: k | ||
}); | ||
} | ||
} | ||
return selectedColumns; | ||
}; | ||
buildColumns = (table, selection, params) => params?.columns ? (() => { | ||
const columnIdentifiers = []; | ||
const selectedColumns = this.getSelectedTableColumns(table, params?.columns); | ||
for (const column of selectedColumns) { | ||
columnIdentifiers.push(sql`${column.column} as ${sql.identifier(column.tsName)}`); | ||
selection.push({ | ||
key: column.tsName, | ||
field: column.column | ||
}); | ||
} | ||
return columnIdentifiers.length ? sql.join(columnIdentifiers, sql`, `) : this.unwrapAllColumns(table, selection); | ||
})() : (() => { | ||
const columnIdentifiers = [this.unwrapAllColumns(table, selection)]; | ||
return sql.join(columnIdentifiers, sql`, `); | ||
})(); | ||
buildRelationalQuery({ | ||
tables, | ||
schema, | ||
tableNamesMap, | ||
table, | ||
tableConfig, | ||
queryConfig: config, | ||
relationWhere, | ||
mode, | ||
isNested | ||
}) { | ||
const selection = []; | ||
const isSingle = mode === "first"; | ||
const params = config === true ? void 0 : config; | ||
const limit = isSingle ? 1 : params?.limit; | ||
const offset = params?.offset; | ||
const columns = this.buildColumns(table, selection, params); | ||
const where = params?.where && relationWhere ? and(relationFilterToSQL(table, params.where), relationWhere) : params?.where ? relationFilterToSQL(table, params.where) : relationWhere; | ||
const order = params?.orderBy ? relationsOrderToSQL(table, params.orderBy) : void 0; | ||
const extras = params?.extras ? relationExtrasToSQL(table, params.extras) : void 0; | ||
if (extras) | ||
selection.push(...extras.selection); | ||
const joins = params ? (() => { | ||
const { with: joins2 } = params; | ||
if (!joins2) | ||
return; | ||
const withEntries = Object.entries(joins2).filter(([_, v]) => v); | ||
if (!withEntries.length) | ||
return; | ||
return sql.join( | ||
withEntries.map(([k, join]) => { | ||
if (is(tableConfig.relations[k], AggregatedField)) { | ||
const relation2 = tableConfig.relations[k]; | ||
relation2.onTable(table); | ||
const query2 = relation2.getSQL(); | ||
selection.push({ | ||
key: k, | ||
field: relation2 | ||
}); | ||
return sql`(${query2}) as ${sql.identifier(k)}`; | ||
} | ||
const relation = tableConfig.relations[k]; | ||
const isSingle2 = is(relation, One); | ||
const targetTable = relation.targetTable; | ||
const relationFilter = relationToSQL(relation); | ||
const innerQuery = this.buildRelationalQuery({ | ||
table: targetTable, | ||
mode: isSingle2 ? "first" : "many", | ||
schema, | ||
queryConfig: join, | ||
tableConfig: schema[tableNamesMap[getTableUniqueName(targetTable)]], | ||
tableNamesMap, | ||
tables, | ||
relationWhere: relationFilter, | ||
isNested: true | ||
}); | ||
selection.push({ | ||
field: targetTable, | ||
key: k, | ||
selection: innerQuery.selection, | ||
isArray: !isSingle2 | ||
}); | ||
const jsonColumns = sql.join( | ||
innerQuery.selection.map((s) => { | ||
return sql`${sql.raw(this.escapeString(s.key))}, ${s.selection ? sql`jsonb(${sql.identifier(s.key)})` : sql.identifier(s.key)}`; | ||
}), | ||
sql`, ` | ||
); | ||
return isNested ? isSingle2 ? sql`(select jsonb_object(${jsonColumns}) as ${sql.identifier("r")} from (${innerQuery.sql}) as ${sql.identifier("t")}) as ${sql.identifier(k)}` : sql`coalesce((select jsonb_group_array(json_object(${jsonColumns})) as ${sql.identifier("r")} from (${innerQuery.sql}) as ${sql.identifier("t")}), jsonb_array()) as ${sql.identifier(k)}` : isSingle2 ? sql`(select json_object(${jsonColumns}) as ${sql.identifier("r")} from (${innerQuery.sql}) as ${sql.identifier("t")}) as ${sql.identifier(k)}` : sql`coalesce((select json_group_array(json_object(${jsonColumns})) as ${sql.identifier("r")} from (${innerQuery.sql}) as ${sql.identifier("t")}), jsonb_array()) as ${sql.identifier(k)}`; | ||
}), | ||
sql`, ` | ||
); | ||
})() : void 0; | ||
const selectionSet = sql.join([columns, extras?.sql, joins].filter((e) => e !== void 0), sql`, `); | ||
const query = sql`select ${selectionSet} from ${table}${sql` where ${where}`.if(where)}${sql` order by ${order}`.if(order)}${sql` limit ${limit}`.if(limit !== void 0)}${sql` offset ${offset}`.if(offset !== void 0)}`; | ||
return { | ||
sql: query, | ||
selection | ||
}; | ||
} | ||
} | ||
@@ -574,0 +722,0 @@ class SQLiteSyncDialect extends SQLiteDialect { |
@@ -6,3 +6,3 @@ import { entityKind } from "../../entity.js"; | ||
import type { SQLiteView } from "../view.js"; | ||
export declare class SQLiteCountBuilder<TSession extends SQLiteSession<any, any, any, any>> extends SQL<number> implements Promise<number>, SQLWrapper { | ||
export declare class SQLiteCountBuilder<TSession extends SQLiteSession<any, any, any, any>> extends SQL<number> implements Promise<number>, SQLWrapper<number> { | ||
readonly params: { | ||
@@ -9,0 +9,0 @@ source: SQLiteTable | SQLiteView | SQL | SQLWrapper; |
@@ -53,3 +53,3 @@ import { entityKind } from "../../entity.js"; | ||
static readonly [entityKind]: string; | ||
constructor(table: TTable, session: SQLiteSession<any, any, any, any>, dialect: SQLiteDialect, withList?: Subquery[]); | ||
constructor(table: TTable, session: SQLiteSession<any, any, any, any, any, any>, dialect: SQLiteDialect, withList?: Subquery[]); | ||
/** | ||
@@ -56,0 +56,0 @@ * Adds a `where` clause to the query. |
@@ -34,7 +34,7 @@ import { entityKind } from "../../entity.js"; | ||
protected table: TTable; | ||
protected session: SQLiteSession<any, any, any, any>; | ||
protected session: SQLiteSession<any, any, any, any, any, any>; | ||
protected dialect: SQLiteDialect; | ||
private withList?; | ||
static readonly [entityKind]: string; | ||
constructor(table: TTable, session: SQLiteSession<any, any, any, any>, dialect: SQLiteDialect, withList?: Subquery[] | undefined); | ||
constructor(table: TTable, session: SQLiteSession<any, any, any, any, any, any>, dialect: SQLiteDialect, withList?: Subquery[] | undefined); | ||
values(value: SQLiteInsertValue<TTable>): SQLiteInsertBase<TTable, TResultType, TRunResult>; | ||
@@ -86,3 +86,3 @@ values(values: SQLiteInsertValue<TTable>[]): SQLiteInsertBase<TTable, TResultType, TRunResult>; | ||
static readonly [entityKind]: string; | ||
constructor(table: TTable, values: SQLiteInsertConfig['values'], session: SQLiteSession<any, any, any, any>, dialect: SQLiteDialect, withList?: Subquery[], select?: boolean); | ||
constructor(table: TTable, values: SQLiteInsertConfig['values'], session: SQLiteSession<any, any, any, any, any, any>, dialect: SQLiteDialect, withList?: Subquery[], select?: boolean); | ||
/** | ||
@@ -89,0 +89,0 @@ * Adds a `returning` clause to the query. |
@@ -11,18 +11,17 @@ import { entityKind } from "../../entity.js"; | ||
export type SQLiteRelationalQueryKind<TMode extends 'sync' | 'async', TResult> = TMode extends 'async' ? SQLiteRelationalQuery<TMode, TResult> : SQLiteSyncRelationalQuery<TResult>; | ||
export declare class RelationalQueryBuilder<TMode extends 'sync' | 'async', TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig, TFields extends TableRelationalConfig> { | ||
protected mode: TMode; | ||
protected fullSchema: Record<string, unknown>; | ||
protected schema: TSchema; | ||
protected tableNamesMap: Record<string, string>; | ||
protected table: SQLiteTable; | ||
protected tableConfig: TableRelationalConfig; | ||
protected dialect: SQLiteDialect; | ||
protected session: SQLiteSession<'async', unknown, TFullSchema, TSchema>; | ||
export declare class RelationalQueryBuilder<TMode extends 'sync' | 'async', TSchema extends TablesRelationalConfig, TFields extends TableRelationalConfig> { | ||
private tables; | ||
private schema; | ||
private tableNamesMap; | ||
private table; | ||
private tableConfig; | ||
private dialect; | ||
private session; | ||
static readonly [entityKind]: string; | ||
constructor(mode: TMode, fullSchema: Record<string, unknown>, schema: TSchema, tableNamesMap: Record<string, string>, table: SQLiteTable, tableConfig: TableRelationalConfig, dialect: SQLiteDialect, session: SQLiteSession<'async', unknown, TFullSchema, TSchema>); | ||
findMany<TConfig extends DBQueryConfig<'many', true, TSchema, TFields>>(config?: KnownKeysOnly<TConfig, DBQueryConfig<'many', true, TSchema, TFields>>): SQLiteRelationalQueryKind<TMode, BuildQueryResult<TSchema, TFields, TConfig>[]>; | ||
findFirst<TSelection extends Omit<DBQueryConfig<'many', true, TSchema, TFields>, 'limit'>>(config?: KnownKeysOnly<TSelection, Omit<DBQueryConfig<'many', true, TSchema, TFields>, 'limit'>>): SQLiteRelationalQueryKind<TMode, BuildQueryResult<TSchema, TFields, TSelection> | undefined>; | ||
constructor(tables: Record<string, SQLiteTable>, schema: TSchema, tableNamesMap: Record<string, string>, table: SQLiteTable, tableConfig: TableRelationalConfig, dialect: SQLiteDialect, session: SQLiteSession<TMode, any, any, any, any, any>); | ||
findMany<TConfig extends DBQueryConfig<'many', TSchema, TFields>>(config?: KnownKeysOnly<TConfig, DBQueryConfig<'many', TSchema, TFields>>): SQLiteRelationalQuery<TMode, BuildQueryResult<TSchema, TFields, TConfig>[]>; | ||
findFirst<TConfig extends DBQueryConfig<'one', TSchema, TFields>>(config?: KnownKeysOnly<TConfig, DBQueryConfig<'one', TSchema, TFields>>): SQLiteRelationalQuery<TMode, BuildQueryResult<TSchema, TFields, TConfig> | undefined>; | ||
} | ||
export declare class SQLiteRelationalQuery<TType extends 'sync' | 'async', TResult> extends QueryPromise<TResult> implements RunnableQuery<TResult, 'sqlite'>, SQLWrapper { | ||
private fullSchema; | ||
private tables; | ||
private schema; | ||
@@ -40,5 +39,3 @@ private tableNamesMap; | ||
}; | ||
constructor(fullSchema: Record<string, unknown>, schema: TablesRelationalConfig, tableNamesMap: Record<string, string>, | ||
/** @internal */ | ||
table: SQLiteTable, tableConfig: TableRelationalConfig, dialect: SQLiteDialect, session: SQLiteSession<'sync' | 'async', unknown, Record<string, unknown>, TablesRelationalConfig>, config: DBQueryConfig<'many', true> | true, mode: 'many' | 'first'); | ||
constructor(tables: Record<string, SQLiteTable>, schema: TablesRelationalConfig, tableNamesMap: Record<string, string>, table: SQLiteTable, tableConfig: TableRelationalConfig, dialect: SQLiteDialect, session: SQLiteSession<TType, any, any, any, any, any>, config: DBQueryConfig<'many' | 'one'> | true, mode: 'many' | 'first'); | ||
prepare(): SQLitePreparedQuery<PreparedQueryConfig & { | ||
@@ -50,2 +47,3 @@ type: TType; | ||
}>; | ||
private _getQuery; | ||
private _toSQL; | ||
@@ -52,0 +50,0 @@ toSQL(): Query; |
@@ -7,5 +7,4 @@ import { entityKind } from "../../entity.js"; | ||
class RelationalQueryBuilder { | ||
constructor(mode, fullSchema, schema, tableNamesMap, table, tableConfig, dialect, session) { | ||
this.mode = mode; | ||
this.fullSchema = fullSchema; | ||
constructor(tables, schema, tableNamesMap, table, tableConfig, dialect, session) { | ||
this.tables = tables; | ||
this.schema = schema; | ||
@@ -18,6 +17,6 @@ this.tableNamesMap = tableNamesMap; | ||
} | ||
static [entityKind] = "SQLiteAsyncRelationalQueryBuilder"; | ||
static [entityKind] = "SQLiteAsyncRelationalQueryBuilderV2"; | ||
findMany(config) { | ||
return this.mode === "sync" ? new SQLiteSyncRelationalQuery( | ||
this.fullSchema, | ||
return new SQLiteRelationalQuery( | ||
this.tables, | ||
this.schema, | ||
@@ -29,19 +28,9 @@ this.tableNamesMap, | ||
this.session, | ||
config ? config : {}, | ||
config ?? true, | ||
"many" | ||
) : new SQLiteRelationalQuery( | ||
this.fullSchema, | ||
this.schema, | ||
this.tableNamesMap, | ||
this.table, | ||
this.tableConfig, | ||
this.dialect, | ||
this.session, | ||
config ? config : {}, | ||
"many" | ||
); | ||
} | ||
findFirst(config) { | ||
return this.mode === "sync" ? new SQLiteSyncRelationalQuery( | ||
this.fullSchema, | ||
return new SQLiteRelationalQuery( | ||
this.tables, | ||
this.schema, | ||
@@ -53,14 +42,4 @@ this.tableNamesMap, | ||
this.session, | ||
config ? { ...config, limit: 1 } : { limit: 1 }, | ||
config ?? true, | ||
"first" | ||
) : new SQLiteRelationalQuery( | ||
this.fullSchema, | ||
this.schema, | ||
this.tableNamesMap, | ||
this.table, | ||
this.tableConfig, | ||
this.dialect, | ||
this.session, | ||
config ? { ...config, limit: 1 } : { limit: 1 }, | ||
"first" | ||
); | ||
@@ -70,8 +49,7 @@ } | ||
class SQLiteRelationalQuery extends QueryPromise { | ||
constructor(fullSchema, schema, tableNamesMap, table, tableConfig, dialect, session, config, mode) { | ||
constructor(tables, schema, tableNamesMap, table, tableConfig, dialect, session, config, mode) { | ||
super(); | ||
this.fullSchema = fullSchema; | ||
this.tables = tables; | ||
this.schema = schema; | ||
this.tableNamesMap = tableNamesMap; | ||
this.table = table; | ||
this.tableConfig = tableConfig; | ||
@@ -82,10 +60,12 @@ this.dialect = dialect; | ||
this.mode = mode; | ||
this.table = table; | ||
} | ||
static [entityKind] = "SQLiteAsyncRelationalQuery"; | ||
static [entityKind] = "SQLiteAsyncRelationalQueryV2"; | ||
/** @internal */ | ||
mode; | ||
/** @internal */ | ||
table; | ||
/** @internal */ | ||
getSQL() { | ||
return this.dialect.buildRelationalQuery({ | ||
fullSchema: this.fullSchema, | ||
const query = this.dialect.buildRelationalQuery({ | ||
schema: this.schema, | ||
@@ -96,4 +76,6 @@ tableNamesMap: this.tableNamesMap, | ||
queryConfig: this.config, | ||
tableAlias: this.tableConfig.tsName | ||
}).sql; | ||
tables: this.tables, | ||
mode: this.mode | ||
}); | ||
return query.sql; | ||
} | ||
@@ -103,11 +85,8 @@ /** @internal */ | ||
const { query, builtQuery } = this._toSQL(); | ||
return this.session[isOneTimeQuery ? "prepareOneTimeQuery" : "prepareQuery"]( | ||
return this.session[isOneTimeQuery ? "prepareOneTimeRelationalQuery" : "prepareRelationalQuery"]( | ||
builtQuery, | ||
void 0, | ||
this.mode === "first" ? "get" : "all", | ||
true, | ||
(rawRows, mapColumnValue) => { | ||
const rows = rawRows.map( | ||
(row) => mapRelationalRow(this.schema, this.tableConfig, row, query.selection, mapColumnValue) | ||
); | ||
const rows = rawRows.map((row) => mapRelationalRow(row, query.selection, mapColumnValue, true)); | ||
if (this.mode === "first") { | ||
@@ -123,5 +102,4 @@ return rows[0]; | ||
} | ||
_toSQL() { | ||
const query = this.dialect.buildRelationalQuery({ | ||
fullSchema: this.fullSchema, | ||
_getQuery() { | ||
return this.dialect.buildRelationalQuery({ | ||
schema: this.schema, | ||
@@ -132,4 +110,8 @@ tableNamesMap: this.tableNamesMap, | ||
queryConfig: this.config, | ||
tableAlias: this.tableConfig.tsName | ||
tables: this.tables, | ||
mode: this.mode | ||
}); | ||
} | ||
_toSQL() { | ||
const query = this._getQuery(); | ||
const builtQuery = this.dialect.sqlToQuery(query.sql); | ||
@@ -153,3 +135,3 @@ return { query, builtQuery }; | ||
class SQLiteSyncRelationalQuery extends SQLiteRelationalQuery { | ||
static [entityKind] = "SQLiteSyncRelationalQuery"; | ||
static [entityKind] = "SQLiteSyncRelationalQueryV2"; | ||
sync() { | ||
@@ -156,0 +138,0 @@ return this.executeRaw(); |
@@ -26,3 +26,3 @@ import { entityKind } from "../../entity.js"; | ||
fields: TSelection; | ||
session: SQLiteSession<any, any, any, any> | undefined; | ||
session: SQLiteSession<any, any, any, any, any, any> | undefined; | ||
dialect: SQLiteDialect; | ||
@@ -53,3 +53,3 @@ withList?: Subquery[]; | ||
private isPartialSelect; | ||
protected session: SQLiteSession<any, any, any, any> | undefined; | ||
protected session: SQLiteSession<any, any, any, any, any, any> | undefined; | ||
protected dialect: SQLiteDialect; | ||
@@ -60,3 +60,3 @@ constructor({ table, fields, isPartialSelect, session, dialect, withList, distinct }: { | ||
isPartialSelect: boolean; | ||
session: SQLiteSession<any, any, any, any> | undefined; | ||
session: SQLiteSession<any, any, any, any, any, any> | undefined; | ||
dialect: SQLiteDialect; | ||
@@ -63,0 +63,0 @@ withList: Subquery[] | undefined; |
@@ -31,3 +31,3 @@ import type { GetColumnData } from "../../column.js"; | ||
protected table: TTable; | ||
protected session: SQLiteSession<any, any, any, any>; | ||
protected session: SQLiteSession<any, any, any, any, any, any>; | ||
protected dialect: SQLiteDialect; | ||
@@ -39,3 +39,3 @@ private withList?; | ||
}; | ||
constructor(table: TTable, session: SQLiteSession<any, any, any, any>, dialect: SQLiteDialect, withList?: Subquery[] | undefined); | ||
constructor(table: TTable, session: SQLiteSession<any, any, any, any, any, any>, dialect: SQLiteDialect, withList?: Subquery[] | undefined); | ||
set(values: SQLiteUpdateSetSource<TTable>): SQLiteUpdateWithout<SQLiteUpdateBase<TTable, TResultType, TRunResult>, false, 'leftJoin' | 'rightJoin' | 'innerJoin' | 'fullJoin'>; | ||
@@ -77,3 +77,3 @@ } | ||
static readonly [entityKind]: string; | ||
constructor(table: TTable, set: UpdateSet, session: SQLiteSession<any, any, any, any>, dialect: SQLiteDialect, withList?: Subquery[]); | ||
constructor(table: TTable, set: UpdateSet, session: SQLiteSession<any, any, any, any, any, any>, dialect: SQLiteDialect, withList?: Subquery[]); | ||
from<TFrom extends SQLiteTable | Subquery | SQLiteViewBase | SQL>(source: TFrom): SQLiteUpdateWithJoins<this, TDynamic, TFrom>; | ||
@@ -80,0 +80,0 @@ private createJoin; |
@@ -0,7 +1,8 @@ | ||
import type * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
import type { TablesRelationalConfig } from "../relations.js"; | ||
import { QueryPromise } from "../query-promise.js"; | ||
import type { AnyRelations, EmptyRelations, ExtractTablesWithRelations, TablesRelationalConfig } from "../relations.js"; | ||
import type { PreparedQuery } from "../session.js"; | ||
import type { Query, SQL } from "../sql/sql.js"; | ||
import type { SQLiteAsyncDialect, SQLiteSyncDialect } from "./dialect.js"; | ||
import { QueryPromise } from "../query-promise.js"; | ||
import { BaseSQLiteDatabase } from "./db.js"; | ||
@@ -47,3 +48,3 @@ import type { SQLiteRaw } from "./query-builders/raw.js"; | ||
export type SQLiteExecuteMethod = 'run' | 'all' | 'get'; | ||
export declare abstract class SQLiteSession<TResultKind extends 'sync' | 'async', TRunResult, TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> { | ||
export declare abstract class SQLiteSession<TResultKind extends 'sync' | 'async', TRunResult, TFullSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations, TTablesConfig extends TablesRelationalConfig = ExtractTablesWithRelations<TRelations>, TSchema extends V1.TablesRelationalConfig = V1.ExtractTablesWithRelations<TFullSchema>> { | ||
static readonly [entityKind]: string; | ||
@@ -62,3 +63,9 @@ constructor( | ||
}>; | ||
abstract transaction<T>(transaction: (tx: SQLiteTransaction<TResultKind, TRunResult, TFullSchema, TSchema>) => Result<TResultKind, T>, config?: SQLiteTransactionConfig): Result<TResultKind, T>; | ||
abstract prepareRelationalQuery(query: Query, fields: SelectedFieldsOrdered | undefined, executeMethod: SQLiteExecuteMethod, customResultMapper: (rows: Record<string, unknown>[], mapColumnValue?: (value: unknown) => unknown) => unknown): SQLitePreparedQuery<PreparedQueryConfig & { | ||
type: TResultKind; | ||
}>; | ||
prepareOneTimeRelationalQuery(query: Query, fields: SelectedFieldsOrdered | undefined, executeMethod: SQLiteExecuteMethod, customResultMapper: (rows: Record<string, unknown>[], mapColumnValue?: (value: unknown) => unknown) => unknown): SQLitePreparedQuery<PreparedQueryConfig & { | ||
type: TResultKind; | ||
}>; | ||
abstract transaction<T>(transaction: (tx: SQLiteTransaction<TResultKind, TRunResult, TFullSchema, TRelations, TTablesConfig, TSchema>) => Result<TResultKind, T>, config?: SQLiteTransactionConfig): Result<TResultKind, T>; | ||
run(query: SQL): Result<TResultKind, TRunResult>; | ||
@@ -78,3 +85,4 @@ all<T = unknown>(query: SQL): Result<TResultKind, T[]>; | ||
}[TKind]; | ||
export declare abstract class SQLiteTransaction<TResultType extends 'sync' | 'async', TRunResult, TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends BaseSQLiteDatabase<TResultType, TRunResult, TFullSchema, TSchema> { | ||
export declare abstract class SQLiteTransaction<TResultType extends 'sync' | 'async', TRunResult, TFullSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations, TTablesConfig extends TablesRelationalConfig = ExtractTablesWithRelations<TRelations>, TSchema extends V1.TablesRelationalConfig = V1.ExtractTablesWithRelations<TFullSchema>> extends BaseSQLiteDatabase<TResultType, TRunResult, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
protected relations: AnyRelations | undefined; | ||
protected schema: { | ||
@@ -90,3 +98,3 @@ fullSchema: Record<string, unknown>; | ||
async: SQLiteAsyncDialect; | ||
}[TResultType], session: SQLiteSession<TResultType, TRunResult, TFullSchema, TSchema>, schema: { | ||
}[TResultType], session: SQLiteSession<TResultType, TRunResult, TFullSchema, TRelations, TTablesConfig, TSchema>, relations: AnyRelations | undefined, schema: { | ||
fullSchema: Record<string, unknown>; | ||
@@ -93,0 +101,0 @@ schema: TSchema; |
@@ -67,2 +67,5 @@ import { entityKind } from "../entity.js"; | ||
} | ||
prepareOneTimeRelationalQuery(query, fields, executeMethod, customResultMapper) { | ||
return this.prepareRelationalQuery(query, fields, executeMethod, customResultMapper); | ||
} | ||
run(query) { | ||
@@ -107,4 +110,5 @@ const staticQuery = this.dialect.sqlToQuery(query); | ||
class SQLiteTransaction extends BaseSQLiteDatabase { | ||
constructor(resultType, dialect, session, schema, nestedIndex = 0) { | ||
super(resultType, dialect, session, schema); | ||
constructor(resultType, dialect, session, relations, schema, nestedIndex = 0) { | ||
super(resultType, dialect, session, relations, schema); | ||
this.relations = relations; | ||
this.schema = schema; | ||
@@ -111,0 +115,0 @@ this.nestedIndex = nestedIndex; |
import type { BatchItem, BatchResponse } from "../batch.js"; | ||
import { entityKind } from "../entity.js"; | ||
import type { AnyRelations, EmptyRelations } from "../relations.js"; | ||
import { BaseSQLiteDatabase } from "../sqlite-core/db.js"; | ||
@@ -8,3 +9,3 @@ import type { DrizzleConfig } from "../utils.js"; | ||
} | ||
export declare class SqliteRemoteDatabase<TSchema extends Record<string, unknown> = Record<string, never>> extends BaseSQLiteDatabase<'async', SqliteRemoteResult, TSchema> { | ||
export declare class SqliteRemoteDatabase<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations> extends BaseSQLiteDatabase<'async', SqliteRemoteResult, TSchema, TRelations> { | ||
static readonly [entityKind]: string; | ||
@@ -24,3 +25,3 @@ batch<U extends BatchItem<'sqlite'>, T extends Readonly<[U, ...U[]]>>(batch: T): Promise<BatchResponse<T>>; | ||
export type RemoteCallback = AsyncRemoteCallback; | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(callback: RemoteCallback, config?: DrizzleConfig<TSchema>): SqliteRemoteDatabase<TSchema>; | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(callback: RemoteCallback, batchCallback?: AsyncBatchRemoteCallback, config?: DrizzleConfig<TSchema>): SqliteRemoteDatabase<TSchema>; | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations>(callback: RemoteCallback, config?: DrizzleConfig<TSchema, TRelations>): SqliteRemoteDatabase<TSchema>; | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations>(callback: RemoteCallback, batchCallback?: AsyncBatchRemoteCallback, config?: DrizzleConfig<TSchema, TRelations>): SqliteRemoteDatabase<TSchema>; |
@@ -0,4 +1,4 @@ | ||
import * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
import { DefaultLogger } from "../logger.js"; | ||
import { createTableRelationsHelpers, extractTablesRelationalConfig } from "../relations.js"; | ||
import { BaseSQLiteDatabase } from "../sqlite-core/db.js"; | ||
@@ -34,5 +34,5 @@ import { SQLiteAsyncDialect } from "../sqlite-core/dialect.js"; | ||
if (_config.schema) { | ||
const tablesConfig = extractTablesRelationalConfig( | ||
const tablesConfig = V1.extractTablesRelationalConfig( | ||
_config.schema, | ||
createTableRelationsHelpers | ||
V1.createTableRelationsHelpers | ||
); | ||
@@ -45,4 +45,11 @@ schema = { | ||
} | ||
const session = new SQLiteRemoteSession(callback, dialect, schema, _batchCallback, { logger }); | ||
return new SqliteRemoteDatabase("async", dialect, session, schema); | ||
const relations = config?.relations; | ||
const session = new SQLiteRemoteSession(callback, dialect, relations, schema, _batchCallback, { logger }); | ||
return new SqliteRemoteDatabase( | ||
"async", | ||
dialect, | ||
session, | ||
relations, | ||
schema | ||
); | ||
} | ||
@@ -49,0 +56,0 @@ export { |
import type { MigrationConfig } from "../migrator.js"; | ||
import type { AnyRelations } from "../relations.js"; | ||
import type { SqliteRemoteDatabase } from "./driver.js"; | ||
export type ProxyMigrator = (migrationQueries: string[]) => Promise<void>; | ||
export declare function migrate<TSchema extends Record<string, unknown>>(db: SqliteRemoteDatabase<TSchema>, callback: ProxyMigrator, config: MigrationConfig): Promise<void>; | ||
export declare function migrate<TSchema extends Record<string, unknown>, TRelations extends AnyRelations>(db: SqliteRemoteDatabase<TSchema, TRelations>, callback: ProxyMigrator, config: MigrationConfig): Promise<void>; |
@@ -0,5 +1,6 @@ | ||
import type * as V1 from "../_relations.js"; | ||
import type { BatchItem } from "../batch.js"; | ||
import { entityKind } from "../entity.js"; | ||
import type { Logger } from "../logger.js"; | ||
import type { RelationalSchemaConfig, TablesRelationalConfig } from "../relations.js"; | ||
import type { AnyRelations, TablesRelationalConfig } from "../relations.js"; | ||
import { type Query } from "../sql/sql.js"; | ||
@@ -16,4 +17,5 @@ import type { SQLiteAsyncDialect } from "../sqlite-core/dialect.js"; | ||
export type PreparedQueryConfig = Omit<PreparedQueryConfigBase, 'statement' | 'run'>; | ||
export declare class SQLiteRemoteSession<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends SQLiteSession<'async', SqliteRemoteResult, TFullSchema, TSchema> { | ||
export declare class SQLiteRemoteSession<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends SQLiteSession<'async', SqliteRemoteResult, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
private client; | ||
private relations; | ||
private schema; | ||
@@ -23,6 +25,7 @@ private batchCLient?; | ||
private logger; | ||
constructor(client: RemoteCallback, dialect: SQLiteAsyncDialect, schema: RelationalSchemaConfig<TSchema> | undefined, batchCLient?: AsyncBatchRemoteCallback | undefined, options?: SQLiteRemoteSessionOptions); | ||
constructor(client: RemoteCallback, dialect: SQLiteAsyncDialect, relations: AnyRelations | undefined, schema: V1.RelationalSchemaConfig<TSchema> | undefined, batchCLient?: AsyncBatchRemoteCallback | undefined, options?: SQLiteRemoteSessionOptions); | ||
prepareQuery<T extends Omit<PreparedQueryConfig, 'run'>>(query: Query, fields: SelectedFieldsOrdered | undefined, executeMethod: SQLiteExecuteMethod, isResponseInArrayMode: boolean, customResultMapper?: (rows: unknown[][]) => unknown): RemotePreparedQuery<T>; | ||
prepareRelationalQuery<T extends Omit<PreparedQueryConfig, 'run'>>(query: Query, fields: SelectedFieldsOrdered | undefined, executeMethod: SQLiteExecuteMethod, customResultMapper: (rows: Record<string, unknown>[]) => unknown): RemotePreparedQuery<T, true>; | ||
batch<T extends BatchItem<'sqlite'>[] | readonly BatchItem<'sqlite'>[]>(queries: T): Promise<unknown[]>; | ||
transaction<T>(transaction: (tx: SQLiteProxyTransaction<TFullSchema, TSchema>) => Promise<T>, config?: SQLiteTransactionConfig): Promise<T>; | ||
transaction<T>(transaction: (tx: SQLiteProxyTransaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => Promise<T>, config?: SQLiteTransactionConfig): Promise<T>; | ||
extractRawAllValueFromBatchResult(result: unknown): unknown; | ||
@@ -32,7 +35,7 @@ extractRawGetValueFromBatchResult(result: unknown): unknown; | ||
} | ||
export declare class SQLiteProxyTransaction<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends SQLiteTransaction<'async', SqliteRemoteResult, TFullSchema, TSchema> { | ||
export declare class SQLiteProxyTransaction<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends SQLiteTransaction<'async', SqliteRemoteResult, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
static readonly [entityKind]: string; | ||
transaction<T>(transaction: (tx: SQLiteProxyTransaction<TFullSchema, TSchema>) => Promise<T>): Promise<T>; | ||
transaction<T>(transaction: (tx: SQLiteProxyTransaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => Promise<T>): Promise<T>; | ||
} | ||
export declare class RemotePreparedQuery<T extends PreparedQueryConfig = PreparedQueryConfig> extends SQLitePreparedQuery<{ | ||
export declare class RemotePreparedQuery<T extends PreparedQueryConfig = PreparedQueryConfig, TIsRqbV2 extends boolean = false> extends SQLitePreparedQuery<{ | ||
type: 'async'; | ||
@@ -49,6 +52,7 @@ run: SqliteRemoteResult; | ||
private _isResponseInArrayMode; | ||
private isRqbV2Query?; | ||
static readonly [entityKind]: string; | ||
private method; | ||
constructor(client: RemoteCallback, query: Query, logger: Logger, fields: SelectedFieldsOrdered | undefined, executeMethod: SQLiteExecuteMethod, _isResponseInArrayMode: boolean, | ||
/** @internal */ customResultMapper?: ((rows: unknown[][], mapColumnValue?: (value: unknown) => unknown) => unknown) | undefined); | ||
/** @internal */ customResultMapper?: ((rows: TIsRqbV2 extends true ? Record<string, unknown>[] : unknown[][]) => unknown) | undefined, isRqbV2Query?: TIsRqbV2 | undefined); | ||
getQuery(): Query & { | ||
@@ -61,4 +65,6 @@ method: SQLiteExecuteMethod; | ||
get(placeholderValues?: Record<string, unknown>): Promise<T['get']>; | ||
private allRqbV2; | ||
private getRqbV2; | ||
mapGetResult(rows: unknown, isFromBatch?: boolean): unknown; | ||
values<T extends any[] = unknown[]>(placeholderValues?: Record<string, unknown>): Promise<T[]>; | ||
} |
@@ -8,5 +8,6 @@ import { entityKind } from "../entity.js"; | ||
class SQLiteRemoteSession extends SQLiteSession { | ||
constructor(client, dialect, schema, batchCLient, options = {}) { | ||
constructor(client, dialect, relations, schema, batchCLient, options = {}) { | ||
super(dialect); | ||
this.client = client; | ||
this.relations = relations; | ||
this.schema = schema; | ||
@@ -29,2 +30,14 @@ this.batchCLient = batchCLient; | ||
} | ||
prepareRelationalQuery(query, fields, executeMethod, customResultMapper) { | ||
return new RemotePreparedQuery( | ||
this.client, | ||
query, | ||
this.logger, | ||
fields, | ||
executeMethod, | ||
false, | ||
customResultMapper, | ||
true | ||
); | ||
} | ||
async batch(queries) { | ||
@@ -43,3 +56,3 @@ const preparedQueries = []; | ||
async transaction(transaction, config) { | ||
const tx = new SQLiteProxyTransaction("async", this.dialect, this, this.schema); | ||
const tx = new SQLiteProxyTransaction("async", this.dialect, this, this.relations, this.schema); | ||
await this.run(sql.raw(`begin${config?.behavior ? " " + config.behavior : ""}`)); | ||
@@ -69,3 +82,10 @@ try { | ||
const savepointName = `sp${this.nestedIndex}`; | ||
const tx = new SQLiteProxyTransaction("async", this.dialect, this.session, this.schema, this.nestedIndex + 1); | ||
const tx = new SQLiteProxyTransaction( | ||
"async", | ||
this.dialect, | ||
this.session, | ||
this.relations, | ||
this.schema, | ||
this.nestedIndex + 1 | ||
); | ||
await this.session.run(sql.raw(`savepoint ${savepointName}`)); | ||
@@ -83,3 +103,3 @@ try { | ||
class RemotePreparedQuery extends SQLitePreparedQuery { | ||
constructor(client, query, logger, fields, executeMethod, _isResponseInArrayMode, customResultMapper) { | ||
constructor(client, query, logger, fields, executeMethod, _isResponseInArrayMode, customResultMapper, isRqbV2Query) { | ||
super("async", executeMethod, query); | ||
@@ -91,2 +111,3 @@ this.client = client; | ||
this.customResultMapper = customResultMapper; | ||
this.isRqbV2Query = isRqbV2Query; | ||
this.customResultMapper = customResultMapper; | ||
@@ -124,2 +145,4 @@ this.method = executeMethod; | ||
async all(placeholderValues) { | ||
if (this.isRqbV2Query) | ||
return this.allRqbV2(placeholderValues); | ||
const { query, logger, client } = this; | ||
@@ -132,2 +155,4 @@ const params = fillPlaceholders(query.params, placeholderValues ?? {}); | ||
async get(placeholderValues) { | ||
if (this.isRqbV2Query) | ||
return this.getRqbV2(placeholderValues); | ||
const { query, logger, client } = this; | ||
@@ -139,2 +164,20 @@ const params = fillPlaceholders(query.params, placeholderValues ?? {}); | ||
} | ||
async allRqbV2(placeholderValues) { | ||
const { query, logger, client, customResultMapper } = this; | ||
const params = fillPlaceholders(query.params, placeholderValues ?? {}); | ||
logger.logQuery(query.sql, params); | ||
const { rows } = await client(query.sql, params, "all"); | ||
return customResultMapper(rows); | ||
} | ||
async getRqbV2(placeholderValues) { | ||
const { query, logger, client, customResultMapper } = this; | ||
const params = fillPlaceholders(query.params, placeholderValues ?? {}); | ||
logger.logQuery(query.sql, params); | ||
const clientResult = await client(query.sql, params, "get"); | ||
const row = clientResult.rows[0]; | ||
if (!row) { | ||
return void 0; | ||
} | ||
return customResultMapper([row]); | ||
} | ||
mapGetResult(rows, isFromBatch) { | ||
@@ -141,0 +184,0 @@ if (isFromBatch) { |
@@ -50,3 +50,3 @@ import type { Column, GetColumnData } from "./column.js"; | ||
export declare function getTableName<T extends Table>(table: T): T['_']['name']; | ||
export declare function getTableUniqueName<T extends Table>(table: T): `${T['_']['schema']}.${T['_']['name']}`; | ||
export declare function getTableUniqueName<T extends Table, TResult extends string = T['_']['schema'] extends undefined ? `public.${T['_']['name']}` : `${T['_']['schema']}.${T['_']['name']}`>(table: T): TResult; | ||
export type MapColumnName<TName extends string, TColumn extends Column, TDBColumNames extends boolean> = TDBColumNames extends true ? TColumn['_']['name'] : TName; | ||
@@ -53,0 +53,0 @@ export type InferModelFromColumns<TColumns extends Record<string, Column>, TInferMode extends 'select' | 'insert' = 'select', TConfig extends { |
@@ -5,2 +5,3 @@ import { type Config, type Connection } from '@tidbcloud/serverless'; | ||
import { MySqlDatabase } from "../mysql-core/db.js"; | ||
import type { AnyRelations, EmptyRelations } from "../relations.js"; | ||
import { type DrizzleConfig } from "../utils.js"; | ||
@@ -11,10 +12,10 @@ import type { TiDBServerlessPreparedQueryHKT, TiDBServerlessQueryResultHKT } from "./session.js"; | ||
} | ||
export declare class TiDBServerlessDatabase<TSchema extends Record<string, unknown> = Record<string, never>> extends MySqlDatabase<TiDBServerlessQueryResultHKT, TiDBServerlessPreparedQueryHKT, TSchema> { | ||
export declare class TiDBServerlessDatabase<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations> extends MySqlDatabase<TiDBServerlessQueryResultHKT, TiDBServerlessPreparedQueryHKT, TSchema, TRelations> { | ||
static readonly [entityKind]: string; | ||
} | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TClient extends Connection = Connection>(...params: [ | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations, TClient extends Connection = Connection>(...params: [ | ||
TClient | string | ||
] | [ | ||
TClient | string, | ||
DrizzleConfig<TSchema> | ||
DrizzleConfig<TSchema, TRelations> | ||
] | [ | ||
@@ -25,10 +26,10 @@ ({ | ||
client: TClient; | ||
}) & DrizzleConfig<TSchema> | ||
]): TiDBServerlessDatabase<TSchema> & { | ||
}) & DrizzleConfig<TSchema, TRelations> | ||
]): TiDBServerlessDatabase<TSchema, TRelations> & { | ||
$client: TClient; | ||
}; | ||
export declare namespace drizzle { | ||
function mock<TSchema extends Record<string, unknown> = Record<string, never>>(config?: DrizzleConfig<TSchema>): TiDBServerlessDatabase<TSchema> & { | ||
function mock<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations>(config?: DrizzleConfig<TSchema, TRelations>): TiDBServerlessDatabase<TSchema, TRelations> & { | ||
$client: '$client is not available on drizzle.mock()'; | ||
}; | ||
} |
import { connect } from "@tidbcloud/serverless"; | ||
import * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
@@ -6,6 +7,2 @@ import { DefaultLogger } from "../logger.js"; | ||
import { MySqlDialect } from "../mysql-core/dialect.js"; | ||
import { | ||
createTableRelationsHelpers, | ||
extractTablesRelationalConfig | ||
} from "../relations.js"; | ||
import { isConfig } from "../utils.js"; | ||
@@ -26,5 +23,5 @@ import { TiDBServerlessSession } from "./session.js"; | ||
if (config.schema) { | ||
const tablesConfig = extractTablesRelationalConfig( | ||
const tablesConfig = V1.extractTablesRelationalConfig( | ||
config.schema, | ||
createTableRelationsHelpers | ||
V1.createTableRelationsHelpers | ||
); | ||
@@ -37,4 +34,11 @@ schema = { | ||
} | ||
const session = new TiDBServerlessSession(client, dialect, void 0, schema, { logger }); | ||
const db = new TiDBServerlessDatabase(dialect, session, schema, "default"); | ||
const relations = config.relations; | ||
const session = new TiDBServerlessSession(client, dialect, void 0, relations, schema, { logger }); | ||
const db = new TiDBServerlessDatabase( | ||
dialect, | ||
session, | ||
relations, | ||
schema, | ||
"default" | ||
); | ||
db.$client = client; | ||
@@ -41,0 +45,0 @@ return db; |
import type { MigrationConfig } from "../migrator.js"; | ||
import type { AnyRelations } from "../relations.js"; | ||
import type { TiDBServerlessDatabase } from "./driver.js"; | ||
export declare function migrate<TSchema extends Record<string, unknown>>(db: TiDBServerlessDatabase<TSchema>, config: MigrationConfig): Promise<void>; | ||
export declare function migrate<TSchema extends Record<string, unknown>, TRelations extends AnyRelations>(db: TiDBServerlessDatabase<TSchema, TRelations>, config: MigrationConfig): Promise<void>; |
import type { Connection, FullResult, Tx } from '@tidbcloud/serverless'; | ||
import type * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
@@ -7,6 +8,6 @@ import type { Logger } from "../logger.js"; | ||
import { MySqlPreparedQuery, type MySqlPreparedQueryConfig, type MySqlPreparedQueryHKT, type MySqlQueryResultHKT, MySqlSession, MySqlTransaction } from "../mysql-core/session.js"; | ||
import type { RelationalSchemaConfig, TablesRelationalConfig } from "../relations.js"; | ||
import type { AnyRelations, TablesRelationalConfig } from "../relations.js"; | ||
import { type Query, type SQL } from "../sql/sql.js"; | ||
import { type Assume } from "../utils.js"; | ||
export declare class TiDBServerlessPreparedQuery<T extends MySqlPreparedQueryConfig> extends MySqlPreparedQuery<T> { | ||
export declare class TiDBServerlessPreparedQuery<T extends MySqlPreparedQueryConfig, TIsRqbV2 extends boolean = false> extends MySqlPreparedQuery<T> { | ||
private client; | ||
@@ -20,5 +21,7 @@ private queryString; | ||
private returningIds?; | ||
private isRqbV2Query?; | ||
static readonly [entityKind]: string; | ||
constructor(client: Tx | Connection, queryString: string, params: unknown[], logger: Logger, fields: SelectedFieldsOrdered | undefined, customResultMapper?: ((rows: unknown[][]) => T["execute"]) | undefined, generatedIds?: Record<string, unknown>[] | undefined, returningIds?: SelectedFieldsOrdered | undefined); | ||
constructor(client: Tx | Connection, queryString: string, params: unknown[], logger: Logger, fields: SelectedFieldsOrdered | undefined, customResultMapper?: ((rows: TIsRqbV2 extends true ? Record<string, unknown>[] : unknown[][]) => T["execute"]) | undefined, generatedIds?: Record<string, unknown>[] | undefined, returningIds?: SelectedFieldsOrdered | undefined, isRqbV2Query?: TIsRqbV2 | undefined); | ||
execute(placeholderValues?: Record<string, unknown> | undefined): Promise<T['execute']>; | ||
private executeRqbV2; | ||
iterator(_placeholderValues?: Record<string, unknown>): AsyncGenerator<T['iterator']>; | ||
@@ -29,4 +32,5 @@ } | ||
} | ||
export declare class TiDBServerlessSession<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends MySqlSession<TiDBServerlessQueryResultHKT, TiDBServerlessPreparedQueryHKT, TFullSchema, TSchema> { | ||
export declare class TiDBServerlessSession<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends MySqlSession<TiDBServerlessQueryResultHKT, TiDBServerlessPreparedQueryHKT, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
private baseClient; | ||
private relations; | ||
private schema; | ||
@@ -37,12 +41,13 @@ private options; | ||
private client; | ||
constructor(baseClient: Connection, dialect: MySqlDialect, tx: Tx | undefined, schema: RelationalSchemaConfig<TSchema> | undefined, options?: TiDBServerlessSessionOptions); | ||
constructor(baseClient: Connection, dialect: MySqlDialect, tx: Tx | undefined, relations: AnyRelations | undefined, schema: V1.RelationalSchemaConfig<TSchema> | undefined, options?: TiDBServerlessSessionOptions); | ||
prepareQuery<T extends MySqlPreparedQueryConfig = MySqlPreparedQueryConfig>(query: Query, fields: SelectedFieldsOrdered | undefined, customResultMapper?: (rows: unknown[][]) => T['execute'], generatedIds?: Record<string, unknown>[], returningIds?: SelectedFieldsOrdered): MySqlPreparedQuery<T>; | ||
prepareRelationalQuery<T extends MySqlPreparedQueryConfig = MySqlPreparedQueryConfig>(query: Query, fields: SelectedFieldsOrdered | undefined, customResultMapper: (rows: Record<string, unknown>[]) => T['execute'], generatedIds?: Record<string, unknown>[], returningIds?: SelectedFieldsOrdered): MySqlPreparedQuery<T>; | ||
all<T = unknown>(query: SQL): Promise<T[]>; | ||
count(sql: SQL): Promise<number>; | ||
transaction<T>(transaction: (tx: TiDBServerlessTransaction<TFullSchema, TSchema>) => Promise<T>): Promise<T>; | ||
transaction<T>(transaction: (tx: TiDBServerlessTransaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => Promise<T>): Promise<T>; | ||
} | ||
export declare class TiDBServerlessTransaction<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends MySqlTransaction<TiDBServerlessQueryResultHKT, TiDBServerlessPreparedQueryHKT, TFullSchema, TSchema> { | ||
export declare class TiDBServerlessTransaction<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends MySqlTransaction<TiDBServerlessQueryResultHKT, TiDBServerlessPreparedQueryHKT, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
static readonly [entityKind]: string; | ||
constructor(dialect: MySqlDialect, session: MySqlSession, schema: RelationalSchemaConfig<TSchema> | undefined, nestedIndex?: number); | ||
transaction<T>(transaction: (tx: TiDBServerlessTransaction<TFullSchema, TSchema>) => Promise<T>): Promise<T>; | ||
constructor(dialect: MySqlDialect, session: MySqlSession, relations: AnyRelations | undefined, schema: V1.RelationalSchemaConfig<TSchema> | undefined, nestedIndex?: number); | ||
transaction<T>(transaction: (tx: TiDBServerlessTransaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => Promise<T>): Promise<T>; | ||
} | ||
@@ -49,0 +54,0 @@ export interface TiDBServerlessQueryResultHKT extends MySqlQueryResultHKT { |
@@ -14,3 +14,3 @@ import { Column } from "../column.js"; | ||
class TiDBServerlessPreparedQuery extends MySqlPreparedQuery { | ||
constructor(client, queryString, params, logger, fields, customResultMapper, generatedIds, returningIds) { | ||
constructor(client, queryString, params, logger, fields, customResultMapper, generatedIds, returningIds, isRqbV2Query) { | ||
super(); | ||
@@ -25,5 +25,8 @@ this.client = client; | ||
this.returningIds = returningIds; | ||
this.isRqbV2Query = isRqbV2Query; | ||
} | ||
static [entityKind] = "TiDBPreparedQuery"; | ||
async execute(placeholderValues = {}) { | ||
if (this.isRqbV2Query) | ||
return this.executeRqbV2(placeholderValues); | ||
const params = fillPlaceholders(this.params, placeholderValues); | ||
@@ -63,2 +66,33 @@ this.logger.logQuery(this.queryString, params); | ||
} | ||
async executeRqbV2(placeholderValues = {}) { | ||
const params = fillPlaceholders(this.params, placeholderValues); | ||
this.logger.logQuery(this.queryString, params); | ||
const { client, queryString, customResultMapper, returningIds, generatedIds } = this; | ||
const res = await client.execute(queryString, params, executeRawConfig); | ||
const insertId = res.lastInsertId ?? 0; | ||
const affectedRows = res.rowsAffected ?? 0; | ||
if (returningIds) { | ||
const returningResponse = []; | ||
let j = 0; | ||
for (let i = insertId; i < insertId + affectedRows; i++) { | ||
for (const column of returningIds) { | ||
const key = returningIds[0].path[0]; | ||
if (is(column.field, Column)) { | ||
if (column.field.primary && column.field.autoIncrement) { | ||
returningResponse.push({ [key]: i }); | ||
} | ||
if (column.field.defaultFn && generatedIds) { | ||
returningResponse.push({ [key]: generatedIds[j][key] }); | ||
} | ||
} | ||
} | ||
j++; | ||
} | ||
return customResultMapper(returningResponse); | ||
} | ||
const { rows } = res; | ||
return customResultMapper( | ||
rows ?? [] | ||
); | ||
} | ||
iterator(_placeholderValues) { | ||
@@ -69,5 +103,6 @@ throw new Error("Streaming is not supported by the TiDB Cloud Serverless driver"); | ||
class TiDBServerlessSession extends MySqlSession { | ||
constructor(baseClient, dialect, tx, schema, options = {}) { | ||
constructor(baseClient, dialect, tx, relations, schema, options = {}) { | ||
super(dialect); | ||
this.baseClient = baseClient; | ||
this.relations = relations; | ||
this.schema = schema; | ||
@@ -93,2 +128,15 @@ this.options = options; | ||
} | ||
prepareRelationalQuery(query, fields, customResultMapper, generatedIds, returningIds) { | ||
return new TiDBServerlessPreparedQuery( | ||
this.client, | ||
query.sql, | ||
query.params, | ||
this.logger, | ||
fields, | ||
customResultMapper, | ||
generatedIds, | ||
returningIds, | ||
true | ||
); | ||
} | ||
all(query) { | ||
@@ -108,6 +156,14 @@ const querySql = this.dialect.sqlToQuery(query); | ||
try { | ||
const session = new TiDBServerlessSession(this.baseClient, this.dialect, nativeTx, this.schema, this.options); | ||
const session = new TiDBServerlessSession( | ||
this.baseClient, | ||
this.dialect, | ||
nativeTx, | ||
this.relations, | ||
this.schema, | ||
this.options | ||
); | ||
const tx = new TiDBServerlessTransaction( | ||
this.dialect, | ||
session, | ||
this.relations, | ||
this.schema | ||
@@ -126,4 +182,4 @@ ); | ||
static [entityKind] = "TiDBServerlessTransaction"; | ||
constructor(dialect, session, schema, nestedIndex = 0) { | ||
super(dialect, session, schema, nestedIndex, "default"); | ||
constructor(dialect, session, relations, schema, nestedIndex = 0) { | ||
super(dialect, session, relations, schema, nestedIndex, "default"); | ||
} | ||
@@ -135,2 +191,3 @@ async transaction(transaction) { | ||
this.session, | ||
this.relations, | ||
this.schema, | ||
@@ -137,0 +194,0 @@ this.nestedIndex + 1 |
import type { AnyColumn } from "./column.js"; | ||
import type { Logger } from "./logger.js"; | ||
import type { AnyRelations, EmptyRelations } from "./relations.js"; | ||
import { Param, SQL } from "./sql/sql.js"; | ||
@@ -39,6 +40,7 @@ import { Table } from "./table.js"; | ||
export type Casing = 'snake_case' | 'camelCase'; | ||
export interface DrizzleConfig<TSchema extends Record<string, unknown> = Record<string, never>> { | ||
export interface DrizzleConfig<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations> { | ||
logger?: boolean | Logger; | ||
schema?: TSchema; | ||
casing?: Casing; | ||
relations?: TRelations; | ||
} | ||
@@ -45,0 +47,0 @@ export type ValidateShape<T, ValidShape, TResult = T> = T extends ValidShape ? Exclude<keyof T, keyof ValidShape> extends never ? TResult : DrizzleTypeError<`Invalid key(s): ${Exclude<(keyof T) & (string | number | bigint | boolean | null | undefined), keyof ValidShape>}`> : never; |
@@ -133,3 +133,3 @@ import { Column } from "./column.js"; | ||
if ("schema" in data) { | ||
const type = typeof data["logger"]; | ||
const type = typeof data["schema"]; | ||
if (type !== "object" && type !== "undefined") | ||
@@ -140,3 +140,3 @@ return false; | ||
if ("casing" in data) { | ||
const type = typeof data["logger"]; | ||
const type = typeof data["casing"]; | ||
if (type !== "string" && type !== "undefined") | ||
@@ -143,0 +143,0 @@ return false; |
import { sql } from '@vercel/postgres'; | ||
import * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
@@ -6,3 +7,3 @@ import type { Logger } from "../logger.js"; | ||
import { PgDialect } from "../pg-core/index.js"; | ||
import { type RelationalSchemaConfig, type TablesRelationalConfig } from "../relations.js"; | ||
import type { AnyRelations, EmptyRelations, TablesRelationalConfig } from "../relations.js"; | ||
import { type DrizzleConfig } from "../utils.js"; | ||
@@ -19,23 +20,23 @@ import { type VercelPgClient, type VercelPgQueryResultHKT, VercelPgSession } from "./session.js"; | ||
constructor(client: VercelPgClient, dialect: PgDialect, options?: VercelPgDriverOptions); | ||
createSession(schema: RelationalSchemaConfig<TablesRelationalConfig> | undefined): VercelPgSession<Record<string, unknown>, TablesRelationalConfig>; | ||
createSession(relations: AnyRelations | undefined, schema: V1.RelationalSchemaConfig<V1.TablesRelationalConfig> | undefined): VercelPgSession<Record<string, unknown>, AnyRelations, TablesRelationalConfig, V1.TablesRelationalConfig>; | ||
} | ||
export declare class VercelPgDatabase<TSchema extends Record<string, unknown> = Record<string, never>> extends PgDatabase<VercelPgQueryResultHKT, TSchema> { | ||
export declare class VercelPgDatabase<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations> extends PgDatabase<VercelPgQueryResultHKT, TSchema, TRelations> { | ||
static readonly [entityKind]: string; | ||
} | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TClient extends VercelPgClient = typeof sql>(...params: [] | [ | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations, TClient extends VercelPgClient = typeof sql>(...params: [] | [ | ||
TClient | ||
] | [ | ||
TClient, | ||
DrizzleConfig<TSchema> | ||
DrizzleConfig<TSchema, TRelations> | ||
] | [ | ||
(DrizzleConfig<TSchema> & ({ | ||
(DrizzleConfig<TSchema, TRelations> & ({ | ||
client?: TClient; | ||
})) | ||
]): VercelPgDatabase<TSchema> & { | ||
]): VercelPgDatabase<TSchema, TRelations> & { | ||
$client: TClient; | ||
}; | ||
export declare namespace drizzle { | ||
function mock<TSchema extends Record<string, unknown> = Record<string, never>>(config?: DrizzleConfig<TSchema>): VercelPgDatabase<TSchema> & { | ||
function mock<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations>(config?: DrizzleConfig<TSchema, TRelations>): VercelPgDatabase<TSchema, TRelations> & { | ||
$client: '$client is not available on drizzle.mock()'; | ||
}; | ||
} |
import { sql } from "@vercel/postgres"; | ||
import * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
@@ -6,6 +7,2 @@ import { DefaultLogger } from "../logger.js"; | ||
import { PgDialect } from "../pg-core/index.js"; | ||
import { | ||
createTableRelationsHelpers, | ||
extractTablesRelationalConfig | ||
} from "../relations.js"; | ||
import { isConfig } from "../utils.js"; | ||
@@ -20,4 +17,4 @@ import { VercelPgSession } from "./session.js"; | ||
static [entityKind] = "VercelPgDriver"; | ||
createSession(schema) { | ||
return new VercelPgSession(this.client, this.dialect, schema, { logger: this.options.logger }); | ||
createSession(relations, schema) { | ||
return new VercelPgSession(this.client, this.dialect, relations, schema, { logger: this.options.logger }); | ||
} | ||
@@ -38,5 +35,5 @@ } | ||
if (config.schema) { | ||
const tablesConfig = extractTablesRelationalConfig( | ||
const tablesConfig = V1.extractTablesRelationalConfig( | ||
config.schema, | ||
createTableRelationsHelpers | ||
V1.createTableRelationsHelpers | ||
); | ||
@@ -49,5 +46,11 @@ schema = { | ||
} | ||
const relations = config.relations; | ||
const driver = new VercelPgDriver(client, dialect, { logger }); | ||
const session = driver.createSession(schema); | ||
const db = new VercelPgDatabase(dialect, session, schema); | ||
const session = driver.createSession(relations, schema); | ||
const db = new VercelPgDatabase( | ||
dialect, | ||
session, | ||
relations, | ||
schema | ||
); | ||
db.$client = client; | ||
@@ -54,0 +57,0 @@ return db; |
import type { MigrationConfig } from "../migrator.js"; | ||
import type { AnyRelations } from "../relations.js"; | ||
import type { VercelPgDatabase } from "./driver.js"; | ||
export declare function migrate<TSchema extends Record<string, unknown>>(db: VercelPgDatabase<TSchema>, config: MigrationConfig): Promise<void>; | ||
export declare function migrate<TSchema extends Record<string, unknown>, TRelations extends AnyRelations>(db: VercelPgDatabase<TSchema, TRelations>, config: MigrationConfig): Promise<void>; |
import { type QueryResult, type QueryResultRow, type VercelClient, VercelPool, type VercelPoolClient } from '@vercel/postgres'; | ||
import type * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
@@ -8,7 +9,7 @@ import { type Logger } from "../logger.js"; | ||
import { PgPreparedQuery, PgSession } from "../pg-core/session.js"; | ||
import type { RelationalSchemaConfig, TablesRelationalConfig } from "../relations.js"; | ||
import type { AnyRelations, TablesRelationalConfig } from "../relations.js"; | ||
import { type Query } from "../sql/sql.js"; | ||
import { type Assume } from "../utils.js"; | ||
export type VercelPgClient = VercelPool | VercelClient | VercelPoolClient; | ||
export declare class VercelPgPreparedQuery<T extends PreparedQueryConfig> extends PgPreparedQuery<T> { | ||
export declare class VercelPgPreparedQuery<T extends PreparedQueryConfig, TIsRqbV2 extends boolean = false> extends PgPreparedQuery<T> { | ||
private client; | ||
@@ -20,7 +21,9 @@ private params; | ||
private customResultMapper?; | ||
private isRqbV2Query?; | ||
static readonly [entityKind]: string; | ||
private rawQuery; | ||
private queryConfig; | ||
constructor(client: VercelPgClient, queryString: string, params: unknown[], logger: Logger, fields: SelectedFieldsOrdered | undefined, name: string | undefined, _isResponseInArrayMode: boolean, customResultMapper?: ((rows: unknown[][]) => T["execute"]) | undefined); | ||
constructor(client: VercelPgClient, queryString: string, params: unknown[], logger: Logger, fields: SelectedFieldsOrdered | undefined, name: string | undefined, _isResponseInArrayMode: boolean, customResultMapper?: ((rows: TIsRqbV2 extends true ? Record<string, unknown>[] : unknown[][]) => T["execute"]) | undefined, isRqbV2Query?: TIsRqbV2 | undefined); | ||
execute(placeholderValues?: Record<string, unknown> | undefined): Promise<T['execute']>; | ||
private executeRqbV2; | ||
all(placeholderValues?: Record<string, unknown> | undefined): Promise<T['all']>; | ||
@@ -32,4 +35,5 @@ values(placeholderValues?: Record<string, unknown> | undefined): Promise<T['values']>; | ||
} | ||
export declare class VercelPgSession<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends PgSession<VercelPgQueryResultHKT, TFullSchema, TSchema> { | ||
export declare class VercelPgSession<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends PgSession<VercelPgQueryResultHKT, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
private client; | ||
private relations; | ||
private schema; | ||
@@ -39,11 +43,12 @@ private options; | ||
private logger; | ||
constructor(client: VercelPgClient, dialect: PgDialect, schema: RelationalSchemaConfig<TSchema> | undefined, options?: VercelPgSessionOptions); | ||
constructor(client: VercelPgClient, dialect: PgDialect, relations: AnyRelations | undefined, schema: V1.RelationalSchemaConfig<TSchema> | undefined, options?: VercelPgSessionOptions); | ||
prepareQuery<T extends PreparedQueryConfig = PreparedQueryConfig>(query: Query, fields: SelectedFieldsOrdered | undefined, name: string | undefined, isResponseInArrayMode: boolean, customResultMapper?: (rows: unknown[][]) => T['execute']): PgPreparedQuery<T>; | ||
prepareRelationalQuery<T extends PreparedQueryConfig = PreparedQueryConfig>(query: Query, fields: SelectedFieldsOrdered | undefined, name: string | undefined, customResultMapper: (rows: Record<string, unknown>[]) => T['execute']): PgPreparedQuery<T>; | ||
query(query: string, params: unknown[]): Promise<QueryResult>; | ||
queryObjects<T extends QueryResultRow>(query: string, params: unknown[]): Promise<QueryResult<T>>; | ||
transaction<T>(transaction: (tx: VercelPgTransaction<TFullSchema, TSchema>) => Promise<T>, config?: PgTransactionConfig | undefined): Promise<T>; | ||
transaction<T>(transaction: (tx: VercelPgTransaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => Promise<T>, config?: PgTransactionConfig | undefined): Promise<T>; | ||
} | ||
export declare class VercelPgTransaction<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends PgTransaction<VercelPgQueryResultHKT, TFullSchema, TSchema> { | ||
export declare class VercelPgTransaction<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends PgTransaction<VercelPgQueryResultHKT, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
static readonly [entityKind]: string; | ||
transaction<T>(transaction: (tx: VercelPgTransaction<TFullSchema, TSchema>) => Promise<T>): Promise<T>; | ||
transaction<T>(transaction: (tx: VercelPgTransaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => Promise<T>): Promise<T>; | ||
} | ||
@@ -50,0 +55,0 @@ export interface VercelPgQueryResultHKT extends PgQueryResultHKT { |
@@ -12,3 +12,3 @@ import { | ||
class VercelPgPreparedQuery extends PgPreparedQuery { | ||
constructor(client, queryString, params, logger, fields, name, _isResponseInArrayMode, customResultMapper) { | ||
constructor(client, queryString, params, logger, fields, name, _isResponseInArrayMode, customResultMapper, isRqbV2Query) { | ||
super({ sql: queryString, params }); | ||
@@ -21,2 +21,3 @@ this.client = client; | ||
this.customResultMapper = customResultMapper; | ||
this.isRqbV2Query = isRqbV2Query; | ||
this.rawQuery = { | ||
@@ -72,2 +73,4 @@ name, | ||
async execute(placeholderValues = {}) { | ||
if (this.isRqbV2Query) | ||
return this.executeRqbV2(placeholderValues); | ||
const params = fillPlaceholders(this.params, placeholderValues); | ||
@@ -85,2 +88,9 @@ this.logger.logQuery(this.rawQuery.text, params); | ||
} | ||
async executeRqbV2(placeholderValues = {}) { | ||
const params = fillPlaceholders(this.params, placeholderValues); | ||
this.logger.logQuery(this.rawQuery.text, params); | ||
const { rawQuery, client, customResultMapper } = this; | ||
const { rows } = await client.query(rawQuery, params); | ||
return customResultMapper(rows); | ||
} | ||
all(placeholderValues = {}) { | ||
@@ -102,5 +112,6 @@ const params = fillPlaceholders(this.params, placeholderValues); | ||
class VercelPgSession extends PgSession { | ||
constructor(client, dialect, schema, options = {}) { | ||
constructor(client, dialect, relations, schema, options = {}) { | ||
super(dialect); | ||
this.client = client; | ||
this.relations = relations; | ||
this.schema = schema; | ||
@@ -124,2 +135,15 @@ this.options = options; | ||
} | ||
prepareRelationalQuery(query, fields, name, customResultMapper) { | ||
return new VercelPgPreparedQuery( | ||
this.client, | ||
query.sql, | ||
query.params, | ||
this.logger, | ||
fields, | ||
name, | ||
false, | ||
customResultMapper, | ||
true | ||
); | ||
} | ||
async query(query, params) { | ||
@@ -138,4 +162,9 @@ this.logger.logQuery(query, params); | ||
async transaction(transaction, config) { | ||
const session = this.client instanceof VercelPool ? new VercelPgSession(await this.client.connect(), this.dialect, this.schema, this.options) : this; | ||
const tx = new VercelPgTransaction(this.dialect, session, this.schema); | ||
const session = this.client instanceof VercelPool ? new VercelPgSession(await this.client.connect(), this.dialect, this.relations, this.schema, this.options) : this; | ||
const tx = new VercelPgTransaction( | ||
this.dialect, | ||
session, | ||
this.relations, | ||
this.schema | ||
); | ||
await tx.execute(sql`begin${config ? sql` ${tx.getTransactionConfigSQL(config)}` : void 0}`); | ||
@@ -163,2 +192,3 @@ try { | ||
this.session, | ||
this.relations, | ||
this.schema, | ||
@@ -165,0 +195,0 @@ this.nestedIndex + 1 |
@@ -1,2 +0,2 @@ | ||
var version = "0.36.4-166fb8d"; | ||
var version = "0.36.4-3c69a1f"; | ||
@@ -3,0 +3,0 @@ declare const compatibilityVersion = 10; |
// package.json | ||
var version = "0.36.4-166fb8d"; | ||
var version = "0.36.4-3c69a1f"; | ||
@@ -4,0 +4,0 @@ // src/version.ts |
@@ -0,1 +1,2 @@ | ||
import * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
@@ -5,3 +6,3 @@ import type { Logger } from "../logger.js"; | ||
import { PgDialect } from "../pg-core/dialect.js"; | ||
import type { RelationalSchemaConfig, TablesRelationalConfig } from "../relations.js"; | ||
import type { AnyRelations, EmptyRelations, TablesRelationalConfig } from "../relations.js"; | ||
import type { DrizzleConfig } from "../utils.js"; | ||
@@ -19,10 +20,10 @@ import type { XataHttpClient, XataHttpQueryResultHKT } from "./session.js"; | ||
constructor(client: XataHttpClient, dialect: PgDialect, options?: XataDriverOptions); | ||
createSession(schema: RelationalSchemaConfig<TablesRelationalConfig> | undefined): XataHttpSession<Record<string, unknown>, TablesRelationalConfig>; | ||
createSession(relations: AnyRelations | undefined, schema: V1.RelationalSchemaConfig<V1.TablesRelationalConfig> | undefined): XataHttpSession<Record<string, unknown>, AnyRelations, TablesRelationalConfig, V1.TablesRelationalConfig>; | ||
initMappers(): void; | ||
} | ||
export declare class XataHttpDatabase<TSchema extends Record<string, unknown> = Record<string, never>> extends PgDatabase<XataHttpQueryResultHKT, TSchema> { | ||
export declare class XataHttpDatabase<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations> extends PgDatabase<XataHttpQueryResultHKT, TSchema, TRelations> { | ||
static readonly [entityKind]: string; | ||
} | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(client: XataHttpClient, config?: DrizzleConfig<TSchema>): XataHttpDatabase<TSchema> & { | ||
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations>(client: XataHttpClient, config?: DrizzleConfig<TSchema, TRelations>): XataHttpDatabase<TSchema, TRelations> & { | ||
$client: XataHttpClient; | ||
}; |
@@ -0,1 +1,2 @@ | ||
import * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
@@ -5,3 +6,2 @@ import { DefaultLogger } from "../logger.js"; | ||
import { PgDialect } from "../pg-core/dialect.js"; | ||
import { createTableRelationsHelpers, extractTablesRelationalConfig } from "../relations.js"; | ||
import { XataHttpSession } from "./session.js"; | ||
@@ -16,4 +16,4 @@ class XataHttpDriver { | ||
static [entityKind] = "XataDriver"; | ||
createSession(schema) { | ||
return new XataHttpSession(this.client, this.dialect, schema, { | ||
createSession(relations, schema) { | ||
return new XataHttpSession(this.client, this.dialect, relations, schema, { | ||
logger: this.options.logger | ||
@@ -38,3 +38,3 @@ }); | ||
if (config.schema) { | ||
const tablesConfig = extractTablesRelationalConfig(config.schema, createTableRelationsHelpers); | ||
const tablesConfig = V1.extractTablesRelationalConfig(config.schema, V1.createTableRelationsHelpers); | ||
schema = { | ||
@@ -46,7 +46,9 @@ fullSchema: config.schema, | ||
} | ||
const relations = config.relations; | ||
const driver = new XataHttpDriver(client, dialect, { logger }); | ||
const session = driver.createSession(schema); | ||
const session = driver.createSession(relations, schema); | ||
const db = new XataHttpDatabase( | ||
dialect, | ||
session, | ||
relations, | ||
schema | ||
@@ -53,0 +55,0 @@ ); |
@@ -0,1 +1,2 @@ | ||
import type { AnyRelations, EmptyRelations } from "../relations.js"; | ||
import type { XataHttpDatabase } from "./driver.js"; | ||
@@ -13,2 +14,2 @@ export interface MigrationConfig { | ||
* @param config - path to migration folder generated by drizzle-kit | ||
*/ export declare function migrate<TSchema extends Record<string, unknown>>(db: XataHttpDatabase<TSchema>, config: MigrationConfig): Promise<void>; | ||
*/ export declare function migrate<TSchema extends Record<string, unknown>, TRelations extends AnyRelations = EmptyRelations>(db: XataHttpDatabase<TSchema, TRelations>, config: MigrationConfig): Promise<void>; |
import type { SQLPluginResult, SQLQueryResult } from '@xata.io/client'; | ||
import type * as V1 from "../_relations.js"; | ||
import { entityKind } from "../entity.js"; | ||
@@ -9,3 +10,3 @@ import type { Logger } from "../logger.js"; | ||
import { PgPreparedQuery, PgSession } from "../pg-core/session.js"; | ||
import type { RelationalSchemaConfig, TablesRelationalConfig } from "../relations.js"; | ||
import type { AnyRelations, TablesRelationalConfig } from "../relations.js"; | ||
import { type Query } from "../sql/sql.js"; | ||
@@ -20,3 +21,3 @@ export type XataHttpClient = { | ||
} | ||
export declare class XataHttpPreparedQuery<T extends PreparedQueryConfig> extends PgPreparedQuery<T> { | ||
export declare class XataHttpPreparedQuery<T extends PreparedQueryConfig, TIsRqbV2 extends boolean = false> extends PgPreparedQuery<T> { | ||
private client; | ||
@@ -27,5 +28,7 @@ private logger; | ||
private customResultMapper?; | ||
private isRqbV2Query?; | ||
static readonly [entityKind]: string; | ||
constructor(client: XataHttpClient, query: Query, logger: Logger, fields: SelectedFieldsOrdered | undefined, _isResponseInArrayMode: boolean, customResultMapper?: ((rows: unknown[][]) => T["execute"]) | undefined); | ||
constructor(client: XataHttpClient, query: Query, logger: Logger, fields: SelectedFieldsOrdered | undefined, _isResponseInArrayMode: boolean, customResultMapper?: ((rows: TIsRqbV2 extends true ? Record<string, unknown>[] : unknown[][]) => T["execute"]) | undefined, isRqbV2Query?: TIsRqbV2 | undefined); | ||
execute(placeholderValues?: Record<string, unknown> | undefined): Promise<T['execute']>; | ||
private executeRqbV2; | ||
all(placeholderValues?: Record<string, unknown> | undefined): Promise<T['all']>; | ||
@@ -37,4 +40,5 @@ values(placeholderValues?: Record<string, unknown> | undefined): Promise<T['values']>; | ||
} | ||
export declare class XataHttpSession<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends PgSession<XataHttpQueryResultHKT, TFullSchema, TSchema> { | ||
export declare class XataHttpSession<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends PgSession<XataHttpQueryResultHKT, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
private client; | ||
private relations; | ||
private schema; | ||
@@ -44,11 +48,12 @@ private options; | ||
private logger; | ||
constructor(client: XataHttpClient, dialect: PgDialect, schema: RelationalSchemaConfig<TSchema> | undefined, options?: XataHttpSessionOptions); | ||
constructor(client: XataHttpClient, dialect: PgDialect, relations: AnyRelations | undefined, schema: V1.RelationalSchemaConfig<TSchema> | undefined, options?: XataHttpSessionOptions); | ||
prepareQuery<T extends PreparedQueryConfig = PreparedQueryConfig>(query: Query, fields: SelectedFieldsOrdered | undefined, name: string | undefined, isResponseInArrayMode: boolean, customResultMapper?: (rows: unknown[][]) => T['execute']): PgPreparedQuery<T>; | ||
prepareRelationalQuery<T extends PreparedQueryConfig = PreparedQueryConfig>(query: Query, fields: SelectedFieldsOrdered | undefined, name: string | undefined, customResultMapper: (rows: Record<string, unknown>[]) => T['execute']): PgPreparedQuery<T>; | ||
query(query: string, params: unknown[]): Promise<QueryResults<'array'>>; | ||
queryObjects(query: string, params: unknown[]): Promise<QueryResults<'json'>>; | ||
transaction<T>(_transaction: (tx: XataTransaction<TFullSchema, TSchema>) => Promise<T>, _config?: PgTransactionConfig): Promise<T>; | ||
transaction<T>(_transaction: (tx: XataTransaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => Promise<T>, _config?: PgTransactionConfig): Promise<T>; | ||
} | ||
export declare class XataTransaction<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends PgTransaction<XataHttpQueryResultHKT, TFullSchema, TSchema> { | ||
export declare class XataTransaction<TFullSchema extends Record<string, unknown>, TRelations extends AnyRelations, TTablesConfig extends TablesRelationalConfig, TSchema extends V1.TablesRelationalConfig> extends PgTransaction<XataHttpQueryResultHKT, TFullSchema, TRelations, TTablesConfig, TSchema> { | ||
static readonly [entityKind]: string; | ||
transaction<T>(_transaction: (tx: XataTransaction<TFullSchema, TSchema>) => Promise<T>): Promise<T>; | ||
transaction<T>(_transaction: (tx: XataTransaction<TFullSchema, TRelations, TTablesConfig, TSchema>) => Promise<T>): Promise<T>; | ||
} | ||
@@ -55,0 +60,0 @@ export interface XataHttpQueryResultHKT extends PgQueryResultHKT { |
@@ -8,3 +8,3 @@ import { entityKind } from "../entity.js"; | ||
class XataHttpPreparedQuery extends PgPreparedQuery { | ||
constructor(client, query, logger, fields, _isResponseInArrayMode, customResultMapper) { | ||
constructor(client, query, logger, fields, _isResponseInArrayMode, customResultMapper, isRqbV2Query) { | ||
super(query); | ||
@@ -16,5 +16,8 @@ this.client = client; | ||
this.customResultMapper = customResultMapper; | ||
this.isRqbV2Query = isRqbV2Query; | ||
} | ||
static [entityKind] = "XataHttpPreparedQuery"; | ||
async execute(placeholderValues = {}) { | ||
if (this.isRqbV2Query) | ||
return this.executeRqbV2(placeholderValues); | ||
const params = fillPlaceholders(this.query.params, placeholderValues); | ||
@@ -31,2 +34,15 @@ this.logger.logQuery(this.query.sql, params); | ||
} | ||
async executeRqbV2(placeholderValues = {}) { | ||
const params = fillPlaceholders(this.query.params, placeholderValues); | ||
this.logger.logQuery(this.query.sql, params); | ||
const { client, query, customResultMapper } = this; | ||
const { warning, records } = await client.sql({ | ||
statement: query.sql, | ||
params, | ||
responseType: "json" | ||
}); | ||
if (warning) | ||
console.warn(warning); | ||
return customResultMapper(records); | ||
} | ||
all(placeholderValues = {}) { | ||
@@ -48,5 +64,6 @@ const params = fillPlaceholders(this.query.params, placeholderValues); | ||
class XataHttpSession extends PgSession { | ||
constructor(client, dialect, schema, options = {}) { | ||
constructor(client, dialect, relations, schema, options = {}) { | ||
super(dialect); | ||
this.client = client; | ||
this.relations = relations; | ||
this.schema = schema; | ||
@@ -68,2 +85,13 @@ this.options = options; | ||
} | ||
prepareRelationalQuery(query, fields, name, customResultMapper) { | ||
return new XataHttpPreparedQuery( | ||
this.client, | ||
query, | ||
this.logger, | ||
fields, | ||
false, | ||
customResultMapper, | ||
true | ||
); | ||
} | ||
async query(query, params) { | ||
@@ -70,0 +98,0 @@ this.logger.logQuery(query, params); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
7191256
1874
69443