mn_type_sql;
}
/**
* Adds column options.
*
* @param string $type The native type.
* @param array $options The options.
*
* @return string The SQL statement for the column options.
*
* @throws Exception If invalid arguments are supplied.
*/
public function add_column_options( $type, $options ) {
$sql = '';
if ( ! \is_array( $options ) ) {
return $sql;
}
if ( \array_key_exists( 'unsigned', $options ) && $options['unsigned'] === true ) {
$sql .= ' UNSIGNED';
}
if ( \array_key_exists( 'character', $options ) ) {
$sql .= \sprintf( ' CHARACTER SET %s', $this->identifier( $options['character'] ) );
}
if ( \array_key_exists( 'collate', $options ) ) {
$sql .= \sprintf( ' COLLATE %s', $this->identifier( $options['collate'] ) );
}
if ( \array_key_exists( 'auto_increment', $options ) && $options['auto_increment'] === true ) {
$sql .= ' auto_increment';
}
if ( \array_key_exists( 'default', $options ) && $options['default'] !== null ) {
if ( $this->is_sql_method_call( $options['default'] ) ) {
throw new Exception( 'MySQL does not support function calls as default values, constants only.' );
}
if ( \is_int( $options['default'] ) ) {
$default_format = '%d';
}
elseif ( \is_bool( $options['default'] ) ) {
$default_format = "'%d'";
}
elseif ( $options['default'] === 'CURRENT_TIMESTAMP' ) {
$default_format = '%s';
}
else {
$default_format = "'%s'";
}
$default_value = \sprintf( $default_format, $options['default'] );
$sql .= \sprintf( ' DEFAULT %s', $default_value );
}
if ( \array_key_exists( 'null', $options ) ) {
if ( $options['null'] === false || $options['null'] === 'NO' ) {
$sql .= ' NOT NULL';
}
elseif ( $type === 'timestamp' ) {
$sql .= ' NULL';
}
}
if ( \array_key_exists( 'comment', $options ) ) {
$sql .= \sprintf( " COMMENT '%s'", $this->quote_string( $options['comment'] ) );
}
if ( \array_key_exists( 'extra', $options ) ) {
$sql .= \sprintf( ' %s', $this->quote_string( $options['extra'] ) );
}
if ( \array_key_exists( 'after', $options ) ) {
$sql .= \sprintf( ' AFTER %s', $this->identifier( $options['after'] ) );
}
return $sql;
}
/**
* Returns a list of all versions that have been migrated.
*
* @return string[] The version numbers that have been migrated.
*/
public function get_migrated_versions() {
$result = $this->select_all( \sprintf( 'SELECT version FROM %s', $this->get_schema_version_table_name() ) );
return \array_column( $result, 'version' );
}
/**
* Adds a migrated version.
*
* @param string $version The version.
*
* @return bool Whether or not the version was succesfully set.
*/
public function add_version( $version ) {
$sql = \sprintf( "INSERT INTO %s (version) VALUES ('%s')", $this->get_schema_version_table_name(), $version );
return $this->execute_ddl( $sql );
}
/**
* Removes a migrated version.
*
* @param string $version The version.
*
* @return bool Whether or not the version was succesfully removed.
*/
public function remove_version( $version ) {
$sql = \sprintf( "DELETE FROM %s WHERE version = '%s'", $this->get_schema_version_table_name(), $version );
return $this->execute_ddl( $sql );
}
/**
* Returns a message displaying the current version
*
* @return string
*/
public function __toString() {
return self::class . ', version ' . $this->version;
}
/**
* Returns an index name.
*
* @param string $table_name The table name.
* @param string $column_name The column name.
*
* @return string The index name.
*/
private function get_index_name( $table_name, $column_name ) {
$name = \preg_replace( '/\\W/', '_', $table_name );
$name = \preg_replace( '/\\_{2,}/', '_', $name );
// If the column parameter is an array then the user wants to create a multi-column index.
if ( \is_array( $column_name ) ) {
$column_str = \implode( '_and_', $column_name );
}
else {
$column_str = $column_name;
}
$name .= \sprintf( '_%s', $column_str );
return $name;
}
/**
* Returns the type of a query.
*
* @param string $query The query to run.
*
* @return int The query type.
*/
private function determine_query_type( $query ) {
$query = \strtolower( \trim( $query ) );
$match = [];
\preg_match( '/^(\\w)*/i', $query, $match );
$type = $match[0];
switch ( $type ) {
case 'select':
return Constants::SQL_SELECT;
case 'update':
return Constants::SQL_UPDATE;
case 'delete':
return Constants::SQL_DELETE;
case 'insert':
return Constants::SQL_INSERT;
case 'alter':
return Constants::SQL_ALTER;
case 'drop':
return Constants::SQL_DROP;
case 'create':
return Constants::SQL_CREATE;
case 'show':
return Constants::SQL_SHOW;
case 'rename':
return Constants::SQL_RENAME;
case 'set':
return Constants::SQL_SET;
default:
return Constants::SQL_UNKNOWN_QUERY_TYPE;
}
}
/**
* Detect whether or not the string represents a function call and if so
* do not wrap it in single-quotes, otherwise do wrap in single quotes.
*
* @param string $text The string.
*
* @return bool Whether or not it's a SQL function call.
*/
private function is_sql_method_call( $text ) {
$text = \trim( $text );
if ( \substr( $text, -2, 2 ) === '()' ) {
return true;
}
return false;
}
/**
* Checks if a transaction is active.
*
* @return bool
*/
private function in_transaction() {
return $this->in_transaction;
}
/**
* Starts a transaction.
*
* @return void
*
* @throws Exception If a transaction was already started.
*/
private function begin_transaction() {
global $wpdb;
if ( $this->in_transaction === true ) {
throw new Exception( 'Transaction already started' );
}
$wpdb->query( 'START TRANSACTION' );
$this->in_transaction = true;
}
/**
* Commits a transaction.
*
* @return void
*
* @throws Exception If no transaction was strated.
*/
private function commit() {
global $wpdb;
if ( $this->in_transaction === false ) {
throw new Exception( 'Transaction not started' );
}
$wpdb->query( 'COMMIT' );
$this->in_transaction = false;
}
/**
* Rollbacks a transaction.
*
* @return void
*
* @throws Exception If no transaction was started.
*/
private function rollback() {
global $wpdb;
if ( $this->in_transaction === false ) {
throw new Exception( 'Transaction not started' );
}
$wpdb->query( 'ROLLBACK' );
$this->in_transaction = false;
}
}