drizzle-orm
Version:
Drizzle ORM package for SQL databases
262 lines • 8.1 kB
JavaScript
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