diff --git a/classes/db/DB.class.php b/classes/db/DB.class.php index 95ad0755b..f312ff97e 100644 --- a/classes/db/DB.class.php +++ b/classes/db/DB.class.php @@ -23,24 +23,7 @@ class DB * @var array */ protected static $priority_dbms = array( - 'mysqli' => 6, - 'cubrid' => 2, - 'mssql' => 1 - ); - - /** - * operations for condition - * @var array - */ - protected static $cond_operation = array( - 'equal' => '=', - 'more' => '>=', - 'excess' => '>', - 'less' => '<=', - 'below' => '<', - 'notequal' => '<>', - 'notnull' => 'is not null', - 'null' => 'is null', + 'mysql' => 1, ); /** @@ -108,7 +91,7 @@ class DB protected $cache_file = 'files/cache/queries/'; /** - * stores database type: 'mysql','cubrid','mssql' etc. or 'db' when database is not yet set + * stores database type, e.g. mysql * @var string */ public $db_type; @@ -136,15 +119,15 @@ class DB if(!$db_type) { $db_type = config('db.master.type'); - if (config('db.master.engine') === 'innodb') - { - $db_type .= '_innodb'; - } } if(!$db_type && Context::isInstalled()) { return new BaseObject(-1, 'msg_db_not_setted'); } + if(!strncmp($db_type, 'mysql', 5)) + { + $db_type = 'mysql'; + } if(!isset($GLOBALS['__DB__'])) { @@ -271,7 +254,7 @@ class DB // after creating instance of class, check is supported foreach ($supported_list as $db_type) { - if (strncasecmp($db_type, 'mysql', 5) === 0 && strtolower($db_type) !== 'mysqli') + if (strtolower($db_type) !== 'mysql') { continue; } @@ -707,6 +690,7 @@ class DB $tableObjects = $query->getTables(); $index_hint_list = ''; + /* foreach($tableObjects as $tableObject) { if(is_a($tableObject, 'CubridTableWithHint')) @@ -719,6 +703,7 @@ class DB { $index_hint_list = 'USING INDEX ' . $index_hint_list; } + */ $groupBy = $query->getGroupByString(); if($groupBy != '') diff --git a/classes/db/DBCubrid.class.php b/classes/db/DBCubrid.class.php deleted file mode 100644 index 0cc8217af..000000000 --- a/classes/db/DBCubrid.class.php +++ /dev/null @@ -1,1326 +0,0 @@ - */ - -/** - * - DB child class - * - Cubrid DBMS to use the class - * - Works with CUBRID up to 8.4.1 - * - * @author NAVER (developers@xpressengine.com) - * @package /classes/db - * @version 0.1 - */ -class DBCubrid extends DB -{ - - /** - * prefix of Rhymix tables(One more Rhymix can be installed on a single DB) - * @var string - */ - var $prefix = 'rx_'; - - /** - * max size of constant in CUBRID(if string is larger than this, '...'+'...' should be used) - * @var int - */ - var $cutlen = 12000; - var $comment_syntax = '/* %s */'; - - /** - * column type used in CUBRID - * - * column_type should be replaced for each DBMS's type - * becasue it uses commonly defined type in the schema/query xml - * @var array - */ - var $column_type = array( - 'bignumber' => 'numeric(20)', - 'number' => 'integer', - 'varchar' => 'character varying', - 'char' => 'character', - 'tinytext' => 'character varying(256)', - 'bigtext' => 'character varying(1073741823)', - 'text' => 'character varying(1073741823)', - 'date' => 'character varying(14)', - 'float' => 'float', - ); - - /** - * constructor - * @return void - */ - function __construct() - { - $this->_setDBInfo(); - $this->_connect(); - } - - /** - * DB Connect - * this method is private - * @param array $connection connection's value is db_hostname, db_port, db_database, db_userid, db_password - * @return resource - */ - function __connect($connection) - { - // attempts to connect - $result = @cubrid_connect($connection['host'], $connection['port'], $connection['database'], $connection['user'], $connection['pass']); - - // check connections - if(!$result) - { - $this->setError(-1, 'database connect fail'); - return; - } - - if(!defined('__CUBRID_VERSION__')) - { - $cubrid_version = cubrid_get_server_info($result); - $cubrid_version_elem = explode('.', $cubrid_version); - $cubrid_version = $cubrid_version_elem[0] . '.' . $cubrid_version_elem[1] . '.' . $cubrid_version_elem[2]; - define('__CUBRID_VERSION__', $cubrid_version); - } - - if(version_compare(__CUBRID_VERSION__, '9.0', '<')) - { - $this->setError(-1, 'Rhymix requires CUBRID 9.0 or later. Current CUBRID version is ' . __CUBRID_VERSION__); - return; - } - - $this->db_version = __CUBRID_VERSION__; - cubrid_set_autocommit($result, CUBRID_AUTOCOMMIT_TRUE); - - return $result; - } - - /** - * DB disconnection - * this method is private - * @param resource $connection - * @return void - */ - function _close($connection) - { - @cubrid_commit($connection); - @cubrid_disconnect($connection); - $this->transaction_started = FALSE; - } - - /** - * Handles quatation of the string variables from the query - * @param string $string - * @return string - */ - function addQuotes($string) - { - if(!is_numeric($string)) - { - /* - if ($this->isConnected()) { - $string = cubrid_real_escape_string($string); - } - else { - $string = str_replace("'","\'",$string); - } - */ - - $string = str_replace("'", "''", $string); - } - - return $string; - } - - /** - * DB transaction start - * this method is private - * @return boolean - */ - function _begin($transactionLevel = 0) - { - if(__CUBRID_VERSION__ >= '8.4.0') - { - $connection = $this->_getConnection('master'); - - if(!$transactionLevel) - { - cubrid_set_autocommit($connection, CUBRID_AUTOCOMMIT_FALSE); - } - else - { - $this->_query("SAVEPOINT SP" . $transactionLevel, $connection); - } - } - return TRUE; - } - - /** - * DB transaction rollback - * this method is private - * @return boolean - */ - function _rollback($transactionLevel = 0) - { - $connection = $this->_getConnection('master'); - - $point = $transactionLevel - 1; - - if($point) - { - $this->_query("ROLLBACK TO SP" . $point, $connection); - } - else - { - @cubrid_rollback($connection); - } - - return TRUE; - } - - /** - * DB transaction commit - * this method is private - * @return boolean - */ - function _commit() - { - $connection = $this->_getConnection('master'); - @cubrid_commit($connection); - return TRUE; - } - - /** - * Execute the query - * this method is private - * @param string $query - * @param resource $connection - * @return resource - */ - function __query($query, $connection) - { - if($this->use_prepared_statements == 'Y') - { - $req = @cubrid_prepare($connection, $query); - if(!$req) - { - $this->_setError(); - return false; - } - - $position = 0; - if($this->param) - { - foreach($this->param as $param) - { - $value = $param->getUnescapedValue(); - $type = $param->getType(); - - if($param->isColumnName()) - { - continue; - } - - switch($type) - { - case 'number' : - $bind_type = 'numeric'; - break; - case 'varchar' : - $bind_type = 'string'; - break; - default: - $bind_type = 'string'; - } - - if(is_array($value)) - { - foreach($value as $v) - { - $bound = @cubrid_bind($req, ++$position, $v, $bind_type); - if(!$bound) - { - $this->_setError(); - return false; - } - } - } - else - { - $bound = @cubrid_bind($req, ++$position, $value, $bind_type); - if(!$bound) - { - $this->_setError(); - return false; - } - } - } - } - - $result = @cubrid_execute($req); - if(!$result) - { - $this->_setError(); - return false; - } - return $req; - } - // Execute the query - $result = @cubrid_execute($connection, $query); - // error check - if(!$result) - { - $this->_setError(); - return false; - } - // Return the result - return $result; - } - - /** - * Retrieve CUBRID error and set to object - * - * @author Corina Udrescu (dev@xpressengine.org) - */ - function _setError() - { - $code = cubrid_error_code(); - $msg = cubrid_error_msg(); - - $this->setError($code, $msg); - } - - /** - * Fetch the result - * @param resource $result - * @param int|NULL $arrayIndexEndValue - * @return array - */ - function _fetch($result, $arrayIndexEndValue = NULL) - { - $output = array(); - if(!$this->isConnected() || $this->isError() || !$result) - { - return array(); - } - - if($this->use_prepared_statements == 'Y') - { - - } - - // TODO Improve this piece of code - // This code trims values from char type columns - $col_types = cubrid_column_types($result); - $col_names = cubrid_column_names($result); - $max = count($col_types); - - for($count = 0; $count < $max; $count++) - { - if(preg_match("/^char/", $col_types[$count]) > 0) - { - $char_type_fields[] = $col_names[$count]; - } - } - - while($tmp = cubrid_fetch($result, CUBRID_OBJECT)) - { - if(is_array($char_type_fields)) - { - foreach($char_type_fields as $val) - { - $tmp->{$val} = rtrim($tmp->{$val}); - } - } - - if($arrayIndexEndValue) - { - $output[$arrayIndexEndValue--] = $tmp; - } - else - { - $output[] = $tmp; - } - } - - unset($char_type_fields); - - if($result) - { - cubrid_close_request($result); - } - - if(count($output) == 1) - { - // If call is made for pagination, always return array - if(isset($arrayIndexEndValue)) - { - return $output; - } - // Else return object instead of array - else - { - return $output[0]; - } - } - return $output; - } - - /** - * Return the sequence value incremented by 1 - * Auto_increment column only used in the CUBRID sequence table - * @return int - */ - function getNextSequence() - { - $this->_makeSequence(); - - $query = sprintf("select \"%ssequence\".\"nextval\" as \"seq\" from db_root", $this->prefix); - $result = $this->_query($query); - $output = $this->_fetch($result); - - return $output->seq; - } - - /** - * if the table already exists, set the status to GLOBALS - * @return void - */ - function _makeSequence() - { - if($_GLOBALS['XE_EXISTS_SEQUENCE']) - return; - - // check cubrid serial - $query = sprintf('select count(*) as "count" from "db_serial" where name=\'%ssequence\'', $this->prefix); - $result = $this->_query($query); - $output = $this->_fetch($result); - - // if do not create serial - if($output->count == 0) - { - $query = sprintf('select max("a"."srl") as "srl" from ' . - '( select max("document_srl") as "srl" from ' . - '"%sdocuments" UNION ' . - 'select max("comment_srl") as "srl" from ' . - '"%scomments" UNION ' . - 'select max("member_srl") as "srl" from ' . - '"%smember"' . - ') as "a"', $this->prefix, $this->prefix, $this->prefix); - - $result = $this->_query($query); - $output = $this->_fetch($result); - $srl = $output->srl; - if($srl < 1) - { - $start = 1; - } - else - { - $start = $srl + 1000000; - } - - // create sequence - $query = sprintf('create serial "%ssequence" start with %s increment by 1 minvalue 1 maxvalue 10000000000000000000000000000000000000 nocycle;', $this->prefix, $start); - $this->_query($query); - } - - $_GLOBALS['XE_EXISTS_SEQUENCE'] = TRUE; - } - - /** - * Check a table exists status - * @param string $target_name - * @return boolean - */ - function isTableExists($target_name) - { - if($target_name == 'sequence') - { - $query = sprintf("select \"name\" from \"db_serial\" where \"name\" = '%s%s'", $this->prefix, $target_name); - } - else - { - $query = sprintf("select \"class_name\" from \"db_class\" where \"class_name\" = '%s%s'", $this->prefix, $target_name); - } - - $result = $this->_query($query); - if(cubrid_num_rows($result) > 0) - { - $output = TRUE; - } - else - { - $output = FALSE; - } - - if($result) - { - cubrid_close_request($result); - } - - return $output; - } - - /** - * Add a column to the table - * @param string $table_name table name - * @param string $column_name column name - * @param string $type column type, default value is 'number' - * @param int $size column size - * @param string|int $default default value - * @param boolean $notnull not null status, default value is false - * @return void - */ - function addColumn($table_name, $column_name, $type = 'number', $size = '', $default = null, $notnull = FALSE) - { - $type = strtoupper($this->column_type[$type]); - if($type == 'INTEGER') - { - $size = ''; - } - - $query = sprintf("alter class \"%s%s\" add \"%s\" ", $this->prefix, $table_name, $column_name); - - if($type == 'char' || $type == 'varchar') - { - if($size) - { - $size = $size * 3; - } - } - - if($size) - { - $query .= sprintf("%s(%s) ", $type, $size); - } - else - { - $query .= sprintf("%s ", $type); - } - - if(isset($default)) - { - if($type == 'INTEGER' || $type == 'BIGINT' || $type == 'INT') - { - $query .= sprintf("default %d ", $default); - } - else - { - $query .= sprintf("default '%s' ", $default); - } - } - - if($notnull) - { - $query .= "not null "; - } - - return $this->_query($query); - } - - /** - * Drop a column from the table - * @param string $table_name table name - * @param string $column_name column name - * @return void - */ - function dropColumn($table_name, $column_name) - { - $query = sprintf("alter class \"%s%s\" drop \"%s\" ", $this->prefix, $table_name, $column_name); - - $this->_query($query); - } - - /** - * Modify a column (only supported in CUBRID 8.4 and above, otherwise returns false) - * @param string $table_name table name - * @param string $column_name column name - * @param string $type column type, default value is 'number' - * @param int $size column size - * @param string|int $default default value - * @param boolean $notnull not null status, default value is false - * @return bool - */ - function modifyColumn($table_name, $column_name, $type = 'number', $size = '', $default = '', $notnull = FALSE) - { - if(!version_compare(__CUBRID_VERSION__, '8.4.0', '>=')) - { - return false; - } - - $type = strtoupper($this->column_type[$type]); - if($type == 'INTEGER') - { - $size = ''; - } - - $query = sprintf("alter class \"%s%s\" modify \"%s\" ", $this->prefix, $table_name, $column_name); - - if($type == 'char' || $type == 'varchar') - { - if($size) - { - $size = $size * 3; - } - } - - if($size) - { - $query .= sprintf("%s(%s) ", $type, $size); - } - else - { - $query .= sprintf("%s ", $type); - } - - if($default) - { - if($type == 'INTEGER' || $type == 'BIGINT' || $type == 'INT') - { - $query .= sprintf("default %d ", $default); - } - else - { - $query .= sprintf("default '%s' ", $default); - } - } - - if($notnull) - { - $query .= "not null "; - } - - return $this->_query($query) ? true : false; - } - - /** - * Check column exist status of the table - * @param string $table_name table name - * @param string $column_name column name - * @return boolean - */ - function isColumnExists($table_name, $column_name) - { - $query = sprintf("select \"attr_name\" from \"db_attribute\" where " . "\"attr_name\" ='%s' and \"class_name\" = '%s%s'", $column_name, $this->prefix, $table_name); - $result = $this->_query($query); - - if(cubrid_num_rows($result) > 0) - { - $output = TRUE; - } - else - { - $output = FALSE; - } - - if($result) - { - cubrid_close_request($result); - } - - return $output; - } - - /** - * Get information about a column - * @param string $table_name table name - * @param string $column_name column name - * @return BaseObject - */ - function getColumnInfo($table_name, $column_name) - { - $query = sprintf("select * from \"db_attribute\" where " . "\"attr_name\" ='%s' and \"class_name\" = '%s%s'", $column_name, $this->prefix, $table_name); - $result = $this->_query($query); - if($this->isError()) - { - return; - } - $output = $this->_fetch($result); - if($output) - { - $dbtype = strtolower($output->data_type); - if($dbtype === 'string') $dbtype = 'character varying'; - $size = ($output->prec > 0) ? $output->prec : null; - if($xetype = array_search("$dbtype($size)", $this->column_type)) - { - $dbtype = "$dbtype($size)"; - $size = null; - } - elseif($size !== null) - { - if($xetype = array_search($dbtype, $this->column_type)) - { - if($size % 3 == 0) $size = intval($size / 3); - } - else - { - $xetype = $dbtype; - } - } - else - { - $xetype = $dbtype; - $size = null; - } - return (object)array( - 'name' => $output->attr_name, - 'dbtype' => $dbtype, - 'xetype' => $xetype, - 'size' => $size, - 'default_value' => $output->default_value, - 'notnull' => !$output->is_nullable, - ); - } - else - { - return false; - } - } - - /** - * Add an index to the table - * $target_columns = array(col1, col2) - * $is_unique? unique : none - * @param string $table_name table name - * @param string $index_name index name - * @param string|array $target_columns target column or columns - * @param boolean $is_unique - * @return void - */ - function addIndex($table_name, $index_name, $target_columns, $is_unique = FALSE) - { - if(!is_array($target_columns)) - { - $target_columns = array($target_columns); - } - - $query = sprintf("create %s index \"%s\" on \"%s%s\" (%s);", $is_unique ? 'unique' : '', $index_name, $this->prefix, $table_name, '"' . implode('","', $target_columns) . '"'); - - $this->_query($query); - } - - /** - * Drop an index from the table - * @param string $table_name table name - * @param string $index_name index name - * @param boolean $is_unique - * @return void - */ - function dropIndex($table_name, $index_name, $is_unique = FALSE) - { - $query = sprintf("drop %s index \"%s\" on \"%s%s\"", $is_unique ? 'unique' : '', $index_name, $this->prefix, $table_name); - - $this->_query($query); - } - - /** - * Check index status of the table - * @param string $table_name table name - * @param string $index_name index name - * @return boolean - */ - function isIndexExists($table_name, $index_name) - { - $query = sprintf("select \"index_name\" from \"db_index\" where " . "\"class_name\" = '%s%s' and (\"index_name\" = '%s' or \"index_name\" = '%s') ", $this->prefix, $table_name, $this->prefix . $index_name, $index_name); - $result = $this->_query($query); - - if($this->isError()) - { - return FALSE; - } - - $output = $this->_fetch($result); - - if(!$output) - { - return FALSE; - } - return TRUE; - } - - /** - * Delete duplicated index of the table - * @return boolean - */ - function deleteDuplicateIndexes() - { - $query = sprintf(" - select \"class_name\" - , case - when substr(\"index_name\", 0, %d) = '%s' - then substr(\"index_name\", %d) - else \"index_name\" end as unprefixed_index_name - , \"is_unique\" - from \"db_index\" - where \"class_name\" like %s - group by \"class_name\" - , case - when substr(\"index_name\", 0, %d) = '%s' - then substr(\"index_name\", %d) - else \"index_name\" - end - having count(*) > 1 - ", strlen($this->prefix) - , $this->prefix - , strlen($this->prefix) + 1 - , "'" . $this->prefix . '%' . "'" - , strlen($this->prefix) - , $this->prefix - , strlen($this->prefix) + 1 - ); - $result = $this->_query($query); - - if($this->isError()) - { - return FALSE; - } - - $output = $this->_fetch($result); - if(!$output) - { - return FALSE; - } - - if(!is_array($output)) - { - $indexes_to_be_deleted = array($output); - } - else - { - $indexes_to_be_deleted = $output; - } - - foreach($indexes_to_be_deleted as $index) - { - $this->dropIndex(substr($index->class_name, strlen($this->prefix)) - , $this->prefix . $index->unprefixed_index_name - , $index->is_unique == 'YES' ? TRUE : FALSE); - } - - return TRUE; - } - - /** - * Creates a table by using xml contents - * @param string $xml_doc xml schema contents - * @return void|object - */ - function createTableByXml($xml_doc) - { - return $this->_createTable($xml_doc); - } - - /** - * Creates a table by using xml file path - * @param string $file_name xml schema file path - * @return void|object - */ - function createTableByXmlFile($file_name) - { - if(!file_exists($file_name)) - { - return; - } - // read xml file - $buff = FileHandler::readFile($file_name); - return $this->_createTable($buff); - } - - /** - * Create table by using the schema xml - * - * type : number, varchar, tinytext, text, bigtext, char, date, \n - * opt : notnull, default, size\n - * index : primary key, index, unique\n - * @param string $xml_doc xml schema contents - * @return void|object - */ - function _createTable($xml_doc) - { - // xml parsing - $oXml = new XmlParser(); - $xml_obj = $oXml->parse($xml_doc); - // Create a table schema - $table_name = $xml_obj->table->attrs->name; - - // if the table already exists exit function - if($this->isTableExists($table_name)) - { - return; - } - - // If the table name is sequence, it creates a serial - if($table_name == 'sequence') - { - $query = sprintf('create serial "%s" start with 1 increment by 1' . - ' minvalue 1 ' . - 'maxvalue 10000000000000000000000000000000000000' . ' nocycle;', $this->prefix . $table_name); - - return $this->_query($query); - } - - - $table_name = $this->prefix . $table_name; - - $query = sprintf('create class "%s";', $table_name); - $this->_query($query); - - if(!is_array($xml_obj->table->column)) - { - $columns[] = $xml_obj->table->column; - } - else - { - $columns = $xml_obj->table->column; - } - - $query = sprintf("alter class \"%s\" add attribute ", $table_name); - - $primary_list = array(); - $unique_list = array(); - $index_list = array(); - - foreach($columns as $column) - { - $name = $column->attrs->name; - $type = $column->attrs->type; - $size = $column->attrs->size; - $notnull = $column->attrs->notnull; - $primary_key = $column->attrs->primary_key; - $index = $column->attrs->index; - $unique = $column->attrs->unique; - $default = $column->attrs->default; - - switch($this->column_type[$type]) - { - case 'integer' : - $size = NULL; - break; - case 'text' : - $size = NULL; - break; - } - - if(isset($default) && ($type == 'varchar' || $type == 'char' || - $type == 'text' || $type == 'tinytext' || $type == 'bigtext')) - { - $default = sprintf("'%s'", $default); - } - - if($type == 'varchar' || $type == 'char') - { - if($size) - $size = $size * 3; - } - - - $column_schema[] = sprintf('"%s" %s%s %s %s', $name, $this->column_type[$type], $size ? '(' . $size . ')' : '', isset($default) ? "default " . $default : '', $notnull ? 'not null' : ''); - - if($primary_key) - { - $primary_list[] = $name; - } - else if($unique) - { - $unique_list[$unique][] = $name; - } - else if($index) - { - $index_list[$index][] = $name; - } - } - - $query .= implode(',', $column_schema) . ';'; - $this->_query($query); - - if(count($primary_list)) - { - $query = sprintf("alter class \"%s\" add attribute constraint " . "\"pkey_%s\" PRIMARY KEY(%s);", $table_name, $table_name, '"' . implode('","', $primary_list) . '"'); - $this->_query($query); - } - - if(count($unique_list)) - { - foreach($unique_list as $key => $val) - { - $query = sprintf("create unique index \"%s\" on \"%s\" " . "(%s);", $key, $table_name, '"' . implode('","', $val) . '"'); - $this->_query($query); - } - } - - if(count($index_list)) - { - foreach($index_list as $key => $val) - { - $query = sprintf("create index \"%s\" on \"%s\" (%s);", $key, $table_name, '"' . implode('","', $val) . '"'); - $this->_query($query); - } - } - } - - /** - * Drop table - * - * @param string $name - * @return bool - */ - function dropTable($table_name) - { - // Generate the drop query - $query = sprintf('drop class "%s"', $this->addQuotes($this->prefix . $table_name)); - - // Execute the drop query - $output = $this->_query($query); - if($output) - { - return true; - } - else - { - return false; - } - } - - /** - * Handles insertAct - * @param BaseObject $queryObject - * @param boolean $with_values - * @return resource - */ - function _executeInsertAct($queryObject, $with_values = TRUE) - { - if($this->use_prepared_statements == 'Y') - { - $this->param = $queryObject->getArguments(); - $with_values = FALSE; - } - $query = $this->getInsertSql($queryObject, $with_values); - if($query instanceof BaseObject) - { - unset($this->param); - return; - } - - $result = $this->_query($query); - if($result && !$this->transaction_started) - { - $this->_commit(); - } - unset($this->param); - return $result; - } - - /** - * Handles updateAct - * @param BaseObject $queryObject - * @param boolean $with_values - * @return resource - */ - function _executeUpdateAct($queryObject, $with_values = TRUE) - { - if($this->use_prepared_statements == 'Y') - { - $this->param = $queryObject->getArguments(); - $with_values = FALSE; - } - $query = $this->getUpdateSql($queryObject, $with_values); - if($query instanceof BaseObject) - { - unset($this->param); - return; - } - - $result = $this->_query($query); - - if($result && !$this->transaction_started) - { - $this->_commit(); - } - unset($this->param); - return $result; - } - - /** - * Handles deleteAct - * @param BaseObject $queryObject - * @param boolean $with_values - * @return resource - */ - function _executeDeleteAct($queryObject, $with_values = TRUE) - { - if($this->use_prepared_statements == 'Y') - { - $this->param = $queryObject->getArguments(); - $with_values = FALSE; - } - $query = $this->getDeleteSql($queryObject, $with_values); - if($query instanceof BaseObject) - { - unset($this->param); - return; - } - - $result = $this->_query($query); - - if($result && !$this->transaction_started) - { - $this->_commit(); - } - - unset($this->param); - return $result; - } - - /** - * Handle selectAct - * To get a specific page list easily in select statement, - * a method, navigation, is used - * @param BaseObject $queryObject - * @param resource $connection - * @param boolean $with_values - * @return BaseObject - */ - function _executeSelectAct($queryObject, $connection = NULL, $with_values = TRUE) - { - if($this->use_prepared_statements == 'Y') - { - $this->param = $queryObject->getArguments(); - $with_values = FALSE; - } - $limit = $queryObject->getLimit(); - if($limit && $limit->isPageHandler()) - { - return $this->queryPageLimit($queryObject, $connection, $with_values); - } - else - { - $query = $this->getSelectSql($queryObject, $with_values); - if($query instanceof BaseObject) - { - unset($this->param); - return; - } - - $result = $this->_query($query, $connection); - - if($this->isError()) - { - unset($this->param); - return $this->queryError($queryObject); - } - - $data = $this->_fetch($result); - $buff = new BaseObject; - $buff->data = $data; - - unset($this->param); - return $buff; - } - } - - /** - * Get the number of rows affected by the last query - * @return int - */ - function getAffectedRows() - { - $connection = $this->_getConnection('master'); - return cubrid_affected_rows($connection); - } - - /** - * Get the ID generated in the last query - * @return int - */ - function getInsertID() - { - $connection = $this->_getConnection('master'); - return cubrid_insert_id($connection); - } - - /** - * If have a error, return error object - * @param BaseObject $queryObject - * @return BaseObject - */ - function queryError($queryObject) - { - $limit = $queryObject->getLimit(); - if($limit && $limit->isPageHandler()) - { - $buff = new BaseObject; - $buff->total_count = 0; - $buff->total_page = 0; - $buff->page = 1; - $buff->data = array(); - $buff->page_navigation = new PageHandler(/* $total_count */0, /* $total_page */1, /* $page */1, /* $page_count */10); //default page handler values - return $buff; - }else - return; - } - - /** - * If select query execute, return page info - * @param BaseObject $queryObject - * @param resource $connection - * @param boolean $with_values - * @return BaseObject Object with page info containing - */ - function queryPageLimit($queryObject, $connection, $with_values) - { - $limit = $queryObject->getLimit(); - // Total count - $temp_where = $queryObject->getWhereString($with_values, FALSE); - $count_query = sprintf('select count(*) as "count" %s %s', 'FROM ' . $queryObject->getFromString($with_values), ($temp_where === '' ? '' : ' WHERE ' . $temp_where)); - - // Check for distinct query and if found update count query structure - $temp_select = $queryObject->getSelectString($with_values); - $uses_distinct = stripos($temp_select, "distinct") !== FALSE; - $uses_groupby = $queryObject->getGroupByString() != ''; - if($uses_distinct || $uses_groupby) - { - $count_query = sprintf('select %s %s %s %s' - , $temp_select - , 'FROM ' . $queryObject->getFromString($with_values) - , ($temp_where === '' ? '' : ' WHERE ' . $temp_where) - , ($uses_groupby ? ' GROUP BY ' . $queryObject->getGroupByString() : '') - ); - - // If query uses grouping or distinct, count from original select - $count_query = sprintf('select count(*) as "count" from (%s) xet', $count_query); - } - - $result = $this->_query($count_query, $connection); - $count_output = $this->_fetch($result); - $total_count = (int) (isset($count_output->count) ? $count_output->count : NULL); - - $list_count = $limit->list_count->getValue(); - if(!$list_count) - { - $list_count = 20; - } - $page_count = $limit->page_count->getValue(); - if(!$page_count) - { - $page_count = 10; - } - $page = $limit->page->getValue(); - if(!$page || $page < 1) - { - $page = 1; - } - - // total pages - if($total_count) - { - $total_page = (int) (($total_count - 1) / $list_count) + 1; - } - else - { - $total_page = 1; - } - - // check the page variables - if($page > $total_page) - { - // If requested page is bigger than total number of pages, return empty list - - $buff = new BaseObject; - $buff->total_count = $total_count; - $buff->total_page = $total_page; - $buff->page = $page; - $buff->data = array(); - $buff->page_navigation = new PageHandler($total_count, $total_page, $page, $page_count); - unset($this->param); - return $buff; - } - $start_count = ($page - 1) * $list_count; - - $query = $this->getSelectPageSql($queryObject, $with_values, $start_count, $list_count); - $result = $this->_query($query, $connection); - if($this->isError()) - { - unset($this->param); - return $this->queryError($queryObject); - } - - $virtual_no = $total_count - ($page - 1) * $list_count; - $data = $this->_fetch($result, $virtual_no); - - $buff = new BaseObject; - $buff->total_count = $total_count; - $buff->total_page = $total_page; - $buff->page = $page; - $buff->data = $data; - $buff->page_navigation = new PageHandler($total_count, $total_page, $page, $page_count); - unset($this->param); - return $buff; - } - - /** - * Return the DBParser - * @param boolean $force - * @return DBParser - */ - function getParser($force = FALSE) - { - return new DBParser('"', '"', $this->prefix); - } - - /** - * If select query execute, return paging sql - * @param object $query - * @param boolean $with_values - * @param int $start_count - * @param int $list_count - * @return string select paging sql - */ - function getSelectPageSql($query, $with_values = TRUE, $start_count = 0, $list_count = 0) - { - - $select = $query->getSelectString($with_values); - if($select == '') - { - return new BaseObject(-1, "Invalid query"); - } - $select = 'SELECT ' . $select; - - $from = $query->getFromString($with_values); - if($from == '') - { - return new BaseObject(-1, "Invalid query"); - } - $from = ' FROM ' . $from; - - $where = $query->getWhereString($with_values); - if($where != '') - { - $where = ' WHERE ' . $where; - } - - $groupBy = $query->getGroupByString(); - if($groupBy != '') - { - $groupBy = ' GROUP BY ' . $groupBy; - } - - $orderBy = $query->getOrderByString(); - if($orderBy != '') - { - $orderBy = ' ORDER BY ' . $orderBy; - } - - $limit = $query->getLimitString(); - if($limit != '') - { - $limit = sprintf(' LIMIT %d, %d', $start_count, $list_count); - } - - return $select . ' ' . $from . ' ' . $where . ' ' . $groupBy . ' ' . $orderBy . ' ' . $limit; - } - -} - -DBCubrid::$isSupported = function_exists('cubrid_connect'); - -/* End of file DBCubrid.class.php */ -/* Location: ./classes/db/DBCubrid.class.php */ diff --git a/classes/db/DBMssql.class.php b/classes/db/DBMssql.class.php deleted file mode 100644 index 2e26d5a66..000000000 --- a/classes/db/DBMssql.class.php +++ /dev/null @@ -1,1161 +0,0 @@ - */ - -/** - * - DBMSSQL - * - Modified to use MSSQL driver by sol (sol@ngleader.com) - * - * @author NAVER (developers@xpressengine.com) - * @package /classes/db - * @version 0.1 - */ -class DBMssql extends DB -{ - - /** - * prefix of Rhymix tables(One more Rhymix can be installed on a single DB) - * @var string - */ - var $prefix = 'rx'; - var $param = array(); - var $comment_syntax = '/* %s */'; - - /** - * column type used in mssql - * - * column_type should be replaced for each DBMS's type - * becasue it uses commonly defined type in the schema/query xml - * @var array - */ - var $column_type = array( - 'bignumber' => 'bigint', - 'number' => 'int', - 'varchar' => 'nvarchar', - 'char' => 'nchar', - 'bigtext' => 'ntext', - 'text' => 'ntext', - 'date' => 'nvarchar(14)', - 'float' => 'float', - ); - - /** - * Last statement executed - */ - var $last_stmt; - - /** - * Constructor - * @return void - */ - function __construct() - { - $this->_setDBInfo(); - $this->_connect(); - } - - /** - * DB Connect - * this method is private - * @param array $connection connection's value is db_hostname, db_database, db_userid, db_password - * @return resource - */ - function __connect($connection) - { - //sqlsrv_configure( 'WarningsReturnAsErrors', 0 ); - //sqlsrv_configure( 'LogSeverity', SQLSRV_LOG_SEVERITY_ALL ); - //sqlsrv_configure( 'LogSubsystems', SQLSRV_LOG_SYSTEM_ALL ); - $result = @sqlsrv_connect($connection['host'], array( - 'Database' => $connection['database'], - 'UID' => $connection['user'], - 'PWD' => $connection['pass'], - )); - - if(!$result) - { - $errors = print_r(sqlsrv_errors(), true); - $this->setError(-1, 'database connect fail' . PHP_EOL . $errors); - return; - } - - $server_info = sqlsrv_server_info($result); - $server_version = $server_info['SQLServerVersion']; - $this->db_version = $server_version; - if ($server_version && version_compare($server_version, '10', '<')) - { - $this->setError(-1, 'Rhymix requires Microsoft SQL Server 2008 or later. Current version is ' . $server_version); - return; - } - - return $result; - } - - /** - * DB disconnection - * this method is private - * @param resource $connection - * @return void - */ - function _close($connection) - { - $this->commit(); - sqlsrv_close($connection); - } - - /** - * Handles quatation of the string variables from the query - * @todo See what to do about this - * @param string $string - * @return string - */ - function addQuotes($string) - { - //if(!is_numeric($string)) $string = str_replace("'","''",$string); - - return $string; - } - - /** - * DB transaction start - * this method is private - * @return boolean - */ - function _begin($transactionLevel = 0) - { - $connection = $this->_getConnection('master'); - - if(!$transactionLevel) - { - if(sqlsrv_begin_transaction($connection) === false) - { - return; - } - } - else - { - $this->_query("SAVE TRANS SP" . $transactionLevel, $connection); - } - return true; - } - - /** - * DB transaction rollback - * this method is private - * @return boolean - */ - function _rollback($transactionLevel = 0) - { - $connection = $this->_getConnection('master'); - - $point = $transactionLevel - 1; - - if($point) - { - $this->_query("ROLLBACK TRANS SP" . $point, $connection); - } - else - { - sqlsrv_rollback($connection); - } - return true; - } - - /** - * DB transaction commit - * this method is private - * @return boolean - */ - function _commit() - { - $connection = $this->_getConnection('master'); - sqlsrv_commit($connection); - return true; - } - - /** - * Execute the query - * this method is private - * @param string $query - * @param resource $connection - * @return resource|boolean Returns a statement resource on success and FALSE if an error occurred. - */ - function __query($query, $connection) - { - $_param = array(); - - if(count($this->param)) - { - foreach($this->param as $k => $o) - { - if($o->isColumnName()) - { - continue; - } - if($o->getType() == 'number') - { - $value = $o->getUnescapedValue(); - if(is_array($value)) - { - $_param = array_merge($_param, $value); - } - else - { - $_param[] = $o->getUnescapedValue(); - } - } - else - { - $value = $o->getUnescapedValue(); - if(is_array($value)) - { - foreach($value as $v) - { - $_param[] = array($v, SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_STRING('utf-8')); - } - } - else - { - $_param[] = array($value, SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_STRING('utf-8')); - } - } - } - } - - // Run the query statement - $result = false; - if(count($_param)) - { - $args = $this->_getParametersByReference($_param); - $stmt = sqlsrv_prepare($connection, $query, $args); - } - else - { - $stmt = sqlsrv_prepare($connection, $query); - } - - if(!$stmt) - { - $result = false; - } - else - { - $result = sqlsrv_execute($stmt); - } - - // Error Check - if(!$result) - { - $this->setError(print_r(sqlsrv_errors(), true)); - } - - $this->last_stmt = $stmt; - $this->param = array(); - - return $stmt; - } - - /** - * Parameters to sqlsrv_prepare need to be references, and not literals - * Parameters are sent as an array, where each parameter can be: - * - a PHP variable (by reference) - * - a PHP array (containng param value, type and direction) -> also needs to be sent by reference - * @param array $_param - * @return array - */ - function _getParametersByReference($_param) - { - $copy = array(); - $args = array(); - $i = 0; - foreach($_param as $key => $value) - { - if(is_array($value)) - { - $value_copy = $value; - $value_arg = array(); - $value_arg[] = &$value_copy[0]; - $value_arg[] = $value_copy[1]; - $value_arg[] = $value_copy[2]; - } - else - { - $value_arg = $value; - } - $copy[$key] = $value_arg; - $args[$i++] = &$copy[$key]; - } - return $args; - } - - /** - * Fetch results - * @param resource $result - * @param int|NULL $arrayIndexEndValue - * @return array - */ - function _fetch($result, $arrayIndexEndValue = NULL) - { - $output = array(); - if(!$this->isConnected() || $this->isError() || !$result) - { - return $output; - } - - $c = sqlsrv_num_fields($result); - $m = null; - - while(sqlsrv_fetch($result)) - { - if(!$m) - { - $m = sqlsrv_field_metadata($result); - } - unset($row); - for($i = 0; $i < $c; $i++) - { - $row->{$m[$i]['Name']} = sqlsrv_get_field($result, $i, SQLSRV_PHPTYPE_STRING('utf-8')); - } - if($arrayIndexEndValue) - { - $output[$arrayIndexEndValue--] = $row; - } - else - { - $output[] = $row; - } - } - - if(count($output) == 1) - { - if(isset($arrayIndexEndValue)) - { - return $output; - } - else - { - return $output[0]; - } - } - return $output; - } - - /** - * Return the sequence value incremented by 1 - * Auto_increment column only used in the sequence table - * @return int - */ - function getNextSequence() - { - $query = sprintf("insert into %ssequence (seq) values (ident_incr('%ssequence'))", $this->prefix, $this->prefix); - $this->_query($query); - - $query = sprintf("select ident_current('%ssequence')+1 as sequence", $this->prefix); - $result = $this->_query($query); - $tmp = $this->_fetch($result); - - - return $tmp->sequence; - } - - /** - * Check a table exists status - * @param string $target_name - * @return boolean - */ - function isTableExists($target_name) - { - $query = sprintf("select name from sysobjects where name = '%s%s' and xtype='U'", $this->prefix, $this->addQuotes($target_name)); - $result = $this->_query($query); - $tmp = $this->_fetch($result); - - if(!$tmp) - { - return false; - } - return true; - } - - /** - * Add a column to the table - * @param string $table_name table name - * @param string $column_name column name - * @param string $type column type, default value is 'number' - * @param int $size column size - * @param string|int $default default value - * @param boolean $notnull not null status, default value is false - * @return void - */ - function addColumn($table_name, $column_name, $type = 'number', $size = '', $default = null, $notnull = false) - { - if($this->isColumnExists($table_name, $column_name)) - { - return; - } - $type = $this->column_type[$type]; - if(strtoupper($type) == 'INTEGER') - { - $size = ''; - } - - $query = sprintf("alter table %s%s add \"%s\" ", $this->prefix, $table_name, $column_name); - if($size) - { - $query .= sprintf(" %s(%s) ", $type, $size); - } - else - { - $query .= sprintf(" %s ", $type); - } - - if(isset($default)) - { - $query .= sprintf(" default '%s' ", $default); - } - if($notnull) - { - $query .= " not null "; - } - - return $this->_query($query); - } - - /** - * Drop a column from the table - * @param string $table_name table name - * @param string $column_name column name - * @return void - */ - function dropColumn($table_name, $column_name) - { - if(!$this->isColumnExists($table_name, $column_name)) - { - return; - } - $query = sprintf("alter table %s%s drop column \"%s\" ", $this->prefix, $table_name, $column_name); - $this->_query($query); - } - - /** - * Modify a column - * @param string $table_name table name - * @param string $column_name column name - * @param string $type column type, default value is 'number' - * @param int $size column size - * @param string|int $default default value - * @param boolean $notnull not null status, default value is false - * @return bool - */ - function modifyColumn($table_name, $column_name, $type = 'number', $size = '', $default = '', $notnull = false) - { - $type = $this->column_type[$type]; - if(strtoupper($type) == 'INTEGER') - { - $size = ''; - } - - $query = sprintf("alter table %s%s alter column %s ", $this->prefix, $table_name, $column_name); - if($size) - { - $query .= sprintf(" %s(%s) ", $type, $size); - } - else - { - $query .= sprintf(" %s ", $type); - } - - if($default) - { - $query .= sprintf(" default '%s' ", $default); - } - if($notnull) - { - $query .= " not null "; - } - - return $this->_query($query) ? true : false; - } - - /** - * Check column exist status of the table - * @param string $table_name table name - * @param string $column_name column name - * @return boolean - */ - function isColumnExists($table_name, $column_name) - { - $query = sprintf("select syscolumns.name as name from syscolumns, sysobjects where sysobjects.name = '%s%s' and sysobjects.id = syscolumns.id and syscolumns.name = '%s'", $this->prefix, $table_name, $column_name); - $result = $this->_query($query); - if($this->isError()) - { - return; - } - $tmp = $this->_fetch($result); - if(!$tmp->name) - { - return false; - } - return true; - } - - /** - * Get information about a column - * @param string $table_name table name - * @param string $column_name column name - * @return BaseObject - */ - function getColumnInfo($table_name, $column_name) - { - $query = sprintf("select syscolumns.name as name, systypes.name as type_name, syscolumns.length as length, " . - "syscolumns.isnullable as isnullable, syscomments.text as default_value from syscolumns " . - "inner join sysobjects on sysobjects.id = syscolumns.id " . - "inner join systypes on systypes.xtype = syscolumns.xtype " . - "left join syscomments on syscolumns.cdefault = syscomments.id " . - "where sysobjects.name = '%s%s' and syscolumns.name = '%s'", $this->prefix, $table_name, $column_name); - $result = $this->_query($query); - if($this->isError()) - { - return; - } - $output = $this->_fetch($result); - if($output) - { - $dbtype = $output->type_name; - $size = ($output->length > 0) ? $output->length : null; - if($xetype = array_search("$dbtype($size)", $this->column_type)) - { - $dbtype = "$dbtype($size)"; - $size = null; - } - elseif($size !== null) - { - if($xetype = array_search($dbtype, $this->column_type)) - { - // no-op - } - else - { - $xetype = $dbtype; - } - } - else - { - $xetype = $dbtype; - $size = null; - } - return (object)array( - 'name' => $output->name, - 'dbtype' => $dbtype, - 'xetype' => $xetype, - 'size' => $size, - 'default_value' => $output->default_value, - 'notnull' => !$output->isnullable, - ); - } - else - { - return false; - } - } - - /** - * Add an index to the table - * $target_columns = array(col1, col2) - * $is_unique? unique : none - * @param string $table_name table name - * @param string $index_name index name - * @param string|array $target_columns target column or columns - * @param boolean $is_unique - * @return void - */ - function addIndex($table_name, $index_name, $target_columns, $is_unique = false) - { - if($this->isIndexExists($table_name, $index_name)) - { - return; - } - if(!is_array($target_columns)) - { - $target_columns = array($target_columns); - } - - $query = sprintf("create %s index %s on %s%s (%s)", $is_unique ? 'unique' : '', $index_name, $this->prefix, $table_name, implode(',', $target_columns)); - $this->_query($query); - } - - /** - * Drop an index from the table - * @param string $table_name table name - * @param string $index_name index name - * @param boolean $is_unique - * @return void - */ - function dropIndex($table_name, $index_name, $is_unique = false) - { - if(!$this->isIndexExists($table_name, $index_name)) - { - return; - } - $query = sprintf("drop index %s%s.%s", $this->prefix, $table_name, $index_name); - $this->_query($query); - } - - /** - * Check index status of the table - * @param string $table_name table name - * @param string $index_name index name - * @return boolean - */ - function isIndexExists($table_name, $index_name) - { - $query = sprintf("select sysindexes.name as name from sysindexes, sysobjects where sysobjects.name = '%s%s' and sysobjects.id = sysindexes.id and sysindexes.name = '%s'", $this->prefix, $table_name, $index_name); - - $result = $this->_query($query); - if($this->isError()) - { - return; - } - $tmp = $this->_fetch($result); - - if(!$tmp->name) - { - return false; - } - return true; - } - - /** - * Creates a table by using xml contents - * @param string $xml_doc xml schema contents - * @return void|object - */ - function createTableByXml($xml_doc) - { - return $this->_createTable($xml_doc); - } - - /** - * Creates a table by using xml file path - * @param string $file_name xml schema file path - * @return void|object - */ - function createTableByXmlFile($file_name) - { - if(!file_exists($file_name)) - { - return; - } - // read xml file - $buff = FileHandler::readFile($file_name); - return $this->_createTable($buff); - } - - /** - * Create table by using the schema xml - * - * type : number, varchar, tinytext, text, bigtext, char, date, \n - * opt : notnull, default, size\n - * index : primary key, index, unique\n - * @param string $xml_doc xml schema contents - * @return void|object - */ - function _createTable($xml_doc) - { - // xml parsing - $oXml = new XmlParser(); - $xml_obj = $oXml->parse($xml_doc); - // Create a table schema - $table_name = $xml_obj->table->attrs->name; - if($this->isTableExists($table_name)) - { - return; - } - - if($table_name == 'sequence') - { - $table_name = $this->prefix . $table_name; - $query = sprintf('create table %s ( sequence int identity(1,1), seq int )', $table_name); - return $this->_query($query); - } - else - { - $table_name = $this->prefix . $table_name; - - if(!is_array($xml_obj->table->column)) - { - $columns[] = $xml_obj->table->column; - } - else - { - $columns = $xml_obj->table->column; - } - - $primary_list = array(); - $unique_list = array(); - $index_list = array(); - - $typeList = array('number' => 1, 'text' => 1); - foreach($columns as $column) - { - $name = $column->attrs->name; - $type = $column->attrs->type; - $size = $column->attrs->size; - $notnull = $column->attrs->notnull; - $primary_key = $column->attrs->primary_key; - $index = $column->attrs->index; - $unique = $column->attrs->unique; - $default = $column->attrs->default; - $auto_increment = $column->attrs->auto_increment; - - $column_schema[] = sprintf('[%s] %s%s %s %s %s', $name, $this->column_type[$type], !isset($typeList[$type]) && $size ? '(' . $size . ')' : '', isset($default) ? "default '" . $default . "'" : '', $notnull ? 'not null' : 'null', $auto_increment ? 'identity(1,1)' : ''); - - if($primary_key) - { - $primary_list[] = $name; - } - else if($unique) - { - $unique_list[$unique][] = $name; - } - else if($index) - { - $index_list[$index][] = $name; - } - } - - if(count($primary_list)) - { - $column_schema[] = sprintf("primary key (%s)", '"' . implode($primary_list, '","') . '"'); - } - - $schema = sprintf('create table [%s] (%s%s)', $this->addQuotes($table_name), "\n", implode($column_schema, ",\n")); - $output = $this->_query($schema); - if(!$output) - { - return false; - } - - if(count($unique_list)) - { - foreach($unique_list as $key => $val) - { - $query = sprintf("create unique index %s on %s (%s);", $key, $table_name, '[' . implode('],[', $val) . ']'); - $this->_query($query); - } - } - - if(count($index_list)) - { - foreach($index_list as $key => $val) - { - $query = sprintf("create index %s on %s (%s);", $key, $table_name, '[' . implode('],[', $val) . ']'); - $this->_query($query); - } - } - return true; - } - } - - /** - * Drop table - * - * @param string $name - * @return bool - */ - function dropTable($table_name) - { - // Generate the drop query - $query = sprintf('DROP TABLE %s', $this->addQuotes($this->prefix . $table_name)); - - // Execute the drop query - $output = $this->_query($query); - if($output) - { - return true; - } - else - { - return false; - } - } - - /** - * Handles insertAct - * @todo Lookup _filterNumber against sql injection - see if it is still needed and how to integrate - * @param BaseObject $queryObject - * @return resource - */ - function _executeInsertAct($queryObject) - { - $query = $this->getInsertSql($queryObject, false); - $this->param = $queryObject->getArguments(); - return $this->_query($query); - } - - /** - * Handles updateAct - * @param BaseObject $queryObject - * @return resource - */ - function _executeUpdateAct($queryObject) - { - $query = $this->getUpdateSql($queryObject, false); - $this->param = $queryObject->getArguments(); - return $this->_query($query); - } - - /** - * Return update query string - * @param object $query - * @param boolean $with_values - * @param boolean $with_priority - * @return string - */ - function getUpdateSql($query, $with_values = true, $with_priority = false) - { - $columnsList = $query->getUpdateString($with_values); - if($columnsList == '') - { - return new BaseObject(-1, "Invalid query"); - } - - $from = $query->getFromString($with_values); - if($from == '') - { - return new BaseObject(-1, "Invalid query"); - } - - $tables = $query->getTables(); - $alias_list = ''; - foreach($tables as $table) - { - $alias_list .= $table->getAlias(); - } - implode(',', explode(' ', $alias_list)); - - $where = $query->getWhereString($with_values); - if($where != '') - { - $where = ' WHERE ' . $where; - } - - $priority = $with_priority ? $query->getPriority() : ''; - - return "UPDATE $priority $alias_list SET $columnsList FROM " . $from . $where; - } - - /** - * Handles deleteAct - * @param BaseObject $queryObject - * @return resource - */ - function _executeDeleteAct($queryObject) - { - $query = $this->getDeleteSql($queryObject, false); - $this->param = $queryObject->getArguments(); - return $this->_query($query); - } - - /** - * Return select query string - * @param object $query - * @param boolean $with_values - * @return string - */ - function getSelectSql($query, $with_values = TRUE, $connection=NULL) - { - $with_values = false; - - //$limitOffset = $query->getLimit()->getOffset(); - //if($limitOffset) - // TODO Implement Limit with offset with subquery - $limit = ''; - $limitCount = ''; - $limitQueryPart = $query->getLimit(); - if($limitQueryPart) - { - $limitCount = $limitQueryPart->getLimit(); - } - if($limitCount != '') - { - $limit = 'SELECT TOP ' . $limitCount; - } - - $select = $query->getSelectString($with_values); - if($select == '') - { - return new BaseObject(-1, "Invalid query"); - } - if($limit != '') - { - $select = $limit . ' ' . $select; - } - else - { - $select = 'SELECT ' . $select; - } - - $from = $query->getFromString($with_values); - if($from == '') - { - return new BaseObject(-1, "Invalid query"); - } - $from = ' FROM ' . $from; - - $where = $query->getWhereString($with_values); - if($where != '') - { - $where = ' WHERE ' . $where; - } - - $groupBy = $query->getGroupByString(); - if($groupBy != '') - { - $groupBy = ' GROUP BY ' . $groupBy; - } - - $orderBy = $query->getOrderByString(); - if($orderBy != '') - { - $orderBy = ' ORDER BY ' . $orderBy; - } - - if($limitCount != '' && $query->limit->start > 0) - { - $order = $query->getOrder(); - $first_columns = array(); - foreach($order as $val) - { - $tmpColumnName = $val->getPureColumnName(); - $first_columns[] = sprintf('%s(%s) as %s', $val->getPureSortOrder()=='asc'?'max':'min', $tmpColumnName, $tmpColumnName); - $first_sub_columns[] = $tmpColumnName; - } - - $first_query = sprintf("select %s from (select top %d %s %s %s %s %s) xet", implode(',',$first_columns), $query->limit->start, implode(',',$first_sub_columns), $from, $where, $groupBy, $orderBy); - $this->param = $query->getArguments(); - $result = $this->__query($first_query, $connection); - $tmp = $this->_fetch($result); - - $sub_cond = array(); - foreach($order as $k => $v) - { - //for example... use Document - if(get_class($v->sort_order) == 'SortArgument') - { - $sort_order = $v->sort_order->value; - } - //for example... use comment, file - else - { - $sort_order = $v->sort_order; - } - - $sub_cond[] = sprintf("%s %s '%s'", $v->getPureColumnName(), $sort_order=='asc'?'>':'<', $tmp->{$v->getPureColumnName()}); - } - - if(!$where) - { - $sub_condition = ' WHERE ( '.implode(' and ',$sub_cond).' )'; - } - else - { - $sub_condition = ' and ( '.implode(' and ',$sub_cond).' )'; - } - } - return $select . ' ' . $from . ' ' . $where .$sub_condition. ' ' . $groupBy . ' ' . $orderBy; - } - - /** - * Handle selectAct - * In order to get a list of pages easily when selecting \n - * it supports a method as navigation - * @param BaseObject $queryObject - * @param resource $connection - * @return BaseObject - */ - function _executeSelectAct($queryObject, $connection = null) - { - $query = $this->getSelectSql($queryObject, true, $connection); - - if(strpos($query, "substr")) - { - $query = str_replace("substr", "substring", $query); - } - - // TODO Decide if we continue to pass parameters like this - $this->param = $queryObject->getArguments(); - $result = $this->_query($query, $connection); - - if($this->isError()) - { - return $this->queryError($queryObject); - } - else - { - return $this->queryPageLimit($queryObject, $result, $connection); - } - } - - /** - * Get the number of rows affected by the last query - * @return int - */ - function getAffectedRows() - { - $stmt = $this->last_stmt; - return $stmt ? sqlsrv_rows_affected($stmt) : -1; - } - - /** - * Get the ID generated in the last query - * @return int - */ - function getInsertID() - { - $result = $this->_query('SELECT @@IDENTITY as id'); - $output = $this->_fetch($result); - return $output->id ?: 0; - } - - /** - * Return the DBParser - * @param boolean $force - * @return DBParser - */ - function getParser($force = FALSE) - { - return new DBParser("[", "]", $this->prefix); - } - - /** - * If have a error, return error object - * @param BaseObject $queryObject - * @return BaseObject - */ - function queryError($queryObject) - { - $limit = $queryObject->getLimit(); - if($limit && $limit->isPageHandler()) - { - $buff = new BaseObject; - $buff->total_count = 0; - $buff->total_page = 0; - $buff->page = 1; - $buff->data = array(); - $buff->page_navigation = new PageHandler(/* $total_count */0, /* $total_page */1, /* $page */1, /* $page_count */10); //default page handler values - return $buff; - } - else - { - return; - } - } - - /** - * If select query execute, return page info - * @param BaseObject $queryObject - * @param resource $result - * @param resource $connection - * @return BaseObject Object with page info containing - */ - function queryPageLimit($queryObject, $result, $connection) - { - $limit = $queryObject->getLimit(); - if($limit && $limit->isPageHandler()) - { - // Total count - $temp_where = $queryObject->getWhereString(true, false); - $count_query = sprintf('select count(*) as "count" %s %s', 'FROM ' . $queryObject->getFromString(), ($temp_where === '' ? '' : ' WHERE ' . $temp_where)); - - // Check for distinct query and if found update count query structure - $temp_select = $queryObject->getSelectString(true); - $uses_distinct = stripos($temp_select, "distinct") !== false; - $uses_groupby = $queryObject->getGroupByString() != ''; - if($uses_distinct || $uses_groupby) - { - $count_query = sprintf('select %s %s %s %s' - , $temp_select - , 'FROM ' . $queryObject->getFromString(true) - , ($temp_where === '' ? '' : ' WHERE ' . $temp_where) - , ($uses_groupby ? ' GROUP BY ' . $queryObject->getGroupByString() : '') - ); - - // If query uses grouping or distinct, count from original select - $count_query = sprintf('select count(*) as "count" from (%s) xet', $count_query); - } - - $this->param = $queryObject->getArguments(); - $result_count = $this->_query($count_query, $connection); - $count_output = $this->_fetch($result_count); - $total_count = (int) $count_output->count; - - $list_count = $limit->list_count->getValue(); - if(!$list_count) - { - $list_count = 20; - } - $page_count = $limit->page_count->getValue(); - if(!$page_count) - { - $page_count = 10; - } - $page = $limit->page->getValue(); - if(!$page || $page < 1) - { - $page = 1; - } - // Total pages - if($total_count) - { - $total_page = (int) (($total_count - 1) / $list_count) + 1; - } - else - { - $total_page = 1; - } - - // check the page variables - if($page > $total_page) - { - // If requested page is bigger than total number of pages, return empty list - - $buff = new BaseObject; - $buff->total_count = $total_count; - $buff->total_page = $total_page; - $buff->page = $page; - $buff->data = array(); - $buff->page_navigation = new PageHandler($total_count, $total_page, $page, $page_count); - return $buff; - - if($queryObject->usesClickCount()) - { - $update_query = $this->getClickCountQuery($queryObject); - $this->_executeUpdateAct($update_query); - } - } - - $start_count = ($page - 1) * $list_count; - $this->param = $queryObject->getArguments(); - $virtual_no = $total_count - $start_count; - $data = $this->_fetch($result, $virtual_no); - - $buff = new BaseObject; - $buff->total_count = $total_count; - $buff->total_page = $total_page; - $buff->page = $page; - $buff->data = $data; - $buff->page_navigation = new PageHandler($total_count, $total_page, $page, $page_count); - } - else - { - $data = $this->_fetch($result); - $buff = new BaseObject; - $buff->data = $data; - } - return $buff; - } - -} - -DBMssql::$isSupported = extension_loaded("sqlsrv"); - -/* End of file DBMssql.class.php */ -/* Location: ./classes/db/DBMssql.class.php */ diff --git a/classes/db/DBMysql.class.php b/classes/db/DBMysql.class.php index 82a68c7ee..a74ac3cff 100644 --- a/classes/db/DBMysql.class.php +++ b/classes/db/DBMysql.class.php @@ -2,24 +2,17 @@ /* Copyright (C) NAVER */ /** - * Class to use MySQL DBMS - * mysql handling class - * - * Does not use prepared statements, since mysql driver does not support them - * - * @author NAVER (developers@xpressengine.com) - * @package /classes/db - * @version 0.1 + * Merged class for MySQL and MySQLi, with or without InnoDB */ -class DBMysql extends DB +class DBMySQL extends DB { /** * prefix of a tablename (One or more Rhymix can be installed in a single DB) * @var string */ - var $prefix = 'rx_'; // / < + var $prefix = 'rx_'; var $comment_syntax = '/* %s */'; - var $charset = 'utf8'; + var $charset = 'utf8mb4'; /** * Column type used in MySQL @@ -43,6 +36,11 @@ class DBMysql extends DB * Last statement executed */ var $last_stmt; + + /** + * Query parameters for prepared statement + */ + var $params = array(); /** * Constructor @@ -58,62 +56,54 @@ class DBMysql extends DB * DB Connect * this method is private * @param array $connection connection's value is db_hostname, db_port, db_database, db_userid, db_password - * @return resource + * @return mysqli */ - function __connect($connection) + protected function __connect($connection) { - // Ignore if no DB information exists - if(strpos($connection['host'], ':') === false && $connection['port']) - { - $connection['host'] .= ':' . $connection['port']; - } - // Attempt to connect - $result = @mysql_connect($connection['host'], $connection['user'], $connection['pass']); - if(!$result) + if($connection['port']) { - $this->setError(-1, 'Unable to connect to DB.'); + $mysqli = new mysqli($connection['host'], $connection['user'], $connection['pass'], $connection['database'], $connection['port']); + } + else + { + $mysqli = new mysqli($connection['host'], $connection['user'], $connection['pass'], $connection['database']); + } + + // Check connection error + if($mysqli->connect_errno) + { + $this->setError($mysqli->connect_errno, $mysqli->connect_error()); return; } - - if(mysql_error()) - { - $this->setError(mysql_errno(), mysql_error()); - return; - } - - // Error appears if the version is lower than 5.0.7 - $this->db_version = mysql_get_server_info($result); - if(version_compare($this->db_version, '5.0.7', '<')) + + // Check DB version + $this->db_version = $mysqli->server_info; + if (version_compare($this->db_version, '5.0.7', '<')) { $this->setError(-1, 'Rhymix requires MySQL 5.0.7 or later. Current MySQL version is ' . $this->db_version); return; } - - // Set charset + + // Set DB charset $this->charset = isset($connection['charset']) ? $connection['charset'] : 'utf8'; - mysql_set_charset($this->charset, $result); - - // select db - @mysql_select_db($connection['database'], $result); - if(mysql_error()) - { - $this->setError(mysql_errno(), mysql_error()); - return; - } - - return $result; + $mysqli->set_charset($this->charset); + + return $mysqli; } /** * DB disconnection * this method is private - * @param resource $connection + * @param mysqli $connection * @return void */ - function _close($connection) + protected function _close($connection) { - @mysql_close($connection); + if ($connection instanceof mysqli) + { + $connection->close(); + } } /** @@ -125,7 +115,8 @@ class DBMysql extends DB { if(!is_numeric($string)) { - $string = @mysql_real_escape_string($string); + $connection = $this->_getConnection('master'); + $string = $connection->real_escape_string($string); } return $string; } @@ -135,8 +126,19 @@ class DBMysql extends DB * this method is private * @return boolean */ - function _begin($transactionLevel = 0) + protected function _begin($transactionLevel = 0) { + $connection = $this->_getConnection('master'); + + if(!$transactionLevel) + { + $connection->begin_transaction(); + $this->setQueryLog(array('query' => 'START TRANSACTION')); + } + else + { + $this->_query("SAVEPOINT SP" . $transactionLevel, $connection); + } return true; } @@ -145,8 +147,20 @@ class DBMysql extends DB * this method is private * @return boolean */ - function _rollback($transactionLevel = 0) + protected function _rollback($transactionLevel = 0) { + $connection = $this->_getConnection('master'); + $point = $transactionLevel - 1; + + if($point) + { + $this->_query("ROLLBACK TO SP" . $point, $connection); + } + else + { + $connection->rollback(); + $this->setQueryLog(array('query' => 'ROLLBACK')); + } return true; } @@ -155,8 +169,11 @@ class DBMysql extends DB * this method is private * @return boolean */ - function _commit() + protected function _commit() { + $connection = $this->_getConnection('master'); + $connection->commit(); + $this->setQueryLog(array('query' => 'COMMIT')); return true; } @@ -169,21 +186,105 @@ class DBMysql extends DB */ function __query($query, $connection) { - if(!$connection) + if (!($connection instanceof mysqli) || $connection->connection_errno) { $this->setError(-1, 'Unable to connect to DB.'); return false; } - // Run the query statement - $result = @mysql_query($query, $connection); - // Error Check - if(mysql_error($connection)) + + if($this->use_prepared_statements == 'Y') { - $this->setError(mysql_errno($connection), mysql_error($connection)); + // 1. Prepare query + $stmt = $connection->prepare($query); + if(!$stmt) + { + $this->setError($connection->errno, $connection->error); + return $this->last_stmt = $result; + } + + // 2. Bind parameters + if ($this->params) + { + $types = ''; + $params = array(); + foreach($this->params as $k => $o) + { + $value = $o->getUnescapedValue(); + $type = $o->getType(); + + // Skip column names -> this should be concatenated to query string + if($o->isColumnName()) + { + continue; + } + + switch($type) + { + case 'number' : + $type = 'i'; + break; + case 'varchar' : + $type = 's'; + break; + default: + $type = 's'; + } + + if(is_array($value)) + { + foreach($value as $v) + { + $params[] = $v; + $types .= $type; + } + } + else + { + $params[] = $value; + $types .= $type; + } + } + + // 2. Bind parameters + $args = array(); + $args[0] = $stmt; + $args[1] = $types; + $i = 2; + foreach($params as $key => $param) + { + $copy[$key] = $param; + $args[$i++] = &$copy[$key]; + } + + $status = call_user_func_array('mysqli_stmt_bind_param', $args); + if(!$status) + { + $this->setError(-1, "Invalid arguments: " . $connection->error); + return $this->last_stmt = $stmt; + } + } + + // 3. Execute query + $status = $stmt->execute(); + if(!$status) + { + $this->setError(-1, "Prepared statement failed: " . $connection->error); + return $this->last_stmt = $stmt; + } + + // Return stmt for other processing + return $this->last_stmt = $stmt; + } + else + { + $result = $connection->query($query); + if($connection->errno) + { + $this->setError($connection->errno, $connection->error); + } + + return $this->last_stmt = $result; } - // Return result - $this->last_stmt = $result; - return $result; } /** @@ -199,17 +300,92 @@ class DBMysql extends DB { return $output; } - while($tmp = $this->db_fetch_object($result)) + + // No prepared statements + if($this->use_prepared_statements != 'Y') { - if($arrayIndexEndValue) + while($tmp = $this->db_fetch_object($result)) { - $output[$arrayIndexEndValue--] = $tmp; - } - else - { - $output[] = $tmp; + if($arrayIndexEndValue) + { + $output[$arrayIndexEndValue--] = $tmp; + } + else + { + $output[] = $tmp; + } } + $result->free_result(); } + + // Prepared stements: bind result variable and fetch data + else + { + $stmt = $result; + $fields = $stmt->result_metadata()->fetch_fields(); + $row = array(); + $resultArray = array(); + + /** + * Mysqli has a bug that causes LONGTEXT columns not to get loaded + * Unless store_result is called before + * MYSQLI_TYPE for longtext is 252 + */ + $longtext_exists = false; + foreach($fields as $field) + { + // When joined tables are used and the same column name appears twice, we should add it separately, otherwise bind_result fails + if(isset($resultArray[$field->name])) + { + $field->name = 'repeat_' . $field->name; + } + + // Array passed needs to contain references, not values + $row[$field->name] = ''; + $resultArray[$field->name] = &$row[$field->name]; + + if($field->type == 252) + { + $longtext_exists = true; + } + } + $resultArray = array_merge(array($stmt), $resultArray); + + if($longtext_exists) + { + $stmt->store_result(); + } + + call_user_func_array('mysqli_stmt_bind_result', $resultArray); + array_shift($resultArray); + + while($stmt->fetch()) + { + $resultObject = new stdClass; + foreach($resultArray as $key => $value) + { + if(strpos($key, 'repeat_')) + { + $key = substr($key, 6); + } + $resultObject->$key = $value; + } + + if($arrayIndexEndValue) + { + $output[$arrayIndexEndValue--] = $resultObject; + } + else + { + $output[] = $resultObject; + } + } + + $stmt->free_result(); + $stmt->close(); + } + + // Return object if there is only 1 result. if(count($output) == 1) { if(isset($arrayIndexEndValue)) @@ -221,8 +397,10 @@ class DBMysql extends DB return $output[0]; } } - $this->db_free_result($result); - return $output; + else + { + return $output; + } } /** @@ -232,12 +410,12 @@ class DBMysql extends DB */ function getNextSequence() { - $query = sprintf("insert into `%ssequence` (seq) values ('0')", $this->prefix); + $query = sprintf("INSERT INTO `%ssequence` (seq) VALUES ('0')", $this->prefix); $this->_query($query); $sequence = $this->getInsertID(); if($sequence % 10000 == 0) { - $query = sprintf("delete from `%ssequence` where seq < %d", $this->prefix, $sequence); + $query = sprintf("DELETE FROM `%ssequence` WHERE seq < %d", $this->prefix, $sequence); $this->_query($query); } @@ -252,7 +430,7 @@ class DBMysql extends DB */ function isValidOldPassword($password, $saved_password) { - $query = sprintf("select password('%s') as password, old_password('%s') as old_password", $this->addQuotes($password), $this->addQuotes($password)); + $query = sprintf("SELECT PASSWORD('%s') AS password, OLD_PASSWORD('%s') AS old_password", $this->addQuotes($password), $this->addQuotes($password)); $result = $this->_query($query); $tmp = $this->_fetch($result); if($tmp->password === $saved_password || $tmp->old_password === $saved_password) @@ -269,7 +447,7 @@ class DBMysql extends DB */ function isTableExists($target_name) { - $query = sprintf("show tables like '%s%s'", $this->prefix, $this->addQuotes($target_name)); + $query = sprintf("SHOW TABLES LIKE '%s%s'", $this->prefix, $this->addQuotes($target_name)); $result = $this->_query($query); $tmp = $this->_fetch($result); if(!$tmp) @@ -297,7 +475,7 @@ class DBMysql extends DB $size = ''; } - $query = sprintf("alter table `%s%s` add `%s` ", $this->prefix, $table_name, $column_name); + $query = sprintf("ALTER TABLE `%s%s` ADD `%s` ", $this->prefix, $table_name, $column_name); if($size) { $query .= sprintf(" %s(%s) ", $type, $size); @@ -308,11 +486,11 @@ class DBMysql extends DB } if(isset($default)) { - $query .= sprintf(" default '%s' ", $default); + $query .= sprintf(" DEFAULT '%s' ", $default); } if($notnull) { - $query .= " not null "; + $query .= " NOT NULL "; } return $this->_query($query); @@ -326,7 +504,7 @@ class DBMysql extends DB */ function dropColumn($table_name, $column_name) { - $query = sprintf("alter table `%s%s` drop `%s` ", $this->prefix, $table_name, $column_name); + $query = sprintf("ALTER TABLE `%s%s` DROP `%s` ", $this->prefix, $table_name, $column_name); $this->_query($query); } @@ -348,7 +526,7 @@ class DBMysql extends DB $size = ''; } - $query = sprintf("alter table `%s%s` modify `%s` ", $this->prefix, $table_name, $column_name); + $query = sprintf("ALTER TABLE `%s%s` MODIFY `%s` ", $this->prefix, $table_name, $column_name); if($size) { $query .= sprintf(" %s(%s) ", $type, $size); @@ -359,11 +537,11 @@ class DBMysql extends DB } if($default) { - $query .= sprintf(" default '%s' ", $default); + $query .= sprintf(" DEFAULT '%s' ", $default); } if($notnull) { - $query .= " not null "; + $query .= " NOT NULL "; } return $this->_query($query) ? true : false; @@ -377,7 +555,7 @@ class DBMysql extends DB */ function isColumnExists($table_name, $column_name) { - $query = sprintf("show fields from `%s%s`", $this->prefix, $table_name); + $query = sprintf("SHOW FIELDS FROM `%s%s`", $this->prefix, $table_name); $result = $this->_query($query); if($this->isError()) { @@ -407,7 +585,7 @@ class DBMysql extends DB */ function getColumnInfo($table_name, $column_name) { - $query = sprintf("show fields from `%s%s` where `Field` = '%s'", $this->prefix, $table_name, $column_name); + $query = sprintf("SHOW FIELDS FROM `%s%s` WHERE `Field` = '%s'", $this->prefix, $table_name, $column_name); $result = $this->_query($query); if($this->isError()) { @@ -471,7 +649,7 @@ class DBMysql extends DB $target_columns = array($target_columns); } - $query = sprintf("alter table `%s%s` add %s index `%s` (%s);", $this->prefix, $table_name, $is_unique ? 'unique' : '', $index_name, implode(',', $target_columns)); + $query = sprintf("ALTER TABLE `%s%s` ADD %s INDEX `%s` (%s);", $this->prefix, $table_name, $is_unique ? 'UNIQUE' : '', $index_name, implode(',', $target_columns)); $this->_query($query); } @@ -484,7 +662,7 @@ class DBMysql extends DB */ function dropIndex($table_name, $index_name, $is_unique = false) { - $query = sprintf("alter table `%s%s` drop index `%s`", $this->prefix, $table_name, $index_name); + $query = sprintf("ALTER TABLE `%s%s` DROP INDEX `%s`", $this->prefix, $table_name, $index_name); $this->_query($query); } @@ -496,8 +674,7 @@ class DBMysql extends DB */ function isIndexExists($table_name, $index_name) { - //$query = sprintf("show indexes from %s%s where key_name = '%s' ", $this->prefix, $table_name, $index_name); - $query = sprintf("show indexes from `%s%s`", $this->prefix, $table_name); + $query = sprintf("SHOW INDEXES FROM `%s%s`", $this->prefix, $table_name); $result = $this->_query($query); if($this->isError()) { @@ -668,7 +845,7 @@ class DBMysql extends DB } // Generate table schema - $engine = stripos(get_class($this), 'innodb') === false ? 'MYISAM' : 'INNODB'; + $engine = config('db.master.engine') === 'innodb' ? 'InnoDB' : 'MyISAM'; $charset = $this->charset ?: 'utf8'; $collation = $charset . '_unicode_ci'; $schema = sprintf("CREATE TABLE `%s` (%s) %s", @@ -716,49 +893,84 @@ class DBMysql extends DB * Handles insertAct * @param BaseObject $queryObject * @param boolean $with_values - * @return resource + * @return mixed */ function _executeInsertAct($queryObject, $with_values = true) { - $query = $this->getInsertSql($queryObject, $with_values, true); - if($query instanceof BaseObject) + if ($this->use_prepared_statements == 'Y') { - return; + $this->params = $queryObject->getArguments(); + $with_values = false; + } + + $query = $this->getInsertSql($queryObject, $with_values, true); + if ($query instanceof BaseObject) + { + $this->params = array(); + return $query; + } + else + { + $output = $this->_query($query); + $this->params = array(); + return $output; } - return $this->_query($query); } /** * Handles updateAct * @param BaseObject $queryObject * @param boolean $with_values - * @return resource + * @return mixed */ function _executeUpdateAct($queryObject, $with_values = true) { - $query = $this->getUpdateSql($queryObject, $with_values, true); - if($query instanceof BaseObject) + if ($this->use_prepared_statements == 'Y') { - if(!$query->toBool()) return $query; - else return; + $this->params = $queryObject->getArguments(); + $with_values = false; + } + + $query = $this->getUpdateSql($queryObject, $with_values, true); + if ($query instanceof BaseObject) + { + $this->params = array(); + return $query; + } + else + { + $output = $this->_query($query); + $this->params = array(); + return $output; } - return $this->_query($query); } /** * Handles deleteAct * @param BaseObject $queryObject * @param boolean $with_values - * @return resource + * @return mixed */ function _executeDeleteAct($queryObject, $with_values = true) { - $query = $this->getDeleteSql($queryObject, $with_values, true); - if($query instanceof BaseObject) + if ($this->use_prepared_statements == 'Y') { - return; + $this->params = $queryObject->getArguments(); + $with_values = false; + } + + $query = $this->getDeleteSql($queryObject, $with_values, true); + if ($query instanceof BaseObject) + { + $this->params = array(); + return $query; + } + else + { + $output = $this->_query($query); + $this->params = array(); + return $output; } - return $this->_query($query); } /** @@ -772,23 +984,33 @@ class DBMysql extends DB */ function _executeSelectAct($queryObject, $connection = null, $with_values = true) { + if ($this->use_prepared_statements == 'Y') + { + $this->params = $queryObject->getArguments(); + $with_values = false; + } + + $result = null; $limit = $queryObject->getLimit(); - $result = NULL; if($limit && $limit->isPageHandler()) { - return $this->queryPageLimit($queryObject, $result, $connection, $with_values); + $output = $this->queryPageLimit($queryObject, $result, $connection, $with_values); + $this->params = array(); + return $output; } else { $query = $this->getSelectSql($queryObject, $with_values); if($query instanceof BaseObject) { - return; + $this->params = array(); + return $query; } $result = $this->_query($query, $connection); if($this->isError()) { + $this->params = array(); return $this->queryError($queryObject); } @@ -802,6 +1024,7 @@ class DBMysql extends DB $this->_executeUpdateAct($update_query, $with_values); } + $this->params = array(); return $buff; } } @@ -812,8 +1035,8 @@ class DBMysql extends DB */ function getAffectedRows() { - $connection = $this->_getConnection('master'); - return mysql_affected_rows($connection); + $stmt = $this->last_stmt; + return $stmt ? $stmt->affected_rows : -1; } /** @@ -823,7 +1046,7 @@ class DBMysql extends DB function getInsertID() { $connection = $this->_getConnection('master'); - return mysql_insert_id($connection); + return $connection->insert_id; } /** @@ -840,9 +1063,9 @@ class DBMysql extends DB * @param resource $result * @return BaseObject */ - function db_fetch_object(&$result) + function db_fetch_object($result) { - return mysql_fetch_object($result); + return $result->fetch_object(); } /** @@ -850,9 +1073,9 @@ class DBMysql extends DB * @param resource $result * @return boolean Returns TRUE on success or FALSE on failure. */ - function db_free_result(&$result) + function db_free_result($result) { - return mysql_free_result($result); + return $result->free_result(); } /** @@ -873,7 +1096,7 @@ class DBMysql extends DB */ function queryError($queryObject) { - $limit = $queryObject->getLimit(); + $limit = method_exists($queryObject, 'getLimit') ? $queryObject->getLimit() : false; if($limit && $limit->isPageHandler()) { $buff = new BaseObject; @@ -1063,7 +1286,4 @@ class DBMysql extends DB } } -DBMysql::$isSupported = function_exists('mysql_connect'); - -/* End of file DBMysql.class.php */ -/* Location: ./classes/db/DBMysql.class.php */ +DBMysql::$isSupported = class_exists('mysqli'); diff --git a/classes/db/DBMysql_innodb.class.php b/classes/db/DBMysql_innodb.class.php deleted file mode 100644 index c685c008c..000000000 --- a/classes/db/DBMysql_innodb.class.php +++ /dev/null @@ -1,76 +0,0 @@ - */ - -require_once('DBMysql.class.php'); - -/** - * Class to use MySQL innoDB DBMS - * mysql innodb handling class - * - * Does not use prepared statements, since mysql driver does not support them - * - * @author NAVER (developers@xpressengine.com) - * @package /classes/db - * @version 0.1 - */ -class DBMysql_innodb extends DBMysql -{ - /** - * DB transaction start - * this method is private - * @return boolean - */ - function _begin($transactionLevel = 0) - { - $connection = $this->_getConnection('master'); - - if(!$transactionLevel) - { - $this->_query("START TRANSACTION", $connection); - } - else - { - $this->_query("SAVEPOINT SP" . $transactionLevel, $connection); - } - return true; - } - - /** - * DB transaction rollback - * this method is private - * @return boolean - */ - function _rollback($transactionLevel = 0) - { - $connection = $this->_getConnection('master'); - - $point = $transactionLevel - 1; - - if($point) - { - $this->_query("ROLLBACK TO SP" . $point, $connection); - } - else - { - $this->_query("ROLLBACK", $connection); - } - return true; - } - - /** - * DB transaction commit - * this method is private - * @return boolean - */ - function _commit() - { - $connection = $this->_getConnection('master'); - $this->_query("COMMIT", $connection); - return true; - } -} - -DBMysql_innodb::$isSupported = function_exists('mysql_connect'); - -/* End of file DBMysql_innodb.class.php */ -/* Location: ./classes/db/DBMysql_innodb.class.php */ diff --git a/classes/db/DBMysqli.class.php b/classes/db/DBMysqli.class.php deleted file mode 100644 index c0c79f2aa..000000000 --- a/classes/db/DBMysqli.class.php +++ /dev/null @@ -1,422 +0,0 @@ - */ - -require_once('DBMysql.class.php'); - -/** - * Class to use MySQLi DBMS as mysqli_* - * mysql handling class - * - * Does not use prepared statements, since mysql driver does not support them - * - * @author NAVER (developers@xpressengine.com) - * @package /classes/db - * @version 0.1 - */ -class DBMysqli extends DBMysql -{ - /** - * DB Connect - * this method is private - * @param array $connection connection's value is db_hostname, db_port, db_database, db_userid, db_password - * @return resource - */ - function __connect($connection) - { - // Attempt to connect - if($connection['port']) - { - $result = @mysqli_connect($connection['host'], $connection['user'], $connection['pass'], $connection['database'], $connection['port']); - } - else - { - $result = @mysqli_connect($connection['host'], $connection['user'], $connection['pass'], $connection['database']); - } - $error = mysqli_connect_errno(); - if($error) - { - $this->setError($error, mysqli_connect_error()); - return; - } - $this->charset = isset($connection['charset']) ? $connection['charset'] : 'utf8'; - $this->db_version = $result->server_info; - mysqli_set_charset($result, $this->charset); - return $result; - } - - /** - * DB disconnection - * this method is private - * @param resource $connection - * @return void - */ - function _close($connection) - { - mysqli_close($connection); - } - - /** - * Handles quatation of the string variables from the query - * @param string $string - * @return string - */ - function addQuotes($string) - { - if(!is_numeric($string)) - { - $connection = $this->_getConnection('master'); - $string = mysqli_escape_string($connection, $string); - } - return $string; - } - - /** - * Execute the query - * this method is private - * @param string $query - * @param resource $connection - * @return resource - */ - function __query($query, $connection) - { - if ($connection === null) - { - $this->setError(-1, 'Unable to connect to DB.'); - return false; - } - if($this->use_prepared_statements == 'Y') - { - // 1. Prepare query - $stmt = mysqli_prepare($connection, $query); - if($stmt) - { - $types = ''; - $params = array(); - $this->_prepareQueryParameters($types, $params); - - if(!empty($params)) - { - $args[0] = $stmt; - $args[1] = $types; - - $i = 2; - foreach($params as $key => $param) - { - $copy[$key] = $param; - $args[$i++] = &$copy[$key]; - } - - // 2. Bind parameters - $status = call_user_func_array('mysqli_stmt_bind_param', $args); - if(!$status) - { - $this->setError(-1, "Invalid arguments: " . mysqli_error($connection)); - } - } - - // 3. Execute query - $status = mysqli_stmt_execute($stmt); - - if(!$status) - { - $this->setError(-1, "Prepared statement failed: " . mysqli_error($connection)); - } - - // Return stmt for other processing - like retrieving resultset (_fetch) - $this->last_stmt = $stmt; - return $stmt; - } - } - // Run the query statement - $result = mysqli_query($connection, $query); - // Error Check - $error = mysqli_error($connection); - if($error) - { - $this->setError(mysqli_errno($connection), $error); - } - // Return result - $this->last_stmt = $result; - return $result; - } - - /** - * Before execute query, prepare statement - * this method is private - * @param string $types - * @param array $params - * @return void - */ - function _prepareQueryParameters(&$types, &$params) - { - $types = ''; - $params = array(); - if(!$this->param) - { - return; - } - - foreach($this->param as $k => $o) - { - $value = $o->getUnescapedValue(); - $type = $o->getType(); - - // Skip column names -> this should be concatenated to query string - if($o->isColumnName()) - { - continue; - } - - switch($type) - { - case 'number' : - $type = 'i'; - break; - case 'varchar' : - $type = 's'; - break; - default: - $type = 's'; - } - - if(is_array($value)) - { - foreach($value as $v) - { - $params[] = $v; - $types .= $type; - } - } - else - { - $params[] = $value; - $types .= $type; - } - } - } - - /** - * Fetch the result - * @param resource $result - * @param int|NULL $arrayIndexEndValue - * @return array - */ - function _fetch($result, $arrayIndexEndValue = NULL) - { - if($this->use_prepared_statements != 'Y') - { - return parent::_fetch($result, $arrayIndexEndValue); - } - $output = array(); - if(!$this->isConnected() || $this->isError() || !$result) - { - return $output; - } - - // Prepared stements: bind result variable and fetch data - $stmt = $result; - $meta = mysqli_stmt_result_metadata($stmt); - $fields = mysqli_fetch_fields($meta); - - /** - * Mysqli has a bug that causes LONGTEXT columns not to get loaded - * Unless store_result is called before - * MYSQLI_TYPE for longtext is 252 - */ - $longtext_exists = false; - foreach($fields as $field) - { - if(isset($resultArray[$field->name])) // When joined tables are used and the same column name appears twice, we should add it separately, otherwise bind_result fails - { - $field->name = 'repeat_' . $field->name; - } - - // Array passed needs to contain references, not values - $row[$field->name] = ""; - $resultArray[$field->name] = &$row[$field->name]; - - if($field->type == 252) - { - $longtext_exists = true; - } - } - $resultArray = array_merge(array($stmt), $resultArray); - - if($longtext_exists) - { - mysqli_stmt_store_result($stmt); - } - - call_user_func_array('mysqli_stmt_bind_result', $resultArray); - - $rows = array(); - while(mysqli_stmt_fetch($stmt)) - { - $resultObject = new stdClass(); - - foreach($resultArray as $key => $value) - { - if($key === 0) - { - continue; // Skip stmt object - } - if(strpos($key, 'repeat_')) - { - $key = substr($key, 6); - } - $resultObject->$key = $value; - } - - $rows[] = $resultObject; - } - - mysqli_stmt_close($stmt); - - if($arrayIndexEndValue) - { - foreach($rows as $row) - { - $output[$arrayIndexEndValue--] = $row; - } - } - else - { - $output = $rows; - } - - if(count($output) == 1) - { - if(isset($arrayIndexEndValue)) - { - return $output; - } - else - { - return $output[0]; - } - } - - return $output; - } - - /** - * Handles insertAct - * @param BaseObject $queryObject - * @param boolean $with_values - * @return resource - */ - function _executeInsertAct($queryObject, $with_values = false) - { - if($this->use_prepared_statements != 'Y') - { - return parent::_executeInsertAct($queryObject); - } - $this->param = $queryObject->getArguments(); - $result = parent::_executeInsertAct($queryObject, $with_values); - unset($this->param); - return $result; - } - - /** - * Handles updateAct - * @param BaseObject $queryObject - * @param boolean $with_values - * @return resource - */ - function _executeUpdateAct($queryObject, $with_values = false) - { - if($this->use_prepared_statements != 'Y') - { - return parent::_executeUpdateAct($queryObject); - } - $this->param = $queryObject->getArguments(); - $result = parent::_executeUpdateAct($queryObject, $with_values); - unset($this->param); - return $result; - } - - /** - * Handles deleteAct - * @param BaseObject $queryObject - * @param boolean $with_values - * @return resource - */ - function _executeDeleteAct($queryObject, $with_values = false) - { - if($this->use_prepared_statements != 'Y') - { - return parent::_executeDeleteAct($queryObject); - } - $this->param = $queryObject->getArguments(); - $result = parent::_executeDeleteAct($queryObject, $with_values); - unset($this->param); - return $result; - } - - /** - * Handle selectAct - * In order to get a list of pages easily when selecting \n - * it supports a method as navigation - * @param BaseObject $queryObject - * @param resource $connection - * @param boolean $with_values - * @return BaseObject - */ - function _executeSelectAct($queryObject, $connection = null, $with_values = false) - { - if($this->use_prepared_statements != 'Y') - { - return parent::_executeSelectAct($queryObject, $connection); - } - $this->param = $queryObject->getArguments(); - $result = parent::_executeSelectAct($queryObject, $connection, $with_values); - unset($this->param); - return $result; - } - - /** - * Get the number of rows affected by the last query - * @return int - */ - function getAffectedRows() - { - $stmt = $this->last_stmt; - return $stmt ? $stmt->affected_rows : -1; - } - - /** - * Get the ID generated in the last query - * @return int - */ - function getInsertID() - { - $connection = $this->_getConnection('master'); - return mysqli_insert_id($connection); - } - - /** - * Fetch a result row as an object - * @param resource $result - * @return BaseObject - */ - function db_fetch_object(&$result) - { - return mysqli_fetch_object($result); - } - - /** - * Free result memory - * @param resource $result - * @return boolean Returns TRUE on success or FALSE on failure. - */ - function db_free_result(&$result) - { - return mysqli_free_result($result); - } - -} - -DBMysqli::$isSupported = function_exists('mysqli_connect'); - -/* End of file DBMysqli.class.php */ -/* Location: ./classes/db/DBMysqli.class.php */ diff --git a/classes/db/DBMysqli_innodb.class.php b/classes/db/DBMysqli_innodb.class.php deleted file mode 100644 index 56a4767ba..000000000 --- a/classes/db/DBMysqli_innodb.class.php +++ /dev/null @@ -1,86 +0,0 @@ - */ - -require_once('DBMysql.class.php'); -require_once('DBMysqli.class.php'); - -/** - * Class to use MySQLi innoDB DBMS as mysqli_* - * mysql innodb handling class - * - * Does not use prepared statements, since mysql driver does not support them - * - * @author NAVER (developers@xpressengine.com) - * @package /classes/db - * @version 0.1 - */ -class DBMysqli_innodb extends DBMysqli -{ - /** - * DB transaction start - * this method is private - * @return boolean - */ - function _begin($transactionLevel = 0) - { - $connection = $this->_getConnection('master'); - - if(!$transactionLevel) - { - if(function_exists('mysqli_begin_transaction')) - { - mysqli_begin_transaction($connection); - $this->setQueryLog(array('query' => 'START TRANSACTION')); - } - else - { - $this->_query("START TRANSACTION" . $point, $connection); - } - } - else - { - $this->_query("SAVEPOINT SP" . $transactionLevel, $connection); - } - return true; - } - - /** - * DB transaction rollback - * this method is private - * @return boolean - */ - function _rollback($transactionLevel = 0) - { - $connection = $this->_getConnection('master'); - $point = $transactionLevel - 1; - - if($point) - { - $this->_query("ROLLBACK TO SP" . $point, $connection); - } - else - { - mysqli_rollback($connection); - $this->setQueryLog(array('query' => 'ROLLBACK')); - } - return true; - } - - /** - * DB transaction commit - * this method is private - * @return boolean - */ - function _commit() - { - $connection = $this->_getConnection('master'); - mysqli_commit($connection); - $this->setQueryLog(array('query' => 'COMMIT')); - return true; - } -} - -DBMysqli_innodb::$isSupported = function_exists('mysqli_connect'); - -/* End of file DBMysqli.class.php */ -/* Location: ./classes/db/DBMysqli.class.php */ diff --git a/classes/db/queryparts/condition/Condition.class.php b/classes/db/queryparts/condition/Condition.class.php index 2e5968e10..447ef24fb 100644 --- a/classes/db/queryparts/condition/Condition.class.php +++ b/classes/db/queryparts/condition/Condition.class.php @@ -41,7 +41,7 @@ class Condition * @param string $pipe * @return void */ - function __construct($column_name, $argument, $operation, $pipe) + function __construct($column_name, $argument, $operation, $pipe = 'and') { $this->column_name = $column_name; $this->argument = $argument; @@ -85,7 +85,7 @@ class Condition */ function toStringWithoutValue() { - return $this->pipe . ' ' . $this->getConditionPart($this->_value); + return strtoupper($this->pipe) . ' ' . $this->getConditionPart($this->_value); } /** @@ -94,7 +94,7 @@ class Condition */ function toStringWithValue() { - return $this->pipe . ' ' . $this->getConditionPart($this->_value); + return strtoupper($this->pipe) . ' ' . $this->getConditionPart($this->_value); } function setPipe($pipe) @@ -122,13 +122,18 @@ class Condition case 'more' : case 'excess' : case 'less' : - case 'below' : + case 'below' : + case 'gte' : + case 'gt' : + case 'lte' : + case 'lt' : case 'like_tail' : case 'like_prefix' : case 'like' : case 'notlike_tail' : case 'notlike_prefix' : case 'notlike' : + case 'not_like' : case 'in' : case 'notin' : case 'not_in' : @@ -137,6 +142,7 @@ class Condition case 'xor': case 'not': case 'notequal' : + case 'not_equal' : // if variable is not set or is not string or number, return if(!isset($this->_value)) { @@ -167,7 +173,8 @@ class Condition break; } case 'null': - case 'notnull': + case 'notnull': + case 'not_null': break; default: // If operation is not one of the above, means the condition is invalid @@ -190,50 +197,52 @@ class Condition switch($operation) { - case 'equal' : + case 'equal' : return $name . ' = ' . $value; break; - case 'more' : + case 'more' : + case 'gte' : return $name . ' >= ' . $value; break; - case 'excess' : + case 'excess' : + case 'gt' : return $name . ' > ' . $value; break; - case 'less' : + case 'less' : + case 'lte' : return $name . ' <= ' . $value; break; - case 'below' : + case 'below' : + case 'lt' : return $name . ' < ' . $value; break; case 'like_tail' : case 'like_prefix' : case 'like' : - if(defined('__CUBRID_VERSION__') - && __CUBRID_VERSION__ >= '8.4.1') - return $name . ' rlike ' . $value; - else - return $name . ' like ' . $value; - break; + return $name . ' LIKE ' . $value; case 'notlike_tail' : case 'notlike_prefix' : case 'notlike' : - return $name . ' not like ' . $value; + case 'not_like' : + return $name . ' NOT LIKE ' . $value; break; case 'in' : - return $name . ' in ' . $value; + return $name . ' IN ' . $value; break; case 'notin' : case 'not_in' : - return $name . ' not in ' . $value; + return $name . ' NOT IN ' . $value; break; - case 'notequal' : + case 'notequal' : + case 'not_equal' : return $name . ' <> ' . $value; break; - case 'notnull' : - return $name . ' is not null'; + case 'notnull' : + case 'not_null' : + return $name . ' IS NOT NULL '; break; case 'null' : - return $name . ' is null'; + return $name . ' IS NULL '; break; case 'and' : return $name . ' & ' . $value; @@ -248,7 +257,7 @@ class Condition return $name . ' ~ ' . $value; break; case 'between' : - return $name . ' between ' . $value[0] . ' and ' . $value[1]; + return $name . ' BETWEEN ' . $value[0] . ' AND ' . $value[1]; break; } } diff --git a/classes/db/queryparts/condition/ConditionGroup.class.php b/classes/db/queryparts/condition/ConditionGroup.class.php index 0c782c3e6..2b6057ed8 100644 --- a/classes/db/queryparts/condition/ConditionGroup.class.php +++ b/classes/db/queryparts/condition/ConditionGroup.class.php @@ -29,7 +29,7 @@ class ConditionGroup * @param string $pipe * @return void */ - function __construct($conditions, $pipe = "") + function __construct($conditions, $pipe = 'and') { $this->conditions = array(); foreach($conditions as $condition) @@ -89,7 +89,7 @@ class ConditionGroup if($this->pipe !== "" && trim($group) !== '') { - $group = $this->pipe . ' (' . $group . ')'; + $group = strtoupper($this->pipe) . ' (' . $group . ')'; } $this->_group = $group; @@ -105,11 +105,24 @@ class ConditionGroup { $args = array(); foreach($this->conditions as $condition) - { - $arg = $condition->getArgument(); - if($arg) + { + if($condition instanceof ConditionGroup) + { + foreach($condition->getArguments() as $arg) + { + if($arg) + { + $args[] = $arg; + } + } + } + else { - $args[] = $arg; + $arg = $condition->getArgument(); + if($arg) + { + $args[] = $arg; + } } } return $args; diff --git a/classes/db/queryparts/condition/ConditionWithArgument.class.php b/classes/db/queryparts/condition/ConditionWithArgument.class.php index 4108ef49d..9f42fd118 100644 --- a/classes/db/queryparts/condition/ConditionWithArgument.class.php +++ b/classes/db/queryparts/condition/ConditionWithArgument.class.php @@ -68,7 +68,7 @@ class ConditionWithArgument extends Condition $q = '?'; } } - return $this->pipe . ' ' . $this->getConditionPart($q); + return strtoupper($this->pipe) . ' ' . $this->getConditionPart($q); } /** diff --git a/classes/db/queryparts/expression/SelectExpression.class.php b/classes/db/queryparts/expression/SelectExpression.class.php index 5c0447c77..78ea23408 100644 --- a/classes/db/queryparts/expression/SelectExpression.class.php +++ b/classes/db/queryparts/expression/SelectExpression.class.php @@ -42,7 +42,7 @@ class SelectExpression extends Expression */ function getExpression() { - return sprintf("%s%s", $this->column_name, $this->column_alias ? " as " . $this->column_alias : ""); + return sprintf("%s%s", $this->column_name, $this->column_alias ? (' AS ' . $this->column_alias) : ""); } function show() diff --git a/classes/db/queryparts/order/OrderByColumn.class.php b/classes/db/queryparts/order/OrderByColumn.class.php index 92bf4b947..7a6a67e08 100644 --- a/classes/db/queryparts/order/OrderByColumn.class.php +++ b/classes/db/queryparts/order/OrderByColumn.class.php @@ -37,7 +37,7 @@ class OrderByColumn { $result = $this->getColumnName(); $result .= ' '; - $result .= is_a($this->sort_order, 'Argument') ? $this->sort_order->getValue() : $this->sort_order; + $result .= is_a($this->sort_order, 'Argument') ? $this->sort_order->getValue() : strtoupper($this->sort_order); return $result; } diff --git a/classes/db/queryparts/table/CubridTableWithHint.class.php b/classes/db/queryparts/table/CubridTableWithHint.class.php deleted file mode 100644 index 9f614a816..000000000 --- a/classes/db/queryparts/table/CubridTableWithHint.class.php +++ /dev/null @@ -1,71 +0,0 @@ - */ - -/** - * @author NAVER (developers@xpressengine.com) - * @package /classes/db/queryparts/table - * @version 0.1 - */ -class CubridTableWithHint extends Table -{ - - /** - * table name - * @var string - */ - var $name; - - /** - * table alias - * @var string - */ - var $alias; - - /** - * index hint list - * @var array - */ - var $index_hints_list; - - /** - * constructor - * @param string $name - * @param string $alias - * @param array $index_hints_list - * @return void - */ - function __construct($name, $alias = NULL, $index_hints_list) - { - parent::__construct($name, $alias); - $this->index_hints_list = $index_hints_list; - } - - /** - * Return index hint string - * @return string - */ - function getIndexHintString() - { - $result = ''; - - // Retrieve table prefix, to add it to index name - $prefix = config('db.master.prefix'); - - foreach($this->index_hints_list as $index_hint) - { - $index_hint_type = $index_hint->getIndexHintType(); - if($index_hint_type !== 'IGNORE') - { - $result .= $this->alias . '.' - . '"' . $prefix . substr($index_hint->getIndexName(), 1) - . ($index_hint_type == 'FORCE' ? '(+)' : '') - . ', '; - } - } - $result = substr($result, 0, -2); - return $result; - } - -} -/* End of file CubridTableWithHint.class.php */ -/* Location: ./classes/db/queryparts/table/CubridTableWithHint.class.php */ diff --git a/classes/db/queryparts/table/JoinTable.class.php b/classes/db/queryparts/table/JoinTable.class.php index 0d6625728..6e882cc28 100644 --- a/classes/db/queryparts/table/JoinTable.class.php +++ b/classes/db/queryparts/table/JoinTable.class.php @@ -41,12 +41,19 @@ class JoinTable extends Table function toString($with_value = true) { - $part = $this->join_type . ' ' . $this->name; - $part .= $this->alias ? ' as ' . $this->alias : ''; - $part .= ' on '; + $part = strtoupper($this->join_type) . ' ' . $this->name; + $part .= $this->alias ? (' AS ' . $this->alias) : ''; + $part .= ' ON '; + + $condition_count = 0; foreach($this->conditions as $conditionGroup) { - $part .= $conditionGroup->toString($with_value); + if($condition_count === 0) + { + $conditionGroup->setPipe(""); + } + $part .= $conditionGroup->toString($with_value); + $condition_count++; } return $part; } diff --git a/classes/db/queryparts/table/MssqlTableWithHint.class.php b/classes/db/queryparts/table/MssqlTableWithHint.class.php deleted file mode 100644 index edc49accc..000000000 --- a/classes/db/queryparts/table/MssqlTableWithHint.class.php +++ /dev/null @@ -1,66 +0,0 @@ - */ - -/** - * @author NAVER (developers@xpressengine.com) - * @package /classes/db/queryparts/table - * @version 0.1 - */ -class MssqlTableWithHint extends Table -{ - - /** - * table name - * @var string - */ - var $name; - - /** - * table alias - * @var string - */ - var $alias; - - /** - * index hint type, ex) IGNORE, FORCE, USE... - * @var array - */ - var $index_hints_list; - - /** - * constructor - * @param string $name - * @param string $alias - * @param string $index_hints_list - * @return void - */ - function __construct($name, $alias = NULL, $index_hints_list) - { - parent::__construct($name, $alias); - $this->index_hints_list = $index_hints_list; - } - - function toString() - { - $result = parent::toString(); - - $index_hint_string = ''; - $indexTypeList = array('USE' => 1, 'FORCE' => 1); - foreach($this->index_hints_list as $index_hint) - { - $index_hint_type = $index_hint->getIndexHintType(); - if(isset($indexTypeList[$index_hint_type])) - { - $index_hint_string .= 'INDEX(' . $index_hint->getIndexName() . '), '; - } - } - if($index_hint_string != '') - { - $result .= ' WITH(' . substr($index_hint_string, 0, -2) . ') '; - } - return $result; - } - -} -/* End of file MssqlTableWithHint.class.php */ -/* Location: ./classes/db/queryparts/table/MssqlTableWithHint.class.php */ diff --git a/classes/db/queryparts/table/Table.class.php b/classes/db/queryparts/table/Table.class.php index dfd42fb7b..6c0a17c69 100644 --- a/classes/db/queryparts/table/Table.class.php +++ b/classes/db/queryparts/table/Table.class.php @@ -36,7 +36,7 @@ class Table function toString() { //return $this->name; - return sprintf("%s%s", $this->name, $this->alias ? ' as ' . $this->alias : ''); + return sprintf("%s%s", $this->name, $this->alias ? (' AS ' . $this->alias) : ''); } function getName() diff --git a/classes/xml/xmlquery/tags/condition/ConditionGroupTag.class.php b/classes/xml/xmlquery/tags/condition/ConditionGroupTag.class.php index 807ff3a1e..194e9eee9 100644 --- a/classes/xml/xmlquery/tags/condition/ConditionGroupTag.class.php +++ b/classes/xml/xmlquery/tags/condition/ConditionGroupTag.class.php @@ -16,7 +16,7 @@ class ConditionGroupTag * @var string|array value is ConditionTag object */ var $conditions; - + /** * pipe * @var string @@ -29,7 +29,7 @@ class ConditionGroupTag * @param string $pipe * @return void */ - function __construct($conditions, $pipe = "") + function __construct($conditions, $pipe = 'and') { $this->pipe = $pipe; @@ -37,11 +37,22 @@ class ConditionGroupTag { $conditions = array($conditions); } - + + //var_dump($conditions); foreach($conditions as $condition) { - //if($condition->node_name === 'query') $this->conditions[] = new QueryTag($condition, true); - $this->conditions[] = new ConditionTag($condition); + if($condition->node_name === 'group') + { + $subconditions = $condition->condition; + $subgroups = $condition->group; + $subconditions = $subconditions ? (is_array($subconditions) ? $subconditions : [$subconditions]) : []; + $subgroups = $subgroups ? (is_array($subgroups) ? $subgroups : [$subgroups]) : []; + $this->conditions[] = new ConditionGroupTag(array_merge($subconditions, $subgroups), $condition->attrs->pipe); + } + else + { + $this->conditions[] = new ConditionTag($condition); + } } } @@ -58,8 +69,15 @@ class ConditionGroupTag { $conditions_string = 'array(' . PHP_EOL; foreach($this->conditions as $condition) - { - $conditions_string .= $condition->getConditionString() . PHP_EOL . ','; + { + if($condition instanceof ConditionGroupTag) + { + $conditions_string .= $condition->getConditionGroupString() . PHP_EOL . ','; + } + else + { + $conditions_string .= $condition->getConditionString() . PHP_EOL . ','; + } } $conditions_string = substr($conditions_string, 0, -2); //remove ',' $conditions_string .= ')'; diff --git a/classes/xml/xmlquery/tags/condition/ConditionTag.class.php b/classes/xml/xmlquery/tags/condition/ConditionTag.class.php index 4d0a2f5fc..fe4ce7ee1 100644 --- a/classes/xml/xmlquery/tags/condition/ConditionTag.class.php +++ b/classes/xml/xmlquery/tags/condition/ConditionTag.class.php @@ -62,7 +62,7 @@ class ConditionTag function __construct($condition) { $this->operation = $condition->attrs->operation; - $this->pipe = $condition->attrs->pipe; + $this->pipe = $condition->attrs->pipe ?: 'and'; $dbParser = DB::getParser(); $this->column_name = $dbParser->parseExpression($condition->attrs->column); diff --git a/classes/xml/xmlquery/tags/condition/ConditionsTag.class.php b/classes/xml/xmlquery/tags/condition/ConditionsTag.class.php index 0042505ff..66a172297 100644 --- a/classes/xml/xmlquery/tags/condition/ConditionsTag.class.php +++ b/classes/xml/xmlquery/tags/condition/ConditionsTag.class.php @@ -61,8 +61,12 @@ class ConditionsTag $xml_groups = array($xml_groups); } foreach($xml_groups as $group) - { - $this->condition_groups[] = new ConditionGroupTag($group->condition, $group->attrs->pipe); + { + $subconditions = $group->condition; + $subgroups = $group->group; + $subconditions = $subconditions ? (is_array($subconditions) ? $subconditions : [$subconditions]) : []; + $subgroups = $subgroups ? (is_array($subgroups) ? $subgroups : [$subgroups]) : []; + $this->condition_groups[] = new ConditionGroupTag(array_merge($subconditions, $subgroups), $group->attrs->pipe); } } } diff --git a/common/autoload.php b/common/autoload.php index c4312273c..cbcd870ba 100644 --- a/common/autoload.php +++ b/common/autoload.php @@ -66,10 +66,8 @@ $GLOBALS['RX_AUTOLOAD_FILE_MAP'] = array_change_key_case(array( 'UpdateExpressionWithoutArgument' => 'classes/db/queryparts/expression/UpdateExpressionWithoutArgument.class.php', 'Limit' => 'classes/db/queryparts/limit/Limit.class.php', 'OrderByColumn' => 'classes/db/queryparts/order/OrderByColumn.class.php', - 'CubridTableWithHint' => 'classes/db/queryparts/table/CubridTableWithHint.class.php', 'IndexHint' => 'classes/db/queryparts/table/IndexHint.class.php', 'JoinTable' => 'classes/db/queryparts/table/JoinTable.class.php', - 'MssqlTableWithHint' => 'classes/db/queryparts/table/MssqlTableWithHint.class.php', 'MysqlTableWithHint' => 'classes/db/queryparts/table/MysqlTableWithHint.class.php', 'Table' => 'classes/db/queryparts/table/Table.class.php', 'DisplayHandler' => 'classes/display/DisplayHandler.class.php',