@adonisjs/lucid
Version:
SQL ORM built on top of Active Record pattern
212 lines (211 loc) • 6.71 kB
JavaScript
/*
* @adonisjs/lucid
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
import { RawBuilder } from '../database/static_builder/raw.js';
export class MysqlDialect {
client;
config;
name = 'mysql';
supportsAdvisoryLocks = true;
supportsViews = true;
supportsTypes = false;
supportsDomains = false;
supportsReturningStatement = false;
/**
* Reference to the database version. Knex.js fetches the version after
* the first database query, so it will be set to undefined initially
*/
version;
/**
* The default format for datetime column. The date formats is
* valid for luxon date parsing library
*/
dateTimeFormat = 'yyyy-MM-dd HH:mm:ss';
constructor(client, config) {
this.client = client;
this.config = config;
this.version = this.client.getReadClient()['context']['client'].version;
}
/**
* Returns a filter function to omit tables, views and
* types from the excludeList
*/
if (!excludeList) {
return () => true;
}
return (name) => {
return !excludeList.includes(name);
};
}
/**
* Truncate mysql table with option to cascade
*/
async truncate(table, cascade = false) {
if (!cascade) {
return this.client.knexQuery().table(table).truncate();
}
/**
* Cascade and truncate
*/
const trx = await this.client.transaction();
try {
await trx.rawQuery('SET FOREIGN_KEY_CHECKS=0;');
await trx.knexQuery().table(table).truncate();
await trx.rawQuery('SET FOREIGN_KEY_CHECKS=1;');
await trx.commit();
}
catch (error) {
await trx.rollback();
throw error;
}
}
/**
* Truncates all the tables that are in the database.
*
* You may exclude certain tables from getting truncated by providing them
* under the "excludeTables" list.
*
* @example
* ```ts
* // Truncate all tables
* await dialect.truncateAllTables()
*
* // Exclude the users table
* await dialect.truncateAllTables(['users'])
* ```
*/
async truncateAllTables(excludeTables) {
const tables = await this.getAllTables();
const knex = this.client.getWriteClient();
/**
* Collecting the tables to be dropped. We ignore tables from the exclude
* tables list.
*/
const tablesToTrunacte = tables.filter(this.
if (tablesToTrunacte.length) {
const trx = await knex.transaction();
try {
await trx.schema.raw('SET FOREIGN_KEY_CHECKS=0;');
for (let table of tablesToTrunacte) {
await trx.table(table).truncate();
}
await trx.schema.raw('SET FOREIGN_KEY_CHECKS=1;');
await trx.commit();
}
catch (error) {
await trx.rollback();
throw error;
}
}
}
/**
* Returns an array of table names
*/
async getAllTables() {
const tables = await this.client
.query()
.from('information_schema.tables')
.select('table_name as table_name')
.where('TABLE_TYPE', 'BASE TABLE')
.where('table_schema', new RawBuilder('database()'))
.orderBy('table_name', 'asc');
return tables.map(({ table_name }) => table_name);
}
/**
* Returns an array of all views names
*/
async getAllViews() {
const tables = await this.client
.query()
.from('information_schema.tables')
.select('table_name as table_name')
.where('TABLE_TYPE', 'VIEW')
.where('table_schema', new RawBuilder('database()'))
.orderBy('table_name', 'asc');
return tables.map(({ table_name }) => table_name);
}
/**
* Returns an array of all types names
*/
async getAllTypes() {
throw new Error("MySQL doesn't support types");
}
/**
* Returns an array of all domain names
*/
async getAllDomains() {
throw new Error("MySQL doesn't support domains");
}
/**
* Drop all tables inside the database
*/
async dropAllTables() {
let tables = await this.getAllTables();
/**
* Filter out tables that are not allowed to be dropped
*/
tables = tables.filter((table) => !(this.config.wipe?.ignoreTables || []).includes(table));
/**
* Add backquote around table names to avoid syntax errors
* in case of a table name with a reserved keyword
*/
tables = tables.map((table) => '`' + table + '`');
if (!tables.length) {
return;
}
/**
* Cascade and truncate
*/
const trx = await this.client.transaction();
try {
await trx.rawQuery('SET FOREIGN_KEY_CHECKS=0;');
await trx.rawQuery(`DROP TABLE ${tables.join(',')};`);
await trx.rawQuery('SET FOREIGN_KEY_CHECKS=1;');
await trx.commit();
}
catch (error) {
await trx.rollback();
throw error;
}
}
/**
* Drop all views inside the database
*/
async dropAllViews() {
const views = await this.getAllViews();
return this.client.rawQuery(`DROP VIEW ${views.join(',')};`);
}
/**
* Drop all custom types inside the database
*/
async dropAllTypes() {
throw new Error("MySQL doesn't support types");
}
/**
* Drop all domains inside the database
*/
async dropAllDomains() {
throw new Error("MySQL doesn't support domains");
}
/**
* Attempts to add advisory lock to the database and
* returns it's status.
*/
async getAdvisoryLock(key, timeout = 0) {
const response = await this.client.rawQuery(`SELECT GET_LOCK('${key}', ${timeout}) as lock_status;`);
return response[0] && response[0][0] && response[0][0].lock_status === 1;
}
/**
* Releases the advisory lock
*/
async releaseAdvisoryLock(key) {
const response = await this.client.rawQuery(`SELECT RELEASE_LOCK('${key}') as lock_status;`);
return response[0] && response[0][0] && response[0][0].lock_status === 1;
}
}