From 7cfb76171a98084d2dc4ab517dbf12a23d481c1d Mon Sep 17 00:00:00 2001 From: "Kamshory, MT" Date: Tue, 3 Dec 2024 23:46:30 +0700 Subject: [PATCH 1/5] Update --- src/Util/Database/PicoDatabaseUtilPostgreSql.php | 4 ++++ src/Util/Database/PicoDatabaseUtilSqlite.php | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/Util/Database/PicoDatabaseUtilPostgreSql.php b/src/Util/Database/PicoDatabaseUtilPostgreSql.php index 6006ff48..e42ed27f 100644 --- a/src/Util/Database/PicoDatabaseUtilPostgreSql.php +++ b/src/Util/Database/PicoDatabaseUtilPostgreSql.php @@ -303,6 +303,10 @@ public function createColumnPostgre($column, $autoIncrementKeys = null) */ public function fixDefaultValue($defaultValue, $type) { + if(stripos($type, 'bool') === 0) + { + return $defaultValue != 0 ? 'true' : 'false'; + } if (strtolower($defaultValue) == 'true' || strtolower($defaultValue) == 'false' || strtolower($defaultValue) == 'null') { return $defaultValue; } diff --git a/src/Util/Database/PicoDatabaseUtilSqlite.php b/src/Util/Database/PicoDatabaseUtilSqlite.php index 0495d099..4fc2e8c9 100644 --- a/src/Util/Database/PicoDatabaseUtilSqlite.php +++ b/src/Util/Database/PicoDatabaseUtilSqlite.php @@ -466,6 +466,10 @@ public function createColumn($column) */ public function fixDefaultValue($defaultValue, $type) { + if(stripos($type, 'bool') === 0) + { + return $defaultValue != 0 ? 'true' : 'false'; + } if(strtolower($defaultValue) == 'true' || strtolower($defaultValue) == 'false' || strtolower($defaultValue) == 'null' From b8e26fd60d59c002bdfe9d13f809a455efaee17e Mon Sep 17 00:00:00 2001 From: "Kamshory, MT" Date: Wed, 4 Dec 2024 00:04:30 +0700 Subject: [PATCH 2/5] Update PicoDatabaseUtilPostgreSql.php --- src/Util/Database/PicoDatabaseUtilPostgreSql.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Util/Database/PicoDatabaseUtilPostgreSql.php b/src/Util/Database/PicoDatabaseUtilPostgreSql.php index e42ed27f..a8b61a68 100644 --- a/src/Util/Database/PicoDatabaseUtilPostgreSql.php +++ b/src/Util/Database/PicoDatabaseUtilPostgreSql.php @@ -310,7 +310,7 @@ public function fixDefaultValue($defaultValue, $type) if (strtolower($defaultValue) == 'true' || strtolower($defaultValue) == 'false' || strtolower($defaultValue) == 'null') { return $defaultValue; } - + if (stripos($type, 'varchar') !== false || stripos($type, 'char') !== false || stripos($type, 'text') !== false) { return "'" . addslashes($defaultValue) . "'"; } From b397a1cd6daf7bbc3d9dc42efe0b3133368c07ab Mon Sep 17 00:00:00 2001 From: "Kamshory, MT" Date: Wed, 4 Dec 2024 06:36:33 +0700 Subject: [PATCH 3/5] Fixing create table --- src/Util/Database/PicoDatabaseUtilMySql.php | 12 ++++++++++-- .../Database/PicoDatabaseUtilPostgreSql.php | 17 +++++++++++------ src/Util/Database/PicoDatabaseUtilSqlite.php | 16 +++++++++------- 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/src/Util/Database/PicoDatabaseUtilMySql.php b/src/Util/Database/PicoDatabaseUtilMySql.php index 4aefc78e..3328544c 100644 --- a/src/Util/Database/PicoDatabaseUtilMySql.php +++ b/src/Util/Database/PicoDatabaseUtilMySql.php @@ -185,14 +185,22 @@ public function createColumn($column) */ public function fixDefaultValue($defaultValue, $type) { - if(strtolower($defaultValue) == 'true' || strtolower($defaultValue) == 'false' || strtolower($defaultValue) == 'null') + if(stripos($type, 'bool') !== false || stripos($type, 'tinyint(1)') !== false) + { + return $defaultValue != 0 ? 'true' : 'false'; + } + else if(strtolower($defaultValue) == 'true' || strtolower($defaultValue) == 'false' || strtolower($defaultValue) == 'null') { return $defaultValue; } - if(stripos($type, 'enum') !== false || stripos($type, 'char') !== false || stripos($type, 'text') !== false || stripos($type, 'int') !== false || stripos($type, 'float') !== false || stripos($type, 'double') !== false) + else if(stripos($type, 'enum') !== false || stripos($type, 'char') !== false || stripos($type, 'text') !== false) { return "'".$defaultValue."'"; } + else if(stripos($type, 'int') !== false || stripos($type, 'decimal') !== false || stripos($type, 'float') !== false || stripos($type, 'double') !== false) + { + return $defaultValue * 1; + } return $defaultValue; } diff --git a/src/Util/Database/PicoDatabaseUtilPostgreSql.php b/src/Util/Database/PicoDatabaseUtilPostgreSql.php index a8b61a68..1712952d 100644 --- a/src/Util/Database/PicoDatabaseUtilPostgreSql.php +++ b/src/Util/Database/PicoDatabaseUtilPostgreSql.php @@ -303,18 +303,23 @@ public function createColumnPostgre($column, $autoIncrementKeys = null) */ public function fixDefaultValue($defaultValue, $type) { - if(stripos($type, 'bool') === 0) + if(stripos($type, 'bool') !== false) { return $defaultValue != 0 ? 'true' : 'false'; } - if (strtolower($defaultValue) == 'true' || strtolower($defaultValue) == 'false' || strtolower($defaultValue) == 'null') { + else if (strtolower($defaultValue) == 'true' || strtolower($defaultValue) == 'false' || strtolower($defaultValue) == 'null') { return $defaultValue; - } - - if (stripos($type, 'varchar') !== false || stripos($type, 'char') !== false || stripos($type, 'text') !== false) { + } + else if (stripos($type, 'enum') !== false || stripos($type, 'varchar') !== false || stripos($type, 'char') !== false || stripos($type, 'text') !== false) { return "'" . addslashes($defaultValue) . "'"; } - + else if(stripos($type, 'int') !== false + || stripos($type, 'real') !== false + || stripos($type, 'float') !== false + || stripos($type, 'double') !== false) + { + return $defaultValue + 0; + } return $defaultValue; } diff --git a/src/Util/Database/PicoDatabaseUtilSqlite.php b/src/Util/Database/PicoDatabaseUtilSqlite.php index 4fc2e8c9..11ce545b 100644 --- a/src/Util/Database/PicoDatabaseUtilSqlite.php +++ b/src/Util/Database/PicoDatabaseUtilSqlite.php @@ -466,27 +466,29 @@ public function createColumn($column) */ public function fixDefaultValue($defaultValue, $type) { - if(stripos($type, 'bool') === 0) + if(stripos($type, 'bool') !== false) { return $defaultValue != 0 ? 'true' : 'false'; } - if(strtolower($defaultValue) == 'true' + else if(strtolower($defaultValue) == 'true' || strtolower($defaultValue) == 'false' || strtolower($defaultValue) == 'null' ) { return $defaultValue; } - if(stripos($type, 'enum') !== false - || stripos($type, 'char') !== false + else if(stripos($type, 'char') !== false || stripos($type, 'text') !== false - || stripos($type, 'int') !== false - || stripos($type, 'float') !== false - || stripos($type, 'double') !== false ) { return "'".$defaultValue."'"; } + else if(stripos($type, 'int') !== false + || stripos($type, 'float') !== false + || stripos($type, 'double') !== false) + { + return $defaultValue + 0; + } return $defaultValue; } From 75594b9ab76d8aa3f2724cc5f00525a1fd6cfea3 Mon Sep 17 00:00:00 2001 From: "Kamshory, MT" Date: Wed, 4 Dec 2024 06:46:12 +0700 Subject: [PATCH 4/5] Update Create Table --- src/Util/Database/PicoDatabaseUtilMySql.php | 85 +++++++------ .../Database/PicoDatabaseUtilPostgreSql.php | 115 +++++++++++------- src/Util/Database/PicoDatabaseUtilSqlite.php | 81 +++++++----- 3 files changed, 165 insertions(+), 116 deletions(-) diff --git a/src/Util/Database/PicoDatabaseUtilMySql.php b/src/Util/Database/PicoDatabaseUtilMySql.php index 3328544c..be0e0994 100644 --- a/src/Util/Database/PicoDatabaseUtilMySql.php +++ b/src/Util/Database/PicoDatabaseUtilMySql.php @@ -83,14 +83,11 @@ public function dumpStructure($tableInfo, $tableName, $createIfNotExists = false $query[] = "-- DROP TABLE IF EXISTS `$tableName`;"; $query[] = ""; } - $createStatement = ""; - $createStatement = "CREATE TABLE"; if($createIfNotExists) { $createStatement .= " IF NOT EXISTS"; } - $autoIncrementKeys = $this->getAutoIncrementKey($tableInfo); $query[] = "$createStatement `$tableName` ("; @@ -101,34 +98,12 @@ public function dumpStructure($tableInfo, $tableName, $createIfNotExists = false { if(isset($cols[$columnName])) { - $columns[] = $this->createColumn($cols[$columnName]); + $columns[] = $this->createColumn($cols[$columnName], $autoIncrementKeys, $tableInfo->getPrimaryKeys()); } } $query[] = implode(",\r\n", $columns); $query[] = ") ENGINE=$engine DEFAULT CHARSET=$charset;"; - $pk = $tableInfo->getPrimaryKeys(); - if(isset($pk) && is_array($pk) && !empty($pk)) - { - $query[] = ""; - $query[] = "ALTER TABLE `$tableName`"; - foreach($pk as $primaryKey) - { - $query[] = "\tADD PRIMARY KEY (`$primaryKey[name]`)"; - } - $query[] = ";"; - } - - foreach($tableInfo->getColumns() as $column) - { - if(isset($autoIncrementKeys) && is_array($autoIncrementKeys) && in_array($column[parent::KEY_NAME], $autoIncrementKeys)) - { - $query[] = ""; - $query[] = "ALTER TABLE `$tableName` \r\n\tMODIFY ".trim($this->createColumn($column), " \r\n\t ")." AUTO_INCREMENT"; - $query[] = ";"; - } - } - return implode("\r\n", $query); } @@ -136,40 +111,64 @@ public function dumpStructure($tableInfo, $tableName, $createIfNotExists = false * Creates a column definition for a SQL statement. * * This method constructs a SQL column definition based on the provided column details, - * including the column name, data type, nullability, and default value. The resulting - * definition is formatted for use in a CREATE TABLE statement. + * including the column name, data type, nullability, default value, primary key status, + * and auto-increment settings. The resulting definition is formatted for use in a CREATE TABLE statement. * * @param array $column An associative array containing details about the column: - * - string name: The name of the column. - * - string type: The data type of the column (e.g., VARCHAR, INT). - * - bool|string nullable: Indicates if the column allows NULL values (true or 'true' for NULL; otherwise, NOT NULL). - * - mixed default_value: The default value for the column (optional). + * - string 'name': The name of the column. + * - string 'type': The data type of the column (e.g., VARCHAR, INT). + * - bool|string 'nullable': Indicates if the column allows NULL values + * ('true' or true for NULL; otherwise, NOT NULL). + * - mixed 'default_value': The default value for the column (optional). + * @param array $autoIncrementKeys An array of column names that should have AUTO_INCREMENT property. + * @param array $primaryKeys An array of primary key columns, each being an associative array + * with at least a 'name' key. * * @return string The SQL column definition formatted as a string, suitable for inclusion in a CREATE TABLE statement. */ - public function createColumn($column) + public function createColumn($column, $autoIncrementKeys, $primaryKeys) { + $pkCols = array(); + foreach ($primaryKeys as $col) { + $pkCols[] = $col['name']; + } + $col = array(); - $col[] = "\t"; - $col[] = "`".$column[parent::KEY_NAME]."`"; - $col[] = $column['type']; - if(isset($column['nullable']) && strtolower(trim($column['nullable'])) == 'true') - { - $col[] = "NULL"; + $col[] = "\t"; // Adding indentation for readability in SQL statements + $columnName = $column[parent::KEY_NAME]; + $columnType = $column['type']; + + $col[] = "`" . $columnName . "`"; // Enclose column name in backticks + $col[] = $columnType; // Add the column type (e.g., INT, VARCHAR) + + // Check if the column is part of primary keys + if (in_array($columnName, $pkCols)) { + $col[] = 'PRIMARY KEY'; } - else - { + + // Check if the column should auto-increment + if (isset($autoIncrementKeys) && is_array($autoIncrementKeys) && in_array($column[parent::KEY_NAME], $autoIncrementKeys)) { + $col[] = 'AUTO_INCREMENT'; + } + + // Determine if the column allows NULL values + if (isset($column['nullable']) && strtolower(trim($column['nullable'])) == 'true') { + $col[] = "NULL"; + } else { $col[] = "NOT NULL"; } - if(isset($column['default_value'])) - { + + // Set default value if specified + if (isset($column['default_value'])) { $defaultValue = $column['default_value']; $defaultValue = $this->fixDefaultValue($defaultValue, $column['type']); $col[] = "DEFAULT $defaultValue"; } + return implode(" ", $col); } + /** * Fixes the default value for SQL insertion based on its type. * diff --git a/src/Util/Database/PicoDatabaseUtilPostgreSql.php b/src/Util/Database/PicoDatabaseUtilPostgreSql.php index 1712952d..f1582f38 100644 --- a/src/Util/Database/PicoDatabaseUtilPostgreSql.php +++ b/src/Util/Database/PicoDatabaseUtilPostgreSql.php @@ -121,28 +121,19 @@ public function dumpStructure($tableInfo, $tableName, $createIfNotExists = false $query[] = "$createStatement \"$tableName\" ("; $cols = $tableInfo->getColumns(); - + $columns = []; + foreach($tableInfo->getSortedColumnName() as $columnName) { if(isset($cols[$columnName])) { - $query[] = $this->createColumnPostgre($cols[$columnName], $autoIncrementKeys); + $columns[] = $this->createColumnPostgre($cols[$columnName], $autoIncrementKeys, $tableInfo->getPrimaryKeys()); } } - $query[] = implode(",\r\n", $query); + $query[] = implode(",\r\n", $columns); $query[] = ");"; - $pk = $tableInfo->getPrimaryKeys(); - if (isset($pk) && is_array($pk) && !empty($pk)) { - $query[] = ""; - $query[] = "ALTER TABLE \"$tableName\""; - foreach ($pk as $primaryKey) { - $query[] = "\tADD PRIMARY KEY (\"$primaryKey[name]\")"; - } - $query[] = ";"; - } - return implode("\r\n", $query); } @@ -229,45 +220,56 @@ private function fixAutoIncrementType($column, $type, $autoIncrementKeys) * Creates a column definition for a PostgreSQL SQL statement. * * This method constructs a SQL column definition based on the provided column details, - * including the column name, data type, nullability, and default value. The resulting - * definition is formatted for use in a CREATE TABLE statement. If the column is specified - * as auto-increment, it will use SERIAL or BIGSERIAL data types as appropriate. + * including the column name, data type, nullability, default value, and whether the column + * should be auto-incrementing. If the column is specified as auto-increment, it will use + * PostgreSQL's SERIAL or BIGSERIAL data types, depending on the column type. * * @param array $column An associative array containing details about the column: - * - string name: The name of the column. - * - string type: The data type of the column (e.g., VARCHAR, INT). - * - bool|string nullable: Indicates if the column allows NULL values + * - string 'name': The name of the column. + * - string 'type': The data type of the column (e.g., VARCHAR, INT). + * - bool|string 'nullable': Indicates if the column allows NULL values * ('true' or true for NULL; otherwise, NOT NULL). - * - mixed default_value: The default value for the column (optional). + * - mixed 'default_value': The default value for the column (optional). * * @param array|null $autoIncrementKeys An optional array of column names that should * be treated as auto-incrementing. * - * @return string The SQL column definition formatted as a string, suitable for - * inclusion in a CREATE TABLE statement. + * @param array $primaryKeys An array of primary key columns, each being an associative + * array with at least a 'name' key. This is used to identify + * if the column is a primary key. + * + * @return string The SQL column definition formatted as a string, suitable for inclusion + * in a CREATE TABLE statement. */ - public function createColumnPostgre($column, $autoIncrementKeys = null) + public function createColumnPostgre($column, $autoIncrementKeys, $primaryKeys) { + $pkCols = array(); + foreach ($primaryKeys as $col) { + $pkCols[] = $col['name']; // Collect primary key column names. + } + $col = array(); - $col[] = "\t"; - $col[] = "\"" . $column[parent::KEY_NAME] . "\""; + $columnName = $column[parent::KEY_NAME]; // Get the column name. // Check if the column should be auto-incrementing. - if(isset($autoIncrementKeys) && is_array($autoIncrementKeys) && in_array($column[parent::KEY_NAME], $autoIncrementKeys)) - { + if (isset($autoIncrementKeys) && is_array($autoIncrementKeys) && in_array($column[parent::KEY_NAME], $autoIncrementKeys)) { // Determine the appropriate serial type based on the column's type. - if(stripos($column['type'], 'big')) - { - $col[] = "BIGSERIAL"; // Use BIGSERIAL for large integers. - } - else - { - $col[] = "SERIAL"; // Use SERIAL for standard integers. + if (stripos($column['type'], 'big') !== false) { + $columnType = "BIGSERIAL"; // Use BIGSERIAL for large integers. + } else { + $columnType = "SERIAL"; // Use SERIAL for standard integers. } + } else { + $columnType = $this->getColumnType($column['type']); // Use the specified type if not auto-incrementing. } - else - { - $col[] = $column['type']; // Use the specified type if not auto-incrementing. + + $col[] = "\t"; // Add tab indentation for readability. + $col[] = $columnName; // Add the column name. + $col[] = $columnType; // Add the column type (SERIAL or BIGSERIAL, or custom type). + + // Add PRIMARY KEY constraint if the column is part of the primary keys. + if (in_array($columnName, $pkCols)) { + $col[] = 'PRIMARY KEY'; } // Determine nullability and add it to the definition. @@ -280,14 +282,14 @@ public function createColumnPostgre($column, $autoIncrementKeys = null) // Handle default value if provided, using a helper method to format it. if (isset($column['default_value'])) { $defaultValue = $column['default_value']; - $defaultValue = $this->fixDefaultValue($defaultValue, $column['type']); + $defaultValue = $this->fixDefaultValue($defaultValue, $columnType); // Format the default value. $col[] = "DEFAULT $defaultValue"; } - return implode(" ", $col); // Join all parts into a single string. + // Join all parts into a single string to form the complete column definition. + return implode(" ", $col); } - /** * Fixes the default value for SQL insertion based on its type. * @@ -488,7 +490,38 @@ public function fixImportData($data, $columns) */ public function getColumnType($columnType) { - return $this->convertMySqlToPostgreSql($columnType); + if(stripos($columnType, 'tinyint(1)') === 0) + { + return 'BOOLEAN'; + } + $type = $this->convertMySqlToPostgreSql($columnType); + if(stripos($type, 'integer(') === 0) + { + $type = 'INTEGER'; + } + else if(stripos($type, 'smallinteger(') === 0) + { + $type = 'INTEGER'; + } + else if(stripos($type, 'biginteger(') === 0) + { + $type = 'INTEGER'; + } + else if (stripos($type, 'enum(') === 0) { + // Extract the enum values between the parentheses + if (preg_match('/^enum\((.+)\)$/i', $type, $matches)) { + // Get the enum values as an array by splitting the string + $enumValues = array_map('trim', explode(',', $matches[1])); + // Find the maximum length of the enum values + $maxLength = max(array_map('strlen', $enumValues)); + // Set the NVARCHAR length to the max length of enum values + 2 + $type = 'CHARACTER VARYING(' . ($maxLength + 2) . ')'; + } + } else if (stripos($type, 'year(') === 0) { + // Extract the enum values between the parentheses + $type = "INTEGER"; + } + return $type; } } diff --git a/src/Util/Database/PicoDatabaseUtilSqlite.php b/src/Util/Database/PicoDatabaseUtilSqlite.php index 11ce545b..86f78dab 100644 --- a/src/Util/Database/PicoDatabaseUtilSqlite.php +++ b/src/Util/Database/PicoDatabaseUtilSqlite.php @@ -196,6 +196,8 @@ private function determineSqlType($column, $autoIncrementKeys = null, $length = // Check if the column type exists in the mapping if (array_key_exists($columnType, $typeMapping)) { $sqlType = $typeMapping[$columnType]; + } else if(stripos($columnType, 'int(') === 0) { + $sqlType = strtoupper($columnType); } else { $sqlType = strtoupper($columnType); if ($sqlType !== 'TINYINT(1)' && $sqlType !== 'FLOAT' && $sqlType !== 'TEXT' && @@ -374,6 +376,9 @@ private function mysqlToSqliteType($type) // If it's just 'varchar', convert it to 'NVARCHAR' without a length $type = 'NVARCHAR'; } + } elseif (stripos($typeCheck, 'char(') === 0) { + // Convert 'char()' to uppercase (MySQL int type conversion) + $type = strtoupper($type); } elseif (stripos($typeCheck, 'int(') === 0) { // Convert 'int()' to uppercase (MySQL int type conversion) $type = strtoupper($type); @@ -395,59 +400,66 @@ private function mysqlToSqliteType($type) return $type; } - /** - * Creates a column definition for a SQL statement. + * Creates a column definition for a SQL statement (SQLite). * * This method constructs a SQL column definition based on the provided column details, - * including the column name, data type, nullability, and default value. The resulting - * definition is formatted for use in a CREATE TABLE statement. - * + * including the column name, data type, nullability, default value, and primary key constraints. + * The resulting definition is formatted for use in a CREATE TABLE statement, suitable for SQLite. + * + * If the column is specified as a primary key with auto-increment, the column type is set to INTEGER, + * and the PRIMARY KEY constraint is added with auto-increment behavior (SQLite uses INTEGER PRIMARY KEY AUTOINCREMENT). + * * @param array $column An associative array containing details about the column: - * - string name: The name of the column. - * - string type: The data type of the column (e.g., VARCHAR, INT). - * - bool|string nullable: Indicates if the column allows NULL values (true or 'true' for NULL; otherwise, NOT NULL). - * - mixed default_value: The default value for the column (optional). - * - * @return string The SQL column definition formatted as a string, suitable for inclusion in a CREATE TABLE statement. + * - string 'name': The name of the column. + * - string 'type': The data type of the column (e.g., VARCHAR, INT). + * - bool|string 'nullable': Indicates if the column allows NULL values + * ('true' or true for NULL; otherwise, NOT NULL). + * - mixed 'default_value': The default value for the column (optional). + * - bool 'primary_key': Whether the column is a primary key (optional). + * - bool 'auto_increment': Whether the column is auto-incrementing (optional). + * + * @return string The SQL column definition formatted as a string, suitable for inclusion + * in a CREATE TABLE statement. */ public function createColumn($column) { - $columnType = $this->mysqlToSqliteType($column['type']); + $columnType = $this->mysqlToSqliteType($column['type']); // Convert MySQL type to SQLite type $col = array(); - $col[] = "\t"; - $col[] = "".$column[parent::KEY_NAME].""; + $col[] = "\t"; // Indentation for readability + $col[] = "" . $column[parent::KEY_NAME] . ""; // Column name - if(isset($column['primary_key']) && isset($column['auto_increment']) && $column['primary_key'] && $column['auto_increment']) - { - $columnType = 'INTEGER'; + // Handle primary key and auto-increment columns + if (isset($column['primary_key']) && isset($column['auto_increment']) && $column['primary_key'] && $column['auto_increment']) { + $columnType = 'INTEGER'; // Use INTEGER for auto-incrementing primary keys in SQLite $col[] = $columnType; $col[] = 'PRIMARY KEY'; } - else if(isset($column['primary_key']) && $column['primary_key']) - { + // Handle primary key only + else if (isset($column['primary_key']) && $column['primary_key']) { $col[] = $columnType; $col[] = 'PRIMARY KEY'; } - else - { + // Handle regular column (non-primary key) + else { $col[] = $columnType; } - if(isset($column['nullable']) && strtolower(trim($column['nullable'])) == 'true') - { - $col[] = "NULL"; - } - else - { - $col[] = "NOT NULL"; + // Handle nullability + if (isset($column['nullable']) && strtolower(trim($column['nullable'])) == 'true') { + $col[] = "NULL"; // Allow NULL values + } else { + $col[] = "NOT NULL"; // Disallow NULL values } - if(isset($column['default_value'])) - { + + // Handle default value if provided + if (isset($column['default_value'])) { $defaultValue = $column['default_value']; - $defaultValue = $this->fixDefaultValue($defaultValue, $columnType); + $defaultValue = $this->fixDefaultValue($defaultValue, $columnType); // Format the default value $col[] = "DEFAULT $defaultValue"; } + + // Join all parts into a single string for the final SQL column definition return implode(" ", $col); } @@ -626,7 +638,12 @@ public function tableExists($database, $tableName) */ public function getColumnType($columnType) { - return $this->mysqlToSqliteType($columnType); + $columnType = $this->mysqlToSqliteType($columnType); + if(stripos($columnType, 'int') === 0) + { + $columnType = strtoupper($columnType); + } + return $columnType; } } \ No newline at end of file From 1ca67e540daa012c88a4bc56b18c6ce325720ac4 Mon Sep 17 00:00:00 2001 From: "Kamshory, MT" Date: Wed, 4 Dec 2024 07:09:10 +0700 Subject: [PATCH 5/5] Fixing schema and charset on PostgreSQL --- src/Database/PicoDatabase.php | 101 ++++++++++++++++++++++------------ 1 file changed, 65 insertions(+), 36 deletions(-) diff --git a/src/Database/PicoDatabase.php b/src/Database/PicoDatabase.php index 3cc98f16..e2f67f49 100644 --- a/src/Database/PicoDatabase.php +++ b/src/Database/PicoDatabase.php @@ -371,8 +371,8 @@ private function connectSqlite() * Connect to the RDMS (Relational Database Management System). * * Establishes a connection to an RDMS database using the provided credentials and optionally selects - * a specific database based on the provided flag. Sets the time zone, charset, and handles schema settings - * for PostgreSQL. + * a specific database based on the provided flag. Sets the time zone for the connection and handles + * schema settings for PostgreSQL. Charset is also set based on the provided configuration. * * @param bool $withDatabase Flag to select the database when connected (default is true). * @return bool True if the connection is successful, false if it fails. @@ -385,56 +385,83 @@ private function connectRDMS($withDatabase = true) $timeZoneOffset = date("P"); try { $connectionString = $this->constructConnectionString($withDatabase); - $charset = $this->databaseCredentials->getCharset(); - + + // Check for database username configuration if (!$this->databaseCredentials->issetUsername()) { throw new InvalidDatabaseConfiguration("Database username may not be empty. Please check your database configuration!"); } + + // Initialize the query to set the timezone + $initialQueries = "SET time_zone = '$timeZoneOffset';"; + + // Get charset from database credentials + $charset = addslashes($this->databaseCredentials->getCharset()); - // Initial queries to set timezone and charset - $initialQueries = "SET time_zone = '$timeZoneOffset'; "; - if(isset($charset) && !empty($charset)) { - $charset = addslashes($charset); - $initialQueries .= "SET NAMES '$charset'; "; - } + // Handle PostgreSQL-specific connection settings + if ($this->getDatabaseType() == PicoDatabaseType::DATABASE_TYPE_PGSQL) { - // Set schema for PostgreSQL - if ($this->getDatabaseType() == PicoDatabaseType::DATABASE_TYPE_PGSQL && - $this->databaseCredentials->getDatabaseSchema() != null && - $this->databaseCredentials->getDatabaseSchema() != "") { - $initialQueries .= "SET search_path TO " . $this->databaseCredentials->getDatabaseSchema() . ";"; - } + // Set charset for PostgreSQL if provided (PostgreSQL does not use `SET NAMES`, but you can set the encoding) + if ($charset) { + $initialQueries .= "SET CLIENT_ENCODING TO '$charset';"; + } - // Additional options for PDO - $pdoOptions = [ - PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, - ]; + // Set schema for PostgreSQL if it is provided + if ($this->databaseCredentials->getDatabaseSchema() != null && $this->databaseCredentials->getDatabaseSchema() != "") { + $initialQueries .= "SET search_path TO " . $this->databaseCredentials->getDatabaseSchema() . ";"; + } - // Additional options specific to MySQL/MariaDB - if ($this->getDatabaseType() == PicoDatabaseType::DATABASE_TYPE_MYSQL || - $this->getDatabaseType() == PicoDatabaseType::DATABASE_TYPE_MARIADB) { - $pdoOptions[PDO::MYSQL_ATTR_INIT_COMMAND] = $initialQueries; - } + // PostgreSQL connection setup + $this->databaseConnection = new PDO( + $connectionString, + $this->databaseCredentials->getUsername(), + $this->databaseCredentials->getPassword(), + [ + PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION + ] + ); + + // Execute the initial queries (timezone, charset, schema) in PostgreSQL + if (!empty($initialQueries)) { + $this->databaseConnection->exec($initialQueries); + } - $this->databaseConnection = new PDO( - $connectionString, - $this->databaseCredentials->getUsername(), - $this->databaseCredentials->getPassword(), - $pdoOptions - ); + } + // Handle MySQL-specific connection settings + elseif ($this->getDatabaseType() == PicoDatabaseType::DATABASE_TYPE_MYSQL) { + + // Add charset to the initial queries for MySQL + if ($charset) { + $initialQueries .= "SET NAMES '$charset';"; // Set charset for MySQL + } - // Execute initial queries for PostgreSQL - if ($this->getDatabaseType() == PicoDatabaseType::DATABASE_TYPE_PGSQL) { - $this->databaseConnection->exec($initialQueries); + // MySQL connection setup + $this->databaseConnection = new PDO( + $connectionString, + $this->databaseCredentials->getUsername(), + $this->databaseCredentials->getPassword(), + [ + PDO::MYSQL_ATTR_INIT_COMMAND => $initialQueries, + PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, + PDO::MYSQL_ATTR_FOUND_ROWS => true + ] + ); + } + // If the database type is neither MySQL nor PostgreSQL, throw an exception + else { + throw new PDOException("Unsupported database type: " . $this->getDatabaseType()); } + // Log successful connection $connected = true; $this->connected = $connected; } catch (Exception $e) { + error_log('ERR ' . $e->getMessage()); + // Handle connection errors throw new PDOException($e->getMessage(), intval($e->getCode())); } return $connected; } + /** * Determine the database type based on the provided database type string. @@ -497,6 +524,7 @@ private function getDbDriver($databaseType) } } + /** * Create a connection string. * @@ -521,12 +549,12 @@ private function constructConnectionString($withDatabase = true) $emptyValue .= $emptyName ? "{database_name}" : ""; throw new InvalidDatabaseConfiguration("Invalid database configuration. $emptyValue. Please check your database configuration!"); } - return $this->getDbDriver($this->databaseCredentials->getDriver()) . ':host=' . $this->databaseCredentials->getHost() . '; port=' . ((int) $this->databaseCredentials->getPort()) . '; dbname=' . $this->databaseCredentials->getDatabaseName(); + return $this->getDbDriver($this->databaseCredentials->getDriver()) . ':host=' . $this->databaseCredentials->getHost() . ';port=' . ((int) $this->databaseCredentials->getPort()) . ';dbname=' . $this->databaseCredentials->getDatabaseName(); } else { if ($invalidParam1) { throw new InvalidDatabaseConfiguration("Invalid database configuration. $emptyValue. Please check your database configuration!"); } - return $this->getDbDriver($this->databaseCredentials->getDriver()) . ':host=' . $this->databaseCredentials->getHost() . '; port=' . ((int) $this->databaseCredentials->getPort()); + return $this->getDbDriver($this->databaseCredentials->getDriver()) . ':host=' . $this->databaseCredentials->getHost() . ';port=' . ((int) $this->databaseCredentials->getPort()); } } @@ -1018,6 +1046,7 @@ public function __toString() return json_encode($val); } + /** * Get the callback function to be executed when modifying data with queries. *