UNPKG

drizzle-orm

Version:

Drizzle ORM package for SQL databases

262 lines • 8.1 kB
import { entityKind } from "../entity.js"; import { SelectionProxyHandler } from "../selection-proxy.js"; import { sql } from "../sql/sql.js"; import { WithSubquery } from "../subquery.js"; import { MySqlCountBuilder } from "./query-builders/count.js"; import { MySqlDeleteBase, MySqlInsertBuilder, MySqlSelectBuilder, MySqlUpdateBuilder, QueryBuilder } from "./query-builders/index.js"; import { RelationalQueryBuilder } from "./query-builders/query.js"; class MySqlDatabase { constructor(dialect, session, schema, mode) { this.dialect = dialect; this.session = session; this.mode = mode; this._ = schema ? { schema: schema.schema, fullSchema: schema.fullSchema, tableNamesMap: schema.tableNamesMap } : { schema: void 0, fullSchema: {}, tableNamesMap: {} }; this.query = {}; if (this._.schema) { for (const [tableName, columns] of Object.entries(this._.schema)) { this.query[tableName] = new RelationalQueryBuilder( schema.fullSchema, this._.schema, this._.tableNamesMap, schema.fullSchema[tableName], columns, dialect, session, this.mode ); } } } static [entityKind] = "MySqlDatabase"; query; /** * Creates a subquery that defines a temporary named result set as a CTE. * * It is useful for breaking down complex queries into simpler parts and for reusing the result set in subsequent parts of the query. * * See docs: {@link https://orm.drizzle.team/docs/select#with-clause} * * @param alias The alias for the subquery. * * Failure to provide an alias will result in a DrizzleTypeError, preventing the subquery from being referenced in other queries. * * @example * * ```ts * // Create a subquery with alias 'sq' and use it in the select query * const sq = db.$with('sq').as(db.select().from(users).where(eq(users.id, 42))); * * const result = await db.with(sq).select().from(sq); * ``` * * To select arbitrary SQL values as fields in a CTE and reference them in other CTEs or in the main query, you need to add aliases to them: * * ```ts * // Select an arbitrary SQL value as a field in a CTE and reference it in the main query * const sq = db.$with('sq').as(db.select({ * name: sql<string>`upper(${users.name})`.as('name'), * }) * .from(users)); * * const result = await db.with(sq).select({ name: sq.name }).from(sq); * ``` */ $with = (alias, selection) => { const self = this; const as = (qb) => { if (typeof qb === "function") { qb = qb(new QueryBuilder(self.dialect)); } return new Proxy( new WithSubquery( qb.getSQL(), selection ?? ("getSelectedFields" in qb ? qb.getSelectedFields() ?? {} : {}), alias, true ), new SelectionProxyHandler({ alias, sqlAliasedBehavior: "alias", sqlBehavior: "error" }) ); }; return { as }; }; $count(source, filters) { return new MySqlCountBuilder({ source, filters, session: this.session }); } /** * Incorporates a previously defined CTE (using `$with`) into the main query. * * This method allows the main query to reference a temporary named result set. * * See docs: {@link https://orm.drizzle.team/docs/select#with-clause} * * @param queries The CTEs to incorporate into the main query. * * @example * * ```ts * // Define a subquery 'sq' as a CTE using $with * const sq = db.$with('sq').as(db.select().from(users).where(eq(users.id, 42))); * * // Incorporate the CTE 'sq' into the main query and select from it * const result = await db.with(sq).select().from(sq); * ``` */ with(...queries) { const self = this; function select(fields) { return new MySqlSelectBuilder({ fields: fields ?? void 0, session: self.session, dialect: self.dialect, withList: queries }); } function selectDistinct(fields) { return new MySqlSelectBuilder({ fields: fields ?? void 0, session: self.session, dialect: self.dialect, withList: queries, distinct: true }); } function update(table) { return new MySqlUpdateBuilder(table, self.session, self.dialect, queries); } function delete_(table) { return new MySqlDeleteBase(table, self.session, self.dialect, queries); } return { select, selectDistinct, update, delete: delete_ }; } select(fields) { return new MySqlSelectBuilder({ fields: fields ?? void 0, session: this.session, dialect: this.dialect }); } selectDistinct(fields) { return new MySqlSelectBuilder({ fields: fields ?? void 0, session: this.session, dialect: this.dialect, distinct: true }); } /** * Creates an update query. * * Calling this method without `.where()` clause will update all rows in a table. The `.where()` clause specifies which rows should be updated. * * Use `.set()` method to specify which values to update. * * See docs: {@link https://orm.drizzle.team/docs/update} * * @param table The table to update. * * @example * * ```ts * // Update all rows in the 'cars' table * await db.update(cars).set({ color: 'red' }); * * // Update rows with filters and conditions * await db.update(cars).set({ color: 'red' }).where(eq(cars.brand, 'BMW')); * ``` */ update(table) { return new MySqlUpdateBuilder(table, this.session, this.dialect); } /** * Creates an insert query. * * Calling this method will create new rows in a table. Use `.values()` method to specify which values to insert. * * See docs: {@link https://orm.drizzle.team/docs/insert} * * @param table The table to insert into. * * @example * * ```ts * // Insert one row * await db.insert(cars).values({ brand: 'BMW' }); * * // Insert multiple rows * await db.insert(cars).values([{ brand: 'BMW' }, { brand: 'Porsche' }]); * ``` */ insert(table) { return new MySqlInsertBuilder(table, this.session, this.dialect); } /** * Creates a delete query. * * Calling this method without `.where()` clause will delete all rows in a table. The `.where()` clause specifies which rows should be deleted. * * See docs: {@link https://orm.drizzle.team/docs/delete} * * @param table The table to delete from. * * @example * * ```ts * // Delete all rows in the 'cars' table * await db.delete(cars); * * // Delete rows with filters and conditions * await db.delete(cars).where(eq(cars.color, 'green')); * ``` */ delete(table) { return new MySqlDeleteBase(table, this.session, this.dialect); } execute(query) { return this.session.execute(typeof query === "string" ? sql.raw(query) : query.getSQL()); } transaction(transaction, config) { return this.session.transaction(transaction, config); } } const withReplicas = (primary, replicas, getReplica = () => replicas[Math.floor(Math.random() * replicas.length)]) => { const select = (...args) => getReplica(replicas).select(...args); const selectDistinct = (...args) => getReplica(replicas).selectDistinct(...args); const $count = (...args) => getReplica(replicas).$count(...args); const $with = (...args) => getReplica(replicas).with(...args); const update = (...args) => primary.update(...args); const insert = (...args) => primary.insert(...args); const $delete = (...args) => primary.delete(...args); const execute = (...args) => primary.execute(...args); const transaction = (...args) => primary.transaction(...args); return { ...primary, update, insert, delete: $delete, execute, transaction, $primary: primary, select, selectDistinct, $count, with: $with, get query() { return getReplica(replicas).query; } }; }; export { MySqlDatabase, withReplicas }; //# sourceMappingURL=db.js.map