jii
Version:
Jii - Full-Stack JavaScript Framework
304 lines (263 loc) • 9.1 kB
JavaScript
/**
* @author <a href="http://www.affka.ru">Vladimir Kozhin</a>
* @license MIT
*/
'use strict';
const Jii = require('../BaseJii');
const ApplicationException = require('../exceptions/ApplicationException');
const Command = require('./Command');
const _isString = require('lodash/isString');
const _isFunction = require('lodash/isFunction');
const _each = require('lodash/each');
const Component = require('../base/Component');
class BaseConnection extends Component {
preInit() {
/**
* @type {boolean}
*/
this._isOpen = false;
/**
* @type {BaseSchema} the database schema
*/
this._schema = null;
/**
* @type {string}
*/
this.driverName = '';
/**
* @type {string|object}
*/
this.schemaClass = '';
/**
* @type {string} the common prefix or suffix for table names. If a table name is given
* as `{{%TableName}}`, then the percentage character `%` will be replaced with this
* property value. For example, `{{%post}}` becomes `{{tbl_post}}`.
*/
this.tablePrefix = '';
/**
* @type {string} the charset used for database connection. The property is only used
* for MySQL, PostgreSQL and CUBRID databases. Defaults to null, meaning using default charset
* as specified by the database.
*
* Note that if you're using GBK or BIG5 then it's highly recommended to
* specify charset via DSN like 'mysql:dbname=mydatabase;host=127.0.0.1;charset=GBK;'.
*/
this.charset = null;
/**
* @type {string} the password for establishing DB connection. Defaults to `null` meaning no password to use.
*/
this.password = null;
/**
* @type {string} the username for establishing DB connection. Defaults to `null` meaning no username to use.
*/
this.username = null;
super.preInit(...arguments);
}
/**
* Returns a value indicating whether the DB connection is established.
* @returns {boolean} whether the DB connection is established
*/
getIsActive() {
return this._isOpen;
}
/**
* @deprecated
* @return {*}
*/
open() {
return this.start();
}
/**
* @deprecated
* @return {*}
*/
close() {
return this.stop();
}
/**
* Establishes a DB connection.
* It does nothing if a DB connection has already been established.
* @throws Exception if connection fails
* @return {Promise}
*/
start() {
if (this._isOpen) {
return;
}
this._isOpen = true;
this._initConnection();
// Load all table schemas in default database
return this.getSchema().loadTableSchemas();
}
/**
* Closes the currently active DB connection.
* It does nothing if the connection is already closed.
*/
stop() {
if (this._isOpen) {
this._isOpen = false;
this._schema = null;
this._closeConnection();
}
}
/**
* Initializes the DB connection.
* This method is invoked right after the DB connection is established.
* if [[emulatePrepare]] is true, and sets the database [[charset]] if it is not empty.
* It then triggers an [[EVENT_AFTER_OPEN]] event.
* @protected
*/
_initConnection() {
}
/**
* @protected
*/
_closeConnection() {
}
/**
* Creates a command for execution.
* @param {string} [sql] the SQL statement to be executed
* @param {object} [params] the parameters to be bound to the SQL statement
* @returns {static} the DB command
*/
createCommand(sql, params) {
sql = sql || null;
params = params || [];
if (!this._isOpen) {
throw new ApplicationException('Database connection is not opened. Use open() method before send queries.');
}
this.open();
var command = new Command({
db: this,
sql: sql
});
return command.bindValues(params);
}
/**
* Returns the schema information for the database opened by this connection.
* @returns {BaseSchema} the schema information for the database opened by this connection.
*/
getSchema() {
if (this._schema === null) {
var config = _isString(this.schemaClass) || _isFunction(this.schemaClass) ? {
className: this.schemaClass
} : this.schemaClass;
this._schema = Jii.createObject(config);
this._schema.db = this;
}
return this._schema;
}
/**
* Returns the query builder for the current DB connection.
* @returns {QueryBuilder} the query builder for the current DB connection.
*/
getQueryBuilder() {
return this.getSchema().getQueryBuilder();
}
/**
* Obtains the schema information for the named table.
* @param {string} name table name.
* @returns {*} table schema information. Null if the named table does not exist.
*/
getTableSchema(name) {
return this.getSchema().getTableSchema(name);
}
/**
*
* @param {string[]} tableNames
* @returns {{}}
*/
getModelSchemaJson(tableNames) {
tableNames = tableNames || [];
var obj = {};
_each(tableNames, name => {
obj[name] = this.getTableSchema(name).toJSON();
});
return obj;
}
/**
* Quotes a string value for use in a query.
* Note that if the parameter is not a string, it will be returned without change.
* @param {string} str string to be quoted
* @returns {string} the properly quoted string
* @see http://www.php.net/manual/en/function.PDO-quote.php
*/
quoteValue(str) {
return this.getSchema().quoteValue(str);
}
/**
* Quotes a table name for use in a query.
* If the table name contains schema prefix, the prefix will also be properly quoted.
* If the table name is already quoted or contains special characters including '(', '[[' and '{{',
* then this method will do nothing.
* @param {string} name table name
* @returns {string} the properly quoted table name
*/
quoteTableName(name) {
return this.getSchema().quoteTableName(name);
}
/**
* Quotes a column name for use in a query.
* If the column name contains prefix, the prefix will also be properly quoted.
* If the column name is already quoted or contains special characters including '(', '[[' and '{{',
* then this method will do nothing.
* @param {string} name column name
* @returns {string} the properly quoted column name
*/
quoteColumnName(name) {
return this.getSchema().quoteColumnName(name);
}
/**
* Processes a SQL statement by quoting table and column names that are enclosed within double brackets.
* Tokens enclosed within double curly brackets are treated as table names, while
* tokens enclosed within double square brackets are column names. They will be quoted accordingly.
* Also, the percentage character "%" at the beginning or ending of a table name will be replaced
* with [[tablePrefix]].
* @param {string} sql the SQL to be quoted
* @returns {string} the quoted SQL
*/
quoteSql(sql) {
return sql.replace(/\{\{(%?[\w\-\. ]+%?)\}\}|\[\[([\w\-\. ]+)\]\]/g, (match, tableName, columnName) => {
if (columnName) {
return this.quoteColumnName(columnName);
}
return this.quoteTableName(tableName.replace(/%/g, this.tablePrefix));
});
}
/**
*
* @param {function} modelClassName
* @returns {Collection|null}
*/
getRootCollection(modelClassName) {
return null;
}
/**
* Returns the name of the DB driver. Based on the the current [[dsn]], in case it was not set explicitly
* by an end user.
* @returns {string} name of the DB driver
*/
getDriverName() {
return this._driverName;
}
/**
* Changes the current driver name.
* @param {string} driverName name of the DB driver
*/
setDriverName(driverName) {
this._driverName = driverName.toLowerCase();
}
/**
*
* @param {string} sql
* @param {string} [method]
*/
exec(sql, method) {
method = method || null;
}
}
/**
* @event Event an event that is triggered after a DB connection is established
*/
BaseConnection.EVENT_AFTER_OPEN = 'afterOpen';
module.exports = BaseConnection;