diff --git a/.gitignore b/.gitignore index 00495dc..ece8efe 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -/nbproject \ No newline at end of file +/nbproject +/vendor \ No newline at end of file diff --git a/php_cs.php.dist b/php_cs.php.dist new file mode 100644 index 0000000..4d9ce5e --- /dev/null +++ b/php_cs.php.dist @@ -0,0 +1,92 @@ +exclude('vendor') + ->in(__DIR__) +; + +return PhpCsFixer\Config::create() + ->setRules([ + 'align_multiline_comment' => [ + 'comment_type' => 'phpdocs_only' + ], + 'array_indentation' => [], + 'array_syntax' => [ + 'syntax' => 'short' + ], + 'binary_operator_spaces' => [ + 'default' => 'single_space' + ], + 'blank_line_before_statement' => [ + 'statements' => [ + 'if','return','while','for','foreach','do' + ] + ], + 'blank_line_after_opening_tag' => true, + 'blank_line_after_namespace' => true, + 'elseif' => false, + 'explicit_string_variable' => false, + 'full_opening_tag' => true, + 'fully_qualified_strict_types' => true, + 'line_ending' => true, + 'linebreak_after_opening_tag' => true, + 'lowercase_cast' => true, + 'lowercase_keywords' => true, + 'lowercase_static_reference' => true, + 'no_alternative_syntax' => true, + 'no_blank_lines_after_class_opening' => true, + 'no_blank_lines_after_phpdoc' => true, + 'no_blank_lines_before_namespace' => true, + 'no_closing_tag' => true, + 'no_empty_comment' => true, + 'no_empty_phpdoc' => true, + 'no_empty_statement' => true, + 'no_multiline_whitespace_around_double_arrow' => true, + 'no_spaces_after_function_name' => true, + 'no_spaces_inside_parenthesis' => true, + 'no_unused_imports' => true, + 'single_import_per_statement' => true, + 'single_blank_line_at_eof' => true, + 'no_whitespace_in_blank_line' => true, + 'not_operator_with_space' => false, + 'ordered_imports' => [ + 'sort_algorithm' => 'alpha' + ], + 'ordered_class_elements' => [ + 'sortAlgorithm' => 'alpha', + 'order' => [ + 'constant_public', + 'constant_protected', + 'constant_private', + 'property_public', + 'property_protected', + 'property_private', + 'construct', + 'method_public', + 'method_private' + ] + ], + 'no_mixed_echo_print' => [ + 'use' => 'echo' + ], + 'constant_case' => [ + 'case' => 'lower' + ], + 'increment_style' => [ + 'style' => 'post' + ], + 'concat_space' => [ + 'spacing' => 'none' + ], + 'braces' => [ + 'allow_single_line_closure' => false, + 'position_after_functions_and_oop_constructs' => 'same', + 'position_after_anonymous_constructs' => 'next', + 'position_after_control_structures' => 'same' + ], + 'class_definition' => [ + 'single_line' => true + ] + ]) + ->setFinder($finder) +; diff --git a/src/ForeignKey.php b/src/ForeignKey.php index 3246543..4d9dbf0 100644 --- a/src/ForeignKey.php +++ b/src/ForeignKey.php @@ -23,8 +23,7 @@ * SOFTWARE. */ namespace phMysql; -use phMysql\MySQLTable; -use phMysql\MySQLColumn; + /** * A class that represents a foreign key. * A foreign key must have an owner table and a source table. The @@ -34,18 +33,6 @@ * @version 1.3.1 */ class ForeignKey { - /** - * The table at which the key will be added to. - * @var MySQLTable - * @since 1.3.1 - */ - private $ownerTableObj; - /** - * The table which the values are taken from. - * @var MySQLTable - * @since 1.3.1 - */ - private $sourceTableObj; /** * An array of allowed conditions for 'on delete' and 'on update'. * The array have the following strings: @@ -59,22 +46,16 @@ class ForeignKey { * @var array * @since 1.0 */ - const CONDITIONS = array( + const CONDITIONS = [ 'set null','restrict','set default', 'no action','cascade' - ); + ]; /** - * An array that contains the names of sources columns. - * @var array - * @since 1.3 - */ - private $ownerCols; - /** - * An array that contains the names of referenced columns. - * @var array - * @since 1.3 + * The name of the key. + * @var string + * @since 1.0 */ - private $sourceCols; + private $keyName; /** * The 'on delete' condition. * @var string @@ -88,89 +69,66 @@ class ForeignKey { */ private $onUpdateCondition; /** - * The name of the key. - * @var string - * @since 1.0 + * An array that contains the names of sources columns. + * @var array + * @since 1.3 */ - private $keyName; + private $ownerCols; /** - * Sets the name of the key. - * @param string $name The name of the key. A valid key name must follow the - * following rules: - * - * @return boolean|string true if the name of the key is set. The method will - * return the constant ForeignKey::INV_KEY_NAME in - * case if the given key name is invalid. - * @since 1.1 + * The table at which the key will be added to. + * @var MySQLTable + * @since 1.3.1 */ - public function setKeyName($name) { - $trim = trim($name); - if($this->validateAttr($trim) == true){ - $this->keyName = $trim; - return true; - } - return false; - } + private $ownerTableObj; /** - * A method that is used to validate the names of the key attributes (such as source column - * name or source table name). - * @param string $trimmed The string to validate. It must be a string and its not empty. - * Also it must not contain any spaces or any characters other than A-Z, a-z and - * underscore. - * @return boolean true if the given parameter is valid. false in - * case if the given parameter is invalid. + * An array that contains the names of referenced columns. + * @var array + * @since 1.3 */ - private function validateAttr($trimmed){ - $len = strlen($trimmed); - if($len != 0){ - if(strpos($trimmed, ' ') === false){ - for ($x = 0 ; $x < $len ; $x++){ - $ch = $trimmed[$x]; - if($x == 0 && ($ch >= '0' && $ch <= '9')){ - return false; - } - if($ch == '_' || ($ch >= 'a' && $ch <= 'z') || ($ch >= 'A' && $ch <= 'Z') || ($ch >= '0' && $ch <= '9')){ - - } - else{ - return false; - } - } - return true; - } - } - return false; - } + private $sourceCols; /** - * Removes a column from the key given owner column name. - * @param string $ownerColName The name of the owner column name. - * @return boolean If a column which has the given name was found and removed, - * the method will return true. Other than that, the method will return false. + * The table which the values are taken from. + * @var MySQLTable * @since 1.3.1 */ - public function removeReference($ownerColName) { - $trimmed = trim($ownerColName); - $colIndex = 0; - foreach ($this->getOwnerCols() as $k => $v){ - if($k == $trimmed){ - $sourceIndex = 0; - foreach ($this->getSourceCols() as $sK => $sV){ - if($sourceIndex == $colIndex){ - unset($this->sourceCols[$sK]); - unset($this->ownerCols[$k]); - return true; - } - $sourceIndex++; - } + private $sourceTableObj; + /** + * Creates new foreign key. + * @param string $name The name of the key. It must be a string and its not empty. + * Also it must not contain any spaces or any characters other than A-Z, a-z and + * underscore. The default value is 'key_name'. + * @param MySQLTable $ownerTable The table that will contain the key. + * @param MySQLTable $sourceTable The name of the table that contains the + * original values. + * @param array|string $cols An associative array that contains the names of key + * columns. The indices must be columns in the owner table and the values are + * columns in the source columns. + */ + public function __construct( + $name = 'key_name', + $ownerTable = null, + $sourceTable = null, + $cols = []) { + $this->sourceCols = []; + $this->ownerCols = []; + + if ($sourceTable instanceof MySQLTable) { + $this->setSource($sourceTable); + } + + if ($ownerTable instanceof MySQLTable) { + $this->setOwner($ownerTable); + } + + if ($this->setKeyName($name) !== true) { + $this->setKeyName('key_name'); + } + + if (gettype($cols) == 'array') { + foreach ($cols as $k => $v) { + $this->addReference($k, $v); } - $colIndex++; } - return false; } /** * Add a column reference to the foreign key. @@ -186,39 +144,41 @@ public function removeReference($ownerColName) { * Other than that, the method will return false. * @since 1.3.1 */ - public function addReference($ownerColName,$sourceColName=null) { + public function addReference($ownerColName,$sourceColName = null) { $ownerTbl = $this->getOwner(); - if($ownerTbl !== null){ + + if ($ownerTbl !== null) { $ownerColName = trim($ownerColName); $sourceTbl = $this->getSource(); - if($sourceTbl !== null){ + + if ($sourceTbl !== null) { $ownerCol = $ownerTbl->getCol($ownerColName); - if($ownerCol instanceof MySQLColumn){ + + if ($ownerCol instanceof MySQLColumn) { $sourceColName = $sourceColName === null ? $ownerColName : trim($sourceColName); $sourceCol = $sourceTbl->getCol($sourceColName); - if($sourceCol instanceof MySQLColumn){ - if($sourceCol->getType() == $ownerCol->getType()){ + + if ($sourceCol instanceof MySQLColumn) { + if ($sourceCol->getType() == $ownerCol->getType()) { $this->ownerCols[$ownerColName] = $ownerCol; $this->sourceCols[$sourceColName] = $sourceCol; + return true; - } - else{ + } else { trigger_error('Source['.$sourceColName.'] and target['.$ownerCol.'] columns have incompatible datatypes. ' - . 'Source type: \''.$sourceCol->getType().'\'. Target type: \''.$ownerCol->getType().'\'.'); + .'Source type: \''.$sourceCol->getType().'\'. Target type: \''.$ownerCol->getType().'\'.'); } } - } - else{ + } else { trigger_error('No column which has the name \''.$ownerColName.'\' was found in the table \''.$ownerTbl->getName().'\'.'); } - } - else{ + } else { trigger_error('Source table is not set.'); } - } - else{ + } else { trigger_error('Owner table is not set.'); } + return false; } /** @@ -230,37 +190,24 @@ public function getKeyName() { return $this->keyName; } /** - * Returns an associative array which contains the columns that belongs to - * the table that will contain the key. - * @return array An associative array. The indices will represent columns - * names and the values are objects of type 'Column'. - * @since 1.3 - */ - public function getOwnerCols() { - return $this->ownerCols; - } - /** - * Returns an associative array which contains the columns that will be - * referenced. - * @return array An associative array. The indices will represent columns - * names and the values are objects of type 'Column'. - * @since 1.3 + * Returns the condition that will happen if the value of the column in the + * reference table is deleted. + * @return string|null The on delete condition as string or null in + * case it is not set. + * @since 1.0 */ - public function getSourceCols(){ - return $this->sourceCols; + public function getOnDelete() { + return $this->onDeleteCondition; } /** - * Sets the table who owns the key. - * The table that owns the key is simply the table that will take values - * from source table. - * @param MySQLTable $table An object of type 'MySQLTable'. - * @since 1.3.1 + * Returns the condition that will happen if the value of the column in the + * reference table is updated. + * @return string|null The on update condition as string or null in + * case it is not set. + * @since 1.0 */ - public function setOwner($table) { - if($table instanceof MySQLTable){ - $this->ownerTableObj = $table; - $this->ownerCols = []; - } + public function getOnUpdate() { + return $this->onUpdateCondition; } /** * Returns the table who owns the key. @@ -275,17 +222,14 @@ public function getOwner() { return $this->ownerTableObj; } /** - * Sets the source table that will be referenced. - * The source table is simply the table that will contain - * original values. - * @param MySQLTable $table An object of type 'MySQLTable'. - * @since 1.3.1 + * Returns an associative array which contains the columns that belongs to + * the table that will contain the key. + * @return array An associative array. The indices will represent columns + * names and the values are objects of type 'Column'. + * @since 1.3 */ - public function setSource($table) { - if($table instanceof MySQLTable){ - $this->sourceTableObj = $table; - $this->sourceCols = []; - } + public function getOwnerCols() { + return $this->ownerCols; } /** * Returns the source table. @@ -300,14 +244,87 @@ public function getSource() { return $this->sourceTableObj; } /** - * Returns the condition that will happen if the value of the column in the - * reference table is deleted. - * @return string|null The on delete condition as string or null in - * case it is not set. - * @since 1.0 + * Returns an associative array which contains the columns that will be + * referenced. + * @return array An associative array. The indices will represent columns + * names and the values are objects of type 'Column'. + * @since 1.3 */ - public function getOnDelete(){ - return $this->onDeleteCondition; + public function getSourceCols() { + return $this->sourceCols; + } + + /** + * Returns the name of the table that is referenced by the key. + * The referenced table is simply the table that contains original values. + * @return string The name of the table that is referenced by the key. If + * it is not set, the method will return empty string. + * @since 1.0 + */ + public function getSourceName() { + $source = $this->getSource(); + + if ($source !== null) { + return $source->getName(); + } + + return ''; + } + /** + * Removes a column from the key given owner column name. + * @param string $ownerColName The name of the owner column name. + * @return boolean If a column which has the given name was found and removed, + * the method will return true. Other than that, the method will return false. + * @since 1.3.1 + */ + public function removeReference($ownerColName) { + $trimmed = trim($ownerColName); + $colIndex = 0; + + foreach ($this->getOwnerCols() as $k => $v) { + if ($k == $trimmed) { + $sourceIndex = 0; + + foreach ($this->getSourceCols() as $sK => $sV) { + if ($sourceIndex == $colIndex) { + unset($this->sourceCols[$sK]); + unset($this->ownerCols[$k]); + + return true; + } + $sourceIndex++; + } + } + $colIndex++; + } + + return false; + } + /** + * Sets the name of the key. + * @param string $name The name of the key. A valid key name must follow the + * following rules: + * + * @return boolean|string true if the name of the key is set. The method will + * return the constant ForeignKey::INV_KEY_NAME in + * case if the given key name is invalid. + * @since 1.1 + */ + public function setKeyName($name) { + $trim = trim($name); + + if ($this->validateAttr($trim) == true) { + $this->keyName = $trim; + + return true; + } + + return false; } /** * Sets the value of the property $onUpdateCondition. @@ -315,24 +332,16 @@ public function getOnDelete(){ * If the given value is null, the condition will be set to null. * @since 1.0 */ - public function setOnDelete($val){ + public function setOnDelete($val) { $fix = strtolower(trim($val)); - if(in_array($fix, self::CONDITIONS)){ + + if (in_array($fix, self::CONDITIONS)) { $this->onDeleteCondition = $fix; + } else { + if ($val === null) { + $this->onDeleteCondition = null; + } } - else if ($val === null) { - $this->onDeleteCondition = null; - } - } - /** - * Returns the condition that will happen if the value of the column in the - * reference table is updated. - * @return string|null The on update condition as string or null in - * case it is not set. - * @since 1.0 - */ - public function getOnUpdate(){ - return $this->onUpdateCondition; } /** * Sets the value of the property $onUpdateCondition. @@ -340,62 +349,72 @@ public function getOnUpdate(){ * If the given value is null, the condition will be set to null. * @since 1.0 */ - public function setOnUpdate($val){ + public function setOnUpdate($val) { $fix = strtolower(trim($val)); - if(in_array($fix, self::CONDITIONS)){ + + if (in_array($fix, self::CONDITIONS)) { $this->onUpdateCondition = $fix; - } - elseif ($val == null) { + } elseif ($val == null) { $this->onUpdateCondition = null; } } - /** - * Returns the name of the table that is referenced by the key. - * The referenced table is simply the table that contains original values. - * @return string The name of the table that is referenced by the key. If - * it is not set, the method will return empty string. - * @since 1.0 + * Sets the table who owns the key. + * The table that owns the key is simply the table that will take values + * from source table. + * @param MySQLTable $table An object of type 'MySQLTable'. + * @since 1.3.1 */ - public function getSourceName(){ - $source = $this->getSource(); - if($source !== null){ - return $source->getName(); + public function setOwner($table) { + if ($table instanceof MySQLTable) { + $this->ownerTableObj = $table; + $this->ownerCols = []; } - return ''; } /** - * Creates new foreign key. - * @param string $name The name of the key. It must be a string and its not empty. - * Also it must not contain any spaces or any characters other than A-Z, a-z and - * underscore. The default value is 'key_name'. - * @param MySQLTable $ownerTable The table that will contain the key. - * @param MySQLTable $sourceTable The name of the table that contains the + * Sets the source table that will be referenced. + * The source table is simply the table that will contain * original values. - * @param array|string $cols An associative array that contains the names of key - * columns. The indices must be columns in the owner table and the values are - * columns in the source columns. + * @param MySQLTable $table An object of type 'MySQLTable'. + * @since 1.3.1 */ - public function __construct( - $name='key_name', - $ownerTable=null, - $sourceTable=null, - $cols=[]) { - $this->sourceCols = []; - $this->ownerCols = []; - if($sourceTable instanceof MySQLTable){ - $this->setSource($sourceTable); - } - if($ownerTable instanceof MySQLTable){ - $this->setOwner($ownerTable); - } - if($this->setKeyName($name) !== true){ - $this->setKeyName('key_name'); + public function setSource($table) { + if ($table instanceof MySQLTable) { + $this->sourceTableObj = $table; + $this->sourceCols = []; } - if(gettype($cols) == 'array'){ - foreach ($cols as $k => $v){ - $this->addReference($k, $v); + } + /** + * A method that is used to validate the names of the key attributes (such as source column + * name or source table name). + * @param string $trimmed The string to validate. It must be a string and its not empty. + * Also it must not contain any spaces or any characters other than A-Z, a-z and + * underscore. + * @return boolean true if the given parameter is valid. false in + * case if the given parameter is invalid. + */ + private function validateAttr($trimmed) { + $len = strlen($trimmed); + + if ($len != 0) { + if (strpos($trimmed, ' ') === false) { + for ($x = 0 ; $x < $len ; $x++) { + $ch = $trimmed[$x]; + + if ($x == 0 && ($ch >= '0' && $ch <= '9')) { + return false; + } + + if ($ch == '_' || ($ch >= 'a' && $ch <= 'z') || ($ch >= 'A' && $ch <= 'Z') || ($ch >= '0' && $ch <= '9')) { + } else { + return false; + } + } + + return true; } } + + return false; } } diff --git a/src/JoinTable.php b/src/JoinTable.php index 34077bb..5faa4d5 100644 --- a/src/JoinTable.php +++ b/src/JoinTable.php @@ -23,22 +23,14 @@ * SOFTWARE. */ namespace phMysql; -use phMysql\MySQLTable; -use phMysql\MySQLColumn; -use phMysql\MySQLQuery; + /** * Experimental class. DO NOT USE. * * @author Ibrahim * @version 1.0 */ -class JoinTable extends MySQLTable{ - private $leftTable; - private $rightTable; - private $joinType; - private $joinCond; - private $hasCommon; - private $keysMap; +class JoinTable extends MySQLTable { /** * An array that contains the names of the columns which are shared between * joined tables. @@ -46,6 +38,12 @@ class JoinTable extends MySQLTable{ * @since 1.0 */ private $commonCols; + private $hasCommon; + private $joinCond; + private $joinType; + private $keysMap; + private $leftTable; + private $rightTable; /** * Creates new instance of the class. * @param MySQLQuery|MySQLTable $leftTable The left table. It can be an @@ -63,35 +61,38 @@ class JoinTable extends MySQLTable{ * joined table. * @since 1.0 */ - public function __construct($leftTable,$rightTable,$tableName=null,$keysMap=[]) { + public function __construct($leftTable,$rightTable,$tableName = null,$keysMap = []) { parent::__construct(); $this->hasCommon = false; - if(!$this->setName($tableName)){ - $this->setName('Temp'. strtoupper(substr(hash('sha256',rand()), 0, 5))); + + if (!$this->setName($tableName)) { + $this->setName('Temp'.strtoupper(substr(hash('sha256',rand()), 0, 5))); } - if($leftTable instanceof MySQLTable){ + + if ($leftTable instanceof MySQLTable) { $this->leftTable = $leftTable; + } else { + if ($leftTable instanceof MySQLQuery) { + $this->leftTable = $leftTable->getTable(); + } else { + $this->leftTable = new MySQLTable('left_table'); + } } - else if($leftTable instanceof MySQLQuery){ - $this->leftTable = $leftTable->getTable(); - } - else{ - $this->leftTable = new MySQLTable('left_table'); - } - if($rightTable instanceof MySQLTable){ + + if ($rightTable instanceof MySQLTable) { $this->rightTable = $rightTable; - } - else if($leftTable instanceof MySQLQuery){ - $this->rightTable = $rightTable->getTable(); - } - else{ - $this->rightTable = new MySQLTable('right_table'); + } else { + if ($leftTable instanceof MySQLQuery) { + $this->rightTable = $rightTable->getTable(); + } else { + $this->rightTable = new MySQLTable('right_table'); + } } $this->joinType = 'left'; $this->commonCols = []; $this->keysMap = [ - 'left'=>[], - 'right'=>[] + 'left' => [], + 'right' => [] ]; $this->_addAndValidateColmns($keysMap); } @@ -106,16 +107,23 @@ public function __construct($leftTable,$rightTable,$tableName=null,$keysMap=[]) * @since 1.0 */ public function getCol($key) { - if(isset($this->keysMap['left'][$key])){ + if (isset($this->keysMap['left'][$key])) { $tmpCol = $this->getLeftTable()->getCol($this->keysMap['left'][$key]); + return $tmpCol; + } else { + if (isset($this->keysMap['right'][$key])) { + $tmpCol = $this->getRightTable()->getCol($this->keysMap['right'][$key]); + + return $tmpCol; + } } - else if(isset($this->keysMap['right'][$key])){ - $tmpCol = $this->getRightTable()->getCol($this->keysMap['right'][$key]); - return $tmpCol; - } + return $this->getJoinCol($key); } + public function getCommonColsNames() { + return $this->commonCols; + } /** * Returns the column object given the key that it was stored in. * This method is used to skip mapping check which is used by the @@ -129,51 +137,70 @@ public function getJoinCol($key) { return parent::getCol($key); } /** - * Checks if a column has the same name in the left and the right table. - * @param string $colName The name of the column as it appears in the - * database. - * @return boolean If the column is common between the two tables, the - * method will return true. Other than that, the method will return false. + * Returns a string that represents join condition. + * @return string|null A string that represents join condition. If join + * condition is not set, the method will return null. * @since 1.0 */ - public function isCommon($colName) { - $trimmed = trim($colName); - return in_array($trimmed, $this->getCommonColsNames()); - } - public function getCommonColsNames() { - return $this->commonCols; + public function getJoinCondition() { + return $this->joinCond; } /** - * Sets the type of the join that will be performed. - * @param string $type A string that represents join type. Possible values - * are: + * Returns a string that represents the type of the join that will + * be performed. + * @return string Possible return values are: * + * Default return value is 'left'. * @since 1.0 */ - public function setJoinType($type) { - $lType = strtolower(trim($type)); - if($lType == 'left' || $lType == 'natural left' || - $lType == 'right' || $lType == 'natural right'|| - $lType == 'cross' || $lType == 'natural' || $lType == 'join'){ - $this->joinType = $lType; - } + public function getJoinType() { + return $this->joinType; } /** - * Returns a string that represents join condition. - * @return string|null A string that represents join condition. If join - * condition is not set, the method will return null. + * Returns the left table of the join. + * @return MySQLTable An instance of the class 'MySQLTable' that represents + * left table of the join. * @since 1.0 */ - public function getJoinCondition() { - return $this->joinCond; + public function getLeftTable() { + return $this->leftTable; + } + /** + * Returns the right table of the join. + * @return MySQLTable An instance of the class 'MySQLTable' that represents + * right table of the join. + * @since 1.0 + */ + public function getRightTable() { + return $this->rightTable; + } + /** + * Checks if the two joined tables has common columns between them. + * A two tables will have common columns if the two share at least one + * column with the same name in the database. + * @return boolean If two tables share same column name, the method will + * return true. If not, it will return false. + * @since 1.0 + */ + public function hasCommon() { + return $this->hasCommon; + } + /** + * Checks if a column has the same name in the left and the right table. + * @param string $colName The name of the column as it appears in the + * database. + * @return boolean If the column is common between the two tables, the + * method will return true. Other than that, the method will return false. + * @since 1.0 + */ + public function isCommon($colName) { + $trimmed = trim($colName); + + return in_array($trimmed, $this->getCommonColsNames()); } /** * Sets the condition at which the two tables will be joined on. @@ -184,105 +211,100 @@ public function getJoinCondition() { * values like '=' or '!='. * @since 1.0 */ - public function setJoinCondition($cols,$conds=[]) { - if(gettype($cols) == 'array'){ - while (count($conds) < count($cols)){ + public function setJoinCondition($cols,$conds = []) { + if (gettype($cols) == 'array') { + while (count($conds) < count($cols)) { $conds[] = '='; } $joinOps = []; - while (count($joinOps) < count($cols)){ + + while (count($joinOps) < count($cols)) { $joinOps[] = 'and'; } $index = 0; $this->joinCond = null; $leftTable = $this->getLeftTable(); $rightTable = $this->getRightTable(); - foreach ($cols as $leftCol => $rightCol){ - if($leftTable instanceof JoinTable){ + + foreach ($cols as $leftCol => $rightCol) { + if ($leftTable instanceof JoinTable) { $leftColObj = $leftTable->getJoinCol($leftCol); - } - else{ + } else { $leftColObj = $leftTable->getCol($leftCol); } - if($leftColObj instanceof MySQLColumn){ - if($rightTable instanceof JoinTable){ + + if ($leftColObj instanceof MySQLColumn) { + if ($rightTable instanceof JoinTable) { $rightColObj = $rightTable->getJoinCol($rightCol); - } - else{ + } else { $rightColObj = $rightTable->getCol($rightCol); } - if($rightColObj instanceof MySQLColumn){ - if($rightColObj->getType() == $leftColObj->getType()){ + + if ($rightColObj instanceof MySQLColumn) { + if ($rightColObj->getType() == $leftColObj->getType()) { $cond = $conds[$index]; - if($index != 0){ + + if ($index != 0) { $joinOp = $joinOps[$index - 1]; - if($joinOp != 'and' && $joinOp != 'or'){ + + if ($joinOp != 'and' && $joinOp != 'or') { $joinOp = 'and'; } $this->joinCond .= ' '.$joinOp.' '.$leftTable->getName().'.' - . $leftColObj->getName().' '.$cond.' ' - . $rightTable->getName().'.' - . $rightColObj->getName(); - } - else{ + .$leftColObj->getName().' '.$cond.' ' + .$rightTable->getName().'.' + .$rightColObj->getName(); + } else { $this->joinCond = 'on '.$leftTable->getName().'.' - . $leftColObj->getName().' '.$cond.' ' - . $rightTable->getName().'.' - . $rightColObj->getName(); + .$leftColObj->getName().' '.$cond.' ' + .$rightTable->getName().'.' + .$rightColObj->getName(); } } } } $index++; } - } + } } /** - * Returns a string that represents the type of the join that will - * be performed. - * @return string Possible return values are: + * Sets the type of the join that will be performed. + * @param string $type A string that represents join type. Possible values + * are: * - * Default return value is 'left'. - * @since 1.0 - */ - public function getJoinType() { - return $this->joinType; - } - /** - * Returns the right table of the join. - * @return MySQLTable An instance of the class 'MySQLTable' that represents - * right table of the join. - * @since 1.0 - */ - public function getRightTable() { - return $this->rightTable; - } - /** - * Returns the left table of the join. - * @return MySQLTable An instance of the class 'MySQLTable' that represents - * left table of the join. * @since 1.0 */ - public function getLeftTable() { - return $this->leftTable; + public function setJoinType($type) { + $lType = strtolower(trim($type)); + + if ($lType == 'left' || $lType == 'natural left' || + $lType == 'right' || $lType == 'natural right' || + $lType == 'cross' || $lType == 'natural' || $lType == 'join') { + $this->joinType = $lType; + } } /** * @since 1.0 */ - private function _addAndValidateColmns($keysMap=[]) { + private function _addAndValidateColmns($keysMap = []) { //collect common keys btween the two tables. $commonColsKeys = []; $leftColsKeys = $this->getLeftTable()->colsKeys(); $rightColsKeys = $this->getRightTable()->colsKeys(); - foreach ($rightColsKeys as $col){ - foreach ($leftColsKeys as $col2){ - if($col == $col2){ + + foreach ($rightColsKeys as $col) { + foreach ($leftColsKeys as $col2) { + if ($col == $col2) { $commonColsKeys[] = $col2; } } @@ -290,51 +312,48 @@ private function _addAndValidateColmns($keysMap=[]) { //collect common columns names in the two tables. $rightCols = $this->getRightTable()->getColsNames(); $leftCols = $this->getLeftTable()->getColsNames(); - foreach ($rightCols as $col){ - foreach ($leftCols as $col2){ - if($col == $col2){ + + foreach ($rightCols as $col) { + foreach ($leftCols as $col2) { + if ($col == $col2) { $this->commonCols[] = $col2; } } } //build an array that contains all columns in the joined table. $colsArr = []; - foreach ($leftColsKeys as $col){ - if(in_array($col, $commonColsKeys)){ - if($this->getLeftTable() instanceof JoinTable){ + + foreach ($leftColsKeys as $col) { + if (in_array($col, $commonColsKeys)) { + if ($this->getLeftTable() instanceof JoinTable) { $newCol = clone $this->getLeftTable()->getJoinCol($col); $colsArr['left-'.$col] = $newCol; - } - else{ + } else { $colsArr['left-'.$col] = clone $this->getLeftTable()->getCol($col); } - } - else{ - if($this->getLeftTable() instanceof JoinTable){ + } else { + if ($this->getLeftTable() instanceof JoinTable) { $newCol = clone $this->getLeftTable()->getJoinCol($col); $colsArr[$col] = $newCol; - } - else{ + } else { $colsArr[$col] = clone $this->getLeftTable()->getCol($col); } } } - foreach ($rightColsKeys as $col){ - if(in_array($col, $commonColsKeys)){ - if($this->getRightTable() instanceof JoinTable){ + + foreach ($rightColsKeys as $col) { + if (in_array($col, $commonColsKeys)) { + if ($this->getRightTable() instanceof JoinTable) { $newCol = clone $this->getRightTable()->getJoinCol($col); $colsArr['right-'.$col] = $newCol; - } - else{ + } else { $colsArr['right-'.$col] = clone $this->getRightTable()->getCol($col); } - } - else{ - if($this->getRightTable() instanceof JoinTable){ + } else { + if ($this->getRightTable() instanceof JoinTable) { $newCol = clone $this->getRightTable()->getJoinCol($col); $colsArr[$col] = $newCol; - } - else{ + } else { $colsArr[$col] = clone $this->getRightTable()->getCol($col); } } @@ -344,29 +363,32 @@ private function _addAndValidateColmns($keysMap=[]) { $leftCount = count($leftCols); $hasCommon = false; $commonNamesArr = $this->getCommonColsNames(); - foreach ($colsArr as $colkey => $colObj){ + + foreach ($colsArr as $colkey => $colObj) { $isAdded = false; $colName = $colObj->getName(); - if(in_array($colName, $commonNamesArr)){ + + if (in_array($colName, $commonNamesArr)) { $hasCommon = true; $isAdded = false; - if($index < $leftCount){ + + if ($index < $leftCount) { $colObj->setName('left_'.$colName); $isAdded = $this->_addWithAlias($colkey, $colObj, $keysMap, 'left'); - } - else{ + } else { $colObj->setName('right_'.$colName); $isAdded = $this->_addWithAlias($colkey, $colObj, $keysMap, 'right'); } } - if(!$isAdded){ - if($index < $leftCount){ + + if (!$isAdded) { + if ($index < $leftCount) { $isAdded = $this->_addWithAlias($colkey, $colObj, $keysMap, 'left'); - } - else{ + } else { $isAdded = $this->_addWithAlias($colkey, $colObj, $keysMap, 'right'); } - if(!$isAdded){ + + if (!$isAdded) { $this->addColumn($colkey, $colObj); } } @@ -378,28 +400,21 @@ private function _addWithAlias($colkey,$colObj,&$aliasArr,$leftOrRight) { $isAdded = false; $colsNames = isset($aliasArr[$leftOrRight]) && gettype($aliasArr[$leftOrRight]) == 'array' ? $aliasArr[$leftOrRight] : []; - foreach ($colsNames as $originalName => $newName){ + + foreach ($colsNames as $originalName => $newName) { $originalNameC = $leftOrRight.'-'.$originalName; - if($originalNameC == $colkey || $originalName == $colkey){ + + if ($originalNameC == $colkey || $originalName == $colkey) { unset($aliasArr[$leftOrRight][$originalName]); $isAdded = $this->addColumn($newName, $colObj); - if($isAdded){ + + if ($isAdded) { $this->keysMap[$leftOrRight][$newName] = $originalName; } break; } } + return $isAdded; } - /** - * Checks if the two joined tables has common columns between them. - * A two tables will have common columns if the two share at least one - * column with the same name in the database. - * @return boolean If two tables share same column name, the method will - * return true. If not, it will return false. - * @since 1.0 - */ - public function hasCommon() { - return $this->hasCommon; - } } diff --git a/src/MySQLColumn.php b/src/MySQLColumn.php index debf1e3..2c88442 100644 --- a/src/MySQLColumn.php +++ b/src/MySQLColumn.php @@ -23,74 +23,13 @@ * SOFTWARE. */ namespace phMysql; + /** * A class that represents a column in MySQL table. * @author Ibrahim * @version 1.6.6 */ -class MySQLColumn{ - /** - * - * @var type - * @since 1.6.6 - */ - private $alias; - /** - * A boolean which can be set to true in order to update column timestamp. - * @var boolean - */ - private $autoUpdate; - /** - * A comment to add to the column. - * @var string|null - * @since 1.6.3 - */ - private $comment; - /** - * Version number of MySQL server. - * @var string - */ - private $mySqlVersion; - /** - * The table that this column belongs to. - * @var MySQLTable - * @since 1.5 - */ - private $ownerTable; - /** - * The index of the column in owner table. - * @var int - * @since 1.6 - */ - private $columnIndex; - /** - * A constant that indicates the datatype of the - * column does not support size. - * @var string - * @since 1.4 - */ - const SIZE_NOT_SUPPORTED = 'TYPE_DOES_NOT_SUPPORT_SIZE'; - /** - * A constant that is returned by some methods to tell that the - * name of a column is invalid. - * @var string - * @since 1.2 - */ - const INV_COL_NAME = 'inv_col_nm'; - /** - * A constant that is returned by some methods to tell that the - * datatype of a column is invalid. - * @var string - * @since 1.2 - */ - const INV_COL_DATATYPE = 'inv_col_datatype'; - /** - * A constant that is returned by some methods to tell that the - * size datatype of a column is invalid (for 'varchar' and 'int'). - * @var string - * @since 1.2 - */ - const INV_DATASIZE = 'inv_col_datatype'; +class MySQLColumn { /** * An array of supported data types. *

The supported types are:

@@ -118,38 +57,69 @@ class MySQLColumn{ 'int','varchar','timestamp','tinyblob','blob','mediumblob','longblob', 'datetime','text','mediumtext','decimal','double','float' ]; - /** - * A boolean value. Set to true if column is unique. - * @var boolean - * @since 1.0 + * A constant that is returned by some methods to tell that the + * datatype of a column is invalid. + * @var string + * @since 1.2 */ - private $isUnique; + const INV_COL_DATATYPE = 'inv_col_datatype'; /** - * A boolean value. Set to true if column is primary and auto increment. - * @var boolean - * @since 1.0 + * A constant that is returned by some methods to tell that the + * name of a column is invalid. + * @var string + * @since 1.2 */ - private $isAutoInc; + const INV_COL_NAME = 'inv_col_nm'; /** - * The name of the column. + * A constant that is returned by some methods to tell that the + * size datatype of a column is invalid (for 'varchar' and 'int'). + * @var string + * @since 1.2 + */ + const INV_DATASIZE = 'inv_col_datatype'; + /** + * A constant that indicates the datatype of the + * column does not support size. * @var string - * @since 1.0 + * @since 1.4 */ - private $name; + const SIZE_NOT_SUPPORTED = 'TYPE_DOES_NOT_SUPPORT_SIZE'; /** - * The size of the data in the column (for 'int' and 'varchar'). It must be - * a positive value. - * @var int + * + * @var type + * @since 1.6.6 + */ + private $alias; + /** + * A boolean which can be set to true in order to update column timestamp. + * @var boolean + */ + private $autoUpdate; + /** + * The index of the column in owner table. + * @var int + * @since 1.6 + */ + private $columnIndex; + /** + * A comment to add to the column. + * @var string|null + * @since 1.6.3 + */ + private $comment; + /** + * Default value for the column. + * @var mixed * @since 1.0 */ - private $size; + private $default; /** - * The type of the data that the column will have. - * @var string + * A boolean value. Set to true if column is primary and auto increment. + * @var boolean * @since 1.0 */ - private $type; + private $isAutoInc; /** * A boolean value. Set to true if column allow null values. Default * is false. @@ -163,18 +133,49 @@ class MySQLColumn{ * @since 1.0 */ private $isPrimary; + /** - * Default value for the column. - * @var mixed - * @since 1.0 + * A boolean value. Set to true if column is unique. + * @var boolean + * @since 1.0 */ - private $default; + private $isUnique; + /** + * Version number of MySQL server. + * @var string + */ + private $mySqlVersion; + /** + * The name of the column. + * @var string + * @since 1.0 + */ + private $name; + /** + * The table that this column belongs to. + * @var MySQLTable + * @since 1.5 + */ + private $ownerTable; /** * The number of numbers that will appear after the decimal point. * @var int * @since 1.6.2 */ private $scale; + /** + * The size of the data in the column (for 'int' and 'varchar'). It must be + * a positive value. + * @var int + * @since 1.0 + */ + private $size; + /** + * The type of the data that the column will have. + * @var string + * @since 1.0 + */ + private $type; /** * Creates new instance of the class. * This method is used to initialize basic attributes of the column. @@ -194,76 +195,95 @@ class MySQLColumn{ * or equal to 3, scale is set to 2 by default. * @since 1.0 */ - public function __construct($colName='col',$datatype='varchar',$size=1) { + public function __construct($colName = 'col',$datatype = 'varchar',$size = 1) { $this->mySqlVersion = '5.5'; $this->autoUpdate = false; $this->isPrimary = false; - if($this->setName($colName) !== true){ + + if ($this->setName($colName) !== true) { $this->setName('col'); } - if(!$this->setType($datatype)){ + + if (!$this->setType($datatype)) { $this->setType('varchar'); } $realDatatype = $this->getType(); - if($realDatatype == 'varchar' || $realDatatype == 'int' || $realDatatype == 'text'){ - if(!$this->setSize($size)){ + + if ($realDatatype == 'varchar' || $realDatatype == 'int' || $realDatatype == 'text') { + if (!$this->setSize($size)) { $this->setSize(1); } } - if($realDatatype == 'decimal' || $realDatatype == 'float' || $realDatatype == 'double'){ - if(!$this->setSize($size)){ + + if ($realDatatype == 'decimal' || $realDatatype == 'float' || $realDatatype == 'double') { + if (!$this->setSize($size)) { $this->setSize(10); $this->setScale(2); - } - else{ + } else { $size = $this->getSize(); - if($size == 0 || $size == 1){ + + if ($size == 0 || $size == 1) { $this->setScale(0); - } - else if($size == 2){ - $this->setScale(1); - } - else{ - $this->setScale(2); + } else { + if ($size == 2) { + $this->setScale(1); + } else { + $this->setScale(2); + } } } } - + $this->setIsNull(false); $this->setIsUnique(false); } /** - * - * @return type - * @since 1.6.6 + * Constructs a string that can be used to create the column in a table. + * @return string A string that can be used to create the column in a table. */ - public function getAlias($tablePrefix=false){ - if($tablePrefix === true && $this->getOwner() !== null){ - return $this->getOwner()->getName().'.'.$this->alias; + public function __toString() { + $retVal = $this->getName().' '; + $type = $this->getType(); + + if ($type == 'int' || $type == 'varchar' || $type == 'text') { + $retVal .= $type.'('.$this->getSize().') '; + } else { + if ($type == 'decimal' || $type == 'float' || $type == 'double') { + if ($this->getSize() != 0) { + $retVal .= $type.'('.$this->getSize().','.$this->getScale().') '; + } else { + $retVal .= $type.' '; + } + } else { + $retVal .= $type.' '; + } } - return $this->alias; - } - /** - * Sets an optional alias name for the column. - * @param string|null $name A string that represents the alias. If null - * is given, it means the alias will be unset. - * @return boolean If the property value is updated, the method will return - * true. Other than that, the method will return false. - * @since 1.6.6 - */ - public function setAlias($name) { - if($name === null){ - $this->alias = null; - return true; + + if (!$this->isNull()) { + $retVal .= 'not null '; + } else { + $retVal .= 'null '; } - $trimmed = trim($name); - if(strlen($trimmed) != 0){ - if($this->_validateName($trimmed)){ - $this->alias = $trimmed; - return true; - } + + if ($this->isUnique()) { + $retVal .= 'unique '; } - return false; + $default = $this->default; + + if ($default !== null) { + $retVal .= 'default '.$default.' '; + } + + if ($type == 'varchar' || $type == 'text' || $type == 'mediumtext') { + $retVal .= 'collate '.$this->getCollation().' '; + } + $comment = $this->getComment(); + + if ($comment !== null) { + $retVal .= 'comment \''.$comment.'\''; + } + + return trim($retVal); } /** * Clean and validates a value against the datatype of the column. @@ -285,70 +305,48 @@ public function setAlias($name) { * * @since 1.6.4 */ - public function cleanValue($val,$dateEndOfDay=false) { + public function cleanValue($val,$dateEndOfDay = false) { $valType = gettype($val); - if($valType == 'array'){ + + if ($valType == 'array') { $retVal = []; - foreach ($val as $arrVal){ + + foreach ($val as $arrVal) { $retVal[] = $this->_cleanValueHelper($arrVal, $dateEndOfDay); } + return $retVal; - } - else{ + } else { return $this->_cleanValueHelper($val, $dateEndOfDay); } } - private function _cleanValueHelper($val,$dateEndOfDay=false){ - $colDatatype = $this->getType(); - if($val === null){ - return null; - } - else if($colDatatype == 'int'){ - return intval($val); - } - else if($colDatatype == 'decimal' || $colDatatype == 'float' || $colDatatype == 'double'){ - return '\''.floatval($val).'\''; - } - else if($colDatatype == 'varchar' || $colDatatype == 'text' || $colDatatype == 'mediumtext'){ - return '\''.str_replace("'", "\'", $val).'\''; - } - else if($colDatatype == 'datetime' || $colDatatype == 'timestamp'){ - $trimmed = strtolower(trim($val)); - if($trimmed == 'current_timestamp'){ - return 'current_timestamp'; - } - else if($trimmed == 'now()'){ - return 'now()'; - } - else if($this->_validateDateAndTime($trimmed)){ - return '\''.$trimmed.'\''; - } - else if($this->_validateDate($trimmed)){ - if($dateEndOfDay === true){ - return '\''.$trimmed.' 23:59:59\''; - } - else{ - return '\''.$trimmed.' 00:00:00\''; - } - } - else{ - return ''; - } - } - else{ - return ''; + /** + * + * @return type + * @since 1.6.6 + */ + public function getAlias($tablePrefix = false) { + if ($tablePrefix === true && $this->getOwner() !== null) { + return $this->getOwner()->getName().'.'.$this->alias; } + + return $this->alias; } /** - * Sets a comment which will appear with the column. - * @param string|null $comment Comment text. It must be non-empty string - * in order to set. If null is passed, the comment will be removed. - * @since 1.6.3 + * Returns the value of column collation. + * @return string If MySQL version is '5.5' or lower, the method will + * return 'utf8mb4_unicode_ci'. Other than that, the method will return + * 'utf8mb4_unicode_520_ci'. + * @since 1.0 */ - public function setComment($comment) { - if($comment == null || strlen($comment) != 0){ - $this->comment = $comment; + public function getCollation() { + $split = explode('.', $this->getMySQLVersion()); + + if (isset($split[0]) && intval($split[0]) <= 5 && isset($split[1]) && intval($split[1]) <= 5) { + return 'utf8mb4_unicode_ci'; } + + return 'utf8mb4_unicode_520_ci'; } /** * Returns a string that represents a comment which was added with the column. @@ -359,116 +357,56 @@ public function setComment($comment) { public function getComment() { return $this->comment; } + /** - * Sets the value of Scale. - * Scale is simply the number of digits that will appear to the right of - * decimal point. Only applicable if the datatype of the column is decimal, - * float and double. - * @param int $val Number of numbers after the decimal point. It must be a - * positive number. - * @return boolean If scale value is set, the method will return true. - * false otherwise. The method will not set the scale in the following cases: - * - * @since 1.6.2 - */ - public function setScale($val) { - $type = $this->getType(); - if($type == 'decimal' || $type == 'float' || $type == 'double'){ - $size = $this->getSize(); - if($size != 0 && $val >= 0 && ($size - $val > 0)){ - $this->scale = $val; - return true; - } - } - return false; - } - /** - * Returns the value of scale. - * Scale is simply the number of digits that will appear to the right of - * decimal point. Only applicable if the datatype of the column is decimal, - * float and double. - * @return int The number of numbers after the decimal point. Note that - * if the size of datatype of the column is 1, scale is set to - * 0 by default. If if the size of datatype of the column is 2, scale is - * set to 1. If if the size of datatype of the column is greater than - * or equal to 3, scale is set to 2 by default. - * @since 1.6.2 - */ - public function getScale() { - return $this->scale; - } - /** - * Checks if a date-time string is valid or not. - * @param string $date A date string in the format 'YYYY-MM-DD HH:MM:SS'. - * @return boolean If the string represents correct date and time, the - * method will return true. False if it is not valid. - */ - private function _validateDateAndTime($date) { - $trimmed = trim($date); - if(strlen($trimmed) == 19){ - $dateAndTime = explode(' ', $trimmed); - if(count($dateAndTime) == 2){ - return $this->_validateDate($dateAndTime[0]) && $this->_validateTime($dateAndTime[1]); - } - } - return false; - } - /** - * - * @param type $time - */ - private function _validateTime($time) { - if(strlen($time) == 8){ - $split = explode(':', $time); - if(count($split) == 3){ - $hours = intval($split[0]); - $minutes = intval($split[1]); - $sec = intval($split[2]); - return $hours >= 0 && $hours <= 23 && $minutes >= 0 && $minutes < 60 && $sec >= 0 && $sec < 60; - } - } - return false; - } - /** - * - * @param type $date + * Returns the default value of the column. + * @return mixed The default value of the column. + * @since 1.0 */ - private function _validateDate($date) { - if(strlen($date) == 10){ - $split = explode('-', $date); - if(count($split) == 3){ - $year = intval($split[0]); - $month = intval($split[1]); - $day = intval($split[2]); - return $year > 1969 && $month > 0 && $month < 13 && $day > 0 && $day < 32; + public function getDefault() { + $defaultVal = $this->default; + + if ($defaultVal !== null) { + $dt = $this->getType(); + + if ($dt == 'varchar' || $dt == 'text' || $dt == 'mediumtext' || + //$dt == 'timestamp' || $dt == 'datetime' || + $dt == 'tinyblob' || $dt == 'blob' || $dt == 'mediumblob' || + $dt == 'longblob' || $dt == 'decimal' || $dt == 'float' || $dt == 'double' + ) { + $retVal = substr($defaultVal, 1, strlen($defaultVal) - 2); + + if ($dt == 'decimal' || $dt == 'float' || $dt == 'double') { + return floatval($retVal); + } + + return $retVal; + } else { + if (($this->default == 'now()' || $this->default == 'current_timestamp') && + ($dt == 'datetime' || $dt == 'timestamp')) { + return date('Y-m-d H:i:s'); + } else { + if ($dt == 'timestamp' || $dt == 'datetime') { + return substr($defaultVal, 1, strlen($defaultVal) - 2); + } else { + if ($dt == 'int') { + return intval($defaultVal); + } + } + } } } - return false; + + return $this->default; } /** - * Sets version number of MySQL server. - * Version number of MySQL is used to set the correct collation for the column - * in case of varchar or text data types. If MySQL version is '5.5' or lower, - * collation will be set to 'utf8mb4_unicode_ci'. Other than that, the - * collation will be set to 'utf8mb4_unicode_520_ci'. - * @param string $vNum MySQL version number (such as '5.5'). - * @since 1.6.1 + * Returns the index of the column in its parent table. + * @return int The index of the column in its parent table starting from 0. + * If the column has no parent table, the method will return -1. + * @since 1.6 */ - public function setMySQLVersion($vNum) { - if(strlen($vNum) > 0){ - $split = explode('.', $vNum); - if(count($split) >= 2){ - $major = intval($split[0]); - $minor = intval($split[1]); - if($major >= 0 && $minor >= 0){ - $this->mySqlVersion = $vNum; - } - } - } + public function getIndex() { + return $this->columnIndex; } /** * Returns version number of MySQL server. @@ -480,33 +418,20 @@ public function getMySQLVersion() { return $this->mySqlVersion; } /** - * Sets or unset the owner table of the column. - * Note that the developer should not call this method manually. It is - * used only if the column is added or removed from MySQLTable object. - * @param MySQLTable|null $table The owner of the column. If null is given, - * The owner will be unset. - * @since 1.5 + * Returns the name of the column. + * @param boolean $tablePrefix If this parameter is set to true and the column + * has an owner table, the name of the column will be prefixed with the owner + * table name. Default value is false. + * @return string The name of the column. If the name is not set, the method + * will return the value 'col'. + * @since 1.0 */ - public function setOwner($table) { - if($table instanceof MySQLTable){ - $this->ownerTable = $table; - $colsCount = count($table->columns()); - $this->columnIndex = $colsCount == 0 ? 0 : $colsCount; - $this->setMySQLVersion($table->getMySQLVersion()); - } - else if($table === null){ - $this->ownerTable = null; - $this->columnIndex = -1; + public function getName($tablePrefix = false) { + if ($tablePrefix === true && $this->getOwner() !== null) { + return $this->getOwner()->getName().'.'.$this->name; } - } - /** - * Returns the index of the column in its parent table. - * @return int The index of the column in its parent table starting from 0. - * If the column has no parent table, the method will return -1. - * @since 1.6 - */ - public function getIndex() { - return $this->columnIndex; + + return $this->name; } /** * Returns the table which owns this column. @@ -518,18 +443,48 @@ public function getOwner() { return $this->ownerTable; } /** - * Sets the value of the property 'autoUpdate'. - * It is used in case the user want to update the date of a column - * that has the type 'datetime' or 'timestamp' automatically if a record is updated. - * This method has no effect for other datatypes. - * @param boolean $bool If true is passed, then the value of the column will - * be updated in case an update query is constructed. + * Returns the value of scale. + * Scale is simply the number of digits that will appear to the right of + * decimal point. Only applicable if the datatype of the column is decimal, + * float and double. + * @return int The number of numbers after the decimal point. Note that + * if the size of datatype of the column is 1, scale is set to + * 0 by default. If if the size of datatype of the column is 2, scale is + * set to 1. If if the size of datatype of the column is greater than + * or equal to 3, scale is set to 2 by default. + * @since 1.6.2 + */ + public function getScale() { + return $this->scale; + } + /** + * Returns the size of the column. + * @return int The size of the column. If column data type is int, decimal, double + * or float, the value will represents the overall number of digits in the + * number (Precision) (e.g: size of 54.323 is 5). If the datatype is varchar, then the + * number will represents number of characters. Default value is 1 for + * all types including datetime and timestamp. + * @since 1.0 + */ + public function getSize() { + return $this->size; + } + /** + * Returns the type of column data (such as 'varchar'). + * @return string The type of column data. Default return value is 'varchar' + * if the column data type is not set. + * @since 1.0 + */ + public function getType() { + return $this->type; + } + /** + * Checks if the column is auto increment or not. + * @return boolean true if the column is auto increment. * @since 1.1 */ - public function setAutoUpdate($bool){ - if($this->getType() == 'datetime' || $this->getType() == 'timestamp'){ - $this->autoUpdate = $bool === true; - } + public function isAutoInc() { + return $this->isAutoInc; } /** * Returns the value of the property 'autoUpdate'. @@ -542,81 +497,130 @@ public function isAutoUpdate() { return $this->autoUpdate; } /** - * Sets the value of the property $isUnique. - * @param boolean $bool True if the column value is unique. false - * if not. + * Checks if the column allows null values. + * @return boolean true if the column allows null values. * @since 1.0 */ - public function setIsUnique($bool){ - $this->isUnique = $bool === true; + public function isNull() { + return $this->isNull; + } + /** + * Checks if the column is a primary key or not. + * @return boolean true if the column is primary. + * @since 1.0 + */ + public function isPrimary() { + return $this->isPrimary; } /** * Returns the value of the property $isUnique. * @return boolean true if the column value is unique. * @since 1.0 */ - public function isUnique(){ + public function isUnique() { return $this->isUnique; } /** - * Sets the name of the column. - * The name of the column must be a string and its not empty. - * Also it must not contain any spaces or any characters other than A-Z, a-z and - * underscore. - * @param string $name The name of the table as it appears in the database. - * @return boolean The method will return true if the column name updated. - * If the given value is null or invalid string, the method will return - * false. - * @since 1.0 + * Sets an optional alias name for the column. + * @param string|null $name A string that represents the alias. If null + * is given, it means the alias will be unset. + * @return boolean If the property value is updated, the method will return + * true. Other than that, the method will return false. + * @since 1.6.6 */ - public function setName($name){ + public function setAlias($name) { + if ($name === null) { + $this->alias = null; + + return true; + } $trimmed = trim($name); - if(strlen($trimmed) != 0){ - if($this->_validateName($trimmed)){ - $this->name = $trimmed; + + if (strlen($trimmed) != 0) { + if ($this->_validateName($trimmed)) { + $this->alias = $trimmed; + return true; } } + return false; } /** - * - * @param type $name - * @return boolean - * @since 1.6.6 - */ - private function _validateName($name) { - if(strpos($name, ' ') === false){ - for ($x = 0 ; $x < strlen($name) ; $x++){ - $ch = $name[$x]; - if($x == 0 && ($ch >= '0' && $ch <= '9')){ - return false; - } - if($ch == '_' || ($ch >= 'a' && $ch <= 'z') || ($ch >= 'A' && $ch <= 'Z') || ($ch >= '0' && $ch <= '9')){ + * Sets the value of the property 'autoUpdate'. + * It is used in case the user want to update the date of a column + * that has the type 'datetime' or 'timestamp' automatically if a record is updated. + * This method has no effect for other datatypes. + * @param boolean $bool If true is passed, then the value of the column will + * be updated in case an update query is constructed. + * @since 1.1 + */ + public function setAutoUpdate($bool) { + if ($this->getType() == 'datetime' || $this->getType() == 'timestamp') { + $this->autoUpdate = $bool === true; + } + } + /** + * Sets a comment which will appear with the column. + * @param string|null $comment Comment text. It must be non-empty string + * in order to set. If null is passed, the comment will be removed. + * @since 1.6.3 + */ + public function setComment($comment) { + if ($comment == null || strlen($comment) != 0) { + $this->comment = $comment; + } + } + /** + * Sets the default value for the column to use in case of insert. + * For integer data type, the passed value must be an integer. For string types such as + * 'varchar' or 'text', the passed value must be a string. If the datatype + * is 'timestamp', the default will be set to current time and date + * if non-null value is passed (the value which is returned by the + * function date('Y-m-d H:i:s). If the passed + * value is a date string in the format 'YYYY-MM-DD HH:MM:SS', then it + * will be set to the given value. If the passed + * value is a date string in the format 'YYYY-MM-DD', then the default + * will be set to 'YYYY-MM-DD 00:00:00'. same applies to 'datetime' datatype. If + * null is passed, it implies that no default value will be used. + * @param mixed $default The default value which will be set. + * @since 1.0 + */ + public function setDefault($default = null) { + $this->default = $this->cleanValue($default); + $type = $this->getType(); - } - else{ - return false; + if ($type == 'datetime' || $type == 'timestamp') { + if ($this->default == 'now()' || $default == 'current_timestamp') { + //$this->default = '\''.date('Y-m-d H:i:s').'\''; + } else { + if (strlen($this->default) == 0 && $this->default !== null) { + $this->default = null; } } - return true; } - return false; } /** - * Returns the name of the column. - * @param boolean $tablePrefix If this parameter is set to true and the column - * has an owner table, the name of the column will be prefixed with the owner - * table name. Default value is false. - * @return string The name of the column. If the name is not set, the method - * will return the value 'col'. + * Sets the value of the property $isAutoInc. + * This attribute can be set only if the column is primary key and the + * datatype of the column is set to 'int'. + * @param boolean $bool true or false. + * @return boolean true if the property value changed. false + * otherwise. * @since 1.0 */ - public function getName($tablePrefix=false){ - if($tablePrefix === true && $this->getOwner() !== null){ - return $this->getOwner()->getName().'.'.$this->name; + public function setIsAutoInc($bool) { + if ($this->isPrimary()) { + if (gettype($bool) == 'boolean') { + if ($this->getType() == 'int') { + $this->isAutoInc = $bool; + + return true; + } + } } - return $this->name; + + return false; } /** * Updates the value of the property $isNull. @@ -630,23 +634,17 @@ public function getName($tablePrefix=false){ * the column represents a primary key, the method will always return false. * @since 1.0 */ - public function setIsNull($bool){ - if(gettype($bool) == 'boolean'){ - if(!$this->isPrimary()){ + public function setIsNull($bool) { + if (gettype($bool) == 'boolean') { + if (!$this->isPrimary()) { $this->isNull = $bool; + return true; } } + return false; } - /** - * Checks if the column allows null values. - * @return boolean true if the column allows null values. - * @since 1.0 - */ - public function isNull(){ - return $this->isNull; - } /** * Updates the value of the property $isPrimary. * Note that once the column become primary, it becomes unique by default. @@ -654,126 +652,121 @@ public function isNull(){ * if not. * @since 1.0 */ - public function setIsPrimary($bool){ + public function setIsPrimary($bool) { $this->isPrimary = $bool === true; - if($this->isPrimary() === true){ + + if ($this->isPrimary() === true) { $this->setIsNull(false); $this->setIsUnique(true); } } /** - * Checks if the column is a primary key or not. - * @return boolean true if the column is primary. + * Sets the value of the property $isUnique. + * @param boolean $bool True if the column value is unique. false + * if not. * @since 1.0 */ - public function isPrimary(){ - return $this->isPrimary; + public function setIsUnique($bool) { + $this->isUnique = $bool === true; } /** - * Sets the type of column data. - * The datatype must be a value from the array Column::DATATYPES. It - * can be in lower case or upper case. - * @param string $type The type of column data. - * @param int $size Size of column data (for 'int', 'varchar', 'float', 'double' and - * 'decimal'). If the passed size is invalid, 1 will be used as a default value. - * @param mixed $default Default value for the column to set in case no value is - * given in case of insert. - * @return boolean The method will return true if the data type is set. False otherwise. - * @since 1.0 + * Sets version number of MySQL server. + * Version number of MySQL is used to set the correct collation for the column + * in case of varchar or text data types. If MySQL version is '5.5' or lower, + * collation will be set to 'utf8mb4_unicode_ci'. Other than that, the + * collation will be set to 'utf8mb4_unicode_520_ci'. + * @param string $vNum MySQL version number (such as '5.5'). + * @since 1.6.1 */ - public function setType($type,$size=1,$default=null){ - $s_type = strtolower(trim($type)); - if(in_array($s_type, self::DATATYPES)){ - if($s_type != 'int'){ - $this->setIsAutoInc(false); - } - $this->type = $s_type; - if($s_type == 'varchar' || $s_type == 'int' || - $s_type == 'double' || $s_type == 'float' || $s_type == 'decimal'){ - if(!$this->setSize($size)){ - $this->setSize(1); + public function setMySQLVersion($vNum) { + if (strlen($vNum) > 0) { + $split = explode('.', $vNum); + + if (count($split) >= 2) { + $major = intval($split[0]); + $minor = intval($split[1]); + + if ($major >= 0 && $minor >= 0) { + $this->mySqlVersion = $vNum; } } - else{ - $this->setSize(1); - } - $this->default = null; - if($default !== null){ - $this->setDefault($default); - } - return true; } - return false; } /** - * Returns the type of column data (such as 'varchar'). - * @return string The type of column data. Default return value is 'varchar' - * if the column data type is not set. + * Sets the name of the column. + * The name of the column must be a string and its not empty. + * Also it must not contain any spaces or any characters other than A-Z, a-z and + * underscore. + * @param string $name The name of the table as it appears in the database. + * @return boolean The method will return true if the column name updated. + * If the given value is null or invalid string, the method will return + * false. * @since 1.0 */ - public function getType(){ - return $this->type; + public function setName($name) { + $trimmed = trim($name); + + if (strlen($trimmed) != 0) { + if ($this->_validateName($trimmed)) { + $this->name = $trimmed; + + return true; + } + } + + return false; } /** - * Sets the default value for the column to use in case of insert. - * For integer data type, the passed value must be an integer. For string types such as - * 'varchar' or 'text', the passed value must be a string. If the datatype - * is 'timestamp', the default will be set to current time and date - * if non-null value is passed (the value which is returned by the - * function date('Y-m-d H:i:s). If the passed - * value is a date string in the format 'YYYY-MM-DD HH:MM:SS', then it - * will be set to the given value. If the passed - * value is a date string in the format 'YYYY-MM-DD', then the default - * will be set to 'YYYY-MM-DD 00:00:00'. same applies to 'datetime' datatype. If - * null is passed, it implies that no default value will be used. - * @param mixed $default The default value which will be set. - * @since 1.0 + * Sets or unset the owner table of the column. + * Note that the developer should not call this method manually. It is + * used only if the column is added or removed from MySQLTable object. + * @param MySQLTable|null $table The owner of the column. If null is given, + * The owner will be unset. + * @since 1.5 */ - public function setDefault($default=null){ - $this->default = $this->cleanValue($default); - $type = $this->getType(); - if($type == 'datetime' || $type == 'timestamp'){ - if($this->default == 'now()' || $default == 'current_timestamp'){ - //$this->default = '\''.date('Y-m-d H:i:s').'\''; - } - else if(strlen($this->default) == 0 && $this->default !== null){ - $this->default = null; + public function setOwner($table) { + if ($table instanceof MySQLTable) { + $this->ownerTable = $table; + $colsCount = count($table->columns()); + $this->columnIndex = $colsCount == 0 ? 0 : $colsCount; + $this->setMySQLVersion($table->getMySQLVersion()); + } else { + if ($table === null) { + $this->ownerTable = null; + $this->columnIndex = -1; } } } - /** - * Returns the default value of the column. - * @return mixed The default value of the column. - * @since 1.0 + * Sets the value of Scale. + * Scale is simply the number of digits that will appear to the right of + * decimal point. Only applicable if the datatype of the column is decimal, + * float and double. + * @param int $val Number of numbers after the decimal point. It must be a + * positive number. + * @return boolean If scale value is set, the method will return true. + * false otherwise. The method will not set the scale in the following cases: + * + * @since 1.6.2 */ - public function getDefault(){ - $defaultVal = $this->default; - if($defaultVal !== null){ - $dt = $this->getType(); - if($dt == 'varchar' || $dt == 'text' || $dt == 'mediumtext' || - //$dt == 'timestamp' || $dt == 'datetime' || - $dt == 'tinyblob' || $dt == 'blob' || $dt == 'mediumblob' || - $dt == 'longblob' || $dt == 'decimal' || $dt == 'float' || $dt == 'double' - ){ - $retVal = substr($defaultVal, 1, strlen($defaultVal) - 2); - if($dt == 'decimal' || $dt == 'float' || $dt == 'double'){ - return floatval($retVal); - } - return $retVal; - } - else if(($this->default == 'now()' || $this->default == 'current_timestamp') && - ($dt == 'datetime' || $dt == 'timestamp')){ - return date('Y-m-d H:i:s'); - } - else if($dt == 'timestamp' || $dt == 'datetime'){ - return substr($defaultVal, 1, strlen($defaultVal) - 2); - } - else if($dt == 'int'){ - return intval($defaultVal); + public function setScale($val) { + $type = $this->getType(); + + if ($type == 'decimal' || $type == 'float' || $type == 'double') { + $size = $this->getSize(); + + if ($size != 0 && $val >= 0 && ($size - $val > 0)) { + $this->scale = $val; + + return true; } } - return $this->default; + + return false; } /** * Sets the size of data (for 'int' and 'varchar' only). @@ -792,133 +785,215 @@ public function getDefault(){ * support size. * @since 1.0 */ - public function setSize($size){ + public function setSize($size) { $type = $this->getType(); - if($type == 'varchar' || $type == 'text'){ - if($size > 0){ + + if ($type == 'varchar' || $type == 'text') { + if ($size > 0) { $this->size = $size; - if($type == 'varchar' && $size > 21845){ + + if ($type == 'varchar' && $size > 21845) { $this->setType('mediumtext'); } + return true; } - } - else if($type == 'int'){ - if($size > 0 && $size < 12){ - $this->size = $size; - return true; - } - else if($size > 11){ - $this->size = 11; - return true; - } - } - else if($type == 'decimal' || $type == 'float' || $type == 'double'){ - if($size >= 0){ - $this->size = $size; - return true; + } else { + if ($type == 'int') { + if ($size > 0 && $size < 12) { + $this->size = $size; + + return true; + } else { + if ($size > 11) { + $this->size = 11; + + return true; + } + } + } else { + if ($type == 'decimal' || $type == 'float' || $type == 'double') { + if ($size >= 0) { + $this->size = $size; + + return true; + } + } else { + return false; + } } } - else{ - return false; - } + return false; } /** - * Sets the value of the property $isAutoInc. - * This attribute can be set only if the column is primary key and the - * datatype of the column is set to 'int'. - * @param boolean $bool true or false. - * @return boolean true if the property value changed. false - * otherwise. + * Sets the type of column data. + * The datatype must be a value from the array Column::DATATYPES. It + * can be in lower case or upper case. + * @param string $type The type of column data. + * @param int $size Size of column data (for 'int', 'varchar', 'float', 'double' and + * 'decimal'). If the passed size is invalid, 1 will be used as a default value. + * @param mixed $default Default value for the column to set in case no value is + * given in case of insert. + * @return boolean The method will return true if the data type is set. False otherwise. * @since 1.0 */ - public function setIsAutoInc($bool){ - if($this->isPrimary()){ - if(gettype($bool) == 'boolean'){ - if($this->getType() == 'int'){ - $this->isAutoInc = $bool; - return true; + public function setType($type,$size = 1,$default = null) { + $s_type = strtolower(trim($type)); + + if (in_array($s_type, self::DATATYPES)) { + if ($s_type != 'int') { + $this->setIsAutoInc(false); + } + $this->type = $s_type; + + if ($s_type == 'varchar' || $s_type == 'int' || + $s_type == 'double' || $s_type == 'float' || $s_type == 'decimal') { + if (!$this->setSize($size)) { + $this->setSize(1); } + } else { + $this->setSize(1); + } + $this->default = null; + + if ($default !== null) { + $this->setDefault($default); } - } + + return true; + } + return false; } + private function _cleanValueHelper($val,$dateEndOfDay = false) { + $colDatatype = $this->getType(); + + if ($val === null) { + return null; + } else { + if ($colDatatype == 'int') { + return intval($val); + } else { + if ($colDatatype == 'decimal' || $colDatatype == 'float' || $colDatatype == 'double') { + return '\''.floatval($val).'\''; + } else { + if ($colDatatype == 'varchar' || $colDatatype == 'text' || $colDatatype == 'mediumtext') { + return '\''.str_replace("'", "\'", $val).'\''; + } else { + if ($colDatatype == 'datetime' || $colDatatype == 'timestamp') { + $trimmed = strtolower(trim($val)); + + if ($trimmed == 'current_timestamp') { + return 'current_timestamp'; + } else { + if ($trimmed == 'now()') { + return 'now()'; + } else { + if ($this->_validateDateAndTime($trimmed)) { + return '\''.$trimmed.'\''; + } else { + if ($this->_validateDate($trimmed)) { + if ($dateEndOfDay === true) { + return '\''.$trimmed.' 23:59:59\''; + } else { + return '\''.$trimmed.' 00:00:00\''; + } + } else { + return ''; + } + } + } + } + } else { + return ''; + } + } + } + } + } + } /** - * Checks if the column is auto increment or not. - * @return boolean true if the column is auto increment. - * @since 1.1 + * + * @param type $date */ - public function isAutoInc(){ - return $this->isAutoInc; + private function _validateDate($date) { + if (strlen($date) == 10) { + $split = explode('-', $date); + + if (count($split) == 3) { + $year = intval($split[0]); + $month = intval($split[1]); + $day = intval($split[2]); + + return $year > 1969 && $month > 0 && $month < 13 && $day > 0 && $day < 32; + } + } + + return false; } /** - * Returns the size of the column. - * @return int The size of the column. If column data type is int, decimal, double - * or float, the value will represents the overall number of digits in the - * number (Precision) (e.g: size of 54.323 is 5). If the datatype is varchar, then the - * number will represents number of characters. Default value is 1 for - * all types including datetime and timestamp. - * @since 1.0 + * Checks if a date-time string is valid or not. + * @param string $date A date string in the format 'YYYY-MM-DD HH:MM:SS'. + * @return boolean If the string represents correct date and time, the + * method will return true. False if it is not valid. */ - public function getSize(){ - return $this->size; + private function _validateDateAndTime($date) { + $trimmed = trim($date); + + if (strlen($trimmed) == 19) { + $dateAndTime = explode(' ', $trimmed); + + if (count($dateAndTime) == 2) { + return $this->_validateDate($dateAndTime[0]) && $this->_validateTime($dateAndTime[1]); + } + } + + return false; } /** - * Returns the value of column collation. - * @return string If MySQL version is '5.5' or lower, the method will - * return 'utf8mb4_unicode_ci'. Other than that, the method will return - * 'utf8mb4_unicode_520_ci'. - * @since 1.0 + * + * @param type $name + * @return boolean + * @since 1.6.6 */ - public function getCollation(){ - $split = explode('.', $this->getMySQLVersion()); - if(isset($split[0]) && intval($split[0]) <= 5 && isset($split[1]) && intval($split[1]) <= 5){ - return 'utf8mb4_unicode_ci'; + private function _validateName($name) { + if (strpos($name, ' ') === false) { + for ($x = 0 ; $x < strlen($name) ; $x++) { + $ch = $name[$x]; + + if ($x == 0 && ($ch >= '0' && $ch <= '9')) { + return false; + } + + if ($ch == '_' || ($ch >= 'a' && $ch <= 'z') || ($ch >= 'A' && $ch <= 'Z') || ($ch >= '0' && $ch <= '9')) { + } else { + return false; + } + } + + return true; } - return 'utf8mb4_unicode_520_ci'; + + return false; } /** - * Constructs a string that can be used to create the column in a table. - * @return string A string that can be used to create the column in a table. + * + * @param type $time */ - public function __toString() { - $retVal = $this->getName().' '; - $type = $this->getType(); - if($type == 'int' || $type == 'varchar' || $type == 'text'){ - $retVal .= $type.'('.$this->getSize().') '; - } - else if($type == 'decimal' || $type == 'float' || $type == 'double'){ - if($this->getSize() != 0){ - $retVal .= $type.'('.$this->getSize().','.$this->getScale().') '; - } - else{ - $retVal .= $type.' '; + private function _validateTime($time) { + if (strlen($time) == 8) { + $split = explode(':', $time); + + if (count($split) == 3) { + $hours = intval($split[0]); + $minutes = intval($split[1]); + $sec = intval($split[2]); + + return $hours >= 0 && $hours <= 23 && $minutes >= 0 && $minutes < 60 && $sec >= 0 && $sec < 60; } } - else{ - $retVal .= $type.' '; - } - if(!$this->isNull()){ - $retVal .= 'not null '; - } - else{ - $retVal .= 'null '; - } - if($this->isUnique()){ - $retVal .= 'unique '; - } - $default = $this->default; - if($default !== null){ - $retVal .= 'default '.$default.' '; - } - if($type == 'varchar' || $type == 'text' || $type == 'mediumtext'){ - $retVal .= 'collate '.$this->getCollation().' '; - } - $comment = $this->getComment(); - if($comment !== null){ - $retVal .= 'comment \''.$comment.'\''; - } - return trim($retVal); + + return false; } -} \ No newline at end of file +} diff --git a/src/MySQLLink.php b/src/MySQLLink.php index b4548ec..f951184 100644 --- a/src/MySQLLink.php +++ b/src/MySQLLink.php @@ -23,6 +23,7 @@ * SOFTWARE. */ namespace phMysql; + use mysqli; /** * A class that is used to connect to MySQL database. It works as an interface @@ -30,39 +31,33 @@ * @author Ibrahim * @version 1.3.1 */ -class MySQLLink{ +class MySQLLink { /** - * The name of database host. It can be an IP address (such as '134.123.111.3') or - * a URL. - * @var string - * @since 1.0 + * The index of the current row in result set. + * @var int + * @since 1.3 */ - private $host; + private $currentRow; /** - * The name of database user (such as 'Admin'). + * The database instance that will be selected once the connection is + * established. * @var string * @since 1.0 */ - private $user; + private $db; /** - * The password of the database user. + * The name of database host. It can be an IP address (such as '134.123.111.3') or + * a URL. * @var string * @since 1.0 */ - private $pass; + private $host; /** - * The database instance that will be selected once the connection is - * established. + * The last generated error message. * @var string * @since 1.0 */ - private $db; - /** - * The result of executing last query, mysqli_result object - * @var mysqli_result|null - * @since 1.0 - */ - private $result; + private $lastErrorMessage = 'NO ERRORS'; /** * The last generated error number. * @var int @@ -70,11 +65,11 @@ class MySQLLink{ */ private $lastErrorNo; /** - * The last generated error message. - * @var string + * The last executed query. + * @var MySQLQuer An object of type 'MySQLQuery. * @since 1.0 */ - private $lastErrorMessage = 'NO ERRORS'; + private $lastQuery; /** * Database connection. It is simply the handler for executing queries. * @var type @@ -82,23 +77,11 @@ class MySQLLink{ */ private $link; /** - * The last executed query. - * @var MySQLQuer An object of type 'MySQLQuery. + * The password of the database user. + * @var string * @since 1.0 */ - private $lastQuery; - /** - * An array which contains rows from executing MySQL query. - * @var array|null - * @since 1.2 - */ - private $resultRows; - /** - * The index of the current row in result set. - * @var int - * @since 1.3 - */ - private $currentRow; + private $pass; /** * Port number of MySQL server. * @var int @@ -106,22 +89,23 @@ class MySQLLink{ */ private $portNum; /** - * Returns the number of port that is used to connect to the host. - * @return int The number of port that is used to connect to the host. - * @since 1.3.1 + * The result of executing last query, mysqli_result object + * @var mysqli_result|null + * @since 1.0 */ - public function getPortNumber() { - return $this->portNum; - } + private $result; /** - * Returns the last generated error message that was generated by MySQL server. - * @return string The last generated error message that was generated by MySQL server. - * If no error is generated, the method will return the string 'NO ERRORS'. + * An array which contains rows from executing MySQL query. + * @var array|null + * @since 1.2 + */ + private $resultRows; + /** + * The name of database user (such as 'Admin'). + * @var string * @since 1.0 */ - public function getErrorMessage(){ - return trim($this->lastErrorMessage); - } + private $user; /** * Creates new instance of the class. * @param string $host Database host address. @@ -130,8 +114,10 @@ public function getErrorMessage(){ * @param int $port The number of the port that is used to connect to * database host. Default is 3306. */ - public function __construct($host, $user, $password,$port=3306) { - set_error_handler(function(){}); + public function __construct($host, $user, $password,$port = 3306) { + set_error_handler(function() + { + }); $this->link = @mysqli_connect($host, $user, $password,null,$port); restore_error_handler(); $this->user = $user; @@ -140,23 +126,156 @@ public function __construct($host, $user, $password,$port=3306) { $this->portNum = $port; $this->currentRow = -1; $this->lastErrorNo = 0; - if($this->link){ + + if ($this->link) { $this->link->set_charset("utf8"); mysqli_query($this->link, "set character_set_client='utf8'"); - mysqli_query ($this->link, "set character_set_results='utf8'" ); - } - else{ + mysqli_query($this->link, "set character_set_results='utf8'"); + } else { $this->lastErrorNo = mysqli_connect_errno(); $this->lastErrorMessage = mysqli_connect_error(); } } + public function __toString() { + return ''; + } /** - * Returns the last executed query object. - * @return MySQLQuery An object of type 'MySQLQuery' - * @since 1.1 + * Execute MySQL query. + * Note that the method does not support the execution of multi-queries in + * one transaction. It supports only one SQL query per transaction. + * @param MySQLQuery $query an object of type 'MySQLQuery'. + * @return boolean true if the query was executed successfully, Other than that, + * the method will return false in case of error. + * @since 1.0 */ - public function getLastQuery(){ - return $this->lastQuery; + public function executeQuery($query) { + if ($query instanceof MySQLQuery) { + $this->resultRows = null; + $this->currentRow = -1; + $this->lastQuery = $query; + + if ($this->isConnected()) { + if (!$query->isBlobInsertOrUpdate()) { + mysqli_query($this->link, 'set collation_connection =\''.$query->getStructure()->getCollation().'\''); + } + //this part has a bug. The bug can happen if query body + //contain other ';'. Example: insert into articles (id,articte_text) + // values (99, 'This is An example; ;; Can Cause a bug;;') + // most queries who have this type of syntax fall under + // insert and update. + $qType = $query->getType(); + + if ($qType != 'insert' && $qType != 'update') { + $eploded = explode(';', trim($query->getQuery(), ';')); + + if (count($eploded) != 1) { + foreach ($eploded as $xQuery) { + if (strlen(trim($xQuery)) != 0) { + $r = mysqli_query($this->link, $xQuery); + + if ($r === false) { + $this->lastErrorMessage = $this->link->error; + $this->lastErrorNo = $this->link->errno; + break; + } + } + } + + $r = mysqli_multi_query($this->link, $query->getQuery()); + + while (mysqli_more_results($this->link)) { + $x = mysqli_store_result($this->link); + mysqli_next_result($this->link); + } + + if ($r !== true) { + $this->lastErrorMessage = $this->link->error; + $this->lastErrorNo = $this->link->errno; + } + $query->setIsBlobInsertOrUpdate(false); + + return $r; + } + } + + if ($query->getType() == 'select' || $query->getType() == 'show' + || $query->getType() == 'describe') { + $r = mysqli_query($this->link, $query->getQuery()); + + if ($r) { + $this->result = $r; + $this->lastErrorNo = 0; + + return true; + } else { + $this->lastErrorMessage = $this->link->error; + $this->lastErrorNo = $this->link->errno; + $this->result = null; + $query->setIsBlobInsertOrUpdate(false); + + return false; + } + } else { + $this->result = null; + $r = mysqli_query($this->link, $query->getQuery()); + + if ($r == false) { + $this->lastErrorMessage = $this->link->error; + $this->lastErrorNo = $this->link->errno; + $this->result = null; + $query->setIsBlobInsertOrUpdate(false); + + return false; + } else { + $this->lastErrorMessage = 'NO ERRORS'; + $this->lastErrorNo = 0; + $this->result = null; + $query->setIsBlobInsertOrUpdate(false); + + return true; + } + } + } + } + + return false; + } + /** + * Returns an array which contains all data from a specific column given its + * name. + * @param string $colKey The name of the column as specified in the last + * executed query. It must be a value when passed to the method + * Table::getCol() will return an object of type 'Column'. + * @return array An array which contains all data from the given column. + * if the column does not exist, the method will return the constant + * 'Table::NO_SUCH_TABLE'. + * @since 1.2 + */ + public function getColumn($colKey) { + $retVal = []; + $rows = $this->getRows(); + $colNameInDb = $this->getLastQuery()->getColName($colKey); + + if ($colKey != MySQLTable::NO_SUCH_COL) { + foreach ($rows as $row) { + if (isset($row[$colNameInDb])) { + $retVal[] = $row[$colNameInDb]; + } else { + break; + } + } + } else { + $retVal = MySQLTable::NO_SUCH_COL; + } + + return $retVal; + } + /** + * Returns the name of the database that the instance is connected to. + * @return string The name of the database. + */ + public function getDBName() { + return $this->db; } /** * Returns the last error number that was generated by MySQL server. @@ -164,24 +283,101 @@ public function getLastQuery(){ * the returned value will be 0. * @since 1.0 */ - public function getErrorCode(){ + public function getErrorCode() { return $this->lastErrorNo; } /** - * Reconnect to MySQL server if a connection was established before. - * @return boolean If the reconnect attempt was succeeded, the method - * will return true. + * Returns the last generated error message that was generated by MySQL server. + * @return string The last generated error message that was generated by MySQL server. + * If no error is generated, the method will return the string 'NO ERRORS'. + * @since 1.0 + */ + public function getErrorMessage() { + return trim($this->lastErrorMessage); + } + /** + * Returns the last executed query object. + * @return MySQLQuery An object of type 'MySQLQuery' + * @since 1.1 + */ + public function getLastQuery() { + return $this->lastQuery; + } + /** + * Returns the number of port that is used to connect to the host. + * @return int The number of port that is used to connect to the host. * @since 1.3.1 */ - public function reconnect() { - return $this->isConnected(); + public function getPortNumber() { + return $this->portNum; } /** - * Returns the name of the database that the instance is connected to. - * @return string The name of the database. + * Returns the result set in case of executing select query. + * The method will return null in case of none-select queries. + * @return mysqli_result|null + * @since 1.0 + * @deprecated since version 1.3.1 */ - public function getDBName() { - return $this->db; + public function getResult() { + return $this->result; + } + /** + * Returns the row which the class is pointing to in the result set. + * @return array|null an associative array that represents a table row. + * If no results are fetched, the method will return null. + * @since 1.0 + */ + public function getRow() { + if (count($this->resultRows) != 0) { + if ($this->currentRow == -1) { + return $this->getRows()[0]; + } else { + if ($this->currentRow < $this->rows()) { + return $this->getRows()[$this->currentRow]; + } + } + } else { + return $this->_getRow(); + } + + return null; + } + /** + * Returns an array which contains all fetched results from the database. + * @return array An array which contains all fetched results from the database. + * Each row will be an associative array. The index will represents the + * column of the table. + * @since 1.2 + */ + public function getRows() { + if ($this->resultRows != null) { + return $this->resultRows; + } + $result = $this->getResult(); + + if (function_exists('mysqli_fetch_all')) { + $rows = $result !== null ? mysqli_fetch_all($result, MYSQLI_ASSOC) : []; + } else { + $rows = []; + + if ($result !== null) { + while ($row = $result->fetch_assoc()) { + $rows[] = $row; + } + } + } + + if ($this->getLastQuery()->getMappedEntity() !== null) { + $this->resultRows = []; + + foreach ($rows as $row) { + $this->resultRows[] = $this->_map($row); + } + } else { + $this->resultRows = $rows; + } + + return $this->resultRows; } /** * Checks if the connection is still active or its dead and try to reconnect. @@ -191,47 +387,79 @@ public function getDBName() { * @since 1.0 * @deprecated since version 1.3.1 */ - public function isConnected(){ + public function isConnected() { $test = false; - if($this->link instanceof mysqli){ - set_error_handler(function(){}); + + if ($this->link instanceof mysqli) { + set_error_handler(function() + { + }); $this->link = @mysqli_connect($this->host, $this->user, $this->pass,null , $this->portNum); restore_error_handler(); - if($this->link){ + + if ($this->link) { $test = true; $this->link->set_charset("utf8"); mysqli_query($this->link, "set character_set_client='utf8'"); mysqli_query($this->link, "set character_set_results='utf8'"); - if($this->db !== null){ + + if ($this->db !== null) { $test = mysqli_select_db($this->link, $this->db); - if($test === false){ + + if ($test === false) { $this->lastErrorMessage = mysqli_error($this->link); $this->lastErrorNo = mysqli_errno($this->link); $test = true; } - } - else{ + } else { $test = true; } - } - else{ + } else { $this->lastErrorNo = mysqli_connect_errno(); $this->lastErrorMessage = mysqli_connect_error(); } } + return $test; } - + /** + * Returns the next row that was resulted from executing a query that has + * results. + * @return array|null The next row in the result set. If no more rows are + * in the set, the method will return null. + * @since 1.3 + */ + public function nextRow() { + $this->currentRow++; + $rows = $this->getRows(); + + if (isset($rows[$this->currentRow])) { + return $rows[$this->currentRow]; + } + + return null; + } + /** + * Reconnect to MySQL server if a connection was established before. + * @return boolean If the reconnect attempt was succeeded, the method + * will return true. + * @since 1.3.1 + */ + public function reconnect() { + return $this->isConnected(); + } + /** * Return the number of rows returned by last query. * If no result returned by MySQL server, the method will return -1. * @return int * @since 1.0 */ - public function rows(){ - if($this->result){ + public function rows() { + if ($this->result) { return count($this->getRows()); } + return -1; } /** @@ -243,43 +471,35 @@ public function rows(){ * otherwise. * @since 1.0 */ - public function setDB($dbName){ + public function setDB($dbName) { $this->db = $dbName; $this->reconnect(); - if($this->getErrorCode() == 1049){ + + if ($this->getErrorCode() == 1049) { return false; } + return true; } /** - * Returns the result set in case of executing select query. - * The method will return null in case of none-select queries. - * @return mysqli_result|null - * @since 1.0 - * @deprecated since version 1.3.1 - */ - public function getResult(){ - return $this->result; - } - /** - * Returns the row which the class is pointing to in the result set. - * @return array|null an associative array that represents a table row. - * If no results are fetched, the method will return null. - * @since 1.0 + * Helper method that is used to initialize the array of rows in case + * of first call to the method getRow() + * @param type $retry + * @return type */ - public function getRow(){ - if(count($this->resultRows) != 0){ - if($this->currentRow == -1){ - return $this->getRows()[0]; - } - else if($this->currentRow < $this->rows()){ - return $this->getRows()[$this->currentRow]; + private function _getRow($retry = 0) { + if (count($this->resultRows) != 0) { + return $this->getRows()[0]; + } else { + if ($retry == 1) { + return null; + } else { + $this->getRows(); + $retry++; + + return $this->_getRow($retry); } } - else{ - return $this->_getRow(); - } - return null; } /** * Map a record to an entity class. @@ -289,204 +509,13 @@ public function getRow(){ private function _map($row) { $entityName = $this->getLastQuery()->getMappedEntity(); $entity = new $entityName(); - foreach ($this->getLastQuery()->getTable()->getSettersMap() as $methodName => $colName){ - if(isset($row[$colName])){ + + foreach ($this->getLastQuery()->getTable()->getSettersMap() as $methodName => $colName) { + if (isset($row[$colName])) { $entity->$methodName($row[$colName]); } } - return $entity; - } - /** - * Helper method that is used to initialize the array of rows in case - * of first call to the method getRow() - * @param type $retry - * @return type - */ - private function _getRow($retry=0){ - if(count($this->resultRows) != 0){ - return $this->getRows()[0]; - } - else if($retry == 1){ - return null; - } - else{ - $this->getRows(); - $retry++; - return $this->_getRow($retry); - } - } - /** - * Returns the next row that was resulted from executing a query that has - * results. - * @return array|null The next row in the result set. If no more rows are - * in the set, the method will return null. - * @since 1.3 - */ - public function nextRow() { - $this->currentRow++; - $rows = $this->getRows(); - if(isset($rows[$this->currentRow])){ - return $rows[$this->currentRow]; - } - return null; - } - /** - * Returns an array which contains all fetched results from the database. - * @return array An array which contains all fetched results from the database. - * Each row will be an associative array. The index will represents the - * column of the table. - * @since 1.2 - */ - public function getRows(){ - if($this->resultRows != null){ - return $this->resultRows; - } - $result = $this->getResult(); - if(function_exists('mysqli_fetch_all')){ - $rows = $result !== null ? mysqli_fetch_all($result, MYSQLI_ASSOC) : []; - } - else{ - $rows = []; - if($result !== null){ - while ($row = $result->fetch_assoc()){ - $rows[] = $row; - } - } - } - if($this->getLastQuery()->getMappedEntity() !== null){ - $this->resultRows = []; - foreach ($rows as $row){ - $this->resultRows[] = $this->_map($row); - } - } - else{ - $this->resultRows = $rows; - } - return $this->resultRows; - } - /** - * Returns an array which contains all data from a specific column given its - * name. - * @param string $colKey The name of the column as specified in the last - * executed query. It must be a value when passed to the method - * Table::getCol() will return an object of type 'Column'. - * @return array An array which contains all data from the given column. - * if the column does not exist, the method will return the constant - * 'Table::NO_SUCH_TABLE'. - * @since 1.2 - */ - public function getColumn($colKey) { - $retVal = []; - $rows = $this->getRows(); - $colNameInDb = $this->getLastQuery()->getColName($colKey); - if($colKey != MySQLTable::NO_SUCH_COL){ - foreach ($rows as $row){ - if(isset($row[$colNameInDb])){ - $retVal[] = $row[$colNameInDb]; - } - else{ - break; - } - } - } - else{ - $retVal = MySQLTable::NO_SUCH_COL; - } - return $retVal; - } - /** - * Execute MySQL query. - * Note that the method does not support the execution of multi-queries in - * one transaction. It supports only one SQL query per transaction. - * @param MySQLQuery $query an object of type 'MySQLQuery'. - * @return boolean true if the query was executed successfully, Other than that, - * the method will return false in case of error. - * @since 1.0 - */ - public function executeQuery($query){ - if($query instanceof MySQLQuery){ - $this->resultRows = null; - $this->currentRow = -1; - $this->lastQuery = $query; - if($this->isConnected()){ - - if(!$query->isBlobInsertOrUpdate()){ - mysqli_query($this->link, 'set collation_connection =\''.$query->getStructure()->getCollation().'\''); - } - //this part has a bug. The bug can happen if query body - //contain other ';'. Example: insert into articles (id,articte_text) - // values (99, 'This is An example; ;; Can Cause a bug;;') - // most queries who have this type of syntax fall under - // insert and update. - $qType = $query->getType(); - if($qType != 'insert' && $qType != 'update'){ - $eploded = explode(';', trim($query->getQuery(), ';')); - if(count($eploded) != 1){ - foreach ($eploded as $xQuery){ - if(strlen(trim($xQuery)) != 0){ - $r = mysqli_query($this->link, $xQuery); - if($r === false){ - $this->lastErrorMessage = $this->link->error; - $this->lastErrorNo = $this->link->errno; - break; - } - } - } - $r = mysqli_multi_query($this->link, $query->getQuery()); - while(mysqli_more_results($this->link)){ - $x = mysqli_store_result($this->link); - mysqli_next_result($this->link); - } - if($r !== true){ - $this->lastErrorMessage = $this->link->error; - $this->lastErrorNo = $this->link->errno; - } - $query->setIsBlobInsertOrUpdate(false); - return $r; - } - } - if($query->getType() == 'select' || $query->getType() == 'show' - || $query->getType() == 'describe' ){ - - $r = mysqli_query($this->link, $query->getQuery()); - if($r){ - $this->result = $r; - $this->lastErrorNo = 0; - return true; - } - else{ - $this->lastErrorMessage = $this->link->error; - $this->lastErrorNo = $this->link->errno; - $this->result = null; - $query->setIsBlobInsertOrUpdate(false); - return false; - } - } - else{ - $this->result = null; - $r = mysqli_query($this->link, $query->getQuery()); - if($r == false){ - $this->lastErrorMessage = $this->link->error; - $this->lastErrorNo = $this->link->errno; - $this->result = null; - $query->setIsBlobInsertOrUpdate(false); - return false; - } - else{ - $this->lastErrorMessage = 'NO ERRORS'; - $this->lastErrorNo = 0; - $this->result = null; - $query->setIsBlobInsertOrUpdate(false); - return true; - } - } - } - } - return false; - } - public function __toString() { - return ''; + return $entity; } } - diff --git a/src/MySQLQuery.php b/src/MySQLQuery.php index ead2ab5..3e966a5 100644 --- a/src/MySQLQuery.php +++ b/src/MySQLQuery.php @@ -23,50 +23,30 @@ * SOFTWARE. */ namespace phMysql; + use Exception; -use phMysql\MySQLTable; /** * A base class that is used to construct MySQL queries. It can be used as a base * class for constructing other MySQL queries. * @author Ibrahim * @version 1.9.0 */ -class MySQLQuery{ - /** - * The name of the entity class at which a select - * statement result will be mapped to. - * @var string|null - * @since 1.9.0 - */ - private $resultMap; +class MySQLQuery { /** - * The linked database table. - * @var MySQLTable - */ - private $table; - /** - * The name of database schema that the query will be executed on. - * @var string - * @since 1.8.7 + * A constant for the query 'delete from'. + * @since 1.0 */ - private $schemaName; + const DELETE = 'delete from '; /** - * An attribute that is set to true if the query is an update or insert of - * blob datatype. - * @var boolean + * A constant for the query 'insert into'. + * @since 1.0 */ - private $isFileInsert; + const INSERT = 'insert into '; /** * Line feed character. * @since 1.8.1 */ const NL = "\n"; - /** - * A constant that indicates an error has occurred while executing the query. - * @var string - * @since 1.4 - */ - const QUERY_ERR = 'query_error'; /** * A constant that indicates a table structure is not linked with the instance. * @since 1.8.3 @@ -76,31 +56,33 @@ class MySQLQuery{ * An array that contains the supported MySQL query types. * @since 1.1 */ - const Q_TYPES = array( + const Q_TYPES = [ 'select','update','delete','insert','show','create','alter','drop' - ); + ]; /** - * A constant for the query 'select * from '. - * @since 1.0 + * A constant that indicates an error has occurred while executing the query. + * @var string + * @since 1.4 */ - const SELECT = 'select * from '; + const QUERY_ERR = 'query_error'; /** - * A constant for the query 'insert into'. + * A constant for the query 'select * from '. * @since 1.0 */ - const INSERT = 'insert into '; + const SELECT = 'select * from '; /** - * A constant for the query 'delete from'. - * @since 1.0 + * An attribute that is set to true if the query is an update or insert of + * blob datatype. + * @var boolean */ - const DELETE = 'delete from '; + private $isFileInsert; + private $origColsNames; /** * The query that will be constructed using class methods. * @var string * @since 1.0 */ private $query; - private $origColsNames; /** * A string that represents the type of the query such as 'select' or 'update'. * @var string @@ -108,208 +90,88 @@ class MySQLQuery{ */ private $queryType; /** - * Constructs a query that can be used to get the number of tables in a - * schema given its name. - * The result of executing - * the query is a table with one row and one column. The column name will be - * 'tables_count' which will contain an integer value that indicates the - * number of tables in the schema. If the schema does not exist or has no tables, - * the result in the given column will be 0. - * @param string $schemaName The name of the schema. - * @since 1.8 - */ - public function schemaTablesCount($schemaName){ - $this->query = 'select count(*) as tables_count from information_schema.tables where TABLE_TYPE = \'BASE TABLE\' and TABLE_SCHEMA = \''.$schemaName.'\';'; - $this->queryType = 'select'; - } - /** - * Returns the name of the entity class at which a select result will - * be mapped to. - * @return string|null If the entity name is set, the method will return - * it as string. If not set, the method will return null. + * The name of the entity class at which a select + * statement result will be mapped to. + * @var string|null * @since 1.9.0 */ - public function getMappedEntity() { - return $this->resultMap; - } - /** - * Constructs a query which can be used to update the server's global - * variable 'max_allowed_packet'. - * The value of the attribute is in bytes. The developer might want to - * update the value of this variable if he wants to send large data to - * database using one query. The maximum value this attribute can have is - * 1073741824 bytes. - * @param int $size The new size. - * @param string $unit One of 4 values: 'B' for byte, 'KB' for kilobyte, - * 'MB' for megabyte and 'GB' for gigabyte. If the given value is none of the - * 4, the type will be set to 'MP'. - */ - public function setMaxPackete($size,$unit='MB'){ - $max = 1073741824; - $updatedSize = 0; - $uUnit = strtoupper($unit); - if($uUnit != 'MB' && $uUnit != 'B' && $uUnit != 'KB' && $uUnit != 'GB'){ - $uUnit = 'MB'; - } - switch ($uUnit){ - case 'B':{ - $updatedSize = $size < $max && $size > 0 ? $size : $max; - break; - } - case 'KB':{ - $new = $size*1024; - $updatedSize = $new < $max && $new > 0 ? $new : $max; - break; - } - case 'MB':{ - $new = $size*1024*1024; - $updatedSize = $new < $max && $new > 0 ? $new : $max; - break; - } - case 'GB':{ - $new = $size*1024*1024*1024; - $updatedSize = $new < $max && $new > 0 ? $new : $max; - break; - } - } - $this->query = 'set global max_allowed_packet = '.$updatedSize.';'; - } - /** - * Constructs a query that can be used to get all tables in a schema given its name. - * The result of executing the query is a table with one colum. The name - * of the column is 'TABLE_NAME'. The column will simply contain all the - * names of the tables in the schema. If the given schema does not exist - * or has no tables, The result will be an empty table. - * @param string $schemaName The name of the schema. - * @since 1.8 - */ - public function getSchemaTables($schemaName) { - $this->query = 'select TABLE_NAME from information_schema.tables where TABLE_TYPE = \'BASE TABLE\' and TABLE_SCHEMA = \''.$schemaName.'\''; - $this->queryType = 'select'; - } - /** - * Constructs a query that can be used to get the number of views in a - * schema given its name. - * The result of executing the query is a table with one row and one column. - * The column name will be 'views_count' which will contain an integer - * value that indicates the number of views in the schema. If the schema - * does not exist or has no views, the result in the given column will be 0. - * @param string $schemaName The name of the schema. - * @since 1.8 - */ - public function schemaViewsCount($schemaName){ - $this->query = 'select count(*) as views_count from information_schema.tables where TABLE_TYPE = \'VIEW\' and TABLE_SCHEMA = \''.$schemaName.'\';'; - $this->queryType = 'select'; - } - /** - * Sets the name of database (Schema) that the query will be executed on. - * A schema is a collection of tables. On the other hand, a database - * is a collection of schema. In MySQL, the two terms usually refer to the - * same thing. - * @param string $name Database schema name. A valid name - * must have the following conditions: - * - * @return boolean If the name of the schema is set, the method will return - * true. Other than that, the method will return false. - * @since 1.8.7 - */ - public function setSchemaName($name) { - $nameT = trim($name); - if(strlen($nameT) != 0){ - $len = strlen($nameT); - if($len > 0){ - for ($x = 0 ; $x < $len ; $x++){ - $ch = $nameT[$x]; - if($x == 0 && ($ch >= '0' && $ch <= '9')){ - return false; - } - if($ch == '_' || ($ch >= 'a' && $ch <= 'z') || ($ch >= 'A' && $ch <= 'Z') || ($ch >= '0' && $ch <= '9')){ - - } - else{ - return false; - } - } - $this->schemaName = $nameT; - $this->getTable()->setSchemaName($nameT); - return true; - } - } - return false; - } + private $resultMap; /** - * Returns database schema name that the query will be executed on. - * A schema is a collection of tables. On the other hand, a database - * is a collection of schema. In MySQL, the two terms usually refer to the - * same thing. - * @return string Database schema name. If not set, the method will - * return null. + * The name of database schema that the query will be executed on. + * @var string * @since 1.8.7 */ - public function getSchemaName() { - return $this->schemaName; - } + private $schemaName; /** - * Constructs a query that can be used to get the names of all views in a - * schema given its name. - * The result of executing the query is a table with one column. The name - * of the column is 'TABLE_NAME'. The column will simply contain all the - * names of the views in the schema. If the given schema does not exist - * or has no views, The result will be an empty table. - * @param string $schemaName The name of the schema. - * @since 1.8 + * The linked database table. + * @var MySQLTable */ - public function getSchemaViews($schemaName) { - $this->query = 'select TABLE_NAME from information_schema.tables where TABLE_TYPE = \'VIEW\' and TABLE_SCHEMA = \''.$schemaName.'\''; - $this->queryType = 'select'; - } + private $table; /** * Creates new instance of the class. * @param string $tableName The name of the table that will be associated * with the queries that will be created. */ - public function __construct($tableName=null) { + public function __construct($tableName = null) { $this->table = new MySQLTable($tableName); $this->query = self::SELECT.$this->getTableName(); $this->queryType = 'select'; $this->setIsBlobInsertOrUpdate(false); $this->origColsNames = []; } - /** - * Links a table to the query. - * @param MySQLTable $tableObj The table that will be linked. - * @since 1.9.0 - */ - public function setTable($tableObj) { - if($tableObj instanceof MySQLTable){ - $this->table = $tableObj; - $this->table->setOwnerQuery($this); - } + public function __toString() { + return $this->getQuery(); } /** - * Constructs a query that can be used to alter the properties of a table - * given its name. - * @param array $alterOps An array that contains the alter operations. + * Constructs a query that can be used to alter a table and add a + * foreign key to it. + * @param ForeignKey $key An object of type ForeignKey. * @since 1.4 */ - public function alter($alterOps){ - $schema = $this->getSchemaName() === null ? '' : $this->getSchemaName().'.'; - $q = 'alter table '.$schema.''.$this->getStructureName().self::NL; - $count = count($alterOps); - for($x = 0 ; $x < $count ; $x++){ - if($x + 1 == $count){ - $q .= $alterOps[$x].';'.self::NL; + public function addForeignKey($key) { + $ownerTable = $key->getOwner(); + $sourceTable = $key->getSource(); + + if ($sourceTable !== null && $ownerTable !== null) { + $query = 'alter table '.$ownerTable->getName() + .' add constraint '.$key->getKeyName().' foreign key ('; + $ownerCols = $key->getOwnerCols(); + $ownerCount = count($ownerCols); + $i0 = 0; + + foreach ($ownerCols as $col) { + if ($i0 + 1 == $ownerCount) { + $query .= $col->getName().') '; + } else { + $query .= $col->getName().', '; + } + $i0++; } - else{ - $q .= $alterOps[$x].','.self::NL; + $query .= 'references '.$key->getSourceName().'('; + $sourceCols = $key->getSourceCols(); + $refCount = count($sourceCols); + $i1 = 0; + + foreach ($sourceCols as $col) { + if ($i1 + 1 == $refCount) { + $query .= $col->getName().') '; + } else { + $query .= $col->getName().', '; + } + $i1++; + } + $onDelete = $key->getOnDelete(); + + if ($onDelete !== null) { + $query .= 'on delete '.$onDelete.' '; + } + $onUpdate = $key->getOnUpdate(); + + if ($onUpdate !== null) { + $query .= 'on update '.$onUpdate; } } - $this->setQuery($q, 'alter'); + $this->setQuery($query, 'alter'); } /** * Constructs a query that can be used to add a primary key to a table. @@ -317,29 +179,33 @@ public function alter($alterOps){ * @since 1.8.8 */ public function addPrimaryKey($table) { - if($table instanceof MySQLTable){ + if ($table instanceof MySQLTable) { $primaryCount = $table->primaryKeyColsCount(); - if($primaryCount != 0){ + + if ($primaryCount != 0) { $stm = 'alter table '.$table->getName().' add constraint '.$table->getPrimaryKeyName().' primary key ('; $index = 0; $alterStm = ''; - foreach ($table->getColumns() as $col){ - if($col->isPrimary()){ - if($index + 1 == $primaryCount){ + + foreach ($table->getColumns() as $col) { + if ($col->isPrimary()) { + if ($index + 1 == $primaryCount) { $stm .= $col->getName().')'; - } - else{ + } else { $stm .= $col->getName().','; } - if($col->isAutoInc()){ + + if ($col->isAutoInc()) { $alterStm .= 'alter table '.$table->getName().' modify '.$col.' auto_increment;'.self::NL; } $index++; } } - if(strlen($stm) !== 0){ + + if (strlen($stm) !== 0) { $stm .= ';'.MySQLQuery::NL.$alterStm; $this->setQuery($stm, 'alter'); + return; } $this->setQuery('', 'alter'); @@ -347,167 +213,305 @@ public function addPrimaryKey($table) { } } /** - * Constructs a query that can be used to alter a table and add a - * foreign key to it. - * @param ForeignKey $key An object of type ForeignKey. + * Constructs a query that can be used to alter the properties of a table + * given its name. + * @param array $alterOps An array that contains the alter operations. * @since 1.4 */ - public function addForeignKey($key){ - $ownerTable = $key->getOwner(); - $sourceTable = $key->getSource(); - if($sourceTable !== null && $ownerTable !== null){ - $query = 'alter table '.$ownerTable->getName() - . ' add constraint '.$key->getKeyName().' foreign key ('; - $ownerCols = $key->getOwnerCols(); - $ownerCount = count($ownerCols); - $i0 = 0; - foreach ($ownerCols as $col){ - if($i0 + 1 == $ownerCount){ - $query .= $col->getName().') '; - } - else{ - $query .= $col->getName().', '; - } - $i0++; - } - $query .= 'references '.$key->getSourceName().'('; - $sourceCols = $key->getSourceCols(); - $refCount = count($sourceCols); - $i1 = 0; - foreach ($sourceCols as $col){ - if($i1 + 1 == $refCount){ - $query .= $col->getName().') '; - } - else{ - $query .= $col->getName().', '; - } - $i1++; - } - $onDelete = $key->getOnDelete(); - if($onDelete !== null){ - $query .= 'on delete '.$onDelete.' '; - } - $onUpdate = $key->getOnUpdate(); - if($onUpdate !== null){ - $query .= 'on update '.$onUpdate; + public function alter($alterOps) { + $schema = $this->getSchemaName() === null ? '' : $this->getSchemaName().'.'; + $q = 'alter table '.$schema.''.$this->getStructureName().self::NL; + $count = count($alterOps); + + for ($x = 0 ; $x < $count ; $x++) { + if ($x + 1 == $count) { + $q .= $alterOps[$x].';'.self::NL; + } else { + $q .= $alterOps[$x].','.self::NL; } } - $this->setQuery($query, 'alter'); + $this->setQuery($q, 'alter'); } /** - * Constructs a query that can be used to create a new table. - * @param MySQLTable $table an instance of MySQLTable. - * @param boolean $inclSqlComments If set to true, a set of comment will appear - * in the generated SQL which description what is happening in every SQL Statement. - * @since 1.4 + * Constructs a string which contains columns names that will be selected. + * @param array $colsArr It can be an indexed array which contains columns + * names as specified while creating the linked table. Or it can be an + * associative array. The key should be the name of the column and the value + * is an alias to the column. For example, If the following array is given: + *

+ * [ + * 'name','id'=>'user_id','email' + * ] + *

+ * And assuming that the column names are the same as given values, + * Then the output will be the following string: + *

+ * name, id as user_id, email + *

+ * @param boolean $withTablePrefix If set to true, then column name will be + * prefixed with table name. + * @return string + * @since 1.9.0 */ - private function _createTable($table,$inclSqlComments=false){ - if($table instanceof MySQLTable){ - $query = ''; - if($inclSqlComments === true){ - $query .= '-- Structure of the table \''.$this->getStructureName().'\''.self::NL; - $query .= '-- Number of columns: \''.count($this->getStructure()->columns()).'\''.self::NL; - $query .= '-- Number of forign keys count: \''.count($this->getStructure()->forignKeys()).'\''.self::NL; - $query .= '-- Number of primary key columns count: \''.$this->getStructure()->primaryKeyColsCount().'\''.self::NL; - } - $query .= 'create table if not exists '.$table->getName().'('.self::NL; - $keys = $table->colsKeys(); - $count = count($keys); - for($x = 0 ; $x < $count ; $x++){ - if($x + 1 == $count){ - $query .= ' '.$table->columns()[$keys[$x]].self::NL; + public function createColsToSelect($colsArr,$withTablePrefix) { + $retVal = ''; + $table = $this->getTable(); + + if ($table instanceof JoinTable && $table->hasCommon()) { + if (count($colsArr) == 0) { + $comma = " \n"; + + foreach ($table->getLeftTable()->getColumns() as $colObj) { + if ($table->isCommon($colObj->getName())) { + $alias = 'left_'.$colObj->getName(); + $colObj->setAlias($alias); + $asPart = $comma.$colObj->getName(true).' as '.$alias; + } else { + $asPart = $comma.$colObj->getName(true); + } + $retVal .= $asPart; + $comma = ",\n"; } - else{ - $query .= ' '.$table->columns()[$keys[$x]].','.self::NL; + + foreach ($table->getRightTable()->getColumns() as $colObj) { + if ($table->isCommon($colObj->getName())) { + $alias = 'right_'.$colObj->getName(); + $colObj->setAlias($alias); + $asPart = $comma.$colObj->getName(true).' as '.$alias; + } else { + $asPart = $comma.$colObj->getName(true); + } + $retVal .= $asPart; } - } - $query .= ')'.self::NL; - $comment = $table->getComment(); - if($comment !== null){ - $query .= 'comment \''.$comment.'\''.self::NL; - } - $query .= 'ENGINE = '.$table->getEngine().self::NL; - $query .= 'DEFAULT CHARSET = '.$table->getCharSet().self::NL; - $query .= 'collate = '.$table->getCollation().';'.self::NL; - $coutPk = $this->getStructure()->primaryKeyColsCount(); - if($coutPk >= 1){ - if($inclSqlComments === true){ - $query .= '-- Add Primary key to the table.'.self::NL; + } else { + $comma = " \n"; + + if (isset($colsArr['left']) && gettype($colsArr['left']) == 'array') { + $retVal .= $this->_createColToSelechH1($colsArr['left'], $comma, 'left'); } - $this->addPrimaryKey($table); - $q = $this->getQuery(); - if(strlen($q) != 0){ - //no need to append ';\n' as it was added before. - $query .= $q; + + if (isset($colsArr['right']) && gettype($colsArr['right']) == 'array') { + $retVal .= $this->_createColToSelechH1($colsArr['right'], $comma, 'right'); } + $retVal .= $this->_createColToSelechH1($colsArr, $comma); } - //add forign keys - $count2 = count($table->forignKeys()); - if($inclSqlComments === true && $count2 != 0){ - $query .= '-- Add Forign keys to the table.'.self::NL; - } - for($x = 0 ; $x < $count2 ; $x++){ - $this->addForeignKey($table->forignKeys()[$x]); - $query .= $this->getQuery().';'.self::NL; - } - if($inclSqlComments === true){ - $query .= '-- End of the Structure of the table \''.$this->getStructureName().'\''.self::NL; + } else { + if (count($colsArr) == 0) { + $retVal = '*'; + } else { + $comma = " \n"; + + foreach ($colsArr as $index => $colName) { + if (gettype($index) == 'string') { + $colObj = $this->getCol($index); + $colObj->setAlias($colName); + $asPart = ' as '.$colName; + } else { + $colObj = $this->getCol($colName); + $asPart = ''; + } + + if ($colObj instanceof MySQLColumn) { + $retVal .= $comma.$colObj->getName($withTablePrefix).$asPart; + $comma = ",\n"; + } + } } - $this->setQuery($query, 'create'); } + + return $retVal."\n"; } + /** - * Escape any MySQL special characters from a string. - * @param string $query The string that the characters will be escaped from. - * @return string A string with escaped MySQL characters. - * @deprecated since version 1.8.9 - * @since 1.4 + * Constructs a 'where' condition given a date. + * @param string $date A date or timestamp. + * @param string $colName The name of the column that will contain + * the date value. + * @param string $format The format of the date. The supported formats + * are: + * */ - public static function escapeMySQLSpeciarChars($query){ - $escapedQuery = ''; - $query = ''.$query; - if($query){ - $mysqlSpecial = array( - "\\","'","\0","\b","\n" - ); - $mysqlSpecialEsc = array( - "\\\\","\'","\\0","\\b","\\n" - ); - $count = count($mysqlSpecial); - for($i = 0 ; $i < $count ; $i++){ - if($i == 0){ - $escapedQuery = str_replace($mysqlSpecial[$i], $mysqlSpecialEsc[$i], $query); + public static function createDateCondition($date,$colName,$format = 'YYYY-MM-DD HH:MM:SS') { + $formatInUpperCase = strtoupper(trim($format)); + $condition = ''; + + if ($formatInUpperCase == 'YYYY-MM-DD HH:MM:SS') { + $dateTimeSplit = explode(' ', $date); + + if (count($date) == 2) { + $datePart = explode('-', $dateTimeSplit[0]); + $timePart = explode(':', $dateTimeSplit[0]); + + if (count($datePart) == 3 && count($timePart) == 3) { + $condition = 'year('.$colName.') = '.$datePart[0].' and ' + .'month('.$colName.') = '.$datePart[1].' and ' + .'day('.$colName.') = '.$datePart[2].' and ' + .'hour('.$colName.') = '.$datePart[2].' and ' + .'minute('.$colName.') = '.$datePart[2].' and ' + .'second('.$colName.') = '.$datePart[2].' and '; } - else{ - $escapedQuery = str_replace($mysqlSpecial[$i], $mysqlSpecialEsc[$i], $escapedQuery); + } + } else { + if ($formatInUpperCase == 'YYYY-MM-DD') { + $datePart = explode('-', $date); + + if (count($datePart) == 3) { + $condition = 'year('.$colName.') = '.$datePart[0].' and ' + .'month('.$colName.') = '.$datePart[1].' and ' + .'day('.$colName.') = '.$datePart[2]; + } + } else { + if ($formatInUpperCase == 'YYYY') { + $asInt = intval($date); + + if ($asInt > 1900 && $asInt < 10000) { + $condition = 'year('.$colName.') = '.$date; + } + } else { + if ($formatInUpperCase == 'MM') { + $asInt = intval($date); + + if ($asInt > 0 && $asInt < 13) { + $condition = 'month('.$colName.') = '.$date; + } + } else { + if ($formatInUpperCase == 'DD') { + $asInt = intval($date); + + if ($asInt > 0 && $asInt < 32) { + $condition = 'day('.$colName.') = '.$date; + } + } else { + if ($formatInUpperCase == 'HH:MM:SS') { + $datePart = explode(':', $date); + + if (count($datePart) == 3) { + $condition = 'hour('.$colName.') = '.$datePart[0].' and ' + .'minute('.$colName.') = '.$datePart[1].' and ' + .'second('.$colName.') = '.$datePart[2]; + } + } else { + if ($formatInUpperCase == 'HH') { + $asInt = intval($date); + + if ($asInt > 0 && $asInt < 24) { + $condition = 'hour('.$colName.') = '.$date; + } + } else { + if ($formatInUpperCase == 'SS') { + $asInt = intval($date); + + if ($asInt > 0 && $asInt < 60) { + $condition = 'second('.$colName.') = '.$date; + } + } else { + if ($formatInUpperCase == 'MM') { + $asInt = intval($date); + + if ($asInt > 0 && $asInt < 59) { + $condition = 'minute('.$colName.') = '.$date; + } + } + } + } + } + } + } } } } - return $escapedQuery; + + return $condition; } /** - * Constructs a query that can be used to show database table engines. - * The result of executing the query will be a table with the following - * columns: - * - * @since 1.8.7 + * Constructs a query that can be used to create the table which is linked + * with the query class. + * @param boolean $inclComments If set to true, the generated MySQL + * query will have basic comments explaining the structure. + * @return boolean Once the query is structured, the method will return + * true. If the query is not created, the method will return false. + * @deprecated since version 1.9.0 + * @since 1.5 */ - public function showEngines() { - $this->show('engines'); + public function createStructure($inclComments = false) { + $t = $this->getTable(); + + if ($t instanceof MySQLTable) { + $this->_createTable($t,$inclComments); + + return true; + } + + return false; } /** - * Constructs a query that can be used to show some information about something. - * @param string $toShow The thing that will be shown. - * @since 1.4 + * Constructs a query that can be used to create the table which is linked + * with the query class. + * @param boolean $withComments If set to true, the generated MySQL + * query will have basic comments explaining the structure. + * @since 1.9.0 */ - public function show($toShow){ - $this->setQuery('show '.$toShow.';', 'show'); + public function createTable($withComments = false) { + $this->createStructure($withComments); + } + /** + * Removes a record from the table. + * @param array $columnsAndVals An associative array. The indices of the array + * should be the values of the columns and the value at each index is + * an object of type 'Column'. + * @param array $valsConds An array that can have one of the following + * values: '=','!=','<','<=','>' and '>='. The number of elements + * in this array must match number of + * elements in the array $cols. If not provided, '=' is used. Default is empty array. + * @param array $jointOps An array which contains conditional operators + * to join conditions. The operators can be logical or bitwise. Possible + * values include: &&, ||, and, or, |, &, xor. If not provided, + * 'and' is used for all values. + * @since 1.8.2 + */ + public function deleteRecord($columnsAndVals,$valsConds = [],$jointOps = []) { + $colsCount = count($columnsAndVals); + $condsCount = count($valsConds); + $joinOpsCount = count($jointOps); + + while ($colsCount > $condsCount) { + $valsConds[] = '='; + $condsCount = count($valsConds); + } + + while (($colsCount - 1) > $joinOpsCount) { + $jointOps[] = 'and'; + $joinOpsCount = count($jointOps); + } + $cols = []; + $vals = []; + + foreach ($columnsAndVals as $valOrIndex => $colObjOrVal) { + if ($colObjOrVal instanceof MySQLColumn) { + $cols[] = $colObjOrVal; + $vals[] = $valOrIndex; + } else { + if (gettype($valOrIndex) == 'integer') { + $testCol = $this->getTable()->getColByIndex($valOrIndex); + } else { + $testCol = $this->getTable()->getCol($valOrIndex); + } + $cols[] = $testCol; + $vals[] = $colObjOrVal; + } + } + $query = 'delete from '.$this->getTableName(); + $this->setQuery($query.$this->createWhereConditions($cols, $vals, $valsConds, $jointOps).';', 'delete'); } /** * Constructs a query that can be used to delete the table from the @@ -517,6 +521,102 @@ public function show($toShow){ public function dropTable() { $this->setQuery('drop table '.$this->getTableName().';', 'delete'); } + /** + * Escape any MySQL special characters from a string. + * @param string $query The string that the characters will be escaped from. + * @return string A string with escaped MySQL characters. + * @deprecated since version 1.8.9 + * @since 1.4 + */ + public static function escapeMySQLSpeciarChars($query) { + $escapedQuery = ''; + $query = ''.$query; + + if ($query) { + $mysqlSpecial = [ + "\\","'","\0","\b","\n" + ]; + $mysqlSpecialEsc = [ + "\\\\","\'","\\0","\\b","\\n" + ]; + $count = count($mysqlSpecial); + + for ($i = 0 ; $i < $count ; $i++) { + if ($i == 0) { + $escapedQuery = str_replace($mysqlSpecial[$i], $mysqlSpecialEsc[$i], $query); + } else { + $escapedQuery = str_replace($mysqlSpecial[$i], $mysqlSpecialEsc[$i], $escapedQuery); + } + } + } + + return $escapedQuery; + } + /** + * Returns a column from the table given its key. + * @param string $colKey The name of the column key. + * @return string|MySQLColumn The the column in the table. If no column was + * found, the method will return the string 'MySQLTable::NO_SUCH_COL'. If there is + * no table linked with the query object, the method will return the + * string MySQLQuery::NO_STRUCTURE. + * @since 1.6 + */ + public function getCol($colKey) { + $structure = $this->getStructure(); + $retVal = self::NO_STRUCTURE; + + if ($structure instanceof MySQLTable) { + $col = $structure->getCol($colKey); + + if ($col instanceof MySQLColumn) { + return $col; + } + $retVal = MySQLTable::NO_SUCH_COL; + } + + return $retVal; + } + /** + * Returns the index of a column given its key. + * @param string $colKey The name of the column key. + * @return int The index of the column if found starting from 0. + * If the column was not found, the method will return -1. + * @since 1.8.4 + */ + public function getColIndex($colKey) { + $col = $this->getCol($colKey); + $index = $col instanceof MySQLColumn ? $col->getIndex() : -1; + + return $index; + } + /** + * Returns the name of the column from the table given its key. + * @param string $colKey The name of the column key. + * @return string The name of the column in the table. If no column was + * found, the method will return the string MySQLTable::NO_SUCH_COL. If there is + * no table linked with the query object, the method will return the + * string MySQLQuery::NO_STRUCTURE. + * @since 1.5 + */ + public function getColName($colKey) { + $col = $this->getCol($colKey); + + if ($col instanceof MySQLColumn) { + return $col->getName(); + } + + return $col; + } + /** + * Returns the name of the entity class at which a select result will + * be mapped to. + * @return string|null If the entity name is set, the method will return + * it as string. If not set, the method will return null. + * @since 1.9.0 + */ + public function getMappedEntity() { + return $this->resultMap; + } /** * Returns the value of the property $query. * It is simply the query that was constructed by calling any method @@ -524,131 +624,238 @@ public function dropTable() { * @return string a MySql query. * @since 1.0 */ - public function getQuery(){ + public function getQuery() { return $this->query; } /** - * Returns the type of the query. - * @return string The type of the query (such as 'select', 'update'). - * @since 1.0 + * Returns database schema name that the query will be executed on. + * A schema is a collection of tables. On the other hand, a database + * is a collection of schema. In MySQL, the two terms usually refer to the + * same thing. + * @return string Database schema name. If not set, the method will + * return null. + * @since 1.8.7 */ - public function getType(){ - return $this->queryType; + public function getSchemaName() { + return $this->schemaName; } /** - * Sets the value of the property $query. - * The type of the query must be taken from the array MySQLQuery::Q_TYPES. - * @param string $query a MySQL query. - * @param string $type The type of the query (such as 'select', 'update'). - * @since 1.0 - * @throws Exception If the given query type is not supported. + * Constructs a query that can be used to get all tables in a schema given its name. + * The result of executing the query is a table with one colum. The name + * of the column is 'TABLE_NAME'. The column will simply contain all the + * names of the tables in the schema. If the given schema does not exist + * or has no tables, The result will be an empty table. + * @param string $schemaName The name of the schema. + * @since 1.8 */ - public function setQuery($query,$type){ - $ltype = strtolower($type.''); - if(in_array($ltype, self::Q_TYPES)){ - $this->query = $query; - $this->queryType = $ltype; - } - else{ - throw new Exception('Unsupported query type: \''.$type.'\''); - } + public function getSchemaTables($schemaName) { + $this->query = 'select TABLE_NAME from information_schema.tables where TABLE_TYPE = \'BASE TABLE\' and TABLE_SCHEMA = \''.$schemaName.'\''; + $this->queryType = 'select'; } /** - * Constructs a query that can be used to select all columns from a table. - * @param int $limit The value of the attribute 'limit' of the select statement. - * If zero or a negative value is given, it will not be ignored. - * Default is -1. - * @param int $offset The value of the attribute 'offset' of the select statement. - * If zero or a negative value is given, it will not be ignored. - * Default is -1. - * @since 1.0 + * Constructs a query that can be used to get the names of all views in a + * schema given its name. + * The result of executing the query is a table with one column. The name + * of the column is 'TABLE_NAME'. The column will simply contain all the + * names of the views in the schema. If the given schema does not exist + * or has no views, The result will be an empty table. + * @param string $schemaName The name of the schema. + * @since 1.8 */ - public function selectAll($limit=-1,$offset=-1){ - $this->select(array( - 'limit'=>$limit, - 'offset'=>$offset - )); + public function getSchemaViews($schemaName) { + $this->query = 'select TABLE_NAME from information_schema.tables where TABLE_TYPE = \'VIEW\' and TABLE_SCHEMA = \''.$schemaName.'\''; + $this->queryType = 'select'; } /** - * Constructs a select query which is used to count number of rows on a - * table. - * @param array $options An associative array of options to customize the - * select query. Available options are: - * - * @since 1.8.9 + * Returns the table that is used for constructing queries. + * @return MySQLTable The table that is used for constructing queries. + * @since 1.5 + * @deprecated since version 1.9.0 Use MySQLQuery::getTable() instead. */ - public function selectCount($options=[]) { - $asPart = ' as count'; - $where = ''; - if(gettype($options) == 'array'){ - if(isset($options['as'])){ - $trimmedAs = trim($options['as']); - if(strlen($trimmedAs) != 0){ - $asPart = ' as '. str_replace(' ', '_', $trimmedAs); - } - } - $options['join-operators'] = isset($options['join-operators']) && - gettype($options['join-operators']) == 'array' ? $options['join-operators'] : []; - $options['conditions'] = isset($options['conditions']) && - gettype($options['conditions']) == 'array' ? $options['conditions'] : []; - if(isset($options['where']) && isset($options['conditions'])){ - $cols = []; - $vals = []; - foreach($options['where'] as $valOrColIndex => $colOrVal){ - if($colOrVal instanceof MySQLColumn){ - $cols[] = $colOrVal; - $vals[] = $valOrColIndex; - } - else{ - if(gettype($valOrColIndex) == 'integer'){ - $testCol = $this->getStructure()->getColByIndex($valOrColIndex); - } - else{ - $testCol = $this->getStructure()->getCol($valOrColIndex); - } - $cols[] = $testCol; - $vals[] = $colOrVal; - } - } - $where = $this->createWhereConditions($cols, $vals, $options['conditions'], $options['join-operators']); - } - else{ - $where = ''; - } - if(trim($where) == 'where'){ - $where = ''; - } + public function getStructure() { + return $this->table; + } + /** + * Returns the name of the table that is used to construct queries. + * @return string The name of the table that is used to construct queries. + * if no table is linked, the method will return the string MySQLQuery::NO_STRUCTURE. + * @since 1.5 + * @deprecated since version 1.9.0 Use MySQLQuery::getTableName() instead. + */ + public function getStructureName() { + $s = $this->getStructure(); + + if ($s instanceof MySQLTable) { + return $s->getName(); } - $this->setQuery('select count(*)'.$asPart.' from '.$this->getStructureName().$where.';', 'select'); + + return self::NO_STRUCTURE; } /** - * Creates an object of the class which represents a join between two tables. - * For every join, there is a left table, a right table and a join - * condition. The table which - * will be on the left side of the join will be the table which is - * linked with current instance and the right table is the one which is - * supplied as a parameter to the method. - * @param $options array An associative array that contains join information. - * The available options are: - * * @since 1.8.3 */ - public function select($selectOptions=array( - 'columns'=>[], - 'condition-cols-and-vals'=>[], - 'conditions'=>[], - 'join-operators'=>[], - 'limit'=>-1, - 'offset'=>-1, - 'select-min'=>false, - 'select-max'=>false, - 'column'=>'', - 'rename-to'=>'', - 'order-by'=>null, - 'group-by'=>null, - 'without-select'=>false - )) { + public function select($selectOptions = [ + 'columns' => [], + 'condition-cols-and-vals' => [], + 'conditions' => [], + 'join-operators' => [], + 'limit' => -1, + 'offset' => -1, + 'select-min' => false, + 'select-max' => false, + 'column' => '', + 'rename-to' => '', + 'order-by' => null, + 'group-by' => null, + 'without-select' => false + ]) { $table = $this->getTable(); - if($table instanceof MySQLTable){ + + if ($table instanceof MySQLTable) { $vNum = $table->getMySQLVersion(); $vSplit = explode('.', $vNum); - if(intval($vSplit[0]) <= 5 && intval($vSplit[1]) < 6){ - + + if (intval($vSplit[0]) <= 5 && intval($vSplit[1]) < 6) { } $selectQuery = 'select '; $limit = isset($selectOptions['limit']) ? $selectOptions['limit'] : -1; $offset = isset($selectOptions['offset']) ? $selectOptions['offset'] : -1; - if($limit > 0 && $offset > 0){ + + if ($limit > 0 && $offset > 0) { $limitPart = ' limit '.$limit.' offset '.$offset; - } - else if($limit > 0 && $offset <= 0){ - $limitPart = ' limit '.$limit; - } - else{ - $limitPart = ''; + } else { + if ($limit > 0 && $offset <= 0) { + $limitPart = ' limit '.$limit; + } else { + $limitPart = ''; + } } $groupByPart = ''; - if(isset($selectOptions['group-by']) && gettype($selectOptions['group-by']) == 'array'){ + + if (isset($selectOptions['group-by']) && gettype($selectOptions['group-by']) == 'array') { $groupByPart = $this->_buildGroupByCondition($selectOptions['group-by']); } $orderByPart = ''; - if(isset($selectOptions['order-by']) && gettype($selectOptions['order-by']) == 'array'){ + + if (isset($selectOptions['order-by']) && gettype($selectOptions['order-by']) == 'array') { $orderByPart = $this->_buildOrderByCondition($selectOptions['order-by']); } - if(isset($selectOptions['columns']) && gettype($selectOptions['columns']) == 'array'){ + + if (isset($selectOptions['columns']) && gettype($selectOptions['columns']) == 'array') { $withTablePrefix = isset($selectOptions['table-prefix']) ? $selectOptions['table-prefix'] === true : false; - if($table instanceof JoinTable){ - if($table->getJoinType() == 'join'){ + + if ($table instanceof JoinTable) { + if ($table->getJoinType() == 'join') { $joinStm = 'join'; - } - else{ + } else { $joinStm = $table->getJoinType().' join'; } $completeJoin = $this->_getJoinStm($table, $joinStm); $columnsStr = $this->createColsToSelect($selectOptions['columns'], $withTablePrefix); $selectQuery .= trim($columnsStr,' ').'from '.$completeJoin; - } - else{ + } else { $columnsStr = $this->createColsToSelect($selectOptions['columns'], $withTablePrefix); $selectQuery .= trim($columnsStr).' from '.$this->getTableName(); } - } - else if(isset ($selectOptions['select-max']) && $selectOptions['select-max'] === true){ - $renameTo = isset($selectOptions['rename-to']) ? $selectOptions['rename-to'] : ''; - if(strlen($renameTo) != 0){ - $renameTo = 'as '.$renameTo; - } - else{ - $renameTo = ''; - } - if(isset($selectOptions['column']) && $table->hasColumn($selectOptions['column'])){ - $selectQuery .= 'max('.$this->getColName($selectOptions['column']).') '.$renameTo.' from '.$table->getName(); - $limitPart = ''; - } - else{ - return false; - } - } - else if(isset ($selectOptions['select-min']) && $selectOptions['select-min'] === true){ - $renameTo = isset($selectOptions['rename-to']) ? $selectOptions['rename-to'] : ''; - if(strlen($renameTo) != 0){ - $renameTo = 'as '.$renameTo; - } - else{ - $renameTo = ''; - } - if(isset($selectOptions['column']) && $table->hasColumn($selectOptions['column'])){ - $selectQuery .= 'min('.$this->getColName($selectOptions['column']).') '.$renameTo.' from '.$table->getName(); - $limitPart = ''; - } - else{ - return false; - } - } - else{ - if($table instanceof JoinTable){ - $colsToSelect = $this->createColsToSelect([], true); - if($table->getJoinType() == 'join'){ - $joinStm = 'join'; + } else { + if (isset($selectOptions['select-max']) && $selectOptions['select-max'] === true) { + $renameTo = isset($selectOptions['rename-to']) ? $selectOptions['rename-to'] : ''; + + if (strlen($renameTo) != 0) { + $renameTo = 'as '.$renameTo; + } else { + $renameTo = ''; } - else{ - $joinStm = $table->getJoinType().' join'; + + if (isset($selectOptions['column']) && $table->hasColumn($selectOptions['column'])) { + $selectQuery .= 'max('.$this->getColName($selectOptions['column']).') '.$renameTo.' from '.$table->getName(); + $limitPart = ''; + } else { + return false; + } + } else { + if (isset($selectOptions['select-min']) && $selectOptions['select-min'] === true) { + $renameTo = isset($selectOptions['rename-to']) ? $selectOptions['rename-to'] : ''; + + if (strlen($renameTo) != 0) { + $renameTo = 'as '.$renameTo; + } else { + $renameTo = ''; + } + + if (isset($selectOptions['column']) && $table->hasColumn($selectOptions['column'])) { + $selectQuery .= 'min('.$this->getColName($selectOptions['column']).') '.$renameTo.' from '.$table->getName(); + $limitPart = ''; + } else { + return false; + } + } else { + if ($table instanceof JoinTable) { + $colsToSelect = $this->createColsToSelect([], true); + + if ($table->getJoinType() == 'join') { + $joinStm = 'join'; + } else { + $joinStm = $table->getJoinType().' join'; + } + $selectQuery .= trim($colsToSelect,' ')."from ".$this->_getJoinStm($table, $joinStm); + } else { + $selectQuery .= '* from '.$this->getTableName(); + } } - $selectQuery .= trim($colsToSelect,' ')."from ".$this->_getJoinStm($table, $joinStm); - } - else{ - $selectQuery .= '* from '.$this->getTableName(); } } - if(!isset($selectOptions['condition-cols-and-vals'])){ + + if (!isset($selectOptions['condition-cols-and-vals'])) { $selectOptions['condition-cols-and-vals'] = isset($selectOptions['where']) ? $selectOptions['where'] : []; } $selectOptions['join-operators'] = isset($selectOptions['join-operators']) && - gettype($selectOptions['join-operators']) == 'array' ? $selectOptions['join-operators'] : array(); + gettype($selectOptions['join-operators']) == 'array' ? $selectOptions['join-operators'] : []; $selectOptions['conditions'] = isset($selectOptions['conditions']) && - gettype($selectOptions['conditions']) == 'array' ? $selectOptions['conditions'] : array(); - if(isset($selectOptions['condition-cols-and-vals']) && isset($selectOptions['conditions'])){ + gettype($selectOptions['conditions']) == 'array' ? $selectOptions['conditions'] : []; + + if (isset($selectOptions['condition-cols-and-vals']) && isset($selectOptions['conditions'])) { $cols = []; $vals = []; - foreach($selectOptions['condition-cols-and-vals'] as $valOrColIndex => $colOrVal){ - if($colOrVal instanceof MySQLColumn){ + + foreach ($selectOptions['condition-cols-and-vals'] as $valOrColIndex => $colOrVal) { + if ($colOrVal instanceof MySQLColumn) { $cols[] = $colOrVal; $vals[] = $valOrColIndex; - } - else{ - if(gettype($valOrColIndex) == 'integer'){ + } else { + if (gettype($valOrColIndex) == 'integer') { $testCol = $table->getColByIndex($valOrColIndex); - } - else{ + } else { // if($table instanceof JoinTable){ // $testCol = $table->getJoinCol($valOrColIndex); // } // else{ - $testCol = $table->getCol($valOrColIndex); + $testCol = $table->getCol($valOrColIndex); //} } $cols[] = $testCol; @@ -896,316 +1139,505 @@ public function select($selectOptions=array( $where = $table instanceof JoinTable ? $this->createWhereConditions($cols, $vals, $selectOptions['conditions'], $selectOptions['join-operators'],$table->getName()) : $this->createWhereConditions($cols, $vals, $selectOptions['conditions'], $selectOptions['join-operators']); - } - else{ + } else { $where = ''; } - if(trim($where) == 'where'){ + + if (trim($where) == 'where') { $where = ''; } - if($table instanceof JoinTable){ - if(isset($selectOptions['without-select']) && $selectOptions['without-select'] === true){ + + if ($table instanceof JoinTable) { + if (isset($selectOptions['without-select']) && $selectOptions['without-select'] === true) { $this->setQuery($selectQuery.$where.$groupByPart.$orderByPart.$limitPart, 'select'); - } - else{ + } else { $this->setQuery('select * from ('.$selectQuery.")\nas ".$table->getName().$where.$groupByPart.$orderByPart.$limitPart.';', 'select'); } - } - else{ + } else { $this->setQuery($selectQuery.$where.$groupByPart.$orderByPart.$limitPart.';', 'select'); } $asView = isset($selectOptions['as-view']) ? $selectOptions['as-view'] === true : false; - if($asView === true){ + + if ($asView === true) { $viewName = $this->getTableName(); - if(isset($selectOptions['view-name'])){ + + if (isset($selectOptions['view-name'])) { $trimmed = trim($selectOptions['view-name']); - if(strlen($trimmed) != 0){ + + if (strlen($trimmed) != 0) { $viewName = $trimmed; } } $this->setQuery('create view '.$viewName.' as ('.trim($this->getQuery(),';').');', 'create'); } - if(isset($selectOptions['map-result-to'])){ - if(class_exists($selectOptions['map-result-to'])){ + + if (isset($selectOptions['map-result-to'])) { + if (class_exists($selectOptions['map-result-to'])) { $this->resultMap = $selectOptions['map-result-to']; - } - else{ + } else { $this->resultMap = null; } - } - else{ + } else { $this->resultMap = null; } - foreach ($this->origColsNames as $key => $origName){ + + foreach ($this->origColsNames as $key => $origName) { $this->getCol($key)->setName($origName); } + return true; } + return false; } /** - * Constructs a string which contains columns names that will be selected. - * @param array $colsArr It can be an indexed array which contains columns - * names as specified while creating the linked table. Or it can be an - * associative array. The key should be the name of the column and the value - * is an alias to the column. For example, If the following array is given: - *

- * [ - * 'name','id'=>'user_id','email' - * ] - *

- * And assuming that the column names are the same as given values, - * Then the output will be the following string: - *

- * name, id as user_id, email - *

- * @param boolean $withTablePrefix If set to true, then column name will be - * prefixed with table name. - * @return string - * @since 1.9.0 + * Constructs a query that can be used to select all columns from a table. + * @param int $limit The value of the attribute 'limit' of the select statement. + * If zero or a negative value is given, it will not be ignored. + * Default is -1. + * @param int $offset The value of the attribute 'offset' of the select statement. + * If zero or a negative value is given, it will not be ignored. + * Default is -1. + * @since 1.0 */ - public function createColsToSelect($colsArr,$withTablePrefix){ - $retVal = ''; - $table = $this->getTable(); - if($table instanceof JoinTable && $table->hasCommon()){ - if(count($colsArr) == 0){ - $comma = " \n"; - foreach ($table->getLeftTable()->getColumns() as $colObj){ - if($table->isCommon($colObj->getName())){ - $alias = 'left_'.$colObj->getName(); - $colObj->setAlias($alias); - $asPart = $comma.$colObj->getName(true).' as '.$alias; - } - else{ - $asPart = $comma.$colObj->getName(true); - } - $retVal .= $asPart; - $comma = ",\n"; - } - foreach ($table->getRightTable()->getColumns() as $colObj){ - if($table->isCommon($colObj->getName())){ - $alias = 'right_'.$colObj->getName(); - $colObj->setAlias($alias); - $asPart = $comma.$colObj->getName(true).' as '.$alias; - } - else{ - $asPart = $comma.$colObj->getName(true); - } - $retVal .= $asPart; - } - } - else{ - $comma = " \n"; - if(isset($colsArr['left']) && gettype($colsArr['left']) == 'array'){ - $retVal .= $this->_createColToSelechH1($colsArr['left'], $comma, 'left'); - } - if(isset($colsArr['right']) && gettype($colsArr['right']) == 'array'){ - $retVal .= $this->_createColToSelechH1($colsArr['right'], $comma, 'right'); + public function selectAll($limit = -1,$offset = -1) { + $this->select([ + 'limit' => $limit, + 'offset' => $offset + ]); + } + /** + * Constructs a select query which is used to count number of rows on a + * table. + * @param array $options An associative array of options to customize the + * select query. Available options are: + * + * @since 1.8.9 + */ + public function selectCount($options = []) { + $asPart = ' as count'; + $where = ''; + + if (gettype($options) == 'array') { + if (isset($options['as'])) { + $trimmedAs = trim($options['as']); + + if (strlen($trimmedAs) != 0) { + $asPart = ' as '.str_replace(' ', '_', $trimmedAs); } - $retVal .= $this->_createColToSelechH1($colsArr, $comma); - } - } - else{ - if(count($colsArr) == 0){ - $retVal = '*'; } - else{ - $comma = " \n"; - foreach ($colsArr as $index => $colName){ - if(gettype($index) == 'string'){ - $colObj = $this->getCol($index); - $colObj->setAlias($colName); - $asPart = ' as '.$colName; - } - else{ - $colObj = $this->getCol($colName); - $asPart = ''; - } - if($colObj instanceof MySQLColumn){ - $retVal .= $comma.$colObj->getName($withTablePrefix).$asPart; - $comma = ",\n"; + $options['join-operators'] = isset($options['join-operators']) && + gettype($options['join-operators']) == 'array' ? $options['join-operators'] : []; + $options['conditions'] = isset($options['conditions']) && + gettype($options['conditions']) == 'array' ? $options['conditions'] : []; + + if (isset($options['where']) && isset($options['conditions'])) { + $cols = []; + $vals = []; + + foreach ($options['where'] as $valOrColIndex => $colOrVal) { + if ($colOrVal instanceof MySQLColumn) { + $cols[] = $colOrVal; + $vals[] = $valOrColIndex; + } else { + if (gettype($valOrColIndex) == 'integer') { + $testCol = $this->getStructure()->getColByIndex($valOrColIndex); + } else { + $testCol = $this->getStructure()->getCol($valOrColIndex); + } + $cols[] = $testCol; + $vals[] = $colOrVal; } } + $where = $this->createWhereConditions($cols, $vals, $options['conditions'], $options['join-operators']); + } else { + $where = ''; } - } - return $retVal."\n"; - } - private function _createColToSelechH1($colsArr,&$comma,$leftOrRightOrBoth='both') { - $retVal = ''; - foreach ($colsArr as $index => $colName){ - $colPart = null; - if(gettype($index) == 'string'){ - $colPart = $this->_createColToSelectH2($index, $colName, $leftOrRightOrBoth); - } - else{ - $colPart = $this->_createColToSelectH2($colName, null, $leftOrRightOrBoth); - } - if($colPart !== null){ - $retVal .= $comma.$colPart; - $comma = ",\n"; + + if (trim($where) == 'where') { + $where = ''; } } - return $retVal; + $this->setQuery('select count(*)'.$asPart.' from '.$this->getStructureName().$where.';', 'select'); } /** - * - * @param type $colKey - * @param type $alias - * @param type $leftOrRight - * @return type + * Constructs a query that can be used to select maximum value of a table column. + * @param string $col The name of the column as specified while initializing + * linked table. This value should return an object of type Column + * when passed to the method MySQLQuery::getCol(). + * @param string $rename The new name of the column that contains max value. + * The default value is 'max'. + * @since 1.3 */ - private function _createColToSelectH2($colKey,$alias=null,$leftOrRight='both') { - $table = $this->getTable(); - $left = true; - $asPart = null; - $updateName = false; - $leftTable = $table->getLeftTable(); - $rightTable = $table->getRightTable(); - if($leftOrRight == 'left'){ - $colObj = $leftTable->getCol($colKey); - if(!($colObj instanceof MySQLColumn)){ - $colObj = $table->getCol($colKey); - } + public function selectMax($col,$rename = 'max') { + return $this->select([ + 'column' => $col, + 'select-max' => true, + 'rename-to' => $rename + ]); + } + /** + * Constructs a query that can be used to select minimum value of a table column. + * @param string $col The name of the column as specified while initializing + * linked table. This value should return an object of type Column + * when passed to the method MySQLQuery::getCol(). + * @param string $rename The new name of the column that contains min value. + * The default value is 'min'. + * @since 1.3 + */ + public function selectMin($col,$rename = 'min') { + return $this->select([ + 'column' => $col, + 'select-min' => true, + 'rename-to' => $rename + ]); + } + /** + * Sets the property that is used to check if the query represents an insert + * or an update of a blob datatype. + * The attribute is used to fix an issue with setting the collation + * of the connection while executing a query. + * @param boolean $boolean true if the query represents an insert or an update + * of a blob datatype. false if not. + * @since 1.8.5 + */ + public function setIsBlobInsertOrUpdate($boolean) { + $this->isFileInsert = $boolean === true ? true : false; + } + /** + * Constructs a query which can be used to update the server's global + * variable 'max_allowed_packet'. + * The value of the attribute is in bytes. The developer might want to + * update the value of this variable if he wants to send large data to + * database using one query. The maximum value this attribute can have is + * 1073741824 bytes. + * @param int $size The new size. + * @param string $unit One of 4 values: 'B' for byte, 'KB' for kilobyte, + * 'MB' for megabyte and 'GB' for gigabyte. If the given value is none of the + * 4, the type will be set to 'MP'. + */ + public function setMaxPackete($size,$unit = 'MB') { + $max = 1073741824; + $updatedSize = 0; + $uUnit = strtoupper($unit); + + if ($uUnit != 'MB' && $uUnit != 'B' && $uUnit != 'KB' && $uUnit != 'GB') { + $uUnit = 'MB'; } - else if($leftOrRight == 'right'){ - $left = false; - $colObj = $rightTable->getCol($colKey); - if(!($colObj instanceof MySQLColumn)){ - $colObj = $table->getCol($colKey); + switch ($uUnit) { + case 'B':{ + $updatedSize = $size < $max && $size > 0 ? $size : $max; + break; } - } - else{ - $colObj = $leftTable->getCol($colKey); - if(!($colObj instanceof MySQLColumn)){ - $left = false; - $colObj = $rightTable->getCol($colKey); - if(!($colObj instanceof MySQLColumn) /*&& $alias !== null*/){ - $colObj = $table->getCol($colKey); - if($colObj instanceof MySQLColumn && $colObj->getOwner()->getName() == $leftTable->getName()){ - $left = true; - } - $updateName = true; - } + case 'KB':{ + $new = $size * 1024; + $updatedSize = $new < $max && $new > 0 ? $new : $max; + break; } - } - if($colObj instanceof MySQLColumn){ - if($alias !== null){ -// if($colObj->getAlias() !== null){ -// $asPart = $colObj->getAlias(true).' as '.$alias; -// $colObj->setName($colObj->getAlias()); -// $colObj->setAlias($alias); -// } -// else{ - $asPart = $colObj->getName(true).' as '.$alias; - $colObj->setAlias($alias); - //} - if($updateName){ - $this->origColsNames[$colKey] = $colObj->getName(); - $colObj->setName($alias); - } + case 'MB':{ + $new = $size * 1024 * 1024; + $updatedSize = $new < $max && $new > 0 ? $new : $max; + break; } - else{ - if($this->getTable()->isCommon($colObj->getName())){ - if($left === true){ - $alias = 'left_'.$colObj->getName(); - $colObj->setAlias($alias); - $asPart = $colObj->getName(true).' as '.$alias; - } - else{ - $alias = 'right_'.$colObj->getName(); - $colObj->setAlias($alias); - $asPart = $colObj->getName(true).' as '.$alias; - } - } - else{ - $asPart = $colObj->getName(true); - } + case 'GB':{ + $new = $size * 1024 * 1024 * 1024; + $updatedSize = $new < $max && $new > 0 ? $new : $max; + break; } } - else{ - $asPart = null; - } - return $asPart; + $this->query = 'set global max_allowed_packet = '.$updatedSize.';'; } /** - * - * @param JoinTable $table - * @param string $joinStm - * @return string - * @since 1.9.0 + * Sets the value of the property $query. + * The type of the query must be taken from the array MySQLQuery::Q_TYPES. + * @param string $query a MySQL query. + * @param string $type The type of the query (such as 'select', 'update'). + * @since 1.0 + * @throws Exception If the given query type is not supported. */ - private function _getJoinStm($table,$joinStm){ - $selectQuery = ''; - $lt = $table->getLeftTable(); - $rt = $table->getRightTable(); - $joinCond = $table->getJoinCondition(); - if($lt instanceof JoinTable){ - if($rt instanceof JoinTable){ - - } - else{ - $tempQuery = new MySQLQuery(); - $tempQuery->setTable($lt); - $tempQuery->select([ - 'without-select'=>true - ]); - $selectQuery = '('.$tempQuery->getQuery().') as '.$lt->getName().' '.$joinStm.' '.$rt->getName()."\n".$joinCond; - } - } - else if($rt instanceof JoinTable){ - - } - else{ - $selectQuery = $lt->getName().' '.$joinStm.' '.$rt->getName()."\n".$joinCond; + public function setQuery($query,$type) { + $ltype = strtolower($type.''); + + if (in_array($ltype, self::Q_TYPES)) { + $this->query = $query; + $this->queryType = $ltype; + } else { + throw new Exception('Unsupported query type: \''.$type.'\''); } - return $selectQuery; } /** - * Constructs the 'order by' part of a query. - * @param array $orderByArr An indexed array that contains - * sub associative arrays which has columns 'order by' info. The sub associative - * arrays can have the following indices: + * Sets the name of database (Schema) that the query will be executed on. + * A schema is a collection of tables. On the other hand, a database + * is a collection of schema. In MySQL, the two terms usually refer to the + * same thing. + * @param string $name Database schema name. A valid name + * must have the following conditions: * - * @return string The string that represents order by part. + * @return boolean If the name of the schema is set, the method will return + * true. Other than that, the method will return false. + * @since 1.8.7 */ - private function _buildOrderByCondition($orderByArr){ - $colsCount = count($orderByArr); - $orderByStr = 'order by '; - $actualColsArr = []; - for($x = 0 ; $x < $colsCount ; $x++){ - $colName = isset($orderByArr[$x]['col']) ? $orderByArr[$x]['col'] : null; - $colObj = $this->getCol($colName); - if($colObj instanceof MySQLColumn){ - $orderType = isset($orderByArr[$x]['order-type']) ? strtoupper($orderByArr[$x]['order-type']) : null; - $actualColsArr[] = [ - 'object'=>$colObj, - 'order-type'=>$orderType - ]; + public function setSchemaName($name) { + $nameT = trim($name); + + if (strlen($nameT) != 0) { + $len = strlen($nameT); + + if ($len > 0) { + for ($x = 0 ; $x < $len ; $x++) { + $ch = $nameT[$x]; + + if ($x == 0 && ($ch >= '0' && $ch <= '9')) { + return false; + } + + if ($ch == '_' || ($ch >= 'a' && $ch <= 'z') || ($ch >= 'A' && $ch <= 'Z') || ($ch >= '0' && $ch <= '9')) { + } else { + return false; + } + } + $this->schemaName = $nameT; + $this->getTable()->setSchemaName($nameT); + + return true; } } - $actualCount = count($actualColsArr); - for($x = 0 ; $x < $actualCount ; $x++){ - $colObj = $actualColsArr[$x]['object']; - $orderByStr .= $colObj->getName(); - $orderType = $actualColsArr[$x]['order-type']; - if($orderType == 'A'){ - $orderByStr .= ' asc'; + + return false; + } + /** + * Links a table to the query. + * @param MySQLTable $tableObj The table that will be linked. + * @since 1.9.0 + */ + public function setTable($tableObj) { + if ($tableObj instanceof MySQLTable) { + $this->table = $tableObj; + $this->table->setOwnerQuery($this); + } + } + /** + * Constructs a query that can be used to show some information about something. + * @param string $toShow The thing that will be shown. + * @since 1.4 + */ + public function show($toShow) { + $this->setQuery('show '.$toShow.';', 'show'); + } + /** + * Constructs a query that can be used to show database table engines. + * The result of executing the query will be a table with the following + * columns: + * + * @since 1.8.7 + */ + public function showEngines() { + $this->show('engines'); + } + /** + * Updates a table columns that has a datatype of blob from source files. + * @param array $arr An associative array of keys and values. The keys will + * be acting as the columns names and the values should be a path to a file + * on the host machine. + * @param string $id the ID of the record that will be updated. + * @since 1.2 + */ + public function updateBlobFromFile($arr,$id,$idColName) { + $cols = ''; + $count = count($arr); + $index = 0; + + foreach ($arr as $col => $val) { + $fixedPath = str_replace('\\', '/', $val); + $file = fopen($fixedPath, 'r'); + $data = '\'\''; + + if ($file !== false) { + $fileContent = fread($file, filesize($fixedPath)); + + if ($fileContent !== false) { + $data = '\''.addslashes($fileContent).'\''; + $this->setIsBlobInsertOrUpdate(true); + } } - else if($orderType == 'D'){ - $orderByStr .= ' desc'; + + if ($index + 1 == $count) { + $cols .= $col.' = '.$data; + } else { + $cols .= $col.' = '.$data.', '; } - if($x + 1 != $actualCount){ - $orderByStr .= ', '; + $index++; + } + $this->setQuery('update '.$this->getTableName().' set '.$cols.' where '.$idColName.' = '.$id, 'update'); + } + + /** + * Constructs a query that can be used to update a record. + * @param array $colsAndNewVals An associative array. The key must be the + * new value and the value of the index is an object of type 'Column'. Also, the key + * can be column name or its index in the table that it belongs to and + * the value of the index is the condition value. + * @param array $conditionColsAndVals An associative array that contains columns and + * values for the 'where' clause. The indices can be the values and the + * value at each index can be an object of type 'Column'. Also, the key + * can be column name or its index in the table that it belongs to and + * the value of the index is the condition value. + * The number of elements in this array must match number of elements + * in the array $colsAndNewVals. + * @param array $valsConds An array that can have only the following + * values: '=','!=','>','>=','<' and '<='. The number of elements in this array must match number of + * elements in the array $conditionColsAndVals. If not provided, '=' is used by + * default. Default is empty array. + * @param array $jointOps An array which contains conditional operators + * to join conditions. The operators can be logical or bitwise. Possible + * values include: &&, ||, and, or, |, &, xor. It is optional in case there + * is only one condition. If not provided, 'and' is used. Default is empty array. + * @since 1.8.2 + */ + public function updateRecord($colsAndNewVals,$conditionColsAndVals,$valsConds = [],$jointOps = []) { + $condColsCount = count($conditionColsAndVals); + $condsCount = count($valsConds); + $joinOpsCount = count($jointOps); + + while ($condColsCount > $condsCount) { + $valsConds[] = '='; + $condsCount = count($valsConds); + } + + while (($condColsCount - 1) > $joinOpsCount) { + $jointOps[] = 'and'; + $joinOpsCount = count($jointOps); + } + $defaultCols = $this->getTable()->getDefaultColsKeys(); + $lastUpdatedKey = $defaultCols['last-updated']; + + if ($lastUpdatedKey !== null) { + $lastUpdatedColObj = $this->getCol($lastUpdatedKey); + } else { + $lastUpdatedColObj = null; + } + $colsStr = ''; + $comma = ''; + $index = 0; + $count = count($colsAndNewVals); + + foreach ($colsAndNewVals as $colIndex => $val) { + if ($index + 1 == $count) { + $comma = ''; + } else { + $comma = ','; + } + + if (gettype($colIndex) == 'integer') { + $column = $this->getTable()->getColByIndex($colIndex); + } else { + $column = $this->getTable()->getCol($colIndex); + } + + if ($column instanceof MySQLColumn) { + $colsStr .= $column->getName().' = '; + $type = $column->getType(); + + if ($val !== 'null') { + $cleanedVal = $column->cleanValue($val); + + if ($cleanedVal === null) { + if ($lastUpdatedColObj !== null && $lastUpdatedColObj->getIndex() == $column->getIndex()) { + $colsStr .= $column->cleanValue($column->getDefault()).$comma; + $lastUpdatedColObj = null; + } else { + $colsStr .= 'null'.$comma; + } + } else { + if ($type == 'tinyblob' || $type == 'mediumblob' || $type == 'longblob') { + $fixedPath = str_replace('\\', '/', $colIndex); + + if (file_exists($fixedPath)) { + $file = fopen($fixedPath, 'r'); + $data = ''; + + if ($file !== false) { + $fileContent = fread($file, filesize($fixedPath)); + + if ($fileContent !== false) { + $data = '\''.addslashes($fileContent).'\''; + $colsStr .= $data.$comma; + $this->setIsBlobInsertOrUpdate(true); + } else { + $colsStr .= 'null'.$comma; + } + fclose($file); + } else { + $colsStr .= 'null'.$comma; + } + } else { + $colsStr .= 'null'.$comma; + } + } else { + if ($lastUpdatedColObj !== null && $lastUpdatedColObj->getIndex() == $column->getIndex()) { + $colsStr .= $cleanedVal.$comma; + $lastUpdatedColObj = null; + } else { + $colsStr .= $cleanedVal.$comma; + } + } + } + } else { + $colsStr .= 'null'.$comma; + } } + $index++; } - if($orderByStr == 'order by '){ - return ''; + + if ($lastUpdatedColObj !== null) { + $colsStr .= ','.$lastUpdatedColObj->getName().' = ' + .$lastUpdatedColObj->cleanValue(date('Y-m-d H:i:s')); } - return ' '.trim($orderByStr); + $colsArr = []; + $valsArr = []; + + foreach ($conditionColsAndVals as $valueOrIndex => $colObjOrVal) { + if ($colObjOrVal instanceof MySQLColumn) { + $colsArr[] = $colObjOrVal; + $valsArr[] = $valueOrIndex; + } else { + if (gettype($valueOrIndex) == 'integer') { + $testCol = $this->getTable()->getColByIndex($valueOrIndex); + } else { + $testCol = $this->getTable()->getCol($valueOrIndex); + } + $colsArr[] = $testCol; + $valsArr[] = $colObjOrVal; + } + } + $this->setQuery('update '.$this->getTableName().' set '.$colsStr.$this->createWhereConditions($colsArr, $valsArr, $valsConds, $jointOps).';', 'update'); } /** * Constructs the 'group by' part of a query. @@ -1217,816 +1649,486 @@ private function _buildOrderByCondition($orderByArr){ * * @return string The string that represents order by part. */ - private function _buildGroupByCondition($groupByArr){ + private function _buildGroupByCondition($groupByArr) { $colsCount = count($groupByArr); $groupByStr = 'group by '; $actualColsArr = []; - for($x = 0 ; $x < $colsCount ; $x++){ + + for ($x = 0 ; $x < $colsCount ; $x++) { $colName = isset($groupByArr[$x]['col']) ? $groupByArr[$x]['col'] : null; $colObj = $this->getCol($colName); - if($colObj !== null){ + + if ($colObj !== null) { $actualColsArr[] = [ - 'object'=>$colObj + 'object' => $colObj ]; } } $actualCount = count($actualColsArr); - for($x = 0 ; $x < $actualCount ; $x++){ + + for ($x = 0 ; $x < $actualCount ; $x++) { $colObj = $actualColsArr[$x]['object']; $groupByStr .= $colObj->getName(); - if($x + 1 != $actualCount){ + + if ($x + 1 != $actualCount) { $groupByStr .= ', '; } } - if($groupByStr == 'group by '){ + + if ($groupByStr == 'group by ') { return ''; } + return ' '.trim($groupByStr); } - /** - * Constructs a 'where' condition given a date. - * @param string $date A date or timestamp. - * @param string $colName The name of the column that will contain - * the date value. - * @param string $format The format of the date. The supported formats - * are: + * Constructs the 'order by' part of a query. + * @param array $orderByArr An indexed array that contains + * sub associative arrays which has columns 'order by' info. The sub associative + * arrays can have the following indices: * + * @return string The string that represents order by part. */ - public static function createDateCondition($date,$colName,$format='YYYY-MM-DD HH:MM:SS') { - $formatInUpperCase = strtoupper(trim($format)); - $condition = ''; - if($formatInUpperCase == 'YYYY-MM-DD HH:MM:SS'){ - $dateTimeSplit = explode(' ', $date); - if(count($date) == 2){ - $datePart = explode('-', $dateTimeSplit[0]); - $timePart = explode(':', $dateTimeSplit[0]); - if(count($datePart) == 3 && count($timePart) == 3){ - $condition = 'year('.$colName.') = '.$datePart[0].' and ' - .'month('.$colName.') = '.$datePart[1].' and ' - .'day('.$colName.') = '.$datePart[2].' and ' - .'hour('.$colName.') = '.$datePart[2].' and ' - .'minute('.$colName.') = '.$datePart[2].' and ' - .'second('.$colName.') = '.$datePart[2].' and '; - } - } - } - else if($formatInUpperCase == 'YYYY-MM-DD'){ - $datePart = explode('-', $date); - if(count($datePart) == 3){ - $condition = 'year('.$colName.') = '.$datePart[0].' and ' - .'month('.$colName.') = '.$datePart[1].' and ' - .'day('.$colName.') = '.$datePart[2]; - } - } - else if($formatInUpperCase == 'YYYY'){ - $asInt = intval($date); - if($asInt > 1900 && $asInt < 10000){ - $condition = 'year('.$colName.') = '.$date; - } - } - else if($formatInUpperCase == 'MM'){ - $asInt = intval($date); - if($asInt > 0 && $asInt < 13){ - $condition = 'month('.$colName.') = '.$date; + private function _buildOrderByCondition($orderByArr) { + $colsCount = count($orderByArr); + $orderByStr = 'order by '; + $actualColsArr = []; + + for ($x = 0 ; $x < $colsCount ; $x++) { + $colName = isset($orderByArr[$x]['col']) ? $orderByArr[$x]['col'] : null; + $colObj = $this->getCol($colName); + + if ($colObj instanceof MySQLColumn) { + $orderType = isset($orderByArr[$x]['order-type']) ? strtoupper($orderByArr[$x]['order-type']) : null; + $actualColsArr[] = [ + 'object' => $colObj, + 'order-type' => $orderType + ]; } } - else if($formatInUpperCase == 'DD'){ - $asInt = intval($date); - if($asInt > 0 && $asInt < 32){ - $condition = 'day('.$colName.') = '.$date; + $actualCount = count($actualColsArr); + + for ($x = 0 ; $x < $actualCount ; $x++) { + $colObj = $actualColsArr[$x]['object']; + $orderByStr .= $colObj->getName(); + $orderType = $actualColsArr[$x]['order-type']; + + if ($orderType == 'A') { + $orderByStr .= ' asc'; + } else { + if ($orderType == 'D') { + $orderByStr .= ' desc'; + } } - } - else if($formatInUpperCase == 'HH:MM:SS'){ - $datePart = explode(':', $date); - if(count($datePart) == 3){ - $condition = 'hour('.$colName.') = '.$datePart[0].' and ' - .'minute('.$colName.') = '.$datePart[1].' and ' - .'second('.$colName.') = '.$datePart[2]; + + if ($x + 1 != $actualCount) { + $orderByStr .= ', '; } } - else if($formatInUpperCase == 'HH'){ - $asInt = intval($date); - if($asInt > 0 && $asInt < 24){ - $condition = 'hour('.$colName.') = '.$date; - } + + if ($orderByStr == 'order by ') { + return ''; } - else if($formatInUpperCase == 'SS'){ - $asInt = intval($date); - if($asInt > 0 && $asInt < 60){ - $condition = 'second('.$colName.') = '.$date; + + return ' '.trim($orderByStr); + } + private function _createColToSelechH1($colsArr,&$comma,$leftOrRightOrBoth = 'both') { + $retVal = ''; + + foreach ($colsArr as $index => $colName) { + $colPart = null; + + if (gettype($index) == 'string') { + $colPart = $this->_createColToSelectH2($index, $colName, $leftOrRightOrBoth); + } else { + $colPart = $this->_createColToSelectH2($colName, null, $leftOrRightOrBoth); } - } - else if($formatInUpperCase == 'MM'){ - $asInt = intval($date); - if($asInt > 0 && $asInt < 59){ - $condition = 'minute('.$colName.') = '.$date; + + if ($colPart !== null) { + $retVal .= $comma.$colPart; + $comma = ",\n"; } } - return $condition; - } - private function _selectIn($optionsArr){ - + + return $retVal; } /** - * Constructs a query that can be used to insert a new record. - * @param array $colsAndVals An associative array. The indices must be - * columns names taken from the linked table. For example, if we have - * a table which has two columns with names 'student-id' and 'registered-course', - * then the array would look like the following: - *

- * [
- *   'student-id'=>55
- *   'registered-course'=>542
]
- *

- * Note that it is possible for the index to be a numeric value such as 0 - * or 1. The numeric value will represents column position in the table. - * Another thing to note is that if a column does not have a value, either - * the default value of the column will be used or 'null' will be used. - * @since 1.8.2 + * + * @param type $colKey + * @param type $alias + * @param type $leftOrRight + * @return type */ - public function insertRecord($colsAndVals) { - $cols = ''; - $vals = ''; - $count = count($colsAndVals); - $index = 0; - $comma = ''; - $columnsWithVals = []; - $defaultCols = $this->getTable()->getDefaultColsKeys(); - $createdOnKey = $defaultCols['created-on']; - if($createdOnKey !== null){ - $createdOnColObj = $this->getCol($createdOnKey); - } - else{ - $createdOnColObj = null; + private function _createColToSelectH2($colKey,$alias = null,$leftOrRight = 'both') { + $table = $this->getTable(); + $left = true; + $asPart = null; + $updateName = false; + $leftTable = $table->getLeftTable(); + $rightTable = $table->getRightTable(); + + if ($leftOrRight == 'left') { + $colObj = $leftTable->getCol($colKey); + + if (!($colObj instanceof MySQLColumn)) { + $colObj = $table->getCol($colKey); + } + } else { + if ($leftOrRight == 'right') { + $left = false; + $colObj = $rightTable->getCol($colKey); + + if (!($colObj instanceof MySQLColumn)) { + $colObj = $table->getCol($colKey); + } + } else { + $colObj = $leftTable->getCol($colKey); + + if (!($colObj instanceof MySQLColumn)) { + $left = false; + $colObj = $rightTable->getCol($colKey); + + if (!($colObj instanceof MySQLColumn) /*&& $alias !== null*/) { + $colObj = $table->getCol($colKey); + + if ($colObj instanceof MySQLColumn && $colObj->getOwner()->getName() == $leftTable->getName()) { + $left = true; + } + $updateName = true; + } + } + } } - foreach($colsAndVals as $colIndex=>$val){ - if($index + 1 == $count){ - $comma = ''; + + if ($colObj instanceof MySQLColumn) { + if ($alias !== null) { +// if($colObj->getAlias() !== null){ +// $asPart = $colObj->getAlias(true).' as '.$alias; +// $colObj->setName($colObj->getAlias()); +// $colObj->setAlias($alias); +// } +// else{ + $asPart = $colObj->getName(true).' as '.$alias; + $colObj->setAlias($alias); + //} + if ($updateName) { + $this->origColsNames[$colKey] = $colObj->getName(); + $colObj->setName($alias); + } + } else { + if ($this->getTable()->isCommon($colObj->getName())) { + if ($left === true) { + $alias = 'left_'.$colObj->getName(); + $colObj->setAlias($alias); + $asPart = $colObj->getName(true).' as '.$alias; + } else { + $alias = 'right_'.$colObj->getName(); + $colObj->setAlias($alias); + $asPart = $colObj->getName(true).' as '.$alias; + } + } else { + $asPart = $colObj->getName(true); + } } - else{ - $comma = ','; + } else { + $asPart = null; + } + + return $asPart; + } + /** + * Constructs a query that can be used to create a new table. + * @param MySQLTable $table an instance of MySQLTable. + * @param boolean $inclSqlComments If set to true, a set of comment will appear + * in the generated SQL which description what is happening in every SQL Statement. + * @since 1.4 + */ + private function _createTable($table,$inclSqlComments = false) { + if ($table instanceof MySQLTable) { + $query = ''; + + if ($inclSqlComments === true) { + $query .= '-- Structure of the table \''.$this->getStructureName().'\''.self::NL; + $query .= '-- Number of columns: \''.count($this->getStructure()->columns()).'\''.self::NL; + $query .= '-- Number of forign keys count: \''.count($this->getStructure()->forignKeys()).'\''.self::NL; + $query .= '-- Number of primary key columns count: \''.$this->getStructure()->primaryKeyColsCount().'\''.self::NL; } - if(gettype($colIndex) == 'integer'){ - $column = $this->getTable()->getColByIndex($colIndex); + $query .= 'create table if not exists '.$table->getName().'('.self::NL; + $keys = $table->colsKeys(); + $count = count($keys); + + for ($x = 0 ; $x < $count ; $x++) { + if ($x + 1 == $count) { + $query .= ' '.$table->columns()[$keys[$x]].self::NL; + } else { + $query .= ' '.$table->columns()[$keys[$x]].','.self::NL; + } } - else{ - $column = $this->getTable()->getCol($colIndex); + $query .= ')'.self::NL; + $comment = $table->getComment(); + + if ($comment !== null) { + $query .= 'comment \''.$comment.'\''.self::NL; } - if($column instanceof MySQLColumn){ - $columnsWithVals[] = $colIndex; - $cols .= $column->getName().$comma; - $type = $column->getType(); - if($val !== 'null'){ - $cleanedVal = $column->cleanValue($val); - if($cleanedVal === null){ - if($createdOnColObj !== null && $createdOnColObj->getIndex() == $column->getIndex()){ - $vals .= $column->cleanValue($column->getDefault()).$comma; - $createdOnColObj = null; - } - else{ - $vals .= 'null'.$comma; - } - } - else{ - if($type == 'tinyblob' || $type == 'mediumblob' || $type == 'longblob'){ - $fixedPath = str_replace('\\', '/', $val); - if(file_exists($fixedPath)){ - $file = fopen($fixedPath, 'r'); - $data = ''; - if($file !== false){ - $fileContent = fread($file, filesize($fixedPath)); - if($fileContent !== false){ - $data = '\''. addslashes($fileContent).'\''; - $vals .= $data.$comma; - $this->setIsBlobInsertOrUpdate(true); - } - else{ - $vals .= 'null'.$comma; - } - fclose($file); - } - else{ - $vals .= 'null'.$comma; - } - } - else{ - $vals .= 'null'.$comma; - } - } - else{ - if($createdOnColObj !== null && $createdOnColObj->getIndex() == $column->getIndex()){ - $vals .= $cleanedVal.$comma; - $createdOnColObj = null; - } - else{ - $vals .= $cleanedVal.$comma; - } - } - } + $query .= 'ENGINE = '.$table->getEngine().self::NL; + $query .= 'DEFAULT CHARSET = '.$table->getCharSet().self::NL; + $query .= 'collate = '.$table->getCollation().';'.self::NL; + $coutPk = $this->getStructure()->primaryKeyColsCount(); + + if ($coutPk >= 1) { + if ($inclSqlComments === true) { + $query .= '-- Add Primary key to the table.'.self::NL; } - else{ - $vals .= 'null'.$comma; + $this->addPrimaryKey($table); + $q = $this->getQuery(); + + if (strlen($q) != 0) { + //no need to append ';\n' as it was added before. + $query .= $q; } } - $index++; + //add forign keys + $count2 = count($table->forignKeys()); + + if ($inclSqlComments === true && $count2 != 0) { + $query .= '-- Add Forign keys to the table.'.self::NL; + } + + for ($x = 0 ; $x < $count2 ; $x++) { + $this->addForeignKey($table->forignKeys()[$x]); + $query .= $this->getQuery().';'.self::NL; + } + + if ($inclSqlComments === true) { + $query .= '-- End of the Structure of the table \''.$this->getStructureName().'\''.self::NL; + } + $this->setQuery($query, 'create'); } - if($createdOnColObj !== null){ - $cols .= ','.$createdOnColObj->getName(); - if($createdOnColObj->getDefault() == 'now()' || $createdOnColObj->getDefault() == 'current_timestamp'){ - $vals .= ",'".date('Y-m-d H:i:s')."'"; + } + /** + * + * @param JoinTable $table + * @param string $joinStm + * @return string + * @since 1.9.0 + */ + private function _getJoinStm($table,$joinStm) { + $selectQuery = ''; + $lt = $table->getLeftTable(); + $rt = $table->getRightTable(); + $joinCond = $table->getJoinCondition(); + + if ($lt instanceof JoinTable) { + if ($rt instanceof JoinTable) { + } else { + $tempQuery = new MySQLQuery(); + $tempQuery->setTable($lt); + $tempQuery->select([ + 'without-select' => true + ]); + $selectQuery = '('.$tempQuery->getQuery().') as '.$lt->getName().' '.$joinStm.' '.$rt->getName()."\n".$joinCond; } - else{ - $vals .= ','.$createdOnColObj->cleanValue($createdOnColObj->getDefault()); + } else { + if ($rt instanceof JoinTable) { + } else { + $selectQuery = $lt->getName().' '.$joinStm.' '.$rt->getName()."\n".$joinCond; } } - - $cols = ' ('.$cols.')'; - $vals = ' ('.$vals.')'; - $this->setQuery(self::INSERT.$this->getTableName().$cols.' values'.$vals.';', 'insert'); + + return $selectQuery; + } + private function _selectIn($optionsArr) { } /** - * Removes a record from the table. - * @param array $columnsAndVals An associative array. The indices of the array - * should be the values of the columns and the value at each index is - * an object of type 'Column'. - * @param array $valsConds An array that can have one of the following - * values: '=','!=','<','<=','>' and '>='. The number of elements - * in this array must match number of - * elements in the array $cols. If not provided, '=' is used. Default is empty array. + * A method that is used to create the 'where' part of any query in case + * of multiple columns. + * @param array $cols An array that holds an objects of type 'Column'. + * @param array $vals An array that contains columns values. The number of + * elements in this array must match number of elements in the array $cols. + * @param array $valsConds An array that can have only two possible values, + * '=' and '!='. The number of elements in this array must match number of + * elements in the array $cols. * @param array $jointOps An array which contains conditional operators * to join conditions. The operators can be logical or bitwise. Possible - * values include: &&, ||, and, or, |, &, xor. If not provided, - * 'and' is used for all values. + * values include: &&, ||, and, or, |, &, xor. + * @param string $tablePrefix An optional string that represents table prefix. + * @return string A string that represents the 'where' part of the query. * @since 1.8.2 */ - public function deleteRecord($columnsAndVals,$valsConds=[],$jointOps=[]) { - $colsCount = count($columnsAndVals); + private function createWhereConditions($cols,$vals,$valsConds,$jointOps,$tablePrefix = null) { + if ($tablePrefix !== null) { + $tablePrefix = trim($tablePrefix).'.'; + } + $colsCount = count($cols); + $valsCount = count($vals); $condsCount = count($valsConds); $joinOpsCount = count($jointOps); - while ($colsCount > $condsCount){ - $valsConds[] = '='; - $condsCount = count($valsConds); - } - while (($colsCount - 1) > $joinOpsCount){ - $jointOps[] = 'and'; - $joinOpsCount = count($jointOps); - } - $cols = []; - $vals = []; - foreach ($columnsAndVals as $valOrIndex => $colObjOrVal){ - if($colObjOrVal instanceof MySQLColumn){ - $cols[] = $colObjOrVal; - $vals[] = $valOrIndex; - } - else{ - if(gettype($valOrIndex) == 'integer'){ - $testCol = $this->getTable()->getColByIndex($valOrIndex); - } - else{ - $testCol = $this->getTable()->getCol($valOrIndex); - } - $cols[] = $testCol; - $vals[] = $colObjOrVal; - } - } - $query = 'delete from '.$this->getTableName(); - $this->setQuery($query.$this->createWhereConditions($cols, $vals, $valsConds, $jointOps).';', 'delete'); - } - /** - * A method that is used to create the 'where' part of any query in case - * of multiple columns. - * @param array $cols An array that holds an objects of type 'Column'. - * @param array $vals An array that contains columns values. The number of - * elements in this array must match number of elements in the array $cols. - * @param array $valsConds An array that can have only two possible values, - * '=' and '!='. The number of elements in this array must match number of - * elements in the array $cols. - * @param array $jointOps An array which contains conditional operators - * to join conditions. The operators can be logical or bitwise. Possible - * values include: &&, ||, and, or, |, &, xor. - * @param string $tablePrefix An optional string that represents table prefix. - * @return string A string that represents the 'where' part of the query. - * @since 1.8.2 - */ - private function createWhereConditions($cols,$vals,$valsConds,$jointOps,$tablePrefix=null){ - if($tablePrefix !== null){ - $tablePrefix = trim($tablePrefix).'.'; - } - $colsCount = count($cols); - $valsCount = count($vals); - $condsCount = count($valsConds); - $joinOpsCount = count($jointOps); - if($colsCount == 0 || $valsCount == 0){ + + if ($colsCount == 0 || $valsCount == 0) { return ''; } - while ($colsCount > $condsCount){ + + while ($colsCount > $condsCount) { $valsConds[] = '='; $condsCount = count($valsConds); } - while (($colsCount - 1) > $joinOpsCount){ + + while (($colsCount - 1) > $joinOpsCount) { $jointOps[] = 'and'; $joinOpsCount = count($jointOps); } - if($colsCount != $valsCount || $colsCount != $condsCount || ($colsCount - 1) != $joinOpsCount){ + + if ($colsCount != $valsCount || $colsCount != $condsCount || ($colsCount - 1) != $joinOpsCount) { return ''; } $index = 0; $where = ' where '; $supportedConds = ['=','!=','<','<=','>','>=']; - foreach ($cols as $col){ + + foreach ($cols as $col) { //first, check given condition $equalityCond = trim($valsConds[$index]); - if(!in_array($equalityCond, $supportedConds)){ + + if (!in_array($equalityCond, $supportedConds)) { $equalityCond = '='; } //then check if column object is given - if($col instanceof MySQLColumn){ + if ($col instanceof MySQLColumn) { //then check value - if(gettype($vals[$index]) != 'array'){ + if (gettype($vals[$index]) != 'array') { $cleanVal = $col->cleanValue($vals[$index]); $valLower = strtolower(trim($vals[$index])); - } - else{ + } else { $val = isset($vals[$index]['values']) ? $vals[$index]['values'] : null; - if(gettype($val) == 'array'){ + + if (gettype($val) == 'array') { $cleanVal = $col->cleanValue($val); $valLower = gettype($vals[$index]) != 'array' ? strtolower(trim($vals[$index])) : ''; - } - else{ + } else { continue; } } - if($col->getAlias() != null){ + + if ($col->getAlias() != null) { $colName = $tablePrefix.$col->getAlias(); - } - else{ + } else { $colName = $tablePrefix.$col->getName(); } - if($valLower == 'is null' || $valLower == 'is not null'){ + + if ($valLower == 'is null' || $valLower == 'is not null') { $where .= $colName.' '.$valLower.' '; - } - else if($cleanVal === null){ - if($equalityCond == '='){ - $where .= $colName.' is null '; - } - else{ - $where .= $colName.' is not null '; - } - } - else{ - if($col->getType() == 'datetime' || $col->getType() == 'timestamp'){ - if($equalityCond == '='){ - $where .= $colName.' >= '.$cleanVal.' '; - $cleanVal = $col->cleanValue($vals[$index],true); - $where .= 'and '.$colName.' <= '.$cleanVal.' '; + } else { + if ($cleanVal === null) { + if ($equalityCond == '=') { + $where .= $colName.' is null '; + } else { + $where .= $colName.' is not null '; } - else if($equalityCond == '!='){ - $where .= $colName.' < '.$cleanVal.' '; - $cleanVal = $col->cleanValue($vals[$index],true); - $where .= 'and '.$colName.' > '.$cleanVal.' '; - } - else if($equalityCond == '>='){ - $where .= $colName.' >= '.$cleanVal.' '; - $cleanVal = $col->cleanValue($vals[$index],true); - } - else if($equalityCond == '<='){ - $cleanVal = $col->cleanValue($vals[$index],true); - $where .= $colName.' <= '.$cleanVal.' '; - } - else if($equalityCond == '>'){ - $cleanVal = $col->cleanValue($vals[$index],true); - $where .= $colName.' > '.$cleanVal.' '; - } - else if($equalityCond == '<'){ - $where .= $colName.' < '.$cleanVal.' '; - } - } - else if(gettype($vals[$index]) == 'array'){ - $conditions = isset($vals[$index]['conditions']) ? $vals[$index]['conditions'] : []; - $joinConditions = isset($vals[$index]['join-operators']) ? $vals[$index]['join-operators'] : []; - $where .= '('; - if(gettype($conditions) == 'array'){ - $condIndex = 0; - while(count($conditions) < count($cleanVal)){ - $conditions[] = '='; - } - while(count($joinConditions) < count($cleanVal)){ - $joinConditions[] = 'and'; - } - foreach ($cleanVal as $singleVal){ - $cond = $conditions[$condIndex]; - if(!in_array($cond, $supportedConds)){ - $cond = '='; - } - if($condIndex > 0){ - $joinCond = $joinConditions[$condIndex - 1]; - if($joinCond == 'and' || $joinCond == 'or'){ - + } else { + if ($col->getType() == 'datetime' || $col->getType() == 'timestamp') { + if ($equalityCond == '=') { + $where .= $colName.' >= '.$cleanVal.' '; + $cleanVal = $col->cleanValue($vals[$index],true); + $where .= 'and '.$colName.' <= '.$cleanVal.' '; + } else { + if ($equalityCond == '!=') { + $where .= $colName.' < '.$cleanVal.' '; + $cleanVal = $col->cleanValue($vals[$index],true); + $where .= 'and '.$colName.' > '.$cleanVal.' '; + } else { + if ($equalityCond == '>=') { + $where .= $colName.' >= '.$cleanVal.' '; + $cleanVal = $col->cleanValue($vals[$index],true); + } else { + if ($equalityCond == '<=') { + $cleanVal = $col->cleanValue($vals[$index],true); + $where .= $colName.' <= '.$cleanVal.' '; + } else { + if ($equalityCond == '>') { + $cleanVal = $col->cleanValue($vals[$index],true); + $where .= $colName.' > '.$cleanVal.' '; + } else { + if ($equalityCond == '<') { + $where .= $colName.' < '.$cleanVal.' '; + } + } + } } - else{ - $joinCond = 'and'; - } - $where .= $joinCond.' '.$colName.' '.$cond.' '.$singleVal.' '; - } - else{ - $where .= $colName.' '.$cond.' '.$singleVal.' '; } - $condIndex++; } - - } - else{ - $lCond = strtolower(trim($conditions)); - if($lCond == 'in' || $lCond == 'not in'){ - $inCond = $lCond.'('; - for($x = 0 ; $x < count($cleanVal) ; $x++){ - if($x + 1 == count($cleanVal)){ - $inCond .= $cleanVal[$x]; + } else { + if (gettype($vals[$index]) == 'array') { + $conditions = isset($vals[$index]['conditions']) ? $vals[$index]['conditions'] : []; + $joinConditions = isset($vals[$index]['join-operators']) ? $vals[$index]['join-operators'] : []; + $where .= '('; + + if (gettype($conditions) == 'array') { + $condIndex = 0; + + while (count($conditions) < count($cleanVal)) { + $conditions[] = '='; } - else{ - $inCond .= $cleanVal[$x].','; + + while (count($joinConditions) < count($cleanVal)) { + $joinConditions[] = 'and'; } - } - $where .= $colName.' '.$inCond.')'; - } - else{ - - } - } - $where = trim($where).')'; - } - else{ - $where .= $colName.' '.$equalityCond.' '.$cleanVal.' '; - } - } - if($index + 1 != $colsCount){ - $where .= $jointOps[$index].' '; - } - } - $index++; - } - return ' '.trim($where); - } - - /** - * Constructs a query that can be used to update a record. - * @param array $colsAndNewVals An associative array. The key must be the - * new value and the value of the index is an object of type 'Column'. Also, the key - * can be column name or its index in the table that it belongs to and - * the value of the index is the condition value. - * @param array $conditionColsAndVals An associative array that contains columns and - * values for the 'where' clause. The indices can be the values and the - * value at each index can be an object of type 'Column'. Also, the key - * can be column name or its index in the table that it belongs to and - * the value of the index is the condition value. - * The number of elements in this array must match number of elements - * in the array $colsAndNewVals. - * @param array $valsConds An array that can have only the following - * values: '=','!=','>','>=','<' and '<='. The number of elements in this array must match number of - * elements in the array $conditionColsAndVals. If not provided, '=' is used by - * default. Default is empty array. - * @param array $jointOps An array which contains conditional operators - * to join conditions. The operators can be logical or bitwise. Possible - * values include: &&, ||, and, or, |, &, xor. It is optional in case there - * is only one condition. If not provided, 'and' is used. Default is empty array. - * @since 1.8.2 - */ - public function updateRecord($colsAndNewVals,$conditionColsAndVals,$valsConds=[],$jointOps=[]) { - $condColsCount = count($conditionColsAndVals); - $condsCount = count($valsConds); - $joinOpsCount = count($jointOps); - while ($condColsCount > $condsCount){ - $valsConds[] = '='; - $condsCount = count($valsConds); - } - while (($condColsCount - 1) > $joinOpsCount){ - $jointOps[] = 'and'; - $joinOpsCount = count($jointOps); - } - $defaultCols = $this->getTable()->getDefaultColsKeys(); - $lastUpdatedKey = $defaultCols['last-updated']; - if($lastUpdatedKey !== null){ - $lastUpdatedColObj = $this->getCol($lastUpdatedKey); - } - else{ - $lastUpdatedColObj = null; - } - $colsStr = ''; - $comma = ''; - $index = 0; - $count = count($colsAndNewVals); - foreach($colsAndNewVals as $colIndex=>$val){ - if($index + 1 == $count){ - $comma = ''; - } - else{ - $comma = ','; - } - if(gettype($colIndex) == 'integer'){ - $column = $this->getTable()->getColByIndex($colIndex); - } - else{ - $column = $this->getTable()->getCol($colIndex); - } - if($column instanceof MySQLColumn){ - $colsStr .= $column->getName().' = '; - $type = $column->getType(); - if($val !== 'null'){ - $cleanedVal = $column->cleanValue($val); - if($cleanedVal === null){ - if($lastUpdatedColObj !== null && $lastUpdatedColObj->getIndex() == $column->getIndex()){ - $colsStr .= $column->cleanValue($column->getDefault()).$comma; - $lastUpdatedColObj = null; - } - else{ - $colsStr .= 'null'.$comma; - } - } - else{ - if($type == 'tinyblob' || $type == 'mediumblob' || $type == 'longblob'){ - $fixedPath = str_replace('\\', '/', $colIndex); - if(file_exists($fixedPath)){ - $file = fopen($fixedPath, 'r'); - $data = ''; - if($file !== false){ - $fileContent = fread($file, filesize($fixedPath)); - if($fileContent !== false){ - $data = '\''. addslashes($fileContent).'\''; - $colsStr .= $data.$comma; - $this->setIsBlobInsertOrUpdate(true); + + foreach ($cleanVal as $singleVal) { + $cond = $conditions[$condIndex]; + + if (!in_array($cond, $supportedConds)) { + $cond = '='; + } + + if ($condIndex > 0) { + $joinCond = $joinConditions[$condIndex - 1]; + + if ($joinCond == 'and' || $joinCond == 'or') { + } else { + $joinCond = 'and'; + } + $where .= $joinCond.' '.$colName.' '.$cond.' '.$singleVal.' '; + } else { + $where .= $colName.' '.$cond.' '.$singleVal.' '; + } + $condIndex++; } - else{ - $colsStr .= 'null'.$comma; + } else { + $lCond = strtolower(trim($conditions)); + + if ($lCond == 'in' || $lCond == 'not in') { + $inCond = $lCond.'('; + + for ($x = 0 ; $x < count($cleanVal) ; $x++) { + if ($x + 1 == count($cleanVal)) { + $inCond .= $cleanVal[$x]; + } else { + $inCond .= $cleanVal[$x].','; + } + } + $where .= $colName.' '.$inCond.')'; + } else { } - fclose($file); - } - else{ - $colsStr .= 'null'.$comma; } - } - else{ - $colsStr .= 'null'.$comma; - } - } - else{ - if($lastUpdatedColObj !== null && $lastUpdatedColObj->getIndex() == $column->getIndex()){ - $colsStr .= $cleanedVal.$comma; - $lastUpdatedColObj = null; - } - else{ - $colsStr .= $cleanedVal.$comma; + $where = trim($where).')'; + } else { + $where .= $colName.' '.$equalityCond.' '.$cleanVal.' '; } } } } - else{ - $colsStr .= 'null'.$comma; - } - } - $index++; - } - if($lastUpdatedColObj !== null){ - $colsStr .= ','.$lastUpdatedColObj->getName().' = ' - .$lastUpdatedColObj->cleanValue(date('Y-m-d H:i:s')); - } - $colsArr = []; - $valsArr = []; - foreach ($conditionColsAndVals as $valueOrIndex=>$colObjOrVal){ - if($colObjOrVal instanceof MySQLColumn){ - $colsArr[] = $colObjOrVal; - $valsArr[] = $valueOrIndex; - } - else{ - if(gettype($valueOrIndex) == 'integer'){ - $testCol = $this->getTable()->getColByIndex($valueOrIndex); - } - else{ - $testCol = $this->getTable()->getCol($valueOrIndex); - } - $colsArr[] = $testCol; - $valsArr[] = $colObjOrVal; - } - } - $this->setQuery('update '.$this->getTableName().' set '.$colsStr.$this->createWhereConditions($colsArr, $valsArr, $valsConds, $jointOps).';', 'update'); - } - /** - * Checks if the query represents a blob insert or update. - * The aim of this method is to fix an issue with setting the collation - * of the connection while executing a query. - * @return boolean The Function will return true if the query represents an - * insert or un update of blob datatype. false if not. - * @since 1.8.5 - */ - public function isBlobInsertOrUpdate(){ - return $this->isFileInsert; - } - /** - * Sets the property that is used to check if the query represents an insert - * or an update of a blob datatype. - * The attribute is used to fix an issue with setting the collation - * of the connection while executing a query. - * @param boolean $boolean true if the query represents an insert or an update - * of a blob datatype. false if not. - * @since 1.8.5 - */ - public function setIsBlobInsertOrUpdate($boolean) { - $this->isFileInsert = $boolean === true ? true : false; - } - /** - * Updates a table columns that has a datatype of blob from source files. - * @param array $arr An associative array of keys and values. The keys will - * be acting as the columns names and the values should be a path to a file - * on the host machine. - * @param string $id the ID of the record that will be updated. - * @since 1.2 - */ - public function updateBlobFromFile($arr,$id,$idColName){ - $cols = ''; - $count = count($arr); - $index = 0; - foreach($arr as $col => $val){ - $fixedPath = str_replace('\\', '/', $val); - $file = fopen($fixedPath, 'r'); - $data = '\'\''; - if($file !== false){ - $fileContent = fread($file, filesize($fixedPath)); - if($fileContent !== false){ - $data = '\''. addslashes($fileContent).'\''; - $this->setIsBlobInsertOrUpdate(true); + + if ($index + 1 != $colsCount) { + $where .= $jointOps[$index].' '; } } - if($index + 1 == $count){ - $cols .= $col.' = '.$data; - } - else{ - $cols .= $col.' = '.$data.', '; - } $index++; } - $this->setQuery('update '.$this->getTableName().' set '.$cols.' where '.$idColName.' = '.$id, 'update'); - } - /** - * Constructs a query that can be used to select maximum value of a table column. - * @param string $col The name of the column as specified while initializing - * linked table. This value should return an object of type Column - * when passed to the method MySQLQuery::getCol(). - * @param string $rename The new name of the column that contains max value. - * The default value is 'max'. - * @since 1.3 - */ - public function selectMax($col,$rename='max'){ - return $this->select(array( - 'column'=> $col, - 'select-max'=>true, - 'rename-to'=>$rename - )); - } - /** - * Constructs a query that can be used to select minimum value of a table column. - * @param string $col The name of the column as specified while initializing - * linked table. This value should return an object of type Column - * when passed to the method MySQLQuery::getCol(). - * @param string $rename The new name of the column that contains min value. - * The default value is 'min'. - * @since 1.3 - */ - public function selectMin($col,$rename='min'){ - return $this->select(array( - 'column'=>$col, - 'select-min'=>true, - 'rename-to'=>$rename - )); - } - /** - * Constructs a query that can be used to create the table which is linked - * with the query class. - * @param boolean $inclComments If set to true, the generated MySQL - * query will have basic comments explaining the structure. - * @return boolean Once the query is structured, the method will return - * true. If the query is not created, the method will return false. - * @deprecated since version 1.9.0 - * @since 1.5 - */ - public function createStructure($inclComments=false){ - $t = $this->getTable(); - if($t instanceof MySQLTable){ - $this->_createTable($t,$inclComments); - return true; - } - return false; - } - /** - * Constructs a query that can be used to create the table which is linked - * with the query class. - * @param boolean $withComments If set to true, the generated MySQL - * query will have basic comments explaining the structure. - * @since 1.9.0 - */ - public function createTable($withComments=false) { - $this->createStructure($withComments); - } - /** - * Returns the name of the column from the table given its key. - * @param string $colKey The name of the column key. - * @return string The name of the column in the table. If no column was - * found, the method will return the string MySQLTable::NO_SUCH_COL. If there is - * no table linked with the query object, the method will return the - * string MySQLQuery::NO_STRUCTURE. - * @since 1.5 - */ - public function getColName($colKey){ - $col = $this->getCol($colKey); - if($col instanceof MySQLColumn){ - return $col->getName(); - } - return $col; - } - /** - * Returns a column from the table given its key. - * @param string $colKey The name of the column key. - * @return string|MySQLColumn The the column in the table. If no column was - * found, the method will return the string 'MySQLTable::NO_SUCH_COL'. If there is - * no table linked with the query object, the method will return the - * string MySQLQuery::NO_STRUCTURE. - * @since 1.6 - */ - public function getCol($colKey){ - $structure = $this->getStructure(); - $retVal = self::NO_STRUCTURE; - if($structure instanceof MySQLTable){ - $col = $structure->getCol($colKey); - if($col instanceof MySQLColumn){ - return $col; - } - $retVal = MySQLTable::NO_SUCH_COL; - } - return $retVal; - } - /** - * Returns the index of a column given its key. - * @param string $colKey The name of the column key. - * @return int The index of the column if found starting from 0. - * If the column was not found, the method will return -1. - * @since 1.8.4 - */ - public function getColIndex($colKey){ - $col = $this->getCol($colKey); - $index = $col instanceof MySQLColumn ? $col->getIndex() : -1; - return $index; - } - /** - * Returns the table that is used for constructing queries. - * @return MySQLTable The table that is used for constructing queries. - * @since 1.5 - * @deprecated since version 1.9.0 Use MySQLQuery::getTable() instead. - */ - public function getStructure(){ - return $this->table; - } - /** - * Returns the name of the table that is used to construct queries. - * @return string The name of the table that is used to construct queries. - * if no table is linked, the method will return the string MySQLQuery::NO_STRUCTURE. - * @since 1.5 - * @deprecated since version 1.9.0 Use MySQLQuery::getTableName() instead. - */ - public function getStructureName(){ - $s = $this->getStructure(); - if($s instanceof MySQLTable){ - return $s->getName(); - } - return self::NO_STRUCTURE; - } - /** - * Returns the name of the table which is used to constructs the queries. - * @param boolean $dbPrefix If database prefix is set and this parameter is - * set to true, the name of the table will include database prefix. - * @return string The name of the table which is used to constructs the queries. - * @since 1.9.0 - */ - public function getTableName($dbPrefix=true) { - return $this->getTable()->getName($dbPrefix); - } - /** - * Returns the table which is associated with the query. - * @return MySQLTable The table which is used to constructs queries for. - * @since 1.9.0 - */ - public function getTable() { - return $this->table; - } - public function __toString() { - return $this->getQuery(); + + return ' '.trim($where); } } diff --git a/src/MySQLTable.php b/src/MySQLTable.php index 396bcc0..10badad 100644 --- a/src/MySQLTable.php +++ b/src/MySQLTable.php @@ -23,8 +23,7 @@ * SOFTWARE. */ namespace phMysql; -use phMysql\MySQLQuery; -use phMysql\MySQLColumn; + /** * A class that represents MySQL table. * @@ -33,29 +32,31 @@ */ class MySQLTable { /** - * The namespace of the auto-generated entity. - * @var string|null - * @since 1.6.5 + * A constant that is returned by some methods to tell that the + * name of the table is invalid. + * @var string + * @since 1.4 */ - private $entityNamespace; + const INV_TABLE_NAME = 'inv_table_name'; /** - * The location of the auto-generated entity. - * @var string|null - * @since 1.6.5 + * A constant that is returned by some methods to tell that the + * table does not have a given column name. + * @var string + * @since 1.4 */ - private $entityPath; + const NO_SUCH_COL = 'no_such_col'; /** - * The instance of type MySQLQuery at which this table is linked to. - * @var MySQLQuery - * @since 1.6.4 + * Character set of the table. + * @var string + * @since 1.0 */ - private $ownerQuery; + private $charSet; /** - * The name of database schema that the table belongs to. - * @var string - * @since 1.6.1 + * An array of table columns. + * @var array + * @since 1.0 */ - private $schema; + private $colSet = []; /** * A comment to add to the column. * @var string|null @@ -63,24 +64,39 @@ class MySQLTable { */ private $comment; /** - * Version number of MySQL server. - * @var string + * An array of booleans which indicates which default columns has been added + * @var array */ - private $mysqlVnum; + private $defaultColsKeys; /** - * A constant that is returned by some methods to tell that the - * table does not have a given column name. - * @var string - * @since 1.4 + * The engine that will be used by the table. + * @var string + * @since 1.0 */ - const NO_SUCH_COL = 'no_such_col'; + private $engin; /** - * A constant that is returned by some methods to tell that the - * name of the table is invalid. + * The namespace of the auto-generated entity. + * @var string|null + * @since 1.6.5 + */ + private $entityNamespace; + /** + * The location of the auto-generated entity. + * @var string|null + * @since 1.6.5 + */ + private $entityPath; + /** + * An array that contains all table foreign keys. + * @var array + * @since 1.0 + */ + private $foreignKeys = []; + /** + * Version number of MySQL server. * @var string - * @since 1.4 */ - const INV_TABLE_NAME = 'inv_table_name'; + private $mysqlVnum; /** * The order of the table in the database. * @var int The order of the table in the database. The value @@ -93,40 +109,23 @@ class MySQLTable { */ private $order; /** - * An array that contains all table foreign keys. - * @var array - * @since 1.0 - */ - private $foreignKeys = []; - /** - * The name of the table. - * @var string - * @since 1.0 - */ - private $tableName; - /** - * An array of table columns. - * @var array - * @since 1.0 + * The instance of type MySQLQuery at which this table is linked to. + * @var MySQLQuery + * @since 1.6.4 */ - private $colSet = []; + private $ownerQuery; /** - * The engine that will be used by the table. - * @var string - * @since 1.0 + * The name of database schema that the table belongs to. + * @var string + * @since 1.6.1 */ - private $engin; + private $schema; /** - * Character set of the table. + * The name of the table. * @var string * @since 1.0 */ - private $charSet; - /** - * An array of booleans which indicates which default columns has been added - * @var array - */ - private $defaultColsKeys; + private $tableName; /** * Creates a new instance of the class. * This method will initialize the basic settings of the table. It will @@ -138,7 +137,7 @@ class MySQLTable { * or not provided, 'table' will be used as default. */ public function __construct($tName = 'table') { - if($this->setName($tName) !== true){ + if ($this->setName($tName) !== true) { $this->setName('table'); } $this->mysqlVnum = '5.5'; @@ -146,59 +145,88 @@ public function __construct($tName = 'table') { $this->charSet = 'utf8mb4'; $this->order = 0; $this->defaultColsKeys = [ - 'id'=>null, - 'created-on'=>null, - 'last-updated'=>null + 'id' => null, + 'created-on' => null, + 'last-updated' => null ]; $this->schema = null; $this->ownerQuery = null; } /** - * Returns the query object which owns the table. - * @return MySQLQuery|null If the owner is set, the method will return an - * object of type 'MySQLQuery'. Other than that, null is returned. - * @since 1.6.5 - */ - public function getOwnerQuery() { - return $this->ownerQuery; - } - /** - * Returns the namespace at which the auto-generated entity class belongs to. - * @return string|null If no entity class is generated, the method will return - * null. Other than that, the method will return a string that represents - * the namespace that the entity class belongs to. - * @since 1.6.5 - */ - public function getEntityNamespace() { - return $this->entityNamespace; - } - /** - * Returns the name of the directory at which the auto-generated entity class - * was created on. - * @return string|null If no entity class is generated, the method will return - * null. Other than that, the method will return a string that represents - * the name of the directory at which the auto-generated entity class - * was created on. - * @since 1.6.5 - */ - public function getEntityPath() { - return $this->entityPath; - } - /** - * Sets the query object at which the table is belonging to. - * The developer does not have to call this method. It is used automatically - * my the class 'MySQLQuery' to set the owner query. - * @param MySQLQuery $qObj An instance of the class 'MySQLQuery'. - * @since 1.6.4 + * Adds new column to the table. + * @param string $key The index at which the column will be added to. The name + * of the key can only have the following characters: [A-Z], [a-z], [0-9] + * and '-'. + * @param MySQLColumn|array $col An object of type Column. Also, it can be + * an associative array of column options. The available options + * are: + * + * Note that the column will be added only if no column was found in the table which has the same name + * as the given column (key name and database name). + * @return boolean true if the column is added. false otherwise. + * @since 1.0 */ - public function setOwnerQuery($qObj) { - if($qObj instanceof MySQLQuery){ - $this->ownerQuery = $qObj; - $this->setSchemaName($qObj->getSchemaName()); - } - else if($qObj === null){ - $this->ownerQuery = null; + public function addColumn($key,$col) { + $trimmedKey = trim($key); + $keyLen = strlen($trimmedKey); + + if (strlen($keyLen) != 0 && $this->_isKeyNameValid($trimmedKey)) { + if (gettype($col) === 'array') { + if (!isset($col['name'])) { + $col['name'] = str_replace('-', '_', $trimmedKey); + } + $col = $this->_createColObj($col); + } + + if ($col instanceof MySQLColumn) { + if (!isset($this->colSet[$trimmedKey])) { + $givanColName = $col->getName(); + + foreach ($this->columns() as $val) { + $inTableColName = $val->getName(); + + if ($inTableColName == $givanColName) { + return false; + } + } + + if ($this->_isKeyNameValid($trimmedKey)) { + $col->setOwner($this); + $this->colSet[$trimmedKey] = $col; + $this->_checkPKs(); + + return true; + } + } + } } + + return false; } /** * Adds multiple columns at once. @@ -209,94 +237,19 @@ public function setOwnerQuery($qObj) { * @since 1.6.4 */ public function addColumns($colsArr) { - if(gettype($colsArr) === 'array'){ - foreach ($colsArr as $key => $options){ + if (gettype($colsArr) === 'array') { + foreach ($colsArr as $key => $options) { $this->addColumn($key, $options); } } } /** - * Returns the name of the database that the table belongs to. - * @return string|null The name of the database that the table belongs to. - * If it is not set, the method will return null. - * @since 1.6.1 - */ - public function getDatabaseName() { - return $this->schema; - } - /** - * Sets the name of the database that the table belongs to. - * Note that if the owner query object is set, the method will always return - * true and the name of the schema will be taken from the query object regardless - * of the passed value. - * @param string $name Schema name (or database name). A valid name - * must have the following conditions: + * Adds default columns to the table. + * Default columns are the following columns: * - * @return boolean If it was set, the method will return true. If not, - * it will return false. - * @since 1.6.1 - */ - public function setSchemaName($name) { - if($this->ownerQuery !== null){ - $this->schema = $this->ownerQuery->getSchemaName(); - return true; - } - else{ - $trimmed = trim($name); - $len = strlen($trimmed); - if($len > 0){ - for ($x = 0 ; $x < $len ; $x++){ - $ch = $trimmed[$x]; - if($x == 0 && ($ch >= '0' && $ch <= '9')){ - return false; - } - if($ch == '_' || ($ch >= 'a' && $ch <= 'z') || ($ch >= 'A' && $ch <= 'Z') || ($ch >= '0' && $ch <= '9')){ - - } - else{ - return false; - } - } - $this->schema = $trimmed; - return true; - } - } - return false; - } - /** - * Sets version number of MySQL server. - * Version number of MySQL is used to set the correct collation for table columns - * in case of varchar or text data types. If MySQL version is '5.5' or lower, - * collation will be set to 'utf8mb4_unicode_ci'. Other than that, the - * collation will be set to 'utf8mb4_unicode_520_ci'. - * @param string $vNum MySQL version number (such as '5.5'). It must be in - * the format 'X.X.X' or the version won't be set. The last 'X' is optional. - * @since 1.6.1 - */ - public function setMySQLVersion($vNum) { - if(strlen($vNum) > 0){ - $split = explode('.', $vNum); - if(count($split) >= 2){ - $major = intval($split[0]); - $minor = intval($split[1]); - if($major >= 0 && $minor >= 0){ - $this->mysqlVnum = $vNum; - } - } - } - } - /** - * Adds default columns to the table. - * Default columns are the following columns: - * * Depending on the provided options, none of the 3 might be added or * one of them or two or all. @@ -330,190 +283,199 @@ public function setMySQLVersion($vNum) { * * @since 1.6.1 */ - public function addDefaultCols($options=[ - 'id'=>[], - 'created-on'=>[], - 'last-updated'=>[] + public function addDefaultCols($options = [ + 'id' => [], + 'created-on' => [], + 'last-updated' => [] ]) { - if(gettype($options) == 'array'){ - if(isset($options['id']) && $this->defaultColsKeys['id'] === null){ + if (gettype($options) == 'array') { + if (isset($options['id']) && $this->defaultColsKeys['id'] === null) { $id = $options['id']; $key = isset($id['key-name']) ? trim($id['key-name']) : 'id'; - if(!$this->_isKeyNameValid($key)){ + + if (!$this->_isKeyNameValid($key)) { $key = 'id'; } $inDbName = isset($id['db-name']) ? $id['db-name'] : 'id'; $colObj = new MySQLColumn($inDbName, 'int', 11); $colObj->setIsPrimary(true); $colObj->setIsAutoInc(true); - if(!($colObj->getName() == $inDbName)){ + + if (!($colObj->getName() == $inDbName)) { $colObj->setName('id'); } - if($this->addColumn($key, $colObj)){ + + if ($this->addColumn($key, $colObj)) { $this->defaultColsKeys['id'] = $key; } } - if(isset($options['created-on']) && $this->defaultColsKeys['created-on'] === null){ + + if (isset($options['created-on']) && $this->defaultColsKeys['created-on'] === null) { $createdOn = $options['created-on']; $key = isset($createdOn['key-name']) ? trim($createdOn['key-name']) : 'created-on'; - if(!$this->_isKeyNameValid($key)){ + + if (!$this->_isKeyNameValid($key)) { $key = 'created-on'; } $inDbName = isset($createdOn['db-name']) ? $createdOn['db-name'] : 'created_on'; $colObj = new MySQLColumn($inDbName, 'timestamp'); - if(!($colObj->getName() == $inDbName)){ + + if (!($colObj->getName() == $inDbName)) { $colObj->setName('created_on'); } $colObj->setDefault('current_timestamp'); - if($this->addColumn($key, $colObj)){ + + if ($this->addColumn($key, $colObj)) { $this->defaultColsKeys['created-on'] = $key; } } - if(isset($options['last-updated']) && $this->defaultColsKeys['last-updated'] === null){ + + if (isset($options['last-updated']) && $this->defaultColsKeys['last-updated'] === null) { $lastUpdated = $options['last-updated']; $key = isset($lastUpdated['key-name']) ? trim($lastUpdated['key-name']) : 'last-updated'; - if(!$this->_isKeyNameValid($key)){ + + if (!$this->_isKeyNameValid($key)) { $key = 'last-updated'; } $inDbName = isset($lastUpdated['db-name']) ? $lastUpdated['db-name'] : 'last_updated'; $colObj = new MySQLColumn($inDbName, 'datetime'); - if(!($colObj->getName() == $inDbName)){ + + if (!($colObj->getName() == $inDbName)) { $colObj->setName('last_update'); } $colObj->setAutoUpdate(true); $colObj->setIsNull(true); - if($this->addColumn($key, $colObj)){ + + if ($this->addColumn($key, $colObj)) { $this->defaultColsKeys['last-updated'] = $key; } } } } /** - * Returns an associative array that contains default columns keys. - * @return array An associative array which has the following indices: - * - * If the table does not have the specified column, the value of the index - * will beset to null. - * @since 1.6.3 - */ - public function getDefaultColsKeys() { - return $this->defaultColsKeys; - } - /** - * Returns an associative array that maps possible entity methods names with - * table columns names in the database. - * Assuming that the table has two columns. The first one has a key = 'user-id' - * and the second one has a key 'password'. Also, let's assume that the first column - * has the name 'id' in the database and the second one has the name 'user_pass'. - * If this is the case, the method will return something like the following array: - *

- * [
- * 'setUserId'=>'id',
- * 'setPassword'=>'user_pass'
- * ]
- *

- * @return array An associative array. The indices represents the names of - * the methods in the entity class and the values are the names of table - * columns as they appear in the database. - * @since 1.6.5 + * Adds a foreign key to the table. + * Note that it will be added only if no key was added to the table which + * has the same name as the given key. + * @param ForeignKey $key an object of type 'ForeignKey'. + * @since 1.1 + * @return boolean true if the key is added. false otherwise. + * @see ForeignKey + * @since 1.0 */ - public function getSettersMap() { - $keys = array_keys($this->getColumns()); - $retVal = []; - foreach ($keys as $keyName){ - $split = explode('-', $keyName); - $methodName = ''; - foreach ($split as $namePart){ - if(strlen($namePart) == 1){ - $methodName .= strtoupper($namePart); - } - else{ - $firstChar = $namePart[0]; - $methodName .= strtoupper($firstChar).substr($namePart, 1); + public function addForeignKey($key) { + if ($key instanceof ForeignKey) { + foreach ($this->forignKeys() as $val) { + if ($key->getKeyName() == $val->getKeyName()) { + return false; } } - $mappedCol = $this->getCol($keyName)->getName(); - $retVal['set'.$methodName] = $mappedCol; + $key->setOwner($this); + array_push($this->foreignKeys, $key); + + return true; } - return $retVal; + + return false; } /** - * Returns an array that contains the names of attributes mapped from columns - * names. - * Attributes names are generated based on the names of keys. For example, - * if we have two columns one with key 'user-id' and the second one with - * name 'user-PASS', then the two attributes which represents the two columns - * will have the names 'userId' and 'userPASS'. - * @return array An indexed array that contains attributes names. - * @since 1.6.5 + * Adds a foreign key to the table. + * @param MySQLTable|MySQLQuery|string $refTable The referenced table. It is the table that + * will contain original values. This value can be an object of type + * 'MySQLTable', an object of type 'MySQLQuery' or the namespace of a class which is a sub-class of + * the class 'MySQLQuery'. + * @param array $cols An associative array that contains key columns. + * The indices must be names of columns which exist in 'this' table and + * the values must be columns from referenced table. It is possible to + * provide an indexed array. If an indexed array is given, the method will + * assume that the two tables have same column key. + * @param string $keyname The name of the key. + * @param string $onupdate The 'on update' condition for the key. it can be one + * of the following: + * + * Default value is 'set null'. + * @param string $ondelete The 'on delete' condition for the key. it can be one + * of the following: + * + * Default value is 'set null'. + * @return boolean + * @since 1.5 */ - public function getAttribitesNames() { - $keys = array_keys($this->getColumns()); - $retVal = []; - foreach ($keys as $keyName){ - $split = explode('-', $keyName); - $attrName = ''; - $index = 0; - foreach ($split as $namePart){ - if(strlen($namePart) == 1){ - $attrName .= strtolower($namePart); - $index++; - } - else{ - if($index != 0){ - $firstChar = $namePart[0]; - $attrName .= strtoupper($firstChar).substr($namePart, 1); - } - else{ - $index++; - $attrName .= strtolower($namePart); + public function addReference($refTable,$cols,$keyname,$onupdate = 'set null',$ondelete = 'set null') { + if (!($refTable instanceof MySQLTable)) { + if ($refTable instanceof MySQLQuery) { + $refTable = $refTable->getStructure(); + } else { + if (class_exists($refTable)) { + $q = new $refTable(); + + if ($q instanceof MySQLQuery) { + $refTable = $q->getStructure(); } } } - $retVal[] = $attrName; } - return $retVal; - } - /** - * Returns an associative array that contains the possible names - * of the methods which exist in the entity class that the result - * of a select query on the table will be mapped to. - * The names of the methods are constructed from the names of columns - * keys. For example, if the name of the column key is 'user-id', the - * name of setter method will be 'setUserId' and the name of setter - * method will be 'setUserId'. - * @return array An associative array. The array will have two indices. - * The first index has the name 'setters' which will contain the names - * of setters and the second index is 'getters' which contains the names - * of the getters. - * @since 1.6.5 - */ - public function getEntityMethods() { - $keys = array_keys($this->getColumns()); - $retVal = [ - 'setters'=>[], - 'getters'=>[] - ]; - foreach ($keys as $keyName){ - $split = explode('-', $keyName); - $methodName = ''; - foreach ($split as $namePart){ - if(strlen($namePart) == 1){ - $methodName .= strtoupper($namePart); + + if ($refTable instanceof MySQLTable) { + $fk = new ForeignKey(); + $fk->setOwner($this); + $fk->setSource($refTable); + + if ($fk->setKeyName($keyname) === true) { + foreach ($cols as $target => $source) { + if (gettype($target) == 'integer') { + //indexed array. + //It means source and target columns have same name. + $fk->addReference($source, $source); + } else { + //Associative. Probably two columns with different names. + $fk->addReference($target, $source); + } } - else{ - $firstChar = $namePart[0]; - $methodName .= strtoupper($firstChar).substr($namePart, 1); + + if (count($fk->getSourceCols()) != 0) { + $fk->setOnUpdate($onupdate); + $fk->setOnDelete($ondelete); + $this->foreignKeys[] = $fk; + + return true; } + } else { + trigger_error('Invalid FK name: \''.$keyname.'\'.'); } - $retVal['getters'][] = 'get'.$methodName; - $retVal['setters'][] = 'set'.$methodName; + } else { + trigger_error('Referenced table is not an instance of the class \'MySQLTable\'.'); } - return $retVal; + + return false; + } + /** + * Returns an array that contains all the keys the columns was stored in + * the table. + * @return array an array that contains all the set of keys. + * @since 1.2 + */ + public function colsKeys() { + return array_keys($this->colSet); + } + /** + * Returns an array of all the columns in the table. + * @return array An array that contains an objects of type Column + * @since 1.0 + */ + public function columns() { + return $this->colSet; } /** * Create a new entity class that can be used to store table records @@ -538,57 +500,61 @@ public function createEntityClass($options) { $retVal = false; $path = isset($options['store-path']) ? $options['store-path'] : ''; $entityName = isset($options['class-name']) ? trim($options['class-name']) : ''; - if(strlen($entityName) != 0 && !strpos($entityName, ' ')){ + + if (strlen($entityName) != 0 && !strpos($entityName, ' ')) { $namespace = isset($options['namespace']) && strlen($options['namespace']) != 0 ? trim($options['namespace']) : __NAMESPACE__.'\\entity'; $override = isset($options['override']) ? $options['override'] === true : false; - if(is_dir($path.DIRECTORY_SEPARATOR.$entityName) && class_exists($namespace.'\\'.$entityName) && !$override){ + + if (is_dir($path.DIRECTORY_SEPARATOR.$entityName) && class_exists($namespace.'\\'.$entityName) && !$override) { $this->entityNamespace = $namespace.'\\'.$entityName; $this->entityPath = $path.DIRECTORY_SEPARATOR.$entityName.'.php'; $retVal = true; - } - else{ + } else { $file = fopen($path.DIRECTORY_SEPARATOR.$entityName.'.php', 'w+'); - if(is_resource($file)){ + + if (is_resource($file)) { $entityAttrs = $this->getAttribitesNames(); $attrsCount = count($entityAttrs); $settersGettersMap = $this->getEntityMethods(); fwrite($file, "getName()."'\n" - . " **/\n"); + ." * An auto-generated entity class which maps to a record in the\n" + ." * table '".$this->getName()."'\n" + ." **/\n"); fwrite($file, "class ".$entityName."{\n"); $colsNames = $this->getColsNames(); $index = 0; - foreach ($entityAttrs as $attrName){ + + foreach ($entityAttrs as $attrName) { $colName = $colsNames[$index]; fwrite($file, " /**\n" - . " * The attribute which is mapped to the column '".$colName."'.\n" - . " * @var ".$this->_getPHPType($index)."\n" - . " **/\n"); + ." * The attribute which is mapped to the column '".$colName."'.\n" + ." * @var ".$this->_getPHPType($index)."\n" + ." **/\n"); fwrite($file, ' private $'.$attrName.";\n"); $index++; } - for($x = 0 ; $x < $attrsCount ; $x++){ + + for ($x = 0 ; $x < $attrsCount ; $x++) { $colName = $colsNames[$x]; $setterName = $settersGettersMap['setters'][$x]; fwrite($file, " /**\n" - . " * Sets the value of the attribute '".$attrName."'.\n" - . " * The value of the attribute is mapped to the column which has\n" - . " * the name '$colName'.\n" - . " * @param \$$entityAttrs[$x] ".$this->_getPHPType($x)." The new value of the attribute.\n" - . " **/\n"); + ." * Sets the value of the attribute '".$attrName."'.\n" + ." * The value of the attribute is mapped to the column which has\n" + ." * the name '$colName'.\n" + ." * @param \$$entityAttrs[$x] ".$this->_getPHPType($x)." The new value of the attribute.\n" + ." **/\n"); fwrite($file, ' public function '.$setterName.'($'.$entityAttrs[$x]."){\n"); fwrite($file, ' $this->'.$entityAttrs[$x].' = $'.$entityAttrs[$x].";\n"); fwrite($file, " }\n"); $getterName = $settersGettersMap['getters'][$x]; fwrite($file, " /**\n" - . " * Returns the value of the attribute '".$attrName."'.\n" - . " * The value of the attribute is mapped to the column which has\n" - . " * the name '$colName'.\n" - . " * @return ".$this->_getPHPType($x)." The value of the attribute.\n" - . " **/\n"); + ." * Returns the value of the attribute '".$attrName."'.\n" + ." * The value of the attribute is mapped to the column which has\n" + ." * the name '$colName'.\n" + ." * @return ".$this->_getPHPType($x)." The value of the attribute.\n" + ." **/\n"); fwrite($file, ' public function '.$getterName."(){\n"); fwrite($file, ' return $this->'.$entityAttrs[$x].";\n"); fwrite($file, " }\n"); @@ -598,83 +564,118 @@ public function createEntityClass($options) { $this->entityNamespace = $namespace.'\\'.$entityName; $this->entityPath = $path.DIRECTORY_SEPARATOR.$entityName.'.php'; $retVal = true; - } - else{ + } else { $retVal = false; } } } + return $retVal; } - private function _getPHPType($colIndex){ - $colObj = array_values($this->getColumns())[$colIndex]; - $isNull = $colObj->isNull() ? '|null' : ''; - $type = $colObj->getType(); - if($type == 'int'){ - return 'int'.$isNull; - } - else if($type == 'decimal' || $type == 'double' || $type == 'float'){ - return 'double'.$isNull; - } - else if($type == 'boolean'){ - return 'boolean'.$isNull; - } - else{ - return 'string'.$isNull; - } - } /** - * Returns version number of MySQL server. - * @return string MySQL version number (such as '5.5'). If version number - * is not set, The default return value is '5.5'. - * @since 1.6.1 + * Returns an array that contains all table foreign keys. + * @return array An array of FKs. + * @since 1.1 */ - public function getMySQLVersion() { - return $this->mysqlVnum; + public function forignKeys() { + return $this->foreignKeys; } /** - * Returns an array that contains all columns names as they will appear in - * the database. - * @return array An array that contains all columns names as they will appear in - * the database. - * @since 1.6.2 + * Returns an array that contains the names of attributes mapped from columns + * names. + * Attributes names are generated based on the names of keys. For example, + * if we have two columns one with key 'user-id' and the second one with + * name 'user-PASS', then the two attributes which represents the two columns + * will have the names 'userId' and 'userPASS'. + * @return array An indexed array that contains attributes names. + * @since 1.6.5 */ - public function getColsNames() { - $columns = $this->getColumns(); + public function getAttribitesNames() { + $keys = array_keys($this->getColumns()); $retVal = []; - foreach ($columns as $colObj){ - $retVal[] = $colObj->getName(); + + foreach ($keys as $keyName) { + $split = explode('-', $keyName); + $attrName = ''; + $index = 0; + + foreach ($split as $namePart) { + if (strlen($namePart) == 1) { + $attrName .= strtolower($namePart); + $index++; + } else { + if ($index != 0) { + $firstChar = $namePart[0]; + $attrName .= strtoupper($firstChar).substr($namePart, 1); + } else { + $index++; + $attrName .= strtolower($namePart); + } + } + } + $retVal[] = $attrName; } + return $retVal; } /** - * Sets the order of the table in the database. - * The order of the table describes the dependencies between tables. For example, - * if we have three tables, 'A', 'B' and 'C'. Let's assume that table 'B' - * references table 'A' and Table 'A' references table 'C'. In this case, - * table 'C' will have order 0, Table 'A' have order 1 and table 'B' have order - * 2. - * @param int $val The order of the table in the database. - * @since 1.3 - * @return boolean true if the value of the attribute is set. - * false if not. + * Returns the character set that is used by the table. + * @return string The character set that is used by the table.. The default + * value is 'utf8'. + * @since 1.0 */ - public function setOrder($val){ - if(gettype($val) == 'integer'){ - if($val > -1){ - $this->order = $val; - return true; + public function getCharSet() { + return $this->charSet; + } + /** + * Returns the column object given the key that it was stored in. + * @param string $key The name of the column key. + * @return MySQLColumn|null MySQLColumn|null An object of type Column is returned if the given + * column was found. null in case of no column was found. + * @since 1.0 + */ + public function getCol($key) { + $trimmed = trim($key); + + if (isset($this->colSet[$trimmed])) { + return $this->colSet[$trimmed]; + } + $null = null; + + return $null; + } + /** + * Returns a column given its index. + * @param int $index The index of the column. + * @return MySQLColumn|null If a column was found which has the specified index, + * it is returned. Other than that, The method will return null. + * @since 1.6 + */ + public function getColByIndex($index) { + foreach ($this->colSet as $k => $col) { + if ($col->getIndex() == $index) { + return $col; } } - return false; + $null = null; + + return $null; } /** - * Returns the order of the table in the database. - * @return int The order of the table in the database. - * @since 1.3 + * Returns the index of a column given its key. + * @param string $key The name of the column key. + * @return MySQLColumn|null The index of the column if a column was + * found which has the given key. -1 in case of no column was found. + * @since 1.6 */ - public function getOrder() { - return $this->order; + public function getColIndex($key) { + $trimmed = trim($key); + + if (isset($this->colSet[$trimmed])) { + return $this->colSet[$trimmed]->getIndex(); + } + + return -1; } /** * Returns the value of table collation. @@ -684,61 +685,143 @@ public function getOrder() { * @return string Table collation. * @since 1.6 */ - public function getCollation(){ + public function getCollation() { $split = explode('.', $this->getMySQLVersion()); - if(isset($split[0]) && intval($split[0]) <= 5 && isset($split[1]) && intval($split[1]) <= 5){ + + if (isset($split[0]) && intval($split[0]) <= 5 && isset($split[1]) && intval($split[1]) <= 5) { return 'utf8mb4_unicode_ci'; } + return 'utf8mb4_unicode_520_ci'; } /** - * Adds a foreign key to the table. - * Note that it will be added only if no key was added to the table which - * has the same name as the given key. - * @param ForeignKey $key an object of type 'ForeignKey'. - * @since 1.1 - * @return boolean true if the key is added. false otherwise. - * @see ForeignKey + * Returns an array that contains all columns names as they will appear in + * the database. + * @return array An array that contains all columns names as they will appear in + * the database. + * @since 1.6.2 + */ + public function getColsNames() { + $columns = $this->getColumns(); + $retVal = []; + + foreach ($columns as $colObj) { + $retVal[] = $colObj->getName(); + } + + return $retVal; + } + /** + * Returns an associative array that contains table columns. + * @return array An associative array that contains table columns. The indices + * will be columns names and the values are objects of type 'Column'. + * @since 1.6.1 + */ + public function getColumns() { + return $this->colSet; + } + /** + * Returns a string that represents a comment which was added with the table. + * @return string|null Comment text. If it is not set, the method will return + * null. + * @since 1.6.1 + */ + public function getComment() { + return $this->comment; + } + /** + * Returns the name of the database that the table belongs to. + * @return string|null The name of the database that the table belongs to. + * If it is not set, the method will return null. + * @since 1.6.1 + */ + public function getDatabaseName() { + return $this->schema; + } + /** + * Returns an associative array that contains default columns keys. + * @return array An associative array which has the following indices: + * + * If the table does not have the specified column, the value of the index + * will beset to null. + * @since 1.6.3 + */ + public function getDefaultColsKeys() { + return $this->defaultColsKeys; + } + /** + * Returns the name of the storage engine used by the table. + * @return string The name of the storage engine used by the table. The default + * value is 'InnoDB'. * @since 1.0 */ - public function addForeignKey($key){ - if($key instanceof ForeignKey){ - foreach ($this->forignKeys() as $val){ - if($key->getKeyName() == $val->getKeyName()){ - return false; + public function getEngine() { + return $this->engin; + } + /** + * Returns an associative array that contains the possible names + * of the methods which exist in the entity class that the result + * of a select query on the table will be mapped to. + * The names of the methods are constructed from the names of columns + * keys. For example, if the name of the column key is 'user-id', the + * name of setter method will be 'setUserId' and the name of setter + * method will be 'setUserId'. + * @return array An associative array. The array will have two indices. + * The first index has the name 'setters' which will contain the names + * of setters and the second index is 'getters' which contains the names + * of the getters. + * @since 1.6.5 + */ + public function getEntityMethods() { + $keys = array_keys($this->getColumns()); + $retVal = [ + 'setters' => [], + 'getters' => [] + ]; + + foreach ($keys as $keyName) { + $split = explode('-', $keyName); + $methodName = ''; + + foreach ($split as $namePart) { + if (strlen($namePart) == 1) { + $methodName .= strtoupper($namePart); + } else { + $firstChar = $namePart[0]; + $methodName .= strtoupper($firstChar).substr($namePart, 1); } } - $key->setOwner($this); - array_push($this->foreignKeys, $key); - return true; + $retVal['getters'][] = 'get'.$methodName; + $retVal['setters'][] = 'set'.$methodName; } - return false; + + return $retVal; } /** - * Returns the name of table primary key. - * @return string The returned value will be the name of the table added - * to it the suffix '_pk'. - * @since 1.5 + * Returns the namespace at which the auto-generated entity class belongs to. + * @return string|null If no entity class is generated, the method will return + * null. Other than that, the method will return a string that represents + * the namespace that the entity class belongs to. + * @since 1.6.5 */ - public function getPrimaryKeyName() { - return $this->getName().'_pk'; + public function getEntityNamespace() { + return $this->entityNamespace; } /** - * Returns the number of columns that will act as one primary key. - * @return int The number of columns that will act as one primary key. If - * the table has no primary key, the method will return 0. If one column - * is used as primary, the method will return 1. If two, the method - * will return 2 and so on. - * @since 1.5 + * Returns the name of the directory at which the auto-generated entity class + * was created on. + * @return string|null If no entity class is generated, the method will return + * null. Other than that, the method will return a string that represents + * the name of the directory at which the auto-generated entity class + * was created on. + * @since 1.6.5 */ - public function primaryKeyColsCount(){ - $count = 0; - foreach ($this->colSet as $col){ - if($col->isPrimary()){ - $count++; - } - } - return $count; + public function getEntityPath() { + return $this->entityPath; } /** * Returns an array which contains all added foreign keys. @@ -750,114 +833,46 @@ public function getForeignKeys() { return $this->foreignKeys; } /** - * Returns an associative array that contains table columns. - * @return array An associative array that contains table columns. The indices - * will be columns names and the values are objects of type 'Column'. + * Returns version number of MySQL server. + * @return string MySQL version number (such as '5.5'). If version number + * is not set, The default return value is '5.5'. * @since 1.6.1 */ - public function getColumns() { - return $this->colSet; + public function getMySQLVersion() { + return $this->mysqlVnum; } + /** - * Sets a comment which will appear with the table. - * @param string|null $comment Comment text. It must be non-empty string - * in order to set. If null is passed, the comment will be removed. - * @since 1.6.1 + * Returns the name of the table. + * @param boolean $dbPrefix A boolean. If its set to true, the name of + * the table will be prefixed with the name of the database that the + * table belongs to. Default is true. + * @return string The name of the table. Default return value is 'table'. + * @since 1.0 */ - public function setComment($comment) { - if($comment == null || strlen($comment) != 0){ - $this->comment = $comment; + public function getName($dbPrefix = true) { + if ($dbPrefix === true && $this->getDatabaseName() !== null) { + return $this->getDatabaseName().'.'.$this->tableName; } + + return $this->tableName; } /** - * Returns a string that represents a comment which was added with the table. - * @return string|null Comment text. If it is not set, the method will return - * null. - * @since 1.6.1 + * Returns the order of the table in the database. + * @return int The order of the table in the database. + * @since 1.3 */ - public function getComment() { - return $this->comment; + public function getOrder() { + return $this->order; } /** - * Adds a foreign key to the table. - * @param MySQLTable|MySQLQuery|string $refTable The referenced table. It is the table that - * will contain original values. This value can be an object of type - * 'MySQLTable', an object of type 'MySQLQuery' or the namespace of a class which is a sub-class of - * the class 'MySQLQuery'. - * @param array $cols An associative array that contains key columns. - * The indices must be names of columns which exist in 'this' table and - * the values must be columns from referenced table. It is possible to - * provide an indexed array. If an indexed array is given, the method will - * assume that the two tables have same column key. - * @param string $keyname The name of the key. - * @param string $onupdate The 'on update' condition for the key. it can be one - * of the following: - * - * Default value is 'set null'. - * @param string $ondelete The 'on delete' condition for the key. it can be one - * of the following: - * - * Default value is 'set null'. - * @return boolean - * @since 1.5 + * Returns the query object which owns the table. + * @return MySQLQuery|null If the owner is set, the method will return an + * object of type 'MySQLQuery'. Other than that, null is returned. + * @since 1.6.5 */ - public function addReference($refTable,$cols,$keyname,$onupdate='set null',$ondelete='set null') { - if(!($refTable instanceof MySQLTable)){ - if($refTable instanceof MySQLQuery){ - $refTable = $refTable->getStructure(); - } - else{ - if(class_exists($refTable)){ - $q = new $refTable(); - if($q instanceof MySQLQuery){ - $refTable = $q->getStructure(); - } - } - } - } - if($refTable instanceof MySQLTable){ - $fk = new ForeignKey(); - $fk->setOwner($this); - $fk->setSource($refTable); - if($fk->setKeyName($keyname) === true){ - foreach ($cols as $target => $source){ - if(gettype($target) == 'integer'){ - //indexed array. - //It means source and target columns have same name. - $fk->addReference($source, $source); - } - else{ - //Associative. Probably two columns with different names. - $fk->addReference($target, $source); - } - } - if(count($fk->getSourceCols()) != 0){ - $fk->setOnUpdate($onupdate); - $fk->setOnDelete($ondelete); - $this->foreignKeys[] = $fk; - return true; - } - } - else{ - trigger_error('Invalid FK name: \''.$keyname.'\'.'); - } - } - else{ - trigger_error('Referenced table is not an instance of the class \'MySQLTable\'.'); - } - return false; + public function getOwnerQuery() { + return $this->ownerQuery; } /** * Returns the columns of the table which are a part of the primary key. @@ -867,13 +882,74 @@ public function addReference($refTable,$cols,$keyname,$onupdate='set null',$onde */ public function getPrimaryKeyCols() { $arr = []; - foreach ($this->columns() as $col){ - if($col->isPrimary()){ + + foreach ($this->columns() as $col) { + if ($col->isPrimary()) { $arr[] = $col; } } + return $arr; } + /** + * Returns the name of table primary key. + * @return string The returned value will be the name of the table added + * to it the suffix '_pk'. + * @since 1.5 + */ + public function getPrimaryKeyName() { + return $this->getName().'_pk'; + } + /** + * Returns an associative array that maps possible entity methods names with + * table columns names in the database. + * Assuming that the table has two columns. The first one has a key = 'user-id' + * and the second one has a key 'password'. Also, let's assume that the first column + * has the name 'id' in the database and the second one has the name 'user_pass'. + * If this is the case, the method will return something like the following array: + *

+ * [
+ * 'setUserId'=>'id',
+ * 'setPassword'=>'user_pass'
+ * ]
+ *

+ * @return array An associative array. The indices represents the names of + * the methods in the entity class and the values are the names of table + * columns as they appear in the database. + * @since 1.6.5 + */ + public function getSettersMap() { + $keys = array_keys($this->getColumns()); + $retVal = []; + + foreach ($keys as $keyName) { + $split = explode('-', $keyName); + $methodName = ''; + + foreach ($split as $namePart) { + if (strlen($namePart) == 1) { + $methodName .= strtoupper($namePart); + } else { + $firstChar = $namePart[0]; + $methodName .= strtoupper($firstChar).substr($namePart, 1); + } + } + $mappedCol = $this->getCol($keyName)->getName(); + $retVal['set'.$methodName] = $mappedCol; + } + + return $retVal; + } + + /** + * Checks if the table has a column or not. + * @param string $colKey The index at which the column might be exist. + * @return boolean true if the column exist. false otherwise. + * @since 1.4 + */ + public function hasColumn($colKey) { + return isset($this->colSet[trim($colKey)]); + } /** * Checks if a foreign key with the given name exist on the table or not. * @param string $keyName The name of the key. @@ -881,44 +957,99 @@ public function getPrimaryKeyCols() { * false if not. * @since 1.4 */ - public function hasForeignKey($keyName){ - foreach ($this->forignKeys() as $val){ - if($keyName == $val->getKeyName()){ + public function hasForeignKey($keyName) { + foreach ($this->forignKeys() as $val) { + if ($keyName == $val->getKeyName()) { return true; } } + return false; } /** - * Returns an array that contains all table foreign keys. - * @return array An array of FKs. - * @since 1.1 + * Returns the number of columns that will act as one primary key. + * @return int The number of columns that will act as one primary key. If + * the table has no primary key, the method will return 0. If one column + * is used as primary, the method will return 1. If two, the method + * will return 2 and so on. + * @since 1.5 */ - public function forignKeys() { - return $this->foreignKeys; + public function primaryKeyColsCount() { + $count = 0; + + foreach ($this->colSet as $col) { + if ($col->isPrimary()) { + $count++; + } + } + + return $count; } /** - * Returns an array of all the columns in the table. - * @return array An array that contains an objects of type Column - * @since 1.0 + * Removes a column given its key or index in the table. + * The method will first assume that the given value is column key. If + * no column found, then it will assume that the given value is column + * index. + * @param string|int $colKeyOrIndex Column key or index. + * @return boolean If the column was removed, the method will return true. + * Other than that, the method will return false. + * @since 1.6.1 */ - public function columns(){ - return $this->colSet; - } + public function removeColumn($colKeyOrIndex) { + $col = $this->getCol($colKeyOrIndex); + + if (!($col instanceof MySQLColumn)) { + foreach ($this->colSet as $key => $col) { + if ($col->getIndex() == $colKeyOrIndex) { + unset($this->colSet[$key]); + $this->_checkPKs(); + + return true; + } + } + + return false; + } else { + unset($this->colSet[$colKeyOrIndex]); + $this->_checkPKs(); + return true; + } + } /** - * Returns the name of the table. - * @param boolean $dbPrefix A boolean. If its set to true, the name of - * the table will be prefixed with the name of the database that the - * table belongs to. Default is true. - * @return string The name of the table. Default return value is 'table'. - * @since 1.0 + * Sets a comment which will appear with the table. + * @param string|null $comment Comment text. It must be non-empty string + * in order to set. If null is passed, the comment will be removed. + * @since 1.6.1 */ - public function getName($dbPrefix=true){ - if($dbPrefix === true && $this->getDatabaseName() !== null){ - return $this->getDatabaseName().'.'.$this->tableName; + public function setComment($comment) { + if ($comment == null || strlen($comment) != 0) { + $this->comment = $comment; + } + } + /** + * Sets version number of MySQL server. + * Version number of MySQL is used to set the correct collation for table columns + * in case of varchar or text data types. If MySQL version is '5.5' or lower, + * collation will be set to 'utf8mb4_unicode_ci'. Other than that, the + * collation will be set to 'utf8mb4_unicode_520_ci'. + * @param string $vNum MySQL version number (such as '5.5'). It must be in + * the format 'X.X.X' or the version won't be set. The last 'X' is optional. + * @since 1.6.1 + */ + public function setMySQLVersion($vNum) { + if (strlen($vNum) > 0) { + $split = explode('.', $vNum); + + if (count($split) >= 2) { + $major = intval($split[0]); + $minor = intval($split[1]); + + if ($major >= 0 && $minor >= 0) { + $this->mysqlVnum = $vNum; + } + } } - return $this->tableName; } /** * Sets the name of the table. @@ -936,52 +1067,131 @@ public function getName($dbPrefix=true){ public function setName($param) { $trimmedName = trim($param); $len = strlen($trimmedName); - if($len == 0){ + + if ($len == 0) { return false; } - for ($x = 0 ; $x < $len ; $x++){ + + for ($x = 0 ; $x < $len ; $x++) { $ch = $trimmedName[$x]; - if($x == 0){ - if($ch >= '0' && $ch <= '9'){ + + if ($x == 0) { + if ($ch >= '0' && $ch <= '9') { return false; } } - if($ch == '_' || ($ch >= 'a' && $ch <= 'z') || ($ch >= 'A' && $ch <= 'Z') || ($ch >= '0' && $ch <= '9')){ - } - else{ + if ($ch == '_' || ($ch >= 'a' && $ch <= 'z') || ($ch >= 'A' && $ch <= 'Z') || ($ch >= '0' && $ch <= '9')) { + } else { return false; } } $this->tableName = $trimmedName; + return true; } /** - * Removes a column given its key or index in the table. - * The method will first assume that the given value is column key. If - * no column found, then it will assume that the given value is column - * index. - * @param string|int $colKeyOrIndex Column key or index. - * @return boolean If the column was removed, the method will return true. - * Other than that, the method will return false. + * Sets the order of the table in the database. + * The order of the table describes the dependencies between tables. For example, + * if we have three tables, 'A', 'B' and 'C'. Let's assume that table 'B' + * references table 'A' and Table 'A' references table 'C'. In this case, + * table 'C' will have order 0, Table 'A' have order 1 and table 'B' have order + * 2. + * @param int $val The order of the table in the database. + * @since 1.3 + * @return boolean true if the value of the attribute is set. + * false if not. + */ + public function setOrder($val) { + if (gettype($val) == 'integer') { + if ($val > -1) { + $this->order = $val; + + return true; + } + } + + return false; + } + /** + * Sets the query object at which the table is belonging to. + * The developer does not have to call this method. It is used automatically + * my the class 'MySQLQuery' to set the owner query. + * @param MySQLQuery $qObj An instance of the class 'MySQLQuery'. + * @since 1.6.4 + */ + public function setOwnerQuery($qObj) { + if ($qObj instanceof MySQLQuery) { + $this->ownerQuery = $qObj; + $this->setSchemaName($qObj->getSchemaName()); + } else { + if ($qObj === null) { + $this->ownerQuery = null; + } + } + } + /** + * Sets the name of the database that the table belongs to. + * Note that if the owner query object is set, the method will always return + * true and the name of the schema will be taken from the query object regardless + * of the passed value. + * @param string $name Schema name (or database name). A valid name + * must have the following conditions: + * + * @return boolean If it was set, the method will return true. If not, + * it will return false. * @since 1.6.1 */ - public function removeColumn($colKeyOrIndex) { - $col = $this->getCol($colKeyOrIndex); - if(!($col instanceof MySQLColumn)){ - foreach ($this->colSet as $key => $col){ - if($col->getIndex() == $colKeyOrIndex){ - unset($this->colSet[$key]); - $this->_checkPKs(); - return true; + public function setSchemaName($name) { + if ($this->ownerQuery !== null) { + $this->schema = $this->ownerQuery->getSchemaName(); + + return true; + } else { + $trimmed = trim($name); + $len = strlen($trimmed); + + if ($len > 0) { + for ($x = 0 ; $x < $len ; $x++) { + $ch = $trimmed[$x]; + + if ($x == 0 && ($ch >= '0' && $ch <= '9')) { + return false; + } + + if ($ch == '_' || ($ch >= 'a' && $ch <= 'z') || ($ch >= 'A' && $ch <= 'Z') || ($ch >= '0' && $ch <= '9')) { + } else { + return false; + } } + $this->schema = $trimmed; + + return true; } - return false; } - else{ - unset($this->colSet[$colKeyOrIndex]); - $this->_checkPKs(); - return true; + + return false; + } + private function _checkPKs() { + $primaryCount = $this->primaryKeyColsCount(); + + if ($primaryCount > 1) { + foreach ($this->getPrimaryKeyCols() as $col) { + if ($col->isPrimary()) { + $col->setIsUnique(false); + } + } + } else { + foreach ($this->getPrimaryKeyCols() as $col) { + if ($col->isPrimary()) { + $col->setIsUnique(true); + } + } } } /** @@ -1018,124 +1228,65 @@ public function removeColumn($colKeyOrIndex) { * @since 1.6.4 */ private function _createColObj($options) { - if(isset($options['name'])){ + if (isset($options['name'])) { $datatype = isset($options['datatype']) ? $options['datatype'] : 'varchar'; $col = new MySQLColumn($options['name'], $datatype); $size = isset($options['size']) ? intval($options['size']) : 1; $col->setSize($size); $scale = isset($options['scale']) ? intval($options['scale']) : 2; $col->setScale($scale); - if(isset($options['default'])){ + + if (isset($options['default'])) { $col->setDefault($options['default']); } $isNull = isset($options['is-null']) ? $options['is-null'] === true : false; $col->setIsNull($isNull); - if(isset($options['is-primary'])){ + + if (isset($options['is-primary'])) { $col->setIsPrimary($options['is-primary']); - if(isset($options['auto-inc'])){ + + if (isset($options['auto-inc'])) { $col->setIsAutoInc($options['auto-inc']); } } - if(isset($options['is-unique'])){ + + if (isset($options['is-unique'])) { $col->setIsUnique($options['is-unique']); } - if(isset($options['auto-update'])){ + + if (isset($options['auto-update'])) { $col->setAutoUpdate($options['auto-update']); } - if(isset($options['comment'])){ + + if (isset($options['comment'])) { $col->setComment($options['comment']); } + return $col; } + return null; } - private function _checkPKs() { - $primaryCount = $this->primaryKeyColsCount(); - if($primaryCount > 1){ - foreach ($this->getPrimaryKeyCols() as $col){ - if($col->isPrimary()){ - $col->setIsUnique(false); - } - } - } - else{ - foreach ($this->getPrimaryKeyCols() as $col){ - if($col->isPrimary()){ - $col->setIsUnique(true); - } - } - } - } - /** - * Adds new column to the table. - * @param string $key The index at which the column will be added to. The name - * of the key can only have the following characters: [A-Z], [a-z], [0-9] - * and '-'. - * @param MySQLColumn|array $col An object of type Column. Also, it can be - * an associative array of column options. The available options - * are: - * - * Note that the column will be added only if no column was found in the table which has the same name - * as the given column (key name and database name). - * @return boolean true if the column is added. false otherwise. - * @since 1.0 - */ - public function addColumn($key,$col) { - $trimmedKey = trim($key); - $keyLen = strlen($trimmedKey); - if(strlen($keyLen) != 0 && $this->_isKeyNameValid($trimmedKey)){ - if(gettype($col) === 'array'){ - if(!isset($col['name'])){ - $col['name'] = str_replace('-', '_', $trimmedKey); - } - $col = $this->_createColObj($col); - } - if($col instanceof MySQLColumn){ - if(!isset($this->colSet[$trimmedKey])){ - $givanColName = $col->getName(); - foreach ($this->columns() as $val){ - $inTableColName = $val->getName(); - if($inTableColName == $givanColName){ - return false; - } - } - if($this->_isKeyNameValid($trimmedKey)){ - $col->setOwner($this); - $this->colSet[$trimmedKey] = $col; - $this->_checkPKs(); - return true; - } + private function _getPHPType($colIndex) { + $colObj = array_values($this->getColumns())[$colIndex]; + $isNull = $colObj->isNull() ? '|null' : ''; + $type = $colObj->getType(); + + if ($type == 'int') { + return 'int'.$isNull; + } else { + if ($type == 'decimal' || $type == 'double' || $type == 'float') { + return 'double'.$isNull; + } else { + if ($type == 'boolean') { + return 'boolean'.$isNull; + } else { + return 'string'.$isNull; } } } - return false; } - + /** * * @param type $key @@ -1145,99 +1296,19 @@ public function addColumn($key,$col) { private function _isKeyNameValid($key) { $keyLen = strlen($key); $actualKeyLen = $keyLen; - for ($x = 0 ; $x < $keyLen ; $x++){ + + for ($x = 0 ; $x < $keyLen ; $x++) { $ch = $key[$x]; - if($ch == '-' || ($ch >= 'a' && $ch <= 'z') || ($ch >= 'A' && $ch <= 'Z') || ($ch >= '0' && $ch <= '9')){ - if($ch == '-'){ + + if ($ch == '-' || ($ch >= 'a' && $ch <= 'z') || ($ch >= 'A' && $ch <= 'Z') || ($ch >= '0' && $ch <= '9')) { + if ($ch == '-') { $actualKeyLen--; } - } - else{ + } else { return false; } } - return $actualKeyLen != 0; - } - /** - * Checks if the table has a column or not. - * @param string $colKey The index at which the column might be exist. - * @return boolean true if the column exist. false otherwise. - * @since 1.4 - */ - public function hasColumn($colKey) { - return isset($this->colSet[trim($colKey)]); - } - /** - * Returns the column object given the key that it was stored in. - * @param string $key The name of the column key. - * @return MySQLColumn|null MySQLColumn|null An object of type Column is returned if the given - * column was found. null in case of no column was found. - * @since 1.0 - */ - public function getCol($key){ - $trimmed = trim($key); - if(isset($this->colSet[$trimmed])){ - return $this->colSet[$trimmed]; - } - $null = null; - return $null; - } - /** - * Returns the index of a column given its key. - * @param string $key The name of the column key. - * @return MySQLColumn|null The index of the column if a column was - * found which has the given key. -1 in case of no column was found. - * @since 1.6 - */ - public function getColIndex($key){ - $trimmed = trim($key); - if(isset($this->colSet[$trimmed])){ - return $this->colSet[$trimmed]->getIndex(); - } - return -1; - } - /** - * Returns a column given its index. - * @param int $index The index of the column. - * @return MySQLColumn|null If a column was found which has the specified index, - * it is returned. Other than that, The method will return null. - * @since 1.6 - */ - public function getColByIndex($index){ - foreach ($this->colSet as $k => $col){ - if($col->getIndex() == $index){ - return $col; - } - } - $null = null; - return $null; - } - /** - * Returns an array that contains all the keys the columns was stored in - * the table. - * @return array an array that contains all the set of keys. - * @since 1.2 - */ - public function colsKeys(){ - return array_keys($this->colSet); - } - /** - * Returns the name of the storage engine used by the table. - * @return string The name of the storage engine used by the table. The default - * value is 'InnoDB'. - * @since 1.0 - */ - public function getEngine(){ - return $this->engin; - } - /** - * Returns the character set that is used by the table. - * @return string The character set that is used by the table.. The default - * value is 'utf8'. - * @since 1.0 - */ - public function getCharSet(){ - return $this->charSet; + return $actualKeyLen != 0; } } diff --git a/test.php b/test.php index d892d4e..a9544e1 100644 --- a/test.php +++ b/test.php @@ -7,10 +7,10 @@ require 'MySQLQuery.php'; require 'MySQLLink.php'; use phMysql\MySQLColumn; -use phMysql\Table; -use phMysql\MySQLQuery; use phMysql\MySQLLink; -class Q extends MySQLQuery{ +use phMysql\MySQLQuery; +use phMysql\Table; +class Q extends MySQLQuery { /** * * @var Table @@ -26,50 +26,49 @@ public function __construct() { public function getStructure() { return $this->table; } - } $link = new MySQLLink('localhost', 'root', 'xxxx'); -if($link->isConnected()){ + +if ($link->isConnected()) { print_message('Connected.'); $result = $link->setDB('x_db'); - if($result === TRUE){ + + if ($result === true) { print_message('Database Selected.'); $q = new Q(); $q->select(); print_message($q->getQuery()); $result = $link->executeQuery($q); - if($result === TRUE){ + + if ($result === true) { print_message('Query was executed.'); var_dump($link->getColumn('col-3')); fetchRows($link); - } - else{ + } else { print_message('Query not executed.'); print_message('Error Number: '.$link->getErrorCode()); print_message('Details: '.$link->getErrorMessage()); } - } - else{ + } else { print_message('Unable to select database.'); print_message('Error Number: '.$link->getErrorCode()); print_message('Details: '.$link->getErrorMessage()); } -} -else{ +} else { print_message('Error Number: '.$link->getErrorCode()); print_message('Details: '.$link->getErrorMessage()); } -function print_message($message){ +function print_message($message) { echo '
'.$message.'
'; } /** * * @param DatabaseLink $link */ -function fetchRows($link){ - while($row = $link->getRow()){ +function fetchRows($link) { + while ($row = $link->getRow()) { ?>
getTable()->addDefaultCols([ - 'id'=>[ - 'key-name'=>'article-id', - 'db-name'=>'article_id' + 'id' => [ + 'key-name' => 'article-id', + 'db-name' => 'article_id' ], - 'created-on'=>[], - 'last-updated'=>[] + 'created-on' => [], + 'last-updated' => [] ]); $this->getTable()->addColumns([ - 'author-id'=>[ - 'name'=>'author_id', - 'datatype'=>'int', - 'size'=>11 + 'author-id' => [ + 'name' => 'author_id', + 'datatype' => 'int', + 'size' => 11 ], - 'title'=>[ - 'size'=>150, + 'title' => [ + 'size' => 150, ], - 'content'=>[ - 'name'=>'article_content', - 'size'=>5000 + 'content' => [ + 'name' => 'article_content', + 'size' => 5000 ] ]); - + $this->getTable()->addReference('phMysql\tests\UsersQuery', [ - 'author-id'=>'user-id' + 'author-id' => 'user-id' ], 'author_fk'); } } - diff --git a/tests/ColumnTest.php b/tests/ColumnTest.php index 473fb7d..6248a96 100644 --- a/tests/ColumnTest.php +++ b/tests/ColumnTest.php @@ -1,13 +1,59 @@ setComment('A unique ID for the user.'); + $this->assertEquals('A unique ID for the user.',$col->getComment()); + $this->assertEquals('user_id varchar(15) not null collate utf8mb4_unicode_ci comment \'A unique ID for the user.\'',$col.''); + + return $col; + } + /** + * @test + * @depends setCommentTest00 + * @param MySQLColumn $col Description + */ + public function setCommentTest01($col) { + $col->setComment(null); + $this->assertNull($col->getComment()); + $this->assertEquals('user_id varchar(15) not null collate utf8mb4_unicode_ci',$col.''); + } + /** + * @test + */ + public function testAutoUpdate00() { + $col = new MySQLColumn(); + $this->assertFalse($col->isAutoUpdate()); + $col->setAutoUpdate(true); + $this->assertFalse($col->isAutoUpdate()); + $col->setType('datetime'); + $col->setAutoUpdate(true); + $this->assertTrue($col->isAutoUpdate()); + } + /** + * @test + */ + public function testAutoUpdate01() { + $col = new MySQLColumn(); + $this->assertFalse($col->isAutoUpdate()); + $col->setAutoUpdate(true); + $this->assertFalse($col->isAutoUpdate()); + $col->setType('timestamp'); + $col->setAutoUpdate(true); + $this->assertTrue($col->isAutoUpdate()); + } /** * @test */ @@ -81,158 +127,6 @@ public function testCleanValue07() { $this->assertEquals('\'2019-11-01 00:00:00\'',$col->cleanValue('2019-11-01')); $this->assertEquals('\'2019-11-01 23:09:44\'',$col->cleanValue('2019-11-01 23:09:44')); } - /** - * @test - */ - public function testSetName00() { - $col = new MySQLColumn(); - $this->assertFalse($col->setName('invalid,name')); - $this->assertFalse($col->setName('invalid-name')); - $this->assertFalse($col->setName('invalid name')); - $this->assertFalse($col->setName('')); - $this->assertFalse($col->setName(' ')); - } - /** - * @test - */ - public function testSetName01() { - $col = new MySQLColumn(); - $this->assertTrue($col->setName('valid_name')); - $this->assertEquals('valid_name',$col->getName()); - $this->assertTrue($col->setName(' valid_name_2 ')); - $this->assertEquals('valid_name_2',$col->getName()); - $this->assertTrue($col->setName('VALID_name')); - $this->assertEquals('VALID_name',$col->getName()); - } - /** - * @test - */ - public function testSetType00() { - $col = new MySQLColumn(); - $this->assertTrue($col->setType('int', 0)); - $this->assertEquals('int',$col->getType()); - $this->assertEquals(1,$col->getSize()); - $this->assertNull($col->getDefault()); - $this->assertTrue($col->setType(' int', 11,6000)); - $this->assertEquals('int',$col->getType()); - $this->assertEquals(11,$col->getSize()); - $this->assertEquals(6000,$col->getDefault()); - $this->assertTrue($col->setType('int ', 12,698)); - $this->assertEquals('int',$col->getType()); - $this->assertEquals(11,$col->getSize()); - } - /** - * @test - */ - public function testSetType01() { - $col = new MySQLColumn(); - $this->assertTrue($col->setType('varchar', 0)); - $this->assertEquals('varchar',$col->getType()); - $this->assertEquals(1,$col->getSize()); - $this->assertNull($col->getDefault()); - $this->assertTrue($col->setType(' varchar', 5000,6000)); - $this->assertEquals('varchar',$col->getType()); - $this->assertEquals(5000,$col->getSize()); - $this->assertSame('6000',$col->getDefault()); - $this->assertTrue($col->setType('varchar ', 500000,'Hello World')); - $this->assertEquals('mediumtext',$col->getType()); - $this->assertEquals(500000,$col->getSize()); - $this->assertSame('Hello World',$col->getDefault()); - } - /** - * @test - */ - public function testSetType02() { - $col = new MySQLColumn(); - $this->assertTrue($col->setType('varchar', 5000,'Hello')); - $this->assertEquals('varchar',$col->getType()); - $this->assertEquals(5000,$col->getSize()); - $this->assertSame('Hello',$col->getDefault()); - $col->setType('int'); - $this->assertEquals('int',$col->getType()); - $this->assertEquals(1,$col->getSize()); - $this->assertNull($col->getDefault()); - } - /** - * @test - */ - public function testSetType03() { - $col = new MySQLColumn(); - $this->assertTrue($col->setType('datetime', 0,'2019-01-11')); - $this->assertEquals('datetime',$col->getType()); - $this->assertEquals(1,$col->getSize()); - $this->assertSame('2019-01-11 00:00:00',$col->getDefault()); - } - /** - * @test - */ - public function testSetType04() { - $col = new MySQLColumn(); - $this->assertTrue($col->setType('datetime', 0,'2019-01-11 28:00:00')); - $this->assertEquals('datetime',$col->getType()); - $this->assertEquals(1,$col->getSize()); - $this->assertNull($col->getDefault()); - $this->assertTrue($col->setType('timestamp', 0,'2019-13-11 00:00:00')); - $this->assertNull($col->getDefault()); - $this->assertTrue($col->setType('timestamp', 0,'2019-04-44 00:00:00')); - $this->assertNull($col->getDefault()); - $this->assertTrue($col->setType('timestamp', 0,'2019-12-11 00:60:00')); - $this->assertNull($col->getDefault()); - $this->assertTrue($col->setType('timestamp', 0,'2019-12-11 00:00:60')); - $this->assertNull($col->getDefault()); - $this->assertTrue($col->setType('timestamp', 0,'2019-12-30 23:59:59')); - $this->assertEquals('2019-12-30 23:59:59',$col->getDefault()); - } - /** - * @test - */ - public function testSetType05() { - $col = new MySQLColumn(); - $this->assertTrue($col->setType('datetime', 0,'now()')); - $this->assertTrue(in_array($col->getDefault(), - [date('Y-m-d H:i:s + 1'),date('Y-m-d H:i:s'),date('Y-m-d H:i:s - 1')])); - $this->assertTrue($col->setType('datetime', 0,'current_timestamp')); - $this->assertTrue(in_array($col->getDefault(), - [date('Y-m-d H:i:s + 1'),date('Y-m-d H:i:s'),date('Y-m-d H:i:s - 1')])); - - } - /** - * @test - */ - public function testSetType06() { - $col = new MySQLColumn(); - $this->assertTrue($col->setType('timestamp', 0,'now()')); - $this->assertTrue(in_array($col->getDefault(), - [date('Y-m-d H:i:s + 1'),date('Y-m-d H:i:s'),date('Y-m-d H:i:s - 1')])); - $this->assertTrue($col->setType('timestamp', 0,'current_timestamp')); - $this->assertTrue(in_array($col->getDefault(), - [date('Y-m-d H:i:s + 1'),date('Y-m-d H:i:s'),date('Y-m-d H:i:s - 1')])); - - } - /** - * @test - */ - public function testAutoUpdate00() { - $col = new MySQLColumn(); - $this->assertFalse($col->isAutoUpdate()); - $col->setAutoUpdate(true); - $this->assertFalse($col->isAutoUpdate()); - $col->setType('datetime'); - $col->setAutoUpdate(true); - $this->assertTrue($col->isAutoUpdate()); - } - /** - * @test - */ - public function testAutoUpdate01() { - $col = new MySQLColumn(); - $this->assertFalse($col->isAutoUpdate()); - $col->setAutoUpdate(true); - $this->assertFalse($col->isAutoUpdate()); - $col->setType('timestamp'); - $col->setAutoUpdate(true); - $this->assertTrue($col->isAutoUpdate()); - } /** * @test */ @@ -321,6 +215,7 @@ public function testConstructor09() { $col = new MySQLColumn('amount', 'decimal '); $this->assertEquals('decimal',$col->getType()); $this->assertEquals(1,$col->getSize()); + return $col; } /** @@ -331,6 +226,7 @@ public function testConstructor10() { $this->assertEquals('decimal',$col->getType()); $this->assertEquals(0,$col->getSize()); $this->assertEquals(0,$col->getScale()); + return $col; } /** @@ -341,6 +237,7 @@ public function testConstructor11() { $this->assertEquals('decimal',$col->getType()); $this->assertEquals(1,$col->getSize()); $this->assertEquals(0,$col->getScale()); + return $col; } /** @@ -351,6 +248,7 @@ public function testConstructor12() { $this->assertEquals('decimal',$col->getType()); $this->assertEquals(2,$col->getSize()); $this->assertEquals(1,$col->getScale()); + return $col; } /** @@ -361,6 +259,7 @@ public function testConstructor13() { $this->assertEquals('decimal',$col->getType()); $this->assertEquals(3,$col->getSize()); $this->assertEquals(2,$col->getScale()); + return $col; } /** @@ -371,6 +270,7 @@ public function testConstructor14() { $this->assertEquals('decimal',$col->getType()); $this->assertEquals(4,$col->getSize()); $this->assertEquals(2,$col->getScale()); + return $col; } /** @@ -381,60 +281,9 @@ public function testConstructor15() { $this->assertEquals('decimal',$col->getType()); $this->assertEquals(10,$col->getSize()); $this->assertEquals(2,$col->getScale()); + return $col; } - /** - * - * @param MySQLColumn $col - * @depends testConstructor09 - */ - public function testSetScale00($col) { - $col->setSize(10); - $this->assertTrue($col->setScale(3)); - $this->assertEquals(3,$col->getScale()); - $this->assertTrue($col->setScale(0)); - $this->assertEquals(0,$col->getScale()); - $this->assertTrue($col->setScale(9)); - $this->assertEquals(9,$col->getScale()); - $this->assertFalse($col->setScale(10)); - $this->assertEquals(9,$col->getScale()); - } - /** - * @test - */ - public function testSetMySQLVersion00() { - $col = new MySQLColumn(); - $col->setMySQLVersion('5.4'); - $this->assertEquals('5.4',$col->getMySQLVersion()); - $this->assertEquals('utf8mb4_unicode_ci',$col->getCollation()); - } - /** - * @test - */ - public function testSetMySQLVersion01() { - $col = new MySQLColumn(); - $col->setMySQLVersion('8.0'); - $this->assertEquals('8.0',$col->getMySQLVersion()); - $this->assertEquals('utf8mb4_unicode_520_ci',$col->getCollation()); - } - /** - * @test - */ - public function testSetMySQLVersion02() { - $column = new MySQLColumn(); - $column->setMySQLVersion('8'); - $this->assertEquals('5.5',$column->getMySQLVersion()); - $this->assertEquals('utf8mb4_unicode_ci',$column->getCollation()); - } - /** - * @test - */ - public function testSetMySQLVersion03() { - $col = new MySQLColumn(); - $col->setMySQLVersion('8.0.77'); - $this->assertEquals('8.0.77',$col->getMySQLVersion()); - $this->assertEquals('utf8mb4_unicode_520_ci',$col->getCollation()); - } /** * @test */ @@ -448,26 +297,6 @@ public function testSetColName00() { $this->assertFalse($col->setName('use id ')); $this->assertFalse($col->setName(' ')); } - /** - * @test - */ - public function setCommentTest00() { - $col = new MySQLColumn('user_id ', 'varchar', 15); - $col->setComment('A unique ID for the user.'); - $this->assertEquals('A unique ID for the user.',$col->getComment()); - $this->assertEquals('user_id varchar(15) not null collate utf8mb4_unicode_ci comment \'A unique ID for the user.\'',$col.''); - return $col; - } - /** - * @test - * @depends setCommentTest00 - * @param MySQLColumn $col Description - */ - public function setCommentTest01($col) { - $col->setComment(null); - $this->assertNull($col->getComment()); - $this->assertEquals('user_id varchar(15) not null collate utf8mb4_unicode_ci',$col.''); - } /** * @test */ @@ -575,4 +404,182 @@ public function testSetDefault07() { $col->setDefault(''); $this->assertEquals(0,$col->getDefault()); } + /** + * @test + */ + public function testSetMySQLVersion00() { + $col = new MySQLColumn(); + $col->setMySQLVersion('5.4'); + $this->assertEquals('5.4',$col->getMySQLVersion()); + $this->assertEquals('utf8mb4_unicode_ci',$col->getCollation()); + } + /** + * @test + */ + public function testSetMySQLVersion01() { + $col = new MySQLColumn(); + $col->setMySQLVersion('8.0'); + $this->assertEquals('8.0',$col->getMySQLVersion()); + $this->assertEquals('utf8mb4_unicode_520_ci',$col->getCollation()); + } + /** + * @test + */ + public function testSetMySQLVersion02() { + $column = new MySQLColumn(); + $column->setMySQLVersion('8'); + $this->assertEquals('5.5',$column->getMySQLVersion()); + $this->assertEquals('utf8mb4_unicode_ci',$column->getCollation()); + } + /** + * @test + */ + public function testSetMySQLVersion03() { + $col = new MySQLColumn(); + $col->setMySQLVersion('8.0.77'); + $this->assertEquals('8.0.77',$col->getMySQLVersion()); + $this->assertEquals('utf8mb4_unicode_520_ci',$col->getCollation()); + } + /** + * @test + */ + public function testSetName00() { + $col = new MySQLColumn(); + $this->assertFalse($col->setName('invalid,name')); + $this->assertFalse($col->setName('invalid-name')); + $this->assertFalse($col->setName('invalid name')); + $this->assertFalse($col->setName('')); + $this->assertFalse($col->setName(' ')); + } + /** + * @test + */ + public function testSetName01() { + $col = new MySQLColumn(); + $this->assertTrue($col->setName('valid_name')); + $this->assertEquals('valid_name',$col->getName()); + $this->assertTrue($col->setName(' valid_name_2 ')); + $this->assertEquals('valid_name_2',$col->getName()); + $this->assertTrue($col->setName('VALID_name')); + $this->assertEquals('VALID_name',$col->getName()); + } + /** + * + * @param MySQLColumn $col + * @depends testConstructor09 + */ + public function testSetScale00($col) { + $col->setSize(10); + $this->assertTrue($col->setScale(3)); + $this->assertEquals(3,$col->getScale()); + $this->assertTrue($col->setScale(0)); + $this->assertEquals(0,$col->getScale()); + $this->assertTrue($col->setScale(9)); + $this->assertEquals(9,$col->getScale()); + $this->assertFalse($col->setScale(10)); + $this->assertEquals(9,$col->getScale()); + } + /** + * @test + */ + public function testSetType00() { + $col = new MySQLColumn(); + $this->assertTrue($col->setType('int', 0)); + $this->assertEquals('int',$col->getType()); + $this->assertEquals(1,$col->getSize()); + $this->assertNull($col->getDefault()); + $this->assertTrue($col->setType(' int', 11,6000)); + $this->assertEquals('int',$col->getType()); + $this->assertEquals(11,$col->getSize()); + $this->assertEquals(6000,$col->getDefault()); + $this->assertTrue($col->setType('int ', 12,698)); + $this->assertEquals('int',$col->getType()); + $this->assertEquals(11,$col->getSize()); + } + /** + * @test + */ + public function testSetType01() { + $col = new MySQLColumn(); + $this->assertTrue($col->setType('varchar', 0)); + $this->assertEquals('varchar',$col->getType()); + $this->assertEquals(1,$col->getSize()); + $this->assertNull($col->getDefault()); + $this->assertTrue($col->setType(' varchar', 5000,6000)); + $this->assertEquals('varchar',$col->getType()); + $this->assertEquals(5000,$col->getSize()); + $this->assertSame('6000',$col->getDefault()); + $this->assertTrue($col->setType('varchar ', 500000,'Hello World')); + $this->assertEquals('mediumtext',$col->getType()); + $this->assertEquals(500000,$col->getSize()); + $this->assertSame('Hello World',$col->getDefault()); + } + /** + * @test + */ + public function testSetType02() { + $col = new MySQLColumn(); + $this->assertTrue($col->setType('varchar', 5000,'Hello')); + $this->assertEquals('varchar',$col->getType()); + $this->assertEquals(5000,$col->getSize()); + $this->assertSame('Hello',$col->getDefault()); + $col->setType('int'); + $this->assertEquals('int',$col->getType()); + $this->assertEquals(1,$col->getSize()); + $this->assertNull($col->getDefault()); + } + /** + * @test + */ + public function testSetType03() { + $col = new MySQLColumn(); + $this->assertTrue($col->setType('datetime', 0,'2019-01-11')); + $this->assertEquals('datetime',$col->getType()); + $this->assertEquals(1,$col->getSize()); + $this->assertSame('2019-01-11 00:00:00',$col->getDefault()); + } + /** + * @test + */ + public function testSetType04() { + $col = new MySQLColumn(); + $this->assertTrue($col->setType('datetime', 0,'2019-01-11 28:00:00')); + $this->assertEquals('datetime',$col->getType()); + $this->assertEquals(1,$col->getSize()); + $this->assertNull($col->getDefault()); + $this->assertTrue($col->setType('timestamp', 0,'2019-13-11 00:00:00')); + $this->assertNull($col->getDefault()); + $this->assertTrue($col->setType('timestamp', 0,'2019-04-44 00:00:00')); + $this->assertNull($col->getDefault()); + $this->assertTrue($col->setType('timestamp', 0,'2019-12-11 00:60:00')); + $this->assertNull($col->getDefault()); + $this->assertTrue($col->setType('timestamp', 0,'2019-12-11 00:00:60')); + $this->assertNull($col->getDefault()); + $this->assertTrue($col->setType('timestamp', 0,'2019-12-30 23:59:59')); + $this->assertEquals('2019-12-30 23:59:59',$col->getDefault()); + } + /** + * @test + */ + public function testSetType05() { + $col = new MySQLColumn(); + $this->assertTrue($col->setType('datetime', 0,'now()')); + $this->assertTrue(in_array($col->getDefault(), + [date('Y-m-d H:i:s + 1'),date('Y-m-d H:i:s'),date('Y-m-d H:i:s - 1')])); + $this->assertTrue($col->setType('datetime', 0,'current_timestamp')); + $this->assertTrue(in_array($col->getDefault(), + [date('Y-m-d H:i:s + 1'),date('Y-m-d H:i:s'),date('Y-m-d H:i:s - 1')])); + } + /** + * @test + */ + public function testSetType06() { + $col = new MySQLColumn(); + $this->assertTrue($col->setType('timestamp', 0,'now()')); + $this->assertTrue(in_array($col->getDefault(), + [date('Y-m-d H:i:s + 1'),date('Y-m-d H:i:s'),date('Y-m-d H:i:s - 1')])); + $this->assertTrue($col->setType('timestamp', 0,'current_timestamp')); + $this->assertTrue(in_array($col->getDefault(), + [date('Y-m-d H:i:s + 1'),date('Y-m-d H:i:s'),date('Y-m-d H:i:s - 1')])); + } } diff --git a/tests/EntityUser.php b/tests/EntityUser.php index 6f905fa..8f43f61 100644 --- a/tests/EntityUser.php +++ b/tests/EntityUser.php @@ -7,28 +7,28 @@ * @author Ibrahim */ class EntityUser { - private $userId; private $email; private $name; - public function getName() { - return $this->name; + private $userId; + public function __toString() { + return 'ID: ['.$this->userId.'] Name: ['.$this->name.'] Email: ['.$this->email.']'; } public function getEmail() { return $this->email; } + public function getName() { + return $this->name; + } public function getUserId() { return $this->userId; } - public function setUserId($id) { - $this->userId = $id; + public function setEmail($email) { + $this->email = $email; } public function setName($name) { $this->name = $name; } - public function setEmail($email) { - $this->email = $email; - } - public function __toString() { - return 'ID: ['.$this->userId.'] Name: ['.$this->name.'] Email: ['.$this->email.']'; + public function setUserId($id) { + $this->userId = $id; } } diff --git a/tests/FKTest.php b/tests/FKTest.php index f8097b0..814dc02 100644 --- a/tests/FKTest.php +++ b/tests/FKTest.php @@ -5,25 +5,36 @@ * To change this template file, choose Tools | Templates * and open the template in the editor. */ - namespace phMysql\tests; + use phMysql\ForeignKey; -use phMysql\MySQLTable; use phMysql\MySQLColumn; +use phMysql\MySQLTable; use PHPUnit\Framework\TestCase; /** * Description of FKTest * * @author Ibrahim */ -class FKTest extends TestCase{ +class FKTest extends TestCase { /** - * @test + * + * @param ForeignKey $fk + * @depends testRemoveReference00 */ - public function testSetOwner00() { - $fk = new ForeignKey(); - $fk->setOwner(null); - $this->assertNull($fk->getOwner()); + public function testAddReference00($fk) { + $this->assertTrue($fk->addReference('user-id')); + $this->assertEquals(1,count($fk->getOwnerCols())); + $this->assertEquals(1,count($fk->getSourceCols())); + $this->assertTrue($fk->addReference('user-id')); + $this->assertEquals(1,count($fk->getOwnerCols())); + $this->assertEquals(1,count($fk->getSourceCols())); + $this->assertFalse($fk->addReference('user-email')); + $this->assertEquals(1,count($fk->getOwnerCols())); + $this->assertEquals(1,count($fk->getSourceCols())); + $this->assertTrue($fk->addReference('user-email','email-2')); + $this->assertEquals(2,count($fk->getOwnerCols())); + $this->assertEquals(2,count($fk->getSourceCols())); } /** * @test @@ -38,16 +49,7 @@ public function testConstructor00() { $this->assertEquals('key_name',$fk->getKeyName()); $this->assertEquals([],$fk->getSourceCols()); $this->assertEquals([],$fk->getOwnerCols()); - return $fk; - } - /** - * @test - */ - public function testConstructor02() { - $fk = new ForeignKey('invalid name'); - $this->assertEquals('key_name',$fk->getKeyName()); - $this->assertFalse($fk->setKeyName('0invalid')); - $this->assertEquals('key_name',$fk->getKeyName()); + return $fk; } /** @@ -64,12 +66,24 @@ public function testConstructor01() { $source->addColumn('email', new MySQLColumn('email', 'int')); $source->addColumn('email-2', new MySQLColumn('email_2', 'varchar')); $fk = new ForeignKey('new_key',$owner,$source,[ - 'user-id'=>'user-id', - 'user-email'=>'email-2' + 'user-id' => 'user-id', + 'user-email' => 'email-2' ]); $this->assertNotNull($fk->getOwner()); $this->assertEquals(2,count($fk->getOwnerCols())); $this->assertEquals(2,count($fk->getSourceCols())); + + return $fk; + } + /** + * @test + */ + public function testConstructor02() { + $fk = new ForeignKey('invalid name'); + $this->assertEquals('key_name',$fk->getKeyName()); + $this->assertFalse($fk->setKeyName('0invalid')); + $this->assertEquals('key_name',$fk->getKeyName()); + return $fk; } /** @@ -88,26 +102,48 @@ public function testRemoveReference00($fk) { $this->assertTrue($fk->removeReference(' user-id')); $this->assertEquals(0,count($fk->getOwnerCols())); $this->assertEquals(0,count($fk->getSourceCols())); + return $fk; } /** - * - * @param ForeignKey $fk - * @depends testRemoveReference00 + * @test */ - public function testAddReference00($fk) { - $this->assertTrue($fk->addReference('user-id')); - $this->assertEquals(1,count($fk->getOwnerCols())); - $this->assertEquals(1,count($fk->getSourceCols())); - $this->assertTrue($fk->addReference('user-id')); - $this->assertEquals(1,count($fk->getOwnerCols())); - $this->assertEquals(1,count($fk->getSourceCols())); - $this->assertFalse($fk->addReference('user-email')); - $this->assertEquals(1,count($fk->getOwnerCols())); - $this->assertEquals(1,count($fk->getSourceCols())); - $this->assertTrue($fk->addReference('user-email','email-2')); - $this->assertEquals(2,count($fk->getOwnerCols())); - $this->assertEquals(2,count($fk->getSourceCols())); + public function testSetKeyName00() { + $fk = new ForeignKey(); + $this->assertTrue($fk->setKeyName('valid_key_name')); + $this->assertEquals('valid_key_name',$fk->getKeyName()); + } + /** + * @test + */ + public function testSetKeyName01() { + $fk = new ForeignKey(); + $this->assertFalse($fk->setKeyName('0invalid_key_name')); + $this->assertEquals('key_name',$fk->getKeyName()); + } + /** + * @test + */ + public function testSetKeyName02() { + $fk = new ForeignKey(); + $this->assertFalse($fk->setKeyName('invalid-key-name')); + $this->assertEquals('key_name',$fk->getKeyName()); + } + /** + * @test + */ + public function testSetKeyName03() { + $fk = new ForeignKey(); + $this->assertTrue($fk->setKeyName(" valid_key_name \n")); + $this->assertEquals('valid_key_name',$fk->getKeyName()); + } + /** + * @test + */ + public function testSetKeyName04() { + $fk = new ForeignKey(); + $this->assertFalse($fk->setKeyName('')); + $this->assertEquals('key_name',$fk->getKeyName()); } /** * @test @@ -148,41 +184,9 @@ public function testSetOnUpdate() { /** * @test */ - public function testSetKeyName00() { - $fk = new ForeignKey(); - $this->assertTrue($fk->setKeyName('valid_key_name')); - $this->assertEquals('valid_key_name',$fk->getKeyName()); - } - /** - * @test - */ - public function testSetKeyName01() { - $fk = new ForeignKey(); - $this->assertFalse($fk->setKeyName('0invalid_key_name')); - $this->assertEquals('key_name',$fk->getKeyName()); - } - /** - * @test - */ - public function testSetKeyName02() { - $fk = new ForeignKey(); - $this->assertFalse($fk->setKeyName('invalid-key-name')); - $this->assertEquals('key_name',$fk->getKeyName()); - } - /** - * @test - */ - public function testSetKeyName03() { - $fk = new ForeignKey(); - $this->assertTrue($fk->setKeyName(" valid_key_name \n")); - $this->assertEquals('valid_key_name',$fk->getKeyName()); - } - /** - * @test - */ - public function testSetKeyName04() { + public function testSetOwner00() { $fk = new ForeignKey(); - $this->assertFalse($fk->setKeyName('')); - $this->assertEquals('key_name',$fk->getKeyName()); + $fk->setOwner(null); + $this->assertNull($fk->getOwner()); } } diff --git a/tests/JoinTest.php b/tests/JoinTest.php index 6afc256..ee47568 100644 --- a/tests/JoinTest.php +++ b/tests/JoinTest.php @@ -1,17 +1,16 @@ assertTrue($joinTable->hasColumn('right-id')); $this->assertTrue($joinTable->hasColumn('right-created-on')); $this->assertTrue($joinTable->hasColumn('right-last-updated')); - + $this->assertEquals('left_id',$joinTable->getCol('left-id')->getName()); $this->assertEquals('left_created_on',$joinTable->getCol('left-created-on')->getName()); $this->assertEquals('left_last_updated',$joinTable->getCol('left-last-updated')->getName()); $this->assertEquals('right_id',$joinTable->getCol('right-id')->getName()); $this->assertEquals('right_created_on',$joinTable->getCol('right-created-on')->getName()); $this->assertEquals('right_last_updated',$joinTable->getCol('right-last-updated')->getName()); + return $joinTable; } - /** - * @depends testConstructor01 - * @param JoinTable $table - */ - public function testSetJoinCondition00($table) { - $table->setJoinCondition(['id'=>'id']); - $this->assertEquals('on a_left_table.id = a_right_table.id',$table->getJoinCondition()); - $table->setJoinCondition(['id'=>'id','created-on'=>'created-on']); - $this->assertEquals('on a_left_table.id = a_right_table.id and a_left_table.created_on = a_right_table.created_on',$table->getJoinCondition()); - return $table; - } - - /** - * @depends testSetJoinCondition00 - * @param JoinTable $table - */ - public function testJoinSelect00($table) { - $query = new MySQLQuery(); - $query->setTable($table); - $query->select(); - $this->assertEquals('select * from (' - . 'select '."\n" - . 'a_left_table.id as left_id,'."\n" - . 'a_left_table.created_on as left_created_on,'."\n" - . 'a_left_table.last_updated as left_last_updated,'."\n" - . 'a_right_table.id as right_id,'."\n" - . 'a_right_table.created_on as right_created_on,'."\n" - . 'a_right_table.last_updated as right_last_updated'."\n" - . 'from a_left_table left join a_right_table'."\n" - . 'on a_left_table.id = a_right_table.id and a_left_table.created_on = a_right_table.created_on' - . ")\nas JoinTable;",$query->getQuery()); - $query->select([ - 'without-select'=>true - ]); - $this->assertEquals('' - . 'select '."\n" - . 'a_left_table.id as left_id,'."\n" - . 'a_left_table.created_on as left_created_on,'."\n" - . 'a_left_table.last_updated as left_last_updated,'."\n" - . 'a_right_table.id as right_id,'."\n" - . 'a_right_table.created_on as right_created_on,'."\n" - . 'a_right_table.last_updated as right_last_updated'."\n" - . 'from a_left_table left join a_right_table'."\n" - . 'on a_left_table.id = a_right_table.id and a_left_table.created_on = a_right_table.created_on' - . '',$query->getQuery()); - return $query; - } - /** - * @depends testJoinSelect00 - * @param MySQLQuery $query - * @test - */ - public function testJoinSelect01($query) { - $query->select([ - 'columns'=>[ - 'id','created-on' - ] - ]); - $this->assertEquals('select * from (' - . 'select '."\n" - . 'a_left_table.id as left_id,'."\n" - . 'a_left_table.created_on as left_created_on'."\n" - . 'from a_left_table left join a_right_table'."\n" - . 'on a_left_table.id = a_right_table.id and a_left_table.created_on = a_right_table.created_on' - . ")\nas JoinTable;",$query->getQuery()); - $query->select([ - 'columns'=>[ - 'id'=>'user_id', - 'created-on'=>'insert_date' - ] - ]); - $this->assertEquals('select * from (' - . 'select '."\n" - . 'a_left_table.id as user_id,'."\n" - . 'a_left_table.created_on as insert_date'."\n" - . 'from a_left_table left join a_right_table'."\n" - . 'on a_left_table.id = a_right_table.id and a_left_table.created_on = a_right_table.created_on' - . ")\nas JoinTable;",$query->getQuery()); - return $query; - } - /** - * @depends testJoinSelect01 - * @param MySQLQuery $query - * @test - */ - public function testJoinSelect02($query) { - $query->select([ - 'columns'=>[ - 'left'=>[ - 'id','created-on' - ], - 'right'=>[ - 'last-updated' - ] - ] - ]); - $this->assertEquals('select * from (' - . 'select '."\n" - . 'a_left_table.id as left_id,'."\n" - . 'a_left_table.created_on as left_created_on,'."\n" - . 'a_right_table.last_updated as right_last_updated'."\n" - . 'from a_left_table left join a_right_table'."\n" - . 'on a_left_table.id = a_right_table.id and a_left_table.created_on = a_right_table.created_on' - . ")\nas JoinTable;",$query->getQuery()); - $query->select([ - 'columns'=>[ - 'left'=>[ - 'id','created-on'=>'cr_date' - ], - 'right'=>[ - 'last-updated'=>'l_updated' - ] - ] - ]); - $this->assertEquals('select * from (' - . 'select '."\n" - . 'a_left_table.id as left_id,'."\n" - . 'a_left_table.created_on as cr_date,'."\n" - . 'a_right_table.last_updated as l_updated'."\n" - . 'from a_left_table left join a_right_table'."\n" - . 'on a_left_table.id = a_right_table.id and a_left_table.created_on = a_right_table.created_on' - . ")\nas JoinTable;",$query->getQuery()); - return $query; - } - /** - * @depends testJoinSelect02 - * @param MySQLQuery $query - * @test - */ - public function testJoinSelect03($query) { - $query->select([ - 'columns'=>[ - 'left'=>[ - 'id','created-on'=>'cr_date' - ], - 'right'=>[ - 'last-updated'=>'l_updated' - ] - ], - 'where'=>[ - 'left-id'=>44 - ] - ]); - $this->assertEquals('select * from (' - . 'select '."\n" - . 'a_left_table.id as left_id,'."\n" - . 'a_left_table.created_on as cr_date,'."\n" - . 'a_right_table.last_updated as l_updated'."\n" - . 'from a_left_table left join a_right_table'."\n" - . 'on a_left_table.id = a_right_table.id and a_left_table.created_on = a_right_table.created_on' - . ")\nas JoinTable where JoinTable.left_id = 44;",$query->getQuery()); - } public function testJoin00() { $query0 = new MySQLQuery('users'); $query0->getTable()->addColumns([ - 'user-id'=>[ - 'is-primary'=>true, - 'size'=>15 + 'user-id' => [ + 'is-primary' => true, + 'size' => 15 ], - 'created-on'=>[ - 'datatype'=>'timestamp', - 'default'=>'current_timestamp' + 'created-on' => [ + 'datatype' => 'timestamp', + 'default' => 'current_timestamp' ], - 'password'=>[ - 'size'=>64 + 'password' => [ + 'size' => 64 ], - 'display-name'=>[ - 'size'=>30 + 'display-name' => [ + 'size' => 30 ], - 'last-login'=>[ - 'datatype'=>'datetime', - 'is-null'=>true + 'last-login' => [ + 'datatype' => 'datetime', + 'is-null' => true ], - 'last-updated'=>[ - 'datatype'=>'datetime', - 'is-null'=>true + 'last-updated' => [ + 'datatype' => 'datetime', + 'is-null' => true ] ]); $query1 = new MySQLQuery('user_articles'); $query1->getTable()->addColumns([ - 'article-id'=>[ - 'is-primary'=>true, - 'size'=>'10' + 'article-id' => [ + 'is-primary' => true, + 'size' => '10' ], - 'title'=>[ - 'size'=>150 + 'title' => [ + 'size' => 150 ], - 'content'=>[ - 'size'=>5000 + 'content' => [ + 'size' => 5000 ], - 'created-on'=>[ - 'datatype'=>'timestamp', - 'default'=>'current_timestamp' + 'created-on' => [ + 'datatype' => 'timestamp', + 'default' => 'current_timestamp' ], - 'last-updated'=>[ - 'datatype'=>'datetime', - 'is-null'=>true + 'last-updated' => [ + 'datatype' => 'datetime', + 'is-null' => true ], - 'user-id'=>[ - 'is-primary'=>true, - 'size'=>15 + 'user-id' => [ + 'is-primary' => true, + 'size' => 15 ], ]); $this->assertEquals(6,count($query0->getTable()->getColumns())); $this->assertEquals(6,count($query1->getTable()->getColumns())); $joinQuery = $query0->join([ - 'right-table'=>$query1, - 'join-cols'=>[ - 'user-id'=>'user-id' + 'right-table' => $query1, + 'join-cols' => [ + 'user-id' => 'user-id' ], - 'join-type'=>'right', - 'alias'=>'UsersArticles' + 'join-type' => 'right', + 'alias' => 'UsersArticles' ]); $joinQuery->select(); $this->assertEquals('select * from (' - . 'select '."\n" - . 'users.user_id as left_user_id,'."\n" - . 'users.created_on as left_created_on,'."\n" - . 'users.password,'."\n" - . 'users.display_name,'."\n" - . 'users.last_login,'."\n" - . 'users.last_updated as left_last_updated,'."\n" - . 'user_articles.article_id,'."\n" - . 'user_articles.title,'."\n" - . 'user_articles.content,'."\n" - . 'user_articles.created_on as right_created_on,'."\n" - . 'user_articles.last_updated as right_last_updated,'."\n" - . 'user_articles.user_id as right_user_id'."\n" - . 'from users right join user_articles'."\n" - . 'on users.user_id = user_articles.user_id)'."\n" - . 'as UsersArticles;',$joinQuery->getQuery()); + .'select '."\n" + .'users.user_id as left_user_id,'."\n" + .'users.created_on as left_created_on,'."\n" + .'users.password,'."\n" + .'users.display_name,'."\n" + .'users.last_login,'."\n" + .'users.last_updated as left_last_updated,'."\n" + .'user_articles.article_id,'."\n" + .'user_articles.title,'."\n" + .'user_articles.content,'."\n" + .'user_articles.created_on as right_created_on,'."\n" + .'user_articles.last_updated as right_last_updated,'."\n" + .'user_articles.user_id as right_user_id'."\n" + .'from users right join user_articles'."\n" + .'on users.user_id = user_articles.user_id)'."\n" + .'as UsersArticles;',$joinQuery->getQuery()); $joinQuery->select([ - 'columns'=>[ + 'columns' => [ 'user-id' ] ]); $this->assertEquals('select * from (' - . 'select '."\n" - . 'users.user_id as left_user_id'."\n" - . 'from users right join user_articles'."\n" - . 'on users.user_id = user_articles.user_id)'."\n" - . 'as UsersArticles;',$joinQuery->getQuery()); + .'select '."\n" + .'users.user_id as left_user_id'."\n" + .'from users right join user_articles'."\n" + .'on users.user_id = user_articles.user_id)'."\n" + .'as UsersArticles;',$joinQuery->getQuery()); $joinQuery->select([ - 'columns'=>[ - 'user-id'=>'a_user_id' + 'columns' => [ + 'user-id' => 'a_user_id' ] ]); $this->assertEquals('select * from (' - . 'select '."\n" - . 'users.user_id as a_user_id'."\n" - . 'from users right join user_articles'."\n" - . 'on users.user_id = user_articles.user_id)'."\n" - . 'as UsersArticles;',$joinQuery->getQuery()); + .'select '."\n" + .'users.user_id as a_user_id'."\n" + .'from users right join user_articles'."\n" + .'on users.user_id = user_articles.user_id)'."\n" + .'as UsersArticles;',$joinQuery->getQuery()); $joinQuery->select([ - 'columns'=>[ - 'user-id'=>'a_user_id', - 'right'=>[ - 'user-id'=>'x_id', + 'columns' => [ + 'user-id' => 'a_user_id', + 'right' => [ + 'user-id' => 'x_id', 'created-on' ] ] ]); $this->assertEquals('select * from (' - . 'select '."\n" - . 'user_articles.user_id as x_id,'."\n" - . 'user_articles.created_on as right_created_on,'."\n" - . 'users.user_id as a_user_id'."\n" - . 'from users right join user_articles'."\n" - . 'on users.user_id = user_articles.user_id)'."\n" - . 'as UsersArticles;',$joinQuery->getQuery()); + .'select '."\n" + .'user_articles.user_id as x_id,'."\n" + .'user_articles.created_on as right_created_on,'."\n" + .'users.user_id as a_user_id'."\n" + .'from users right join user_articles'."\n" + .'on users.user_id = user_articles.user_id)'."\n" + .'as UsersArticles;',$joinQuery->getQuery()); $joinQuery->select([ - 'columns'=>[ - 'user-id'=>'a_user_id', - 'right'=>[ - 'user-id'=>'x_id', + 'columns' => [ + 'user-id' => 'a_user_id', + 'right' => [ + 'user-id' => 'x_id', 'created-on' ] ], - 'limit'=>6 + 'limit' => 6 ]); $this->assertEquals('select * from (' - . 'select '."\n" - . 'user_articles.user_id as x_id,'."\n" - . 'user_articles.created_on as right_created_on,'."\n" - . 'users.user_id as a_user_id'."\n" - . 'from users right join user_articles'."\n" - . 'on users.user_id = user_articles.user_id)'."\n" - . 'as UsersArticles limit 6;',$joinQuery->getQuery()); + .'select '."\n" + .'user_articles.user_id as x_id,'."\n" + .'user_articles.created_on as right_created_on,'."\n" + .'users.user_id as a_user_id'."\n" + .'from users right join user_articles'."\n" + .'on users.user_id = user_articles.user_id)'."\n" + .'as UsersArticles limit 6;',$joinQuery->getQuery()); $joinQuery->select([ - 'columns'=>[ - 'user-id'=>'a_user_id', - 'right'=>[ - 'user-id'=>'x_id', + 'columns' => [ + 'user-id' => 'a_user_id', + 'right' => [ + 'user-id' => 'x_id', 'created-on' ] ], - 'limit'=>6, - 'offset'=>770 + 'limit' => 6, + 'offset' => 770 ]); $this->assertEquals('select * from (' - . 'select '."\n" - . 'user_articles.user_id as x_id,'."\n" - . 'user_articles.created_on as right_created_on,'."\n" - . 'users.user_id as a_user_id'."\n" - . 'from users right join user_articles'."\n" - . 'on users.user_id = user_articles.user_id)'."\n" - . 'as UsersArticles limit 6 offset 770;',$joinQuery->getQuery()); + .'select '."\n" + .'user_articles.user_id as x_id,'."\n" + .'user_articles.created_on as right_created_on,'."\n" + .'users.user_id as a_user_id'."\n" + .'from users right join user_articles'."\n" + .'on users.user_id = user_articles.user_id)'."\n" + .'as UsersArticles limit 6 offset 770;',$joinQuery->getQuery()); + } + /** + * + * @param MySQLQuery $query + * @depends testSelect01 + */ + public function testJoinLevel2($query) { + $anotherJoin = $query->join([ + 'right-table' => $query->getTable()->getRightTable(), + 'join-cols' => [ + 'main-user-id' => 'user-id' + ], + 'join-type' => 'join', + 'alias' => 'MoreJoins' + ]); + $anotherJoin->select(); + $this->assertEquals("select * from (select \n" + ."NewTable.left_user_id,\n" + ."NewTable.right_user_id,\n" + ."NewTable.article_title as left_article_title,\n" + ."user_articles.user_id,\n" + ."user_articles.article_title as right_article_title\n" + ."from (select \n" + ."users.user_id as left_user_id,\n" + ."user_articles.user_id as right_user_id,\n" + ."user_articles.article_title\n" + ."from users right join user_articles\n" + ."on users.user_id = user_articles.user_id) as NewTable join user_articles\n" + ."on NewTable.left_user_id = user_articles.user_id)\n" + ."as MoreJoins;",$anotherJoin->getQuery()); + } + public function testJoinNewKeys00() { + $query0 = new MySQLQuery('users'); + $query0->getTable()->addColumns([ + 'user-id' => [ + 'is-primary' => true, + 'size' => 15 + ], + 'created-on' => [ + 'datatype' => 'timestamp', + 'default' => 'current_timestamp' + ] + ]); + $query1 = new MySQLQuery('user_articles'); + $query1->getTable()->addColumns([ + 'article-id' => [ + 'is-primary' => true, + 'size' => '10' + ], + 'user-id' => [ + 'is-primary' => true, + 'size' => 15 + ], + ]); + $joinQuery = $query0->join([ + 'right-table' => $query1, + 'join-cols' => [ + 'user-id' => 'user-id' + ], + 'join-type' => 'right', + 'alias' => 'UsersArticles', + 'keys-map' => [ + 'left' => [ + 'user-id' => 'main-user-id' + ] + ] + ]); + $this->assertTrue($joinQuery->getTable()->hasColumn('main-user-id')); + $joinQuery->select([ + 'where' => [ + 'main-user-id' => 77 + ] + ]); + $this->assertEquals('select * from (' + .'select '."\n" + .'users.user_id as left_user_id,'."\n" + .'users.created_on,'."\n" + .'user_articles.article_id,'."\n" + .'user_articles.user_id as right_user_id'."\n" + .'from users right join user_articles'."\n" + .'on users.user_id = user_articles.user_id)'."\n" + .'as UsersArticles where UsersArticles.left_user_id = \'77\';',$joinQuery->getQuery()); + $joinQuery->select([ + 'where' => [ + 'main-user-id' => 77 + ], + 'columns' => [ + 'main-user-id' => 'u_id' + ] + ]); + $this->assertEquals('select * from (' + .'select '."\n" + .'users.user_id as u_id'."\n" + .'from users right join user_articles'."\n" + .'on users.user_id = user_articles.user_id)'."\n" + .'as UsersArticles where UsersArticles.u_id = \'77\';',$joinQuery->getQuery()); + $joinQuery2 = $joinQuery->join([ + 'right-table' => $query0, + 'join-cols' => [ + 'main-user-id' => 'user-id' + ], + 'alias' => 'SubJoin', + 'join-type' => 'left', + 'keys-map' => [ + 'left' => [ + 'main-user-id' => 'l-user', + 'created-on' => 'l-created-on', + 'article-id' => 'article-id', + 'right-user-id' => 'l-user-2' + ], + 'right' => [ + 'user-id' => 'r-user', + 'created-on' => 'r-created-on' + ] + ] + ]); + $this->assertEquals(6,count($joinQuery2->getTable()->getColsNames())); + $this->assertTrue($joinQuery2->getTable()->hasColumn('l-user')); + $this->assertTrue($joinQuery2->getTable()->hasColumn('l-created-on')); + $this->assertTrue($joinQuery2->getTable()->hasColumn('article-id')); + $this->assertTrue($joinQuery2->getTable()->hasColumn('l-user-2')); + $this->assertTrue($joinQuery2->getTable()->hasColumn('r-user')); + $this->assertTrue($joinQuery2->getTable()->hasColumn('r-created-on')); + $joinQuery2->select(); + $this->assertEquals('select * from (select '."\n" + .'UsersArticles.left_user_id,'."\n" + .'UsersArticles.created_on as left_created_on,'."\n" + .'UsersArticles.article_id,'."\n" + .'UsersArticles.right_user_id,'."\n" + .'users.user_id,'."\n" + .'users.created_on as right_created_on'."\n" + .'from (select '."\n" + .'users.user_id as left_user_id,'."\n" + .'users.created_on,'."\n" + .'user_articles.article_id,'."\n" + .'user_articles.user_id as right_user_id'."\n" + .'from users right join user_articles'."\n" + .'on users.user_id = user_articles.user_id) as UsersArticles left join users'."\n" + .'on UsersArticles.left_user_id = users.user_id)'."\n" + .'as SubJoin;' + .'',$joinQuery2->getQuery()); } /** * @test @@ -364,35 +353,35 @@ public function testJoin00() { public function testJoinNewKeys01() { $query0 = new MySQLQuery('users'); $query0->getTable()->addColumns([ - 'user-id'=>[ - 'is-primary'=>true, - 'size'=>15 + 'user-id' => [ + 'is-primary' => true, + 'size' => 15 ] ]); $query1 = new MySQLQuery('user_articles'); $query1->getTable()->addColumns([ - 'user-id'=>[ - 'is-primary'=>true, - 'size'=>'10' + 'user-id' => [ + 'is-primary' => true, + 'size' => '10' ], - 'article-title'=>[ - 'size'=>150 + 'article-title' => [ + 'size' => 150 ] ]); $joinQuery = $query0->join([ - 'right-table'=>$query1, - 'join-cols'=>[ - 'user-id'=>'user-id' + 'right-table' => $query1, + 'join-cols' => [ + 'user-id' => 'user-id' ], - 'join-type'=>'right', - 'alias'=>'NewTable', - 'keys-map'=>[ - 'left'=>[ - 'user-id'=>'main-user-id' + 'join-type' => 'right', + 'alias' => 'NewTable', + 'keys-map' => [ + 'left' => [ + 'user-id' => 'main-user-id' ], - 'right'=>[ - 'user-id'=>'sub-user-id', - 'article-title'=>'title' + 'right' => [ + 'user-id' => 'sub-user-id', + 'article-title' => 'title' ] ] ]); @@ -404,8 +393,153 @@ public function testJoinNewKeys01() { $this->assertTrue($joinQuery->getTable()->getLeftTable()->hasColumn('user-id')); $this->assertTrue($joinQuery->getTable()->getRightTable()->hasColumn('user-id')); $this->assertTrue($joinQuery->getTable()->getRightTable()->hasColumn('article-title')); + return $joinQuery; } + + /** + * @depends testSetJoinCondition00 + * @param JoinTable $table + */ + public function testJoinSelect00($table) { + $query = new MySQLQuery(); + $query->setTable($table); + $query->select(); + $this->assertEquals('select * from (' + .'select '."\n" + .'a_left_table.id as left_id,'."\n" + .'a_left_table.created_on as left_created_on,'."\n" + .'a_left_table.last_updated as left_last_updated,'."\n" + .'a_right_table.id as right_id,'."\n" + .'a_right_table.created_on as right_created_on,'."\n" + .'a_right_table.last_updated as right_last_updated'."\n" + .'from a_left_table left join a_right_table'."\n" + .'on a_left_table.id = a_right_table.id and a_left_table.created_on = a_right_table.created_on' + .")\nas JoinTable;",$query->getQuery()); + $query->select([ + 'without-select' => true + ]); + $this->assertEquals('' + .'select '."\n" + .'a_left_table.id as left_id,'."\n" + .'a_left_table.created_on as left_created_on,'."\n" + .'a_left_table.last_updated as left_last_updated,'."\n" + .'a_right_table.id as right_id,'."\n" + .'a_right_table.created_on as right_created_on,'."\n" + .'a_right_table.last_updated as right_last_updated'."\n" + .'from a_left_table left join a_right_table'."\n" + .'on a_left_table.id = a_right_table.id and a_left_table.created_on = a_right_table.created_on' + .'',$query->getQuery()); + + return $query; + } + /** + * @depends testJoinSelect00 + * @param MySQLQuery $query + * @test + */ + public function testJoinSelect01($query) { + $query->select([ + 'columns' => [ + 'id','created-on' + ] + ]); + $this->assertEquals('select * from (' + .'select '."\n" + .'a_left_table.id as left_id,'."\n" + .'a_left_table.created_on as left_created_on'."\n" + .'from a_left_table left join a_right_table'."\n" + .'on a_left_table.id = a_right_table.id and a_left_table.created_on = a_right_table.created_on' + .")\nas JoinTable;",$query->getQuery()); + $query->select([ + 'columns' => [ + 'id' => 'user_id', + 'created-on' => 'insert_date' + ] + ]); + $this->assertEquals('select * from (' + .'select '."\n" + .'a_left_table.id as user_id,'."\n" + .'a_left_table.created_on as insert_date'."\n" + .'from a_left_table left join a_right_table'."\n" + .'on a_left_table.id = a_right_table.id and a_left_table.created_on = a_right_table.created_on' + .")\nas JoinTable;",$query->getQuery()); + + return $query; + } + /** + * @depends testJoinSelect01 + * @param MySQLQuery $query + * @test + */ + public function testJoinSelect02($query) { + $query->select([ + 'columns' => [ + 'left' => [ + 'id','created-on' + ], + 'right' => [ + 'last-updated' + ] + ] + ]); + $this->assertEquals('select * from (' + .'select '."\n" + .'a_left_table.id as left_id,'."\n" + .'a_left_table.created_on as left_created_on,'."\n" + .'a_right_table.last_updated as right_last_updated'."\n" + .'from a_left_table left join a_right_table'."\n" + .'on a_left_table.id = a_right_table.id and a_left_table.created_on = a_right_table.created_on' + .")\nas JoinTable;",$query->getQuery()); + $query->select([ + 'columns' => [ + 'left' => [ + 'id','created-on' => 'cr_date' + ], + 'right' => [ + 'last-updated' => 'l_updated' + ] + ] + ]); + $this->assertEquals('select * from (' + .'select '."\n" + .'a_left_table.id as left_id,'."\n" + .'a_left_table.created_on as cr_date,'."\n" + .'a_right_table.last_updated as l_updated'."\n" + .'from a_left_table left join a_right_table'."\n" + .'on a_left_table.id = a_right_table.id and a_left_table.created_on = a_right_table.created_on' + .")\nas JoinTable;",$query->getQuery()); + + return $query; + } + /** + * @depends testJoinSelect02 + * @param MySQLQuery $query + * @test + */ + public function testJoinSelect03($query) { + $query->select([ + 'columns' => [ + 'left' => [ + 'id','created-on' => 'cr_date' + ], + 'right' => [ + 'last-updated' => 'l_updated' + ] + ], + 'where' => [ + 'left-id' => 44 + ] + ]); + $this->assertEquals('select * from (' + .'select '."\n" + .'a_left_table.id as left_id,'."\n" + .'a_left_table.created_on as cr_date,'."\n" + .'a_right_table.last_updated as l_updated'."\n" + .'from a_left_table left join a_right_table'."\n" + .'on a_left_table.id = a_right_table.id and a_left_table.created_on = a_right_table.created_on' + .")\nas JoinTable where JoinTable.left_id = 44;",$query->getQuery()); + } /** * * @param MySQLQuery $query @@ -413,45 +547,46 @@ public function testJoinNewKeys01() { */ public function testSelect00($query) { $query->select([ - + ]); $this->assertEquals("select * from (select \n" - . "users.user_id as left_user_id,\n" - . "user_articles.user_id as right_user_id,\n" - . "user_articles.article_title\n" - . "from users right join user_articles\n" - . "on users.user_id = user_articles.user_id)\n" - . "as NewTable;",$query->getQuery()); + ."users.user_id as left_user_id,\n" + ."user_articles.user_id as right_user_id,\n" + ."user_articles.article_title\n" + ."from users right join user_articles\n" + ."on users.user_id = user_articles.user_id)\n" + ."as NewTable;",$query->getQuery()); $query->select([ - 'columns'=>[ + 'columns' => [ 'main-user-id' ] ]); $this->assertEquals("select * from (select \n" - . "users.user_id as left_user_id\n" - . "from users right join user_articles\n" - . "on users.user_id = user_articles.user_id)\n" - . "as NewTable;",$query->getQuery()); + ."users.user_id as left_user_id\n" + ."from users right join user_articles\n" + ."on users.user_id = user_articles.user_id)\n" + ."as NewTable;",$query->getQuery()); $query->select([ - 'columns'=>[ + 'columns' => [ 'sub-user-id' ] ]); $this->assertEquals("select * from (select \n" - . "user_articles.user_id as right_user_id\n" - . "from users right join user_articles\n" - . "on users.user_id = user_articles.user_id)\n" - . "as NewTable;",$query->getQuery()); + ."user_articles.user_id as right_user_id\n" + ."from users right join user_articles\n" + ."on users.user_id = user_articles.user_id)\n" + ."as NewTable;",$query->getQuery()); $query->select([ - 'columns'=>[ + 'columns' => [ 'title' ] ]); $this->assertEquals("select * from (select \n" - . "user_articles.article_title\n" - . "from users right join user_articles\n" - . "on users.user_id = user_articles.user_id)\n" - . "as NewTable;",$query->getQuery()); + ."user_articles.article_title\n" + ."from users right join user_articles\n" + ."on users.user_id = user_articles.user_id)\n" + ."as NewTable;",$query->getQuery()); + return $query; } /** @@ -460,196 +595,62 @@ public function testSelect00($query) { */ public function testSelect01($query) { $query->select([ - 'columns'=>[ - 'main-user-id'=>'l_uid', - 'sub-user-id'=>'r_uid', - 'title'=>'art_title' + 'columns' => [ + 'main-user-id' => 'l_uid', + 'sub-user-id' => 'r_uid', + 'title' => 'art_title' ] ]); $this->assertEquals("select * from (select \n" - . "users.user_id as l_uid,\n" - . "user_articles.user_id as r_uid,\n" - . "user_articles.article_title as art_title\n" - . "from users right join user_articles\n" - . "on users.user_id = user_articles.user_id)\n" - . "as NewTable;",$query->getQuery()); + ."users.user_id as l_uid,\n" + ."user_articles.user_id as r_uid,\n" + ."user_articles.article_title as art_title\n" + ."from users right join user_articles\n" + ."on users.user_id = user_articles.user_id)\n" + ."as NewTable;",$query->getQuery()); $query->select([ - 'columns'=>[ - 'main-user-id'=>'x_user_id' + 'columns' => [ + 'main-user-id' => 'x_user_id' ] ]); $this->assertEquals("select * from (select \n" - . "users.user_id as x_user_id\n" - . "from users right join user_articles\n" - . "on users.user_id = user_articles.user_id)\n" - . "as NewTable;",$query->getQuery()); + ."users.user_id as x_user_id\n" + ."from users right join user_articles\n" + ."on users.user_id = user_articles.user_id)\n" + ."as NewTable;",$query->getQuery()); $query->select([ - 'columns'=>[ - 'sub-user-id'=>'oiy_id' + 'columns' => [ + 'sub-user-id' => 'oiy_id' ] ]); $this->assertEquals("select * from (select \n" - . "user_articles.user_id as oiy_id\n" - . "from users right join user_articles\n" - . "on users.user_id = user_articles.user_id)\n" - . "as NewTable;",$query->getQuery()); + ."user_articles.user_id as oiy_id\n" + ."from users right join user_articles\n" + ."on users.user_id = user_articles.user_id)\n" + ."as NewTable;",$query->getQuery()); $query->select([ - 'columns'=>[ - 'title'=>'article_title_super' + 'columns' => [ + 'title' => 'article_title_super' ] ]); $this->assertEquals("select * from (select \n" - . "user_articles.article_title as article_title_super\n" - . "from users right join user_articles\n" - . "on users.user_id = user_articles.user_id)\n" - . "as NewTable;",$query->getQuery()); + ."user_articles.article_title as article_title_super\n" + ."from users right join user_articles\n" + ."on users.user_id = user_articles.user_id)\n" + ."as NewTable;",$query->getQuery()); + return $query; } /** - * - * @param MySQLQuery $query - * @depends testSelect01 + * @depends testConstructor01 + * @param JoinTable $table */ - public function testJoinLevel2($query) { - $anotherJoin = $query->join([ - 'right-table'=>$query->getTable()->getRightTable(), - 'join-cols'=>[ - 'main-user-id'=>'user-id' - ], - 'join-type'=>'join', - 'alias'=>'MoreJoins' - ]); - $anotherJoin->select(); - $this->assertEquals("select * from (select \n" - . "NewTable.left_user_id,\n" - . "NewTable.right_user_id,\n" - . "NewTable.article_title as left_article_title,\n" - . "user_articles.user_id,\n" - . "user_articles.article_title as right_article_title\n" - . "from (select \n" - . "users.user_id as left_user_id,\n" - . "user_articles.user_id as right_user_id,\n" - . "user_articles.article_title\n" - . "from users right join user_articles\n" - . "on users.user_id = user_articles.user_id) as NewTable join user_articles\n" - . "on NewTable.left_user_id = user_articles.user_id)\n" - . "as MoreJoins;",$anotherJoin->getQuery()); - } - public function testJoinNewKeys00() { - $query0 = new MySQLQuery('users'); - $query0->getTable()->addColumns([ - 'user-id'=>[ - 'is-primary'=>true, - 'size'=>15 - ], - 'created-on'=>[ - 'datatype'=>'timestamp', - 'default'=>'current_timestamp' - ] - ]); - $query1 = new MySQLQuery('user_articles'); - $query1->getTable()->addColumns([ - 'article-id'=>[ - 'is-primary'=>true, - 'size'=>'10' - ], - 'user-id'=>[ - 'is-primary'=>true, - 'size'=>15 - ], - ]); - $joinQuery = $query0->join([ - 'right-table'=>$query1, - 'join-cols'=>[ - 'user-id'=>'user-id' - ], - 'join-type'=>'right', - 'alias'=>'UsersArticles', - 'keys-map'=>[ - 'left'=>[ - 'user-id'=>'main-user-id' - ] - ] - ]); - $this->assertTrue($joinQuery->getTable()->hasColumn('main-user-id')); - $joinQuery->select([ - 'where'=>[ - 'main-user-id'=>77 - ] - ]); - $this->assertEquals('select * from (' - . 'select '."\n" - . 'users.user_id as left_user_id,'."\n" - . 'users.created_on,'."\n" - . 'user_articles.article_id,'."\n" - . 'user_articles.user_id as right_user_id'."\n" - . 'from users right join user_articles'."\n" - . 'on users.user_id = user_articles.user_id)'."\n" - . 'as UsersArticles where UsersArticles.left_user_id = \'77\';',$joinQuery->getQuery()); - $joinQuery->select([ - 'where'=>[ - 'main-user-id'=>77 - ], - 'columns'=>[ - 'main-user-id'=>'u_id' - ] - ]); - $this->assertEquals('select * from (' - . 'select '."\n" - . 'users.user_id as u_id'."\n" - . 'from users right join user_articles'."\n" - . 'on users.user_id = user_articles.user_id)'."\n" - . 'as UsersArticles where UsersArticles.u_id = \'77\';',$joinQuery->getQuery()); - $joinQuery2 = $joinQuery->join([ - 'right-table'=>$query0, - 'join-cols'=>[ - 'main-user-id'=>'user-id' - ], - 'alias'=>'SubJoin', - 'join-type'=>'left', - 'keys-map'=>[ - 'left'=>[ - 'main-user-id'=>'l-user', - 'created-on'=>'l-created-on', - 'article-id'=>'article-id', - 'right-user-id'=>'l-user-2' - ], - 'right'=>[ - 'user-id'=>'r-user', - 'created-on'=>'r-created-on' - ] - ] - ]); - $this->assertEquals(6,count($joinQuery2->getTable()->getColsNames())); - $this->assertTrue($joinQuery2->getTable()->hasColumn('l-user')); - $this->assertTrue($joinQuery2->getTable()->hasColumn('l-created-on')); - $this->assertTrue($joinQuery2->getTable()->hasColumn('article-id')); - $this->assertTrue($joinQuery2->getTable()->hasColumn('l-user-2')); - $this->assertTrue($joinQuery2->getTable()->hasColumn('r-user')); - $this->assertTrue($joinQuery2->getTable()->hasColumn('r-created-on')); - $joinQuery2->select(); - $this->assertEquals('select * from (select '."\n" - . 'UsersArticles.left_user_id,'."\n" - . 'UsersArticles.created_on as left_created_on,'."\n" - . 'UsersArticles.article_id,'."\n" - . 'UsersArticles.right_user_id,'."\n" - . 'users.user_id,'."\n" - . 'users.created_on as right_created_on'."\n" - . 'from (select '."\n" - . 'users.user_id as left_user_id,'."\n" - . 'users.created_on,'."\n" - . 'user_articles.article_id,'."\n" - . 'user_articles.user_id as right_user_id'."\n" - . 'from users right join user_articles'."\n" - . 'on users.user_id = user_articles.user_id) as UsersArticles left join users'."\n" - . 'on UsersArticles.left_user_id = users.user_id)'."\n" - . 'as SubJoin;' - . '',$joinQuery2->getQuery()); + public function testSetJoinCondition00($table) { + $table->setJoinCondition(['id' => 'id']); + $this->assertEquals('on a_left_table.id = a_right_table.id',$table->getJoinCondition()); + $table->setJoinCondition(['id' => 'id','created-on' => 'created-on']); + $this->assertEquals('on a_left_table.id = a_right_table.id and a_left_table.created_on = a_right_table.created_on',$table->getJoinCondition()); + + return $table; } } - - - - - - diff --git a/tests/MySQLLinkTest.php b/tests/MySQLLinkTest.php index 9b0e413..e606588 100644 --- a/tests/MySQLLinkTest.php +++ b/tests/MySQLLinkTest.php @@ -1,10 +1,8 @@ insertRecord([ + 'user-id' => 33, + 'email' => '33@test.com', + 'name' => 'Test User #33' + ]); + $this->assertTrue($conn->executeQuery($q)); + + return $conn; + } /** * @test */ @@ -46,44 +60,7 @@ public function testConnect03() { $conn = new MySQLLink('localhost', 'root', '123456'); $this->assertEquals(0,$conn->getErrorCode()); $this->assertEquals("NO ERRORS",$conn->getErrorMessage()); - return $conn; - } - /** - * - * @param MySQLLink $conn - * @depends testConnect03 - * @test - */ - public function testSetDb00($conn) { - $this->assertFalse($conn->setDB('not_exist')); - $this->assertEquals(1049,$conn->getErrorCode()); - $this->assertEquals("Unknown database 'not_exist'",$conn->getErrorMessage()); - } - /** - * @test - */ - public function testSetDb01() { - $conn = new MySQLLink('localhost', 'root', '123456'); - $this->assertEquals(0,$conn->getErrorCode()); - $this->assertEquals("NO ERRORS",$conn->getErrorMessage()); - $this->assertTrue($conn->setDB('testing_db')); - $this->assertEquals(0,$conn->getErrorCode()); - $this->assertEquals("NO ERRORS",$conn->getErrorMessage()); - return $conn; - } - /** - * @depends testSetDb01 - * @param MySQLLink $conn - * @test - */ - public function testAddDataTest00($conn) { - $q = new UsersQuery(); - $q->insertRecord([ - 'user-id'=>33, - 'email'=>'33@test.com', - 'name'=>'Test User #33' - ]); - $this->assertTrue($conn->executeQuery($q)); + return $conn; } /** @@ -94,12 +71,12 @@ public function testAddDataTest00($conn) { public function testGetDataTest00($conn) { $q = new UsersQuery(); $q->select([ - 'where'=>[ - 'user-id'=>[ - 'values'=>[33] + 'where' => [ + 'user-id' => [ + 'values' => [33] ] ], - 'map-result-to'=>'\phMysql\tests\EntityUser' + 'map-result-to' => '\phMysql\tests\EntityUser' ]); $this->assertTrue($conn->executeQuery($q)); $this->assertEquals(1,$conn->rows()); @@ -116,21 +93,46 @@ public function testGetDataTest01($conn) { $q = new UsersQuery(); $q2 = new ArticleQuery(); $q3 = $q2->join([ - 'right-table'=>$q, - 'join-cols'=>[ - 'author-id'=>'user-id' + 'right-table' => $q, + 'join-cols' => [ + 'author-id' => 'user-id' ] ]); $q3->select([ - 'where'=>[ - 'author-id'=>1 + 'where' => [ + 'author-id' => 1 ] ]); $r = $conn->executeQuery($q3); - if($r === false){ + + if ($r === false) { print_r("\n".$conn->getErrorCode().': '.$conn->getErrorMessage()."\n"); } $this->assertTrue($r); $this->assertEquals(4,$conn->rows()); } + /** + * + * @param MySQLLink $conn + * @depends testConnect03 + * @test + */ + public function testSetDb00($conn) { + $this->assertFalse($conn->setDB('not_exist')); + $this->assertEquals(1049,$conn->getErrorCode()); + $this->assertEquals("Unknown database 'not_exist'",$conn->getErrorMessage()); + } + /** + * @test + */ + public function testSetDb01() { + $conn = new MySQLLink('localhost', 'root', '123456'); + $this->assertEquals(0,$conn->getErrorCode()); + $this->assertEquals("NO ERRORS",$conn->getErrorMessage()); + $this->assertTrue($conn->setDB('testing_db')); + $this->assertEquals(0,$conn->getErrorCode()); + $this->assertEquals("NO ERRORS",$conn->getErrorMessage()); + + return $conn; + } } diff --git a/tests/MySQLQueryTest.php b/tests/MySQLQueryTest.php index 7f93721..97cecaf 100644 --- a/tests/MySQLQueryTest.php +++ b/tests/MySQLQueryTest.php @@ -1,148 +1,87 @@ updateRecord([ - 'content'=>'Hello' - ], [ - 'article-id'=>77 - ]); - $prev = date('Y-m-d H:i:s', time() - 1); - $now = date('Y-m-d H:i:s'); - $query = $aq->getQuery(); - $next = date('Y-m-d H:i:s', time() + 1); - $isEqual = $query == 'update articles set article_content = \'Hello\',last_updated = \''.$prev.'\' where article_id = 77;' - || $query == 'update articles set article_content = \'Hello\',last_updated = \''.$now.'\' where article_id = 77;' - || $query == 'update articles set article_content = \'Hello\',last_updated = \''.$next.'\' where article_id = 77;'; - $this->assertTrue($isEqual); - } - /** - * @test - */ - public function testUpdateRecord01() { - $aq = new ArticleQuery(); - $aq->updateRecord([ - 'content'=>'Hello', - 'last-updated'=>'2019-11-09 10:00:56' - ], [ - 'article-id'=>77 - ]); - $query = $aq->getQuery(); - $isEqual = $query == 'update articles set article_content = \'Hello\',last_updated = \'2019-11-09 10:00:56\' where article_id = 77;'; - $this->assertTrue($isEqual); - } - /** - * @test - */ - public function testUpdateRecord02() { - $aq = new ArticleQuery(); - $aq->updateRecord([ - 'content'=>'Hello', - 'last-updated'=>'2019-11-09 10:00:56' - ], [ - 'article-id'=>77, - 'author-id'=>1 - ]); - $query = $aq->getQuery(); - $isEqual = $query == 'update articles set article_content = \'Hello\',last_updated = \'2019-11-09 10:00:56\' where article_id = 77 and author_id = 1;'; - $this->assertTrue($isEqual); - } - /** - * @test - */ - public function testUpdateRecord03() { - $aq = new ArticleQuery(); - $aq->updateRecord([ - 'content'=>'Hello', - 'last-updated'=>'2019-11-09 10:00:56' - ], [ - 'article-id'=>77, - 'author-id'=>1 - ],['!=']); - $query = $aq->getQuery(); - $isEqual = $query == 'update articles set article_content = \'Hello\',last_updated = \'2019-11-09 10:00:56\' where article_id != 77 and author_id = 1;'; - $this->assertTrue($isEqual); - } +class MySQLQueryTest extends TestCase { /** * @test */ - public function testSetMaxPackete() { - $aq = new ArticleQuery(); - $aq->setMaxPackete(1); - $this->assertEquals('set global max_allowed_packet = 1048576;',$aq->getQuery()); - $aq->setMaxPackete(1,'kb'); - $this->assertEquals('set global max_allowed_packet = 1024;',$aq->getQuery()); - $aq->setMaxPackete(1,'b'); - $this->assertEquals('set global max_allowed_packet = 1;',$aq->getQuery()); - $aq->setMaxPackete(1,'gb'); - $this->assertEquals('set global max_allowed_packet = 1073741824;',$aq->getQuery()); - $aq->setMaxPackete(1,'ggv'); - $this->assertEquals('set global max_allowed_packet = 1048576;',$aq->getQuery()); - } - /** - * @test - */ - public function testSelectMax00() { - $aq = new ArticleQuery(); - $aq->selectMax(''); - $this->assertEquals('select * from articles',$aq->getQuery()); - $this->assertEquals('select',$aq->getType()); - } - /** - * @test - */ - public function testSelectMax01() { - $aq = new ArticleQuery(); - $aq->selectMax('article-id'); - $this->assertEquals('select max(article_id) as max from articles;',$aq->getQuery()); - } - /** - * @test - */ - public function testSelectMax02() { - $aq = new ArticleQuery(); - $aq->selectMax('article-id','maximum_id'); - $this->assertEquals('select max(article_id) as maximum_id from articles;',$aq->getQuery()); + public function createStructureTest00() { + $articleQuery = new ArticleQuery(); + $articleQuery->createStructure(); + $this->assertEquals("",''); } /** * @test */ - public function testSelectMin00() { + public function testAddForeignKey00() { $aq = new ArticleQuery(); - $aq->selectMin(''); - $this->assertEquals('select * from articles',$aq->getQuery()); - $this->assertEquals('select',$aq->getType()); + $aq->addForeignKey($aq->getStructure()->getForeignKeys()[0]); + $this->assertEquals("alter table articles add constraint author_fk foreign key (author_id) references system_users(user_id) on delete set null on update set null",$aq->getQuery()); } /** * @test */ - public function testSelectMin01() { + public function testAddPrimaryKey00() { $aq = new ArticleQuery(); - $aq->selectMin('article-id'); - $this->assertEquals('select min(article_id) as min from articles;',$aq->getQuery()); + $aq->addPrimaryKey($aq->getStructure()); + $this->assertEquals("alter table articles add constraint articles_pk primary key (article_id);\n" + ."alter table articles modify article_id int(11) not null unique auto_increment;\n",$aq->getQuery()); } /** * @test */ - public function testSelectMin02() { - $aq = new ArticleQuery(); - $aq->selectMin('article-id','minimum_id'); - $this->assertEquals('select min(article_id) as minimum_id from articles;',$aq->getQuery()); + public function testCreateTable00() { + $query = new MySQLQuery('users'); + $query->getTable()->addDefaultCols(); + $query->getTable()->addColumns([ + 'username' => [ + 'datatype' => 'varchar', + 'size' => 20, + 'unique' => true + ], + 'password' => [ + 'datatype' => 'varchar', + 'size' => 64, + 'comment' => 'The password of the user must be SHA256 hash (64 characters).' + ], + 'last-success-login' => [ + 'datatype' => 'datetime', + 'is-null' => true + ], + 'last-failed-login' => [ + 'datatype' => 'datetime', + 'is-null' => true + ], + 'failed-login-attempts' => [ + 'datatype' => 'int', + 'name' => 'f_logins', + 'size' => 2, + 'default' => 0 + ], + ]); + $query->createStructure(); + $this->assertEquals('create table if not exists users('."\n" + .' id int(11) not null unique,'."\n" + .' created_on timestamp not null default current_timestamp,'."\n" + .' last_updated datetime null,'."\n" + .' username varchar(20) not null collate utf8mb4_unicode_ci,'."\n" + .' password varchar(64) not null collate utf8mb4_unicode_ci comment \'The password of the user must be SHA256 hash (64 characters).\','."\n" + .' last_success_login datetime null,'."\n" + .' last_failed_login datetime null,'."\n" + .' f_logins int(2) not null default 0'."\n" + .')'."\n" + .'ENGINE = InnoDB'."\n" + .'DEFAULT CHARSET = utf8mb4'."\n" + .'collate = utf8mb4_unicode_ci;'."\n" + .'alter table users add constraint users_pk primary key (id);'."\n" + .'alter table users modify id int(11) not null unique auto_increment;'."\n",$query->getQuery()); } /** * @test @@ -150,7 +89,7 @@ public function testSelectMin02() { public function testDeleteRecord00() { $aq = new ArticleQuery(); $aq->deleteRecord([ - 'article-id'=>77 + 'article-id' => 77 ]); $this->assertEquals('delete from articles where article_id = 77;',$aq->getQuery()); } @@ -160,8 +99,8 @@ public function testDeleteRecord00() { public function testDeleteRecord01() { $aq = new ArticleQuery(); $aq->deleteRecord([ - 'article-id'=>77, - 'author-id'=>98 + 'article-id' => 77, + 'author-id' => 98 ]); $this->assertEquals('delete from articles where article_id = 77 and author_id = 98;',$aq->getQuery()); } @@ -171,8 +110,8 @@ public function testDeleteRecord01() { public function testInsert000() { $aq = new ArticleQuery(); $aq->insertRecord([ - 'author-id'=>66, - 'created-on'=>'2019-11-17 12:08:22' + 'author-id' => 66, + 'created-on' => '2019-11-17 12:08:22' ]); $this->assertEquals('insert into articles (author_id,created_on) values (66,\'2019-11-17 12:08:22\');',$aq->getQuery()); } @@ -182,9 +121,9 @@ public function testInsert000() { public function testInsert001() { $aq = new ArticleQuery(); $aq->insertRecord([ - 'author-id'=>66, - 'content'=>null, - 'created-on'=>'2019-11-17 12:05:02' + 'author-id' => 66, + 'content' => null, + 'created-on' => '2019-11-17 12:05:02' ]); $this->assertEquals('insert into articles (author_id,article_content,created_on) values (66,null,\'2019-11-17 12:05:02\');',$aq->getQuery()); } @@ -194,9 +133,9 @@ public function testInsert001() { public function testInsert002() { $aq = new ArticleQuery(); $aq->insertRecord([ - 'author-id'=>66, - 'content'=>'null', - 'created-on'=>'2019-09-09 00:00:00' + 'author-id' => 66, + 'content' => 'null', + 'created-on' => '2019-09-09 00:00:00' ]); $this->assertEquals('insert into articles (author_id,article_content,created_on) values (66,null,\'2019-09-09 00:00:00\');',$aq->getQuery()); } @@ -206,7 +145,7 @@ public function testInsert002() { public function testInsert003() { $aq = new ArticleQuery(); $aq->insertRecord([ - 'author-id'=>66 + 'author-id' => 66 ]); $prev = date('Y-m-d H:i:s', time() - 1); $now = date('Y-m-d H:i:s'); @@ -217,173 +156,6 @@ public function testInsert003() { || $query == 'insert into articles (author_id,created_on) values (66,\''.$now.'\');'; $this->assertTrue($isEqual); } - /** - * @test - */ - public function testSelectCount00() { - $aq = new ArticleQuery(); - $aq->selectCount(); - $this->assertEquals('select count(*) as count from articles;',$aq->getQuery()); - } - /** - * @test - */ - public function testSelectCount01() { - $aq = new ArticleQuery(); - $aq->selectCount([ - 'as'=>'atrticles count' - ]); - $this->assertEquals('select count(*) as atrticles_count from articles;',$aq->getQuery()); - } - /** - * @test - */ - public function testSelectCount02() { - $aq = new ArticleQuery(); - $aq->selectCount([ - 'where'=>[ - 'author-id'=>'66' - ] - ]); - $this->assertEquals('select count(*) as count from ' - . 'articles where author_id = 66;',$aq->getQuery()); - } - /** - * @test - */ - public function testSelectCount03() { - $aq = new ArticleQuery(); - $aq->selectCount([ - 'where'=>[ - 'author-id'=>'66', - 'last-updated'=>'2019-09-09' - ] - ]); - $this->assertEquals('select count(*) as count from ' - . 'articles where author_id = 66 and ' - . 'last_updated >= \'2019-09-09 00:00:00\' and last_updated <= \'2019-09-09 23:59:59\';',$aq->getQuery()); - } - /** - * @test - */ - public function testSelectCount04() { - $aq = new ArticleQuery(); - $aq->selectCount([ - 'where'=>[ - 'author-id'=>'100', - 'last-updated'=>'2019-09-09' - ], - 'conditions'=>['=','<'] - ]); - $this->assertEquals('select count(*) as count from ' - . 'articles where author_id = 100 and ' - . 'last_updated < \'2019-09-09 00:00:00\';',$aq->getQuery()); - } - /** - * @test - */ - public function testSelectCount05() { - $aq = new ArticleQuery(); - $aq->selectCount([ - 'where'=>[ - 'author-id'=>'76', - 'last-updated'=>'2019-09-09' - ], - 'conditions'=>['=','<='] - ]); - $this->assertEquals('select count(*) as count from ' - . 'articles where author_id = 76 and ' - . 'last_updated <= \'2019-09-09 23:59:59\';',$aq->getQuery()); - } - /** - * @test - */ - public function testSelectCount06() { - $aq = new ArticleQuery(); - $aq->selectCount([ - 'where'=>[ - 'author-id'=>'90', - 'last-updated'=>'2019-09-09 06:00:00' - ], - 'conditions'=>['=','<='] - ]); - $this->assertEquals('select count(*) as count from ' - . 'articles where author_id = 90 and ' - . 'last_updated <= \'2019-09-09 06:00:00\';',$aq->getQuery()); - } - /** - * @test - */ - public function testSelectCount07() { - $aq = new ArticleQuery(); - $aq->selectCount([ - 'where'=>[ - 'author-id'=>'34', - 'last-updated'=>'2019-09-09' - ], - 'conditions'=>['=','>'] - ]); - $this->assertEquals('select count(*) as count from ' - . 'articles where author_id = 34 and ' - . 'last_updated > \'2019-09-09 23:59:59\';',$aq->getQuery()); - } - /** - * @test - */ - public function testSelectCount08() { - $aq = new ArticleQuery(); - $aq->selectCount([ - 'where'=>[ - 'author-id'=>'98', - 'last-updated'=>'2019-09-09' - ], - 'conditions'=>['=','>='] - ]); - $this->assertEquals('select count(*) as count from ' - . 'articles where author_id = 98 and ' - . 'last_updated >= \'2019-09-09 00:00:00\';',$aq->getQuery()); - } - /** - * @test - */ - public function testSelectCount09() { - $aq = new ArticleQuery(); - $aq->selectCount([ - 'where'=>[ - 'author-id'=>'65', - 'last-updated'=>'2019-09-09' - ], - 'conditions'=>['=','!='] - ]); - $this->assertEquals('select count(*) as count from ' - . 'articles where author_id = 65 and ' - . 'last_updated < \'2019-09-09 00:00:00\' and last_updated > \'2019-09-09 23:59:59\';',$aq->getQuery()); - } - /** - * @test - */ - public function testAddPrimaryKey00() { - $aq = new ArticleQuery(); - $aq->addPrimaryKey($aq->getStructure()); - $this->assertEquals("alter table articles add constraint articles_pk primary key (article_id);\n" - . "alter table articles modify article_id int(11) not null unique auto_increment;\n",$aq->getQuery()); - } - /** - * @test - */ - public function testAddForeignKey00() { - $aq = new ArticleQuery(); - $aq->addForeignKey($aq->getStructure()->getForeignKeys()[0]); - $this->assertEquals("alter table articles add constraint author_fk foreign key (author_id) references system_users(user_id) on delete set null on update set null",$aq->getQuery()); - } - /** - * @test - */ - public function createStructureTest00() { - $articleQuery = new ArticleQuery(); - $articleQuery->createStructure(); - $this->assertEquals("",''); - } /** * @test */ @@ -398,7 +170,7 @@ public function testSelect000() { public function testSelect001() { $obj = new QueryTestObj(); $obj->select([ - 'limit'=>3 + 'limit' => 3 ]); $this->assertEquals('select * from first_table limit 3;',$obj->getQuery()); } @@ -408,8 +180,8 @@ public function testSelect001() { public function testSelect002() { $obj = new QueryTestObj(); $obj->select([ - 'limit'=>3, - 'offset'=>7 + 'limit' => 3, + 'offset' => 7 ]); $this->assertEquals('select * from first_table limit 3 offset 7;',$obj->getQuery()); } @@ -419,7 +191,7 @@ public function testSelect002() { public function testSelect004() { $obj = new QueryTestObj(); $obj->select([ - 'offset'=>3 + 'offset' => 3 ]); $this->assertEquals('select * from first_table;',$obj->getQuery()); } @@ -429,9 +201,9 @@ public function testSelect004() { public function testSelect005() { $obj = new QueryTestObj(); $obj->select([ - 'order-by'=>[ + 'order-by' => [ [ - 'col'=>'first-col' + 'col' => 'first-col' ] ] ]); @@ -443,17 +215,17 @@ public function testSelect005() { public function testSelect006() { $obj = new QueryTestObj(); $obj->select([ - 'order-by'=>[ + 'order-by' => [ [ - 'col'=>'first-col', - 'order-type'=>'D' + 'col' => 'first-col', + 'order-type' => 'D' ], [ - 'col'=>'second-col' + 'col' => 'second-col' ], [ - 'col'=>'fourth-col', - 'order-type'=>'A' + 'col' => 'fourth-col', + 'order-type' => 'A' ] ] ]); @@ -465,18 +237,18 @@ public function testSelect006() { public function testSelect007() { $obj = new QueryTestObj(); $obj->select([ - 'columns'=>['first-col'], - 'order-by'=>[ + 'columns' => ['first-col'], + 'order-by' => [ [ - 'col'=>'first-col', - 'order-type'=>'D' + 'col' => 'first-col', + 'order-type' => 'D' ], [ - 'col'=>'second-col' + 'col' => 'second-col' ], [ - 'col'=>'fourth-col', - 'order-type'=>'A' + 'col' => 'fourth-col', + 'order-type' => 'A' ] ] ]); @@ -488,23 +260,23 @@ public function testSelect007() { public function testSelect008() { $obj = new QueryTestObj(); $obj->select([ - 'columns'=>['first-col','fourth-col'], - 'order-by'=>[ + 'columns' => ['first-col','fourth-col'], + 'order-by' => [ [ - 'col'=>'first-col', - 'order-type'=>'D' + 'col' => 'first-col', + 'order-type' => 'D' ], [ - 'col'=>'second-col' + 'col' => 'second-col' ], [ - 'col'=>'fourth-col', - 'order-type'=>'A' + 'col' => 'fourth-col', + 'order-type' => 'A' ] ] ]); $this->assertEquals('select col_00,'."\n" - . 'col_03 from first_table order by col_00 desc, col_01, col_03 asc;',$obj->getQuery()); + .'col_03 from first_table order by col_00 desc, col_01, col_03 asc;',$obj->getQuery()); } /** * @test @@ -512,14 +284,14 @@ public function testSelect008() { public function testSelect009() { $obj = new QueryTestObj(); $obj->select([ - 'order-by'=>[ + 'order-by' => [ [ - 'col'=>'first-col' + 'col' => 'first-col' ] ], - 'group-by'=>[ + 'group-by' => [ [ - 'col'=>'first-col' + 'col' => 'first-col' ] ] ]); @@ -531,20 +303,20 @@ public function testSelect009() { public function testSelect010() { $obj = new QueryTestObj(); $obj->select([ - 'condition-cols-and-vals'=>[ - 'fourth-col'=>'7U' + 'condition-cols-and-vals' => [ + 'fourth-col' => '7U' ], - 'order-by'=>[ + 'order-by' => [ [ - 'col'=>'first-col' + 'col' => 'first-col' ] ], - 'group-by'=>[ + 'group-by' => [ [ - 'col'=>'fourth-col' + 'col' => 'fourth-col' ], [ - 'col'=>'first-col' + 'col' => 'first-col' ] ] ]); @@ -556,22 +328,22 @@ public function testSelect010() { public function testSelect011() { $obj = new QueryTestObj(); $obj->select([ - 'condition-cols-and-vals'=>[ - 'fourth-col'=>'7U', - 'first-col'=>'*I', - 'third-col'=>'X' + 'condition-cols-and-vals' => [ + 'fourth-col' => '7U', + 'first-col' => '*I', + 'third-col' => 'X' ], - 'order-by'=>[ + 'order-by' => [ [ - 'col'=>'first-col' + 'col' => 'first-col' ] ], - 'group-by'=>[ + 'group-by' => [ [ - 'col'=>'fourth-col' + 'col' => 'fourth-col' ], [ - 'col'=>'first-col' + 'col' => 'first-col' ] ] ]); @@ -581,7 +353,7 @@ public function testSelect012() { $aq = new ArticleQuery(); //testing sql injection $aq->select([ - 'where'=>['author-id'=>'5;drop table random;'] + 'where' => ['author-id' => '5;drop table random;'] ]); $this->assertEquals('select * from articles where author_id = 5;',$aq->getQuery()); } @@ -592,7 +364,7 @@ public function testSelect013() { $aq = new ArticleQuery(); //testing sql injection $aq->select([ - 'where'=>['author-id'=>'drop table random;'] + 'where' => ['author-id' => 'drop table random;'] ]); $this->assertEquals('select * from articles where author_id = 0;',$aq->getQuery()); } @@ -602,7 +374,7 @@ public function testSelect013() { public function testSelect014() { $aq = new ArticleQuery(); $aq->select([ - 'where'=>['author-id'=>'is null'] + 'where' => ['author-id' => 'is null'] ]); $this->assertEquals('select * from articles where author_id is null;',$aq->getQuery()); } @@ -612,7 +384,7 @@ public function testSelect014() { public function testSelect015() { $aq = new ArticleQuery(); $aq->select([ - 'where'=>['author-id'=>null] + 'where' => ['author-id' => null] ]); $this->assertEquals('select * from articles where author_id is null;',$aq->getQuery()); } @@ -622,8 +394,8 @@ public function testSelect015() { public function testSelect016() { $aq = new ArticleQuery(); $aq->select([ - 'where'=>['author-id'=>null], - 'conditions'=>['!='] + 'where' => ['author-id' => null], + 'conditions' => ['!='] ]); $this->assertEquals('select * from articles where author_id is not null;',$aq->getQuery()); } @@ -634,36 +406,37 @@ public function testSelect016() { public function testSelect017() { $query = new MySQLQuery('user_data'); $query->getTable()->addColumns([ - 'user-id'=>[ - 'datatype'=>'int', - 'size'=>10, - 'is-primary'=>true + 'user-id' => [ + 'datatype' => 'int', + 'size' => 10, + 'is-primary' => true ], - 'username'=>[ - 'size'=>25, - 'is-unique'=>true + 'username' => [ + 'size' => 25, + 'is-unique' => true ], - 'reg-date'=>[ - 'datatype'=>'timestamp', - 'default'=>'current_timestamp' + 'reg-date' => [ + 'datatype' => 'timestamp', + 'default' => 'current_timestamp' ], - 'last-login'=>[ - 'datatype'=>'datetime' + 'last-login' => [ + 'datatype' => 'datetime' ] ]); $query->select([ - 'where'=>[ - 'user-id'=>[ - 'values'=>[ + 'where' => [ + 'user-id' => [ + 'values' => [ 1,4,6 ], - 'join-operators'=>[ + 'join-operators' => [ 'or','and' ] ] ] ]); $this->assertEquals('select * from user_data where (user_id = 1 or user_id = 4 and user_id = 6);',$query->getQuery()); + return $query; } /** @@ -673,12 +446,12 @@ public function testSelect017() { */ public function testSelect018($query) { $query->select([ - 'where'=>[ - 'user-id'=>[ - 'values'=>[ + 'where' => [ + 'user-id' => [ + 'values' => [ 1,4,6 ], - 'conditions'=>'in' + 'conditions' => 'in' ] ] ]); @@ -691,12 +464,12 @@ public function testSelect018($query) { */ public function testSelect019($query) { $query->select([ - 'where'=>[ - 'user-id'=>[ - 'values'=>[ + 'where' => [ + 'user-id' => [ + 'values' => [ 1,4,6 ], - 'conditions'=>'not in' + 'conditions' => 'not in' ] ] ]); @@ -708,47 +481,47 @@ public function testSelect019($query) { public function testSelect020() { $q = new MySQLQuery('hello'); $q->getTable()->addColumns([ - 'user-id'=>[ - 'name'=>'u_id', - 'type'=>'int', - 'size'=>4, - 'is-primary'=>true + 'user-id' => [ + 'name' => 'u_id', + 'type' => 'int', + 'size' => 4, + 'is-primary' => true ], - 'first-name'=>[ - 'size'=>15 + 'first-name' => [ + 'size' => 15 ], - 'last-name'=>[ - 'size'=>15 + 'last-name' => [ + 'size' => 15 ], - 'email-address'=>[ - 'size'=>150 + 'email-address' => [ + 'size' => 150 ] ]); $q->select([ - 'columns'=>[ + 'columns' => [ 'user-id', - 'first-name'=>'f_name', - 'last-name'=>'l_name', + 'first-name' => 'f_name', + 'last-name' => 'l_name', 'email-address' ] ]); $this->assertEquals('select u_id,'."\n" - . 'first_name as f_name,'."\n" - . 'last_name as l_name,'."\n" - . 'email_address from hello;',$q->getQuery()); + .'first_name as f_name,'."\n" + .'last_name as l_name,'."\n" + .'email_address from hello;',$q->getQuery()); $q->select([ - 'columns'=>[ + 'columns' => [ 'user-id', - 'first-name'=>'f_name', - 'last-name'=>'l_name', + 'first-name' => 'f_name', + 'last-name' => 'l_name', 'email-address' ], - 'table-prefix'=>true + 'table-prefix' => true ]); $this->assertEquals('select hello.u_id,'."\n" - . 'hello.first_name as f_name,'."\n" - . 'hello.last_name as l_name,'."\n" - . 'hello.email_address from hello;',$q->getQuery()); + .'hello.first_name as f_name,'."\n" + .'hello.last_name as l_name,'."\n" + .'hello.email_address from hello;',$q->getQuery()); // $q->select([ // 'columns'=>[ // 'x'=>'bb', @@ -767,55 +540,6 @@ public function testSelect020() { // $q->select(); // $this->assertEquals('select * from hello;',$q->getQuery()); } - /** - * @test - */ - public function testCreateTable00() { - $query = new MySQLQuery('users'); - $query->getTable()->addDefaultCols(); - $query->getTable()->addColumns([ - 'username'=>[ - 'datatype'=>'varchar', - 'size'=>20, - 'unique'=>true - ], - 'password'=>[ - 'datatype'=>'varchar', - 'size'=>64, - 'comment'=>'The password of the user must be SHA256 hash (64 characters).' - ], - 'last-success-login'=>[ - 'datatype'=>'datetime', - 'is-null'=>true - ], - 'last-failed-login'=>[ - 'datatype'=>'datetime', - 'is-null'=>true - ], - 'failed-login-attempts'=>[ - 'datatype'=>'int', - 'name'=>'f_logins', - 'size'=>2, - 'default'=>0 - ], - ]); - $query->createStructure(); - $this->assertEquals('create table if not exists users('."\n" - .' id int(11) not null unique,'."\n" - .' created_on timestamp not null default current_timestamp,'."\n" - .' last_updated datetime null,'."\n" - .' username varchar(20) not null collate utf8mb4_unicode_ci,'."\n" - .' password varchar(64) not null collate utf8mb4_unicode_ci comment \'The password of the user must be SHA256 hash (64 characters).\','."\n" - .' last_success_login datetime null,'."\n" - .' last_failed_login datetime null,'."\n" - .' f_logins int(2) not null default 0'."\n" - .')'."\n" - .'ENGINE = InnoDB'."\n" - .'DEFAULT CHARSET = utf8mb4'."\n" - .'collate = utf8mb4_unicode_ci;'."\n" - .'alter table users add constraint users_pk primary key (id);'."\n" - .'alter table users modify id int(11) not null unique auto_increment;'."\n",$query->getQuery()); - } /** * @test */ @@ -872,4 +596,278 @@ public function testSelectAll06() { $aq->selectAll(-10,50); $this->assertEquals('select * from articles;',$aq->getQuery()); } + /** + * @test + */ + public function testSelectCount00() { + $aq = new ArticleQuery(); + $aq->selectCount(); + $this->assertEquals('select count(*) as count from articles;',$aq->getQuery()); + } + /** + * @test + */ + public function testSelectCount01() { + $aq = new ArticleQuery(); + $aq->selectCount([ + 'as' => 'atrticles count' + ]); + $this->assertEquals('select count(*) as atrticles_count from articles;',$aq->getQuery()); + } + /** + * @test + */ + public function testSelectCount02() { + $aq = new ArticleQuery(); + $aq->selectCount([ + 'where' => [ + 'author-id' => '66' + ] + ]); + $this->assertEquals('select count(*) as count from ' + .'articles where author_id = 66;',$aq->getQuery()); + } + /** + * @test + */ + public function testSelectCount03() { + $aq = new ArticleQuery(); + $aq->selectCount([ + 'where' => [ + 'author-id' => '66', + 'last-updated' => '2019-09-09' + ] + ]); + $this->assertEquals('select count(*) as count from ' + .'articles where author_id = 66 and ' + .'last_updated >= \'2019-09-09 00:00:00\' and last_updated <= \'2019-09-09 23:59:59\';',$aq->getQuery()); + } + /** + * @test + */ + public function testSelectCount04() { + $aq = new ArticleQuery(); + $aq->selectCount([ + 'where' => [ + 'author-id' => '100', + 'last-updated' => '2019-09-09' + ], + 'conditions' => ['=','<'] + ]); + $this->assertEquals('select count(*) as count from ' + .'articles where author_id = 100 and ' + .'last_updated < \'2019-09-09 00:00:00\';',$aq->getQuery()); + } + /** + * @test + */ + public function testSelectCount05() { + $aq = new ArticleQuery(); + $aq->selectCount([ + 'where' => [ + 'author-id' => '76', + 'last-updated' => '2019-09-09' + ], + 'conditions' => ['=','<='] + ]); + $this->assertEquals('select count(*) as count from ' + .'articles where author_id = 76 and ' + .'last_updated <= \'2019-09-09 23:59:59\';',$aq->getQuery()); + } + /** + * @test + */ + public function testSelectCount06() { + $aq = new ArticleQuery(); + $aq->selectCount([ + 'where' => [ + 'author-id' => '90', + 'last-updated' => '2019-09-09 06:00:00' + ], + 'conditions' => ['=','<='] + ]); + $this->assertEquals('select count(*) as count from ' + .'articles where author_id = 90 and ' + .'last_updated <= \'2019-09-09 06:00:00\';',$aq->getQuery()); + } + /** + * @test + */ + public function testSelectCount07() { + $aq = new ArticleQuery(); + $aq->selectCount([ + 'where' => [ + 'author-id' => '34', + 'last-updated' => '2019-09-09' + ], + 'conditions' => ['=','>'] + ]); + $this->assertEquals('select count(*) as count from ' + .'articles where author_id = 34 and ' + .'last_updated > \'2019-09-09 23:59:59\';',$aq->getQuery()); + } + /** + * @test + */ + public function testSelectCount08() { + $aq = new ArticleQuery(); + $aq->selectCount([ + 'where' => [ + 'author-id' => '98', + 'last-updated' => '2019-09-09' + ], + 'conditions' => ['=','>='] + ]); + $this->assertEquals('select count(*) as count from ' + .'articles where author_id = 98 and ' + .'last_updated >= \'2019-09-09 00:00:00\';',$aq->getQuery()); + } + /** + * @test + */ + public function testSelectCount09() { + $aq = new ArticleQuery(); + $aq->selectCount([ + 'where' => [ + 'author-id' => '65', + 'last-updated' => '2019-09-09' + ], + 'conditions' => ['=','!='] + ]); + $this->assertEquals('select count(*) as count from ' + .'articles where author_id = 65 and ' + .'last_updated < \'2019-09-09 00:00:00\' and last_updated > \'2019-09-09 23:59:59\';',$aq->getQuery()); + } + /** + * @test + */ + public function testSelectMax00() { + $aq = new ArticleQuery(); + $aq->selectMax(''); + $this->assertEquals('select * from articles',$aq->getQuery()); + $this->assertEquals('select',$aq->getType()); + } + /** + * @test + */ + public function testSelectMax01() { + $aq = new ArticleQuery(); + $aq->selectMax('article-id'); + $this->assertEquals('select max(article_id) as max from articles;',$aq->getQuery()); + } + /** + * @test + */ + public function testSelectMax02() { + $aq = new ArticleQuery(); + $aq->selectMax('article-id','maximum_id'); + $this->assertEquals('select max(article_id) as maximum_id from articles;',$aq->getQuery()); + } + /** + * @test + */ + public function testSelectMin00() { + $aq = new ArticleQuery(); + $aq->selectMin(''); + $this->assertEquals('select * from articles',$aq->getQuery()); + $this->assertEquals('select',$aq->getType()); + } + /** + * @test + */ + public function testSelectMin01() { + $aq = new ArticleQuery(); + $aq->selectMin('article-id'); + $this->assertEquals('select min(article_id) as min from articles;',$aq->getQuery()); + } + /** + * @test + */ + public function testSelectMin02() { + $aq = new ArticleQuery(); + $aq->selectMin('article-id','minimum_id'); + $this->assertEquals('select min(article_id) as minimum_id from articles;',$aq->getQuery()); + } + /** + * @test + */ + public function testSetMaxPackete() { + $aq = new ArticleQuery(); + $aq->setMaxPackete(1); + $this->assertEquals('set global max_allowed_packet = 1048576;',$aq->getQuery()); + $aq->setMaxPackete(1,'kb'); + $this->assertEquals('set global max_allowed_packet = 1024;',$aq->getQuery()); + $aq->setMaxPackete(1,'b'); + $this->assertEquals('set global max_allowed_packet = 1;',$aq->getQuery()); + $aq->setMaxPackete(1,'gb'); + $this->assertEquals('set global max_allowed_packet = 1073741824;',$aq->getQuery()); + $aq->setMaxPackete(1,'ggv'); + $this->assertEquals('set global max_allowed_packet = 1048576;',$aq->getQuery()); + } + /** + * @test + */ + public function testUpdateRecord00() { + $aq = new ArticleQuery(); + $aq->updateRecord([ + 'content' => 'Hello' + ], [ + 'article-id' => 77 + ]); + $prev = date('Y-m-d H:i:s', time() - 1); + $now = date('Y-m-d H:i:s'); + $query = $aq->getQuery(); + $next = date('Y-m-d H:i:s', time() + 1); + $isEqual = $query == 'update articles set article_content = \'Hello\',last_updated = \''.$prev.'\' where article_id = 77;' + || $query == 'update articles set article_content = \'Hello\',last_updated = \''.$now.'\' where article_id = 77;' + || $query == 'update articles set article_content = \'Hello\',last_updated = \''.$next.'\' where article_id = 77;'; + $this->assertTrue($isEqual); + } + /** + * @test + */ + public function testUpdateRecord01() { + $aq = new ArticleQuery(); + $aq->updateRecord([ + 'content' => 'Hello', + 'last-updated' => '2019-11-09 10:00:56' + ], [ + 'article-id' => 77 + ]); + $query = $aq->getQuery(); + $isEqual = $query == 'update articles set article_content = \'Hello\',last_updated = \'2019-11-09 10:00:56\' where article_id = 77;'; + $this->assertTrue($isEqual); + } + /** + * @test + */ + public function testUpdateRecord02() { + $aq = new ArticleQuery(); + $aq->updateRecord([ + 'content' => 'Hello', + 'last-updated' => '2019-11-09 10:00:56' + ], [ + 'article-id' => 77, + 'author-id' => 1 + ]); + $query = $aq->getQuery(); + $isEqual = $query == 'update articles set article_content = \'Hello\',last_updated = \'2019-11-09 10:00:56\' where article_id = 77 and author_id = 1;'; + $this->assertTrue($isEqual); + } + /** + * @test + */ + public function testUpdateRecord03() { + $aq = new ArticleQuery(); + $aq->updateRecord([ + 'content' => 'Hello', + 'last-updated' => '2019-11-09 10:00:56' + ], [ + 'article-id' => 77, + 'author-id' => 1 + ],['!=']); + $query = $aq->getQuery(); + $isEqual = $query == 'update articles set article_content = \'Hello\',last_updated = \'2019-11-09 10:00:56\' where article_id != 77 and author_id = 1;'; + $this->assertTrue($isEqual); + } } diff --git a/tests/MySQLTableTest.php b/tests/MySQLTableTest.php index ae3261f..eeee371 100644 --- a/tests/MySQLTableTest.php +++ b/tests/MySQLTableTest.php @@ -23,173 +23,193 @@ * SOFTWARE. */ namespace phMysql\tests; -use phMysql\MySQLTable; + use phMysql\MySQLColumn; +use phMysql\MySQLTable; use PHPUnit\Framework\TestCase; -use phMysql\tests\ArticleQuery; /** * A set of test units for testing the class 'MySQLTable'. * * @author Ibrahim */ -class MySQLTableTest extends TestCase{ +class MySQLTableTest extends TestCase { /** * @test */ - public function testSetDBName00() { - $table = new MySQLTable('table'); - $this->assertFalse($table->setSchemaName('')); - $this->assertFalse($table->setSchemaName('0-db')); - $this->assertTrue($table->setSchemaName('_db')); - $this->assertEquals('_db',$table->getDatabaseName()); - $this->assertFalse($table->setSchemaName('_db x')); - $this->assertEquals('_db',$table->getDatabaseName()); - $this->assertEquals('_db.table',$table->getName()); - $this->assertEquals('table',$table->getName(false)); + public function setOwnerQueryTest00() { + $table = new MySQLTable(); + $table->setOwnerQuery(null); + $this->assertNull($table->getOwnerQuery()); } /** * @test */ - public function testPrimaryKey00() { - $table = new MySQLTable('hello'); - $table->addColumn('id-col', [ - 'is-primary'=>true, - 'size'=>3 - ]); - $this->assertTrue($table->getCol('id-col')->isUnique()); + public function testAddColumn00() { + $table = new MySQLTable(); + $this->assertTrue($table->addColumn('new-col', new MySQLColumn())); + $this->assertFalse($table->addColumn('new-col-2', new MySQLColumn())); + $this->assertTrue($table->addColumn('new-col-2', new MySQLColumn('col_2', 'varchar'))); + $this->assertFalse($table->addColumn('new-col-2', new MySQLColumn('col_3', 'varchar'))); + return $table; } /** * @test - * @param MySQLTable $table - * @depends testPrimaryKey00 */ - public function testPrimaryKey01($table) { - $table->addColumn('id-col-2', [ - 'is-primary'=>true - ]); - $this->assertFalse($table->getCol('id-col')->isUnique()); - $this->assertFalse($table->getCol('id-col-2')->isUnique()); + public function testAddColumn01() { + $table = new MySQLTable(); + $this->assertTrue($table->addColumn(' new-col ', new MySQLColumn())); + $this->assertFalse($table->addColumn('invalid key', new MySQLColumn('col_2'))); + $this->assertFalse($table->addColumn('-', new MySQLColumn('col_2'))); + $this->assertFalse($table->addColumn('--', new MySQLColumn('col_2'))); + return $table; } /** * @test - * @param MySQLTable $table - * @depends testPrimaryKey01 */ - public function testPrimaryKey02($table) { - $table->removeColumn('id-col'); - $this->assertTrue($table->getCol('id-col-2')->isUnique()); + public function testAddColumn02() { + $table = new MySQLTable(); + $table->addDefaultCols(); + $this->assertFalse($table->addColumn('id', new MySQLColumn('user_id'))); + $this->assertFalse($table->addColumn('user-id', new MySQLColumn('id'))); + $this->assertFalse($table->addColumn('c-on', new MySQLColumn('created_on'))); + $this->assertFalse($table->addColumn('created-on', new MySQLColumn('cr_date'))); + $this->assertFalse($table->addColumn('last-u', new MySQLColumn('last_updated'))); + $this->assertFalse($table->addColumn('last-updated', new MySQLColumn('l_updated'))); + return $table; } /** * @test */ - public function testAddColumn00() { + public function testAddDefaultCols00() { $table = new MySQLTable(); - $this->assertTrue($table->addColumn('new-col', new MySQLColumn())); - $this->assertFalse($table->addColumn('new-col-2', new MySQLColumn())); - $this->assertTrue($table->addColumn('new-col-2', new MySQLColumn('col_2', 'varchar'))); - $this->assertFalse($table->addColumn('new-col-2', new MySQLColumn('col_3', 'varchar'))); - return $table; + $table->addDefaultCols(); + $this->assertEquals(3,count($table->columns())); + $this->assertTrue($table->hasColumn('id')); + $this->assertTrue($table->hasColumn('created-on')); + $this->assertTrue($table->hasColumn('last-updated')); } /** - * - * @param MySQLTable $table - * @depends testAddColumn00 + * @test */ - public function testAttributesMap01($table) { - $map = $table->getAttribitesNames(); - $this->assertEquals([ - 'newCol', - 'newCol2' - ],$map); + public function testAddDefaultCols01() { + $table = new MySQLTable(); + $table->addDefaultCols([]); + $this->assertEquals(0,count($table->columns())); + $this->assertFalse($table->hasColumn('id')); + $this->assertFalse($table->hasColumn('created-on')); + $this->assertFalse($table->hasColumn('last-updated')); } /** - * - * @param MySQLTable $table - * @depends testGetColsNames + * @test */ - public function testAttributesMap02($table) { - $map = $table->getAttribitesNames(); - $this->assertEquals([ - 'id', - 'createdOn', - 'lastUpdated' - ],$map); + public function testAddDefaultCols02() { + $table = new MySQLTable(); + $table->addDefaultCols([ + 'id' => [ + 'key-name' => 'user-id', + 'db-name' => 'user_id' + ] + ]); + $this->assertEquals(1,count($table->columns())); + $this->assertFalse($table->hasColumn('id')); + $this->assertTrue($table->hasColumn('user-id')); + $this->assertFalse($table->hasColumn('created-on')); + $this->assertFalse($table->hasColumn('last-updated')); + + return $table; } - public function testGetColsNames() { - $t = new MySQLTable(); - $t->addDefaultCols([ - 'id'=>[], - 'created-on'=>[], - 'last-updated'=>[] + /** + * @test + */ + public function testAddDefaultCols03() { + $table = new MySQLTable(); + $table->addDefaultCols([ + 'id' => [ + 'key-name' => 'user id', + 'db-name' => 'user_id' + ] ]); - $colsNamesInDb = $t->getColsNames(); - $this->assertEquals('id',$colsNamesInDb[0]); - $this->assertEquals('created_on',$colsNamesInDb[1]); - $this->assertEquals('last_updated',$colsNamesInDb[2]); - return $t; + $this->assertEquals(1,count($table->columns())); + $this->assertFalse($table->hasColumn('user id')); + $this->assertTrue($table->hasColumn('id')); + $this->assertEquals('user_id',$table->getCol('id')->getName()); } /** * @test */ - public function testGetEntityMethodsTest00() { + public function testAddDefaultCols04() { $table = new MySQLTable(); - $table->addColumn('user-id', new MySQLColumn('user_id', 'varchar', 15)); - $this->assertEquals([ - 'setters'=>[ - 'setUserId' - ], - 'getters'=>[ - 'getUserId' + $table->addDefaultCols([ + 'id' => [ + 'key-name' => 'an-id', + 'db-name' => 'user id' ] - ],$table->getEntityMethods()); - return $table; + ]); + $this->assertEquals(1,count($table->columns())); + $this->assertEquals('id',$table->getCol('an-id')->getName()); } /** - * - * @param MySQLTable $table - * @depends testGetEntityMethodsTest00 + * @test */ - public function testSettersMap00($table) { - $this->assertEquals([ - 'setUserId'=>'user_id' - ],$table->getSettersMap()); + public function testAddDefaultCols05() { + $table = new MySQLTable(); + $table->addDefaultCols([ + 'created-on' => [ + 'key-name' => 'created on', + 'db-name' => 'cr_date' + ] + ]); + $this->assertEquals(1,count($table->columns())); + $this->assertFalse($table->hasColumn('created on')); + $this->assertTrue($table->hasColumn('created-on')); + $this->assertEquals('cr_date',$table->getCol('created-on')->getName()); } /** * @test */ - public function testGetEntityMethodsTest01() { + public function testAddDefaultCols06() { $table = new MySQLTable(); - $table->addColumn('user-id', new MySQLColumn('user_id', 'varchar', 15)); - $table->addColumn('PASS', new MySQLColumn('user_pass', 'varchar', 15)); - $table->addColumn('c-in', new MySQLColumn('created_on', 'datetime')); - $this->assertEquals([ - 'setters'=>[ - 'setUserId', - 'setPASS', - 'setCIn' - ], - 'getters'=>[ - 'getUserId', - 'getPASS', - 'getCIn' + $table->addDefaultCols([ + 'created-on' => [ + 'key-name' => 'a-date', + 'db-name' => 'created on' ] - ],$table->getEntityMethods()); - return $table; + ]); + $this->assertEquals(1,count($table->columns())); + $this->assertEquals('created_on',$table->getCol('a-date')->getName()); } /** - * - * @param MySQLTable $table - * @depends testGetEntityMethodsTest01 + * @test */ - public function testSettersMap01($table) { - $this->assertEquals([ - 'setUserId'=>'user_id', - 'setPASS'=>'user_pass', - 'setCIn'=>'created_on' - ],$table->getSettersMap()); + public function testAddDefaultCols07() { + $table = new MySQLTable(); + $table->addDefaultCols([ + 'last-updated' => [ + 'key-name' => 'updated on', + 'db-name' => 'u_date' + ] + ]); + $this->assertEquals(1,count($table->columns())); + $this->assertFalse($table->hasColumn('updated on')); + $this->assertTrue($table->hasColumn('last-updated')); + $this->assertEquals('u_date',$table->getCol('last-updated')->getName()); + } + /** + * @test + */ + public function testAddDefaultCols08() { + $table = new MySQLTable(); + $table->addDefaultCols([ + 'created-on' => [ + 'key-name' => 'a-date', + 'db-name' => 'updated_on' + ] + ]); + $this->assertEquals(1,count($table->columns())); + $this->assertEquals('updated_on',$table->getCol('a-date')->getName()); } /** * @@ -209,30 +229,33 @@ public function testAttributesMap00($table) { * @param MySQLTable $table * @depends testAddColumn00 */ - public function testHasCol00($table) { - $this->assertTrue($table->hasColumn('new-col')); - $this->assertTrue($table->hasColumn(' new-col ')); - $this->assertTrue($table->hasColumn('new-col-2')); + public function testAttributesMap01($table) { + $map = $table->getAttribitesNames(); + $this->assertEquals([ + 'newCol', + 'newCol2' + ],$map); } /** - * @test + * + * @param MySQLTable $table + * @depends testGetColsNames */ - public function testAddColumn01() { - $table = new MySQLTable(); - $this->assertTrue($table->addColumn(' new-col ', new MySQLColumn())); - $this->assertFalse($table->addColumn('invalid key', new MySQLColumn('col_2'))); - $this->assertFalse($table->addColumn('-', new MySQLColumn('col_2'))); - $this->assertFalse($table->addColumn('--', new MySQLColumn('col_2'))); - return $table; + public function testAttributesMap02($table) { + $map = $table->getAttribitesNames(); + $this->assertEquals([ + 'id', + 'createdOn', + 'lastUpdated' + ],$map); } /** * * @param MySQLTable $table - * @depends testAddColumn00 + * @depends testAddDefaultCols02 */ - public function testHasCol01($table) { - $this->assertTrue($table->hasColumn('new-col')); - $this->assertFalse($table->hasColumn('invalid key')); + public function testAttributesMap04($table) { + $this->assertEquals(['userId'],$table->getAttribitesNames()); } /** * @test @@ -241,20 +264,6 @@ public function testConstructor00() { $table = new MySQLTable(); $this->assertEquals('table',$table->getName()); } - /** - * @test - */ - public function testAddColumn02() { - $table = new MySQLTable(); - $table->addDefaultCols(); - $this->assertFalse($table->addColumn('id', new MySQLColumn('user_id'))); - $this->assertFalse($table->addColumn('user-id', new MySQLColumn('id'))); - $this->assertFalse($table->addColumn('c-on', new MySQLColumn('created_on'))); - $this->assertFalse($table->addColumn('created-on', new MySQLColumn('cr_date'))); - $this->assertFalse($table->addColumn('last-u', new MySQLColumn('last_updated'))); - $this->assertFalse($table->addColumn('last-updated', new MySQLColumn('l_updated'))); - return $table; - } /** * @test */ @@ -293,169 +302,195 @@ public function testConstructor05() { /** * @test */ - public function testAddDefaultCols00() { - $table = new MySQLTable(); + public function testCreateEntity00() { + $table = new MySQLTable('users'); $table->addDefaultCols(); - $this->assertEquals(3,count($table->columns())); - $this->assertTrue($table->hasColumn('id')); - $this->assertTrue($table->hasColumn('created-on')); - $this->assertTrue($table->hasColumn('last-updated')); - } - /** - * @test - */ - public function testAddDefaultCols01() { - $table = new MySQLTable(); - $table->addDefaultCols([]); - $this->assertEquals(0,count($table->columns())); - $this->assertFalse($table->hasColumn('id')); - $this->assertFalse($table->hasColumn('created-on')); - $this->assertFalse($table->hasColumn('last-updated')); + $this->assertTrue($table->createEntityClass([ + 'store-path' => __DIR__, + 'class-name' => 'User' + ])); + $this->assertTrue(file_exists($table->getEntityPath())); + require_once $table->getEntityPath(); + $this->assertTrue(class_exists($table->getEntityNamespace())); } /** + * * @test */ - public function testAddDefaultCols02() { + public function testGetColByIndex() { $table = new MySQLTable(); - $table->addDefaultCols([ - 'id'=>[ - 'key-name'=>'user-id', - 'db-name'=>'user_id' + $table->addColumns([ + 'user-id' => [ + 'datatype' => 'int', + 'size' => 11, + 'is-primary' => true + ], + 'username' => [ + 'size' => 20, + 'is-unique' => true + ], + 'email' => [ + 'size' => 150, + 'is-unique' => true + ], + 'password' => [ + 'size' => 64 ] ]); - $this->assertEquals(1,count($table->columns())); - $this->assertFalse($table->hasColumn('id')); - $this->assertTrue($table->hasColumn('user-id')); - $this->assertFalse($table->hasColumn('created-on')); - $this->assertFalse($table->hasColumn('last-updated')); - return $table; + $col00 = $table->getColByIndex(0); + $this->assertEquals('user_id',$col00->getName()); + $this->assertEquals('int',$col00->getType()); + $this->assertEquals(11,$col00->getSize()); + $this->assertTrue($col00->isPrimary()); + + $col01 = $table->getColByIndex(2); + $this->assertEquals('varchar',$col01->getType()); + $this->assertEquals(150,$col01->getSize()); + $this->assertFalse($col01->isPrimary()); + $this->asserttrue($col01->isUnique()); + + $col02 = $table->getColByIndex(6); + $this->assertNull($col02); } /** - * - * @param MySQLTable $table - * @depends testAddDefaultCols02 + * @test */ - public function testAttributesMap04($table) { - $this->assertEquals(['userId'],$table->getAttribitesNames()); + public function testGetColByKey() { + $table = new MySQLTable(); + $table->addDefaultCols(); + $this->assertNull($table->getCol('not-exist')); + $this->assertEquals('id',$table->getCol('id')->getName()); + $this->assertEquals('timestamp',$table->getCol('created-on ')->getType()); + $this->assertEquals('datetime',$table->getCol(' last-updated')->getType()); } /** * @test */ - public function testAddDefaultCols03() { + public function testGetColIndex() { $table = new MySQLTable(); - $table->addDefaultCols([ - 'id'=>[ - 'key-name'=>'user id', - 'db-name'=>'user_id' - ] + $table->addDefaultCols(); + $this->assertEquals(-1,$table->getColIndex('not-exist')); + $this->assertEquals(0,$table->getColIndex('id')); + $this->assertEquals(1,$table->getColIndex('created-on ')); + $this->assertEquals(2,$table->getColIndex(' last-updated')); + } + public function testGetColsNames() { + $t = new MySQLTable(); + $t->addDefaultCols([ + 'id' => [], + 'created-on' => [], + 'last-updated' => [] ]); - $this->assertEquals(1,count($table->columns())); - $this->assertFalse($table->hasColumn('user id')); - $this->assertTrue($table->hasColumn('id')); - $this->assertEquals('user_id',$table->getCol('id')->getName()); + $colsNamesInDb = $t->getColsNames(); + $this->assertEquals('id',$colsNamesInDb[0]); + $this->assertEquals('created_on',$colsNamesInDb[1]); + $this->assertEquals('last_updated',$colsNamesInDb[2]); + + return $t; } /** * @test */ - public function testAddDefaultCols04() { + public function testGetCreatePrimaryKeyStatement00() { $table = new MySQLTable(); - $table->addDefaultCols([ - 'id'=>[ - 'key-name'=>'an-id', - 'db-name'=>'user id' - ] - ]); - $this->assertEquals(1,count($table->columns())); - $this->assertEquals('id',$table->getCol('an-id')->getName()); + $this->assertTrue(true); } /** * @test */ - public function testAddDefaultCols05() { + public function testGetEntityMethodsTest00() { $table = new MySQLTable(); - $table->addDefaultCols([ - 'created-on'=>[ - 'key-name'=>'created on', - 'db-name'=>'cr_date' + $table->addColumn('user-id', new MySQLColumn('user_id', 'varchar', 15)); + $this->assertEquals([ + 'setters' => [ + 'setUserId' + ], + 'getters' => [ + 'getUserId' ] - ]); - $this->assertEquals(1,count($table->columns())); - $this->assertFalse($table->hasColumn('created on')); - $this->assertTrue($table->hasColumn('created-on')); - $this->assertEquals('cr_date',$table->getCol('created-on')->getName()); + ],$table->getEntityMethods()); + + return $table; } /** * @test */ - public function testAddDefaultCols06() { + public function testGetEntityMethodsTest01() { $table = new MySQLTable(); - $table->addDefaultCols([ - 'created-on'=>[ - 'key-name'=>'a-date', - 'db-name'=>'created on' + $table->addColumn('user-id', new MySQLColumn('user_id', 'varchar', 15)); + $table->addColumn('PASS', new MySQLColumn('user_pass', 'varchar', 15)); + $table->addColumn('c-in', new MySQLColumn('created_on', 'datetime')); + $this->assertEquals([ + 'setters' => [ + 'setUserId', + 'setPASS', + 'setCIn' + ], + 'getters' => [ + 'getUserId', + 'getPASS', + 'getCIn' ] - ]); - $this->assertEquals(1,count($table->columns())); - $this->assertEquals('created_on',$table->getCol('a-date')->getName()); + ],$table->getEntityMethods()); + + return $table; } /** - * @test + * + * @param MySQLTable $table + * @depends testAddColumn00 */ - public function testAddDefaultCols07() { - $table = new MySQLTable(); - $table->addDefaultCols([ - 'last-updated'=>[ - 'key-name'=>'updated on', - 'db-name'=>'u_date' - ] - ]); - $this->assertEquals(1,count($table->columns())); - $this->assertFalse($table->hasColumn('updated on')); - $this->assertTrue($table->hasColumn('last-updated')); - $this->assertEquals('u_date',$table->getCol('last-updated')->getName()); + public function testHasCol00($table) { + $this->assertTrue($table->hasColumn('new-col')); + $this->assertTrue($table->hasColumn(' new-col ')); + $this->assertTrue($table->hasColumn('new-col-2')); } /** - * @test + * + * @param MySQLTable $table + * @depends testAddColumn00 */ - public function testAddDefaultCols08() { - $table = new MySQLTable(); - $table->addDefaultCols([ - 'created-on'=>[ - 'key-name'=>'a-date', - 'db-name'=>'updated_on' - ] - ]); - $this->assertEquals(1,count($table->columns())); - $this->assertEquals('updated_on',$table->getCol('a-date')->getName()); + public function testHasCol01($table) { + $this->assertTrue($table->hasColumn('new-col')); + $this->assertFalse($table->hasColumn('invalid key')); } /** * @test */ - public function testGetColIndex() { - $table = new MySQLTable(); - $table->addDefaultCols(); - $this->assertEquals(-1,$table->getColIndex('not-exist')); - $this->assertEquals(0,$table->getColIndex('id')); - $this->assertEquals(1,$table->getColIndex('created-on ')); - $this->assertEquals(2,$table->getColIndex(' last-updated')); + public function testPrimaryKey00() { + $table = new MySQLTable('hello'); + $table->addColumn('id-col', [ + 'is-primary' => true, + 'size' => 3 + ]); + $this->assertTrue($table->getCol('id-col')->isUnique()); + + return $table; } /** * @test + * @param MySQLTable $table + * @depends testPrimaryKey00 */ - public function testGetColByKey() { - $table = new MySQLTable(); - $table->addDefaultCols(); - $this->assertNull($table->getCol('not-exist')); - $this->assertEquals('id',$table->getCol('id')->getName()); - $this->assertEquals('timestamp',$table->getCol('created-on ')->getType()); - $this->assertEquals('datetime',$table->getCol(' last-updated')->getType()); + public function testPrimaryKey01($table) { + $table->addColumn('id-col-2', [ + 'is-primary' => true + ]); + $this->assertFalse($table->getCol('id-col')->isUnique()); + $this->assertFalse($table->getCol('id-col-2')->isUnique()); + + return $table; } /** * @test + * @param MySQLTable $table + * @depends testPrimaryKey01 */ - public function testGetCreatePrimaryKeyStatement00() { - $table = new MySQLTable(); - $this->assertTrue(true); + public function testPrimaryKey02($table) { + $table->removeColumn('id-col'); + $this->assertTrue($table->getCol('id-col-2')->isUnique()); + + return $table; } /** * @test @@ -509,10 +544,16 @@ public function testRemoveColumn04() { /** * @test */ - public function setOwnerQueryTest00() { - $table = new MySQLTable(); - $table->setOwnerQuery(null); - $this->assertNull($table->getOwnerQuery()); + public function testSetDBName00() { + $table = new MySQLTable('table'); + $this->assertFalse($table->setSchemaName('')); + $this->assertFalse($table->setSchemaName('0-db')); + $this->assertTrue($table->setSchemaName('_db')); + $this->assertEquals('_db',$table->getDatabaseName()); + $this->assertFalse($table->setSchemaName('_db x')); + $this->assertEquals('_db',$table->getDatabaseName()); + $this->assertEquals('_db.table',$table->getName()); + $this->assertEquals('table',$table->getName(false)); } /** * @test @@ -552,55 +593,24 @@ public function testSetMySQLVersion03() { } /** * - * @test + * @param MySQLTable $table + * @depends testGetEntityMethodsTest00 */ - public function testGetColByIndex() { - $table = new MySQLTable(); - $table->addColumns([ - 'user-id'=>[ - 'datatype'=>'int', - 'size'=>11, - 'is-primary'=>true - ], - 'username'=>[ - 'size'=>20, - 'is-unique'=>true - ], - 'email'=>[ - 'size'=>150, - 'is-unique'=>true - ], - 'password'=>[ - 'size'=>64 - ] - ]); - $col00 = $table->getColByIndex(0); - $this->assertEquals('user_id',$col00->getName()); - $this->assertEquals('int',$col00->getType()); - $this->assertEquals(11,$col00->getSize()); - $this->assertTrue($col00->isPrimary()); - - $col01 = $table->getColByIndex(2); - $this->assertEquals('varchar',$col01->getType()); - $this->assertEquals(150,$col01->getSize()); - $this->assertFalse($col01->isPrimary()); - $this->asserttrue($col01->isUnique()); - - $col02 = $table->getColByIndex(6); - $this->assertNull($col02); + public function testSettersMap00($table) { + $this->assertEquals([ + 'setUserId' => 'user_id' + ],$table->getSettersMap()); } /** - * @test + * + * @param MySQLTable $table + * @depends testGetEntityMethodsTest01 */ - public function testCreateEntity00() { - $table = new MySQLTable('users'); - $table->addDefaultCols(); - $this->assertTrue($table->createEntityClass([ - 'store-path'=>__DIR__, - 'class-name'=>'User' - ])); - $this->assertTrue(file_exists($table->getEntityPath())); - require_once $table->getEntityPath(); - $this->assertTrue(class_exists($table->getEntityNamespace())); + public function testSettersMap01($table) { + $this->assertEquals([ + 'setUserId' => 'user_id', + 'setPASS' => 'user_pass', + 'setCIn' => 'created_on' + ],$table->getSettersMap()); } } diff --git a/tests/QueryTestObj.php b/tests/QueryTestObj.php index ed809b3..65cbc33 100644 --- a/tests/QueryTestObj.php +++ b/tests/QueryTestObj.php @@ -5,29 +5,29 @@ * To change this template file, choose Tools | Templates * and open the template in the editor. */ - namespace phMysql\tests; + use phMysql\MySQLQuery; /** * An object which used as a base for testing the class 'MySQLQuery'. * * @author Ibrahim */ -class QueryTestObj extends MySQLQuery{ +class QueryTestObj extends MySQLQuery { public function __construct() { parent::__construct('first_table'); $this->getTable()->addColumns([ - 'first-col'=>[ - 'name'=>'col_00' + 'first-col' => [ + 'name' => 'col_00' ], - 'second-col'=>[ - 'name'=>'col_01' + 'second-col' => [ + 'name' => 'col_01' ], - 'third-col'=>[ - 'name'=>'col_02' + 'third-col' => [ + 'name' => 'col_02' ], - 'fourth-col'=>[ - 'name'=>'col_03' + 'fourth-col' => [ + 'name' => 'col_03' ] ]); } diff --git a/tests/User.php b/tests/User.php new file mode 100644 index 0000000..c58e74d --- /dev/null +++ b/tests/User.php @@ -0,0 +1,77 @@ +id = $id; + } + /** + * Returns the value of the attribute 'lastUpdated'. + * The value of the attribute is mapped to the column which has + * the name 'id'. + * @return int The value of the attribute. + **/ + public function getId(){ + return $this->id; + } + /** + * Sets the value of the attribute 'lastUpdated'. + * The value of the attribute is mapped to the column which has + * the name 'created_on'. + * @param $createdOn string The new value of the attribute. + **/ + public function setCreatedOn($createdOn){ + $this->createdOn = $createdOn; + } + /** + * Returns the value of the attribute 'lastUpdated'. + * The value of the attribute is mapped to the column which has + * the name 'created_on'. + * @return string The value of the attribute. + **/ + public function getCreatedOn(){ + return $this->createdOn; + } + /** + * Sets the value of the attribute 'lastUpdated'. + * The value of the attribute is mapped to the column which has + * the name 'last_updated'. + * @param $lastUpdated string|null The new value of the attribute. + **/ + public function setLastUpdated($lastUpdated){ + $this->lastUpdated = $lastUpdated; + } + /** + * Returns the value of the attribute 'lastUpdated'. + * The value of the attribute is mapped to the column which has + * the name 'last_updated'. + * @return string|null The value of the attribute. + **/ + public function getLastUpdated(){ + return $this->lastUpdated; + } +} diff --git a/tests/UsersQuery.php b/tests/UsersQuery.php index aad4532..479b2e6 100644 --- a/tests/UsersQuery.php +++ b/tests/UsersQuery.php @@ -1,7 +1,8 @@ createStructure(); echo $q00->getQuery(); -if($conn->executeQuery($q00)){ + +if ($conn->executeQuery($q00)) { $q00 = new phMysql\tests\ArticleQuery(); $q00->createStructure(); echo $q00->getQuery(); - if($conn->executeQuery($q00)){ + + if ($conn->executeQuery($q00)) { echo "Successfully Created Tables.\n"; echo "Adding Test Dataset...\n"; - for($x = 0 ; $x < 5 ; $x++){ + + for ($x = 0 ; $x < 5 ; $x++) { $q = new phMysql\tests\UsersQuery(); $q->insertRecord([ - 'user-id'=>$x + 1, - 'email'=>$x.'@test.com', - 'name'=>'Test User #'.$x + 'user-id' => $x + 1, + 'email' => $x.'@test.com', + 'name' => 'Test User #'.$x ]); echo $q->getQuery()."\n"; - if($conn->executeQuery($q)){ - for($y = 0 ; $y < 4 ; $y++){ + + if ($conn->executeQuery($q)) { + for ($y = 0 ; $y < 4 ; $y++) { $q = new \phMysql\tests\ArticleQuery(); $q->insertRecord([ - 'author-id'=>$x + 1, - 'content'=>'This is the body of article number '.$y.' which ' - . 'is created by the user which has the ID '.($x + 1).'.', - 'title'=>'User # '.($x + 1).' Article #'.$y + 'author-id' => $x + 1, + 'content' => 'This is the body of article number '.$y.' which ' + .'is created by the user which has the ID '.($x + 1).'.', + 'title' => 'User # '.($x + 1).' Article #'.$y ]); echo $q->getQuery()."\n"; - if(!$conn->executeQuery($q)){ + + if (!$conn->executeQuery($q)) { echo "Unable to execute query.\n"; echo $conn->getErrorCode().': '.$conn->getErrorMessage()."\n"; } } - } - else{ + } else { echo "Unable to execute query.\n"; echo $conn->getErrorCode().': '.$conn->getErrorMessage()."\n"; } } - } - else{ + } else { echo 'Unable to create the table '.$q00->getTableName()."\n"; echo $conn->getErrorCode().': '.$conn->getErrorMessage()."\n"; } -} -else{ +} else { echo 'Unable to create the table '.$q00->getTableName()."\n"; echo $conn->getErrorCode().': '.$conn->getErrorMessage()."\n"; } -register_shutdown_function(function(){ +register_shutdown_function(function() +{ echo "Dropping tables...\n"; $conn = new phMysql\MySQLLink('localhost', 'root', '123456'); $conn->setDB('testing_db'); @@ -115,4 +118,4 @@ $q->dropTable(); $conn->executeQuery($q); echo "Done.\n"; -}); \ No newline at end of file +});