From 8e08f02718444b4de2d3326633dd729c41458868 Mon Sep 17 00:00:00 2001 From: xdrm-brackets Date: Sat, 9 Sep 2017 12:30:23 +0200 Subject: [PATCH] Add 'db-schema' src package --- src/packages/db-schema/1.0/core/dBuilder.php | 309 +++++++++++++++++++ 1 file changed, 309 insertions(+) create mode 100644 src/packages/db-schema/1.0/core/dBuilder.php diff --git a/src/packages/db-schema/1.0/core/dBuilder.php b/src/packages/db-schema/1.0/core/dBuilder.php new file mode 100644 index 0000000..58d0857 --- /dev/null +++ b/src/packages/db-schema/1.0/core/dBuilder.php @@ -0,0 +1,309 @@ +$column){ + if( $column_name[0] == '#' ){ + $table[$column_name]['foreign'] = true; + $table[substr($column_name,1)] = $table[$column_name]; + unset($table[$column_name]); + continue; + } + } + + } + + + + return true; + + } + + + + + /* [2] Populates a database + * + * @label DatabaseDriver label + * + * @return status False on error + =========================================================*/ + public static function push($label=null){ + + $PDO = DatabaseDriver::getPDO($label); + $QUERY = ''; + $foreign_keys = []; // global foreign keys + + + /* [1] For each table create an entry + =========================================================*/ + foreach(self::$raw as $table_name=>$table){ + + /* (1) Initialise variables + ---------------------------------------------------------*/ + /* (1) The built query */ + $QUERY .= "CREATE TABLE IF NOT EXISTS `$table_name`(\n"; + + /* (2) Constraints */ + $constraints = [ + 'primary' => [], + 'foreign_k' => [], + 'unique' => [], + 'default' => [], + ]; + + + /* (2) For each column create an entry + ---------------------------------------------------------*/ + foreach($table as $column_name=>$column){ + + /* (1) Notify if foreign key */ + $foreign = isset($column['foreign']) && $column['foreign'] == true; + + /* (2) Append column name to query */ + $QUERY .= "\t`$column_name` "; + + + /* (2.1) Manage column type + ---------------------------------------------------------*/ + /* (1) If type missing, ignore this column */ + if( !isset($column['type']) || !is_string($column['type']) ) + continue; + + /* (2) If incorrect type, ignore column */ + if( ($SQLType = self::checkType($column['type'])) == false ) + continue; + + /* (3) Add corresponding SQL type to the query */ + $QUERY .= "$SQLType"; + + + /* (2.2) Manage inline constraints (not null, auto_increment) + ---------------------------------------------------------*/ + /* (1) If 'null' set to FALSE, add NOT NULL constraint */ + if( isset($column['null']) && $column['null'] == false ) + $QUERY .= " NOT NULL"; + + /* (2) If 'auto_increment' set to TRUE, add AUTO_INCREMENT constraint */ + if( isset($column['auto_increment']) && $column['auto_increment'] == true ) + $QUERY .= " AUTO_INCREMENT"; + + /* (3) Append ',' column separator */ + $QUERY .= ",\n"; + + + /* (2.3) Manage global constraints (will be declared outside the CREATE TABLE) + ---------------------------------------------------------*/ + /* (1) Primary key - if 'primary' == true */ + if( isset($column['primary']) && $column['primary'] === true ) + $constraints['primary'][] = $column_name; + + /* (2) Foreign key - if foreign column && 'ref' == [table, column] */ + if( $foreign && isset($column['ref']) && is_array($column['ref']) && sizeof($column['ref']) == 2 ){ + $fk = $column['ref']; + + // {1} Check if the 'ref' field exists in JSON structure // + if( isset(self::$raw[$fk[0]]) && isset(self::$raw[$fk[0]][$fk[1]]) ){ + + // {2} Check if the type matches // + $refSQLType = self::checkType(self::$raw[$fk[0]][$fk[1]]['type']); + + if( $refSQLType == $SQLType ) + $foreign_keys[] = [ $table_name, $column_name, $fk[0], $fk[1] ]; + + } + + } + + /* (3) Unique - if 'unique' == true */ + if( isset($column['unique']) && $column['unique'] == true ) + $constraints['unique'][] = $column_name; + + /* (4) Default - if 'default' is set */ + if( isset($column['default']) ){ + + // {4.1} If null -> use SQL constant (NULL) // + if( is_null($column['default']) ) + $constraints['default'][$column_name] = "NULL"; + + // {4.2} If a string -> add surrounding quotes '' // + else if( is_string($column['default']) ) + $constraints['default'][$column_name] = "'".$column['default']."'"; + + // {4.3} If boolean -> use SQL constants (TRUE,FALSE) // + else if( is_bool($column['default']) ) + $constraints['default'][$column_name] = ($column['default']) ? 'TRUE' : 'FALSE'; + + // {4.4} Else (numeric) -> write as is // + else + $constraints['default'][$column_name] = $column['default']; + + } + + } + + /* (3) Add global constraints + ---------------------------------------------------------*/ + /* (1) Add primary keys -> combine all columns that are primary for each table*/ + if( sizeof($constraints['primary']) > 0 ) + $QUERY .= "CONSTRAINT pk_$table_name PRIMARY KEY(`".implode('`,`', $constraints['primary'])."`),\n"; + + + /* (2) End CREATE TABLE statement + remove last ',' */ + $querylen = strlen($QUERY); + $QUERY[$querylen-2] = ")"; + $QUERY[$querylen-1] = ";"; + $QUERY .= "\n"; + + /* (3) Add 'unique' constraints */ + foreach($constraints['unique'] as $field) + $QUERY .= "ALTER TABLE `$table_name` ADD CONSTRAINT un_${table_name}_$field UNIQUE(`$field`);\n"; + + /* (4) Add 'default' constraint */ + foreach($constraints['default'] as $field=>$val) + $QUERY .= "ALTER TABLE `$table_name` ALTER COLUMN `$field` SET DEFAULT $val;\n"; + + $QUERY .= "\n"; + } + + /* (4) Add global foreign keys */ + foreach($foreign_keys as $fk) + $QUERY .= "ALTER TABLE `${fk[0]}` ADD CONSTRAINT fk_${fk[0]}_${fk[1]} FOREIGN KEY (`${fk[1]}`) REFERENCES `${fk[2]}`(`${fk[3]}`);\n"; + + /* [2] Create the tables + =========================================================*/ + /* (1) Try to execute */ + try{ + $PDO->exec($QUERY); + return true; + + + /* (2) If error -> return FALSE */ + }catch(\Exception $e){ + var_dump('bla'); + return false; + + } + + } + + + + + /* [3] Checks if a given type is correct + * + * @type The human-readable type + * + * @return SQLType The corresponding SQL type + * FALSE on error + * + =========================================================*/ + private static function checkType($type){ + /* [1] Check complex types + =========================================================*/ + /* (1) Varchar + ---------------------------------------------------------*/ + if( preg_match("@^varchar\((\d+)\)$@", $type, $match) ) + return "VARCHAR(${match[1]})"; + + /* (2) Double + ---------------------------------------------------------*/ + if( preg_match("@^(?:double|float|decimal|real)\((\d+), ?(\d+)\)$@", $type, $match) ) + return "DOUBLE(${match[1]},${match[2]})"; + + + /* [2] Check simple types + =========================================================*/ + /* (1) Boolean + ---------------------------------------------------------*/ + if( $type == 'bool' || $type == 'boolean' || $type == 'bit' ) + return 'BIT'; + + /* (2) Character + ---------------------------------------------------------*/ + if( $type == 'char' || $type == 'byte' ) + return 'CHAR'; + + /* (3) Integer + ---------------------------------------------------------*/ + if( $type == 'int' || $type == 'integer' || $type == 'number' ) + return 'INT'; + + /* (4) Float + ---------------------------------------------------------*/ + if( $type == 'float' || $type == 'double' || $type == 'decimal' || $type == 'real' ) + return 'DOUBLE'; + + /* (5) Text + ---------------------------------------------------------*/ + if( $type == 'text' ) + return 'TEXT'; + + /* (6) Date & time + ---------------------------------------------------------*/ + if( $type == 'date' ) + return 'DATE'; + + if( $type == 'time' ) + return 'TIME'; + + if( $type == 'datetime' ) + return 'DATETIME'; + + if( $type == 'timestamp' ) + return 'TIMESTAMP'; + + + return false; + + } + + + + + } \ No newline at end of file