diff --git a/Insertion.php b/Insertion.php index 18ab6de..933ba0b 100644 --- a/Insertion.php +++ b/Insertion.php @@ -5,11 +5,11 @@ use InvalidArgumentException; class Insertion { - private Table $table; + private Schema $table; private array $currentRow = []; private array $batchRows = []; - public function __construct(Table $table) { + public function __construct(Schema $table) { $this->table = $table; } @@ -73,6 +73,6 @@ class Insertion foreach ($this->batchRows as $row) if (!empty($row)) - $wpdb->insert($this->table->tableName, $row); + $wpdb->insert($this->table->name, $row); } } \ No newline at end of file diff --git a/Query.php b/Query.php index 0a3cd8a..70d18e5 100644 --- a/Query.php +++ b/Query.php @@ -6,23 +6,23 @@ use InvalidArgumentException; class Query { - private Table $table; + private Schema $table; private array $columns = ['*']; private array $conditions = []; - /** - * @var ColumnTypes[] - */ - private array $columnTypes = []; - - public function __construct(Table $table) { - $this->columnTypes = array_map(fn($col) => $col['colType'], $table->columns); + public function __construct(Schema $table) { $this->table = $table; } public function select(string ...$cols): Query { if (!empty($cols)) $this->columns = $cols; + + // Validate colum existence + foreach ($cols as $col) + if (!$this->table->existsColumn($col)) + throw new InvalidArgumentException("Unknown column: $col"); + return $this; } @@ -38,23 +38,23 @@ class Query return $this->addCondition($col, $operator, $val, "OR"); } - private function addCondition(string $colName, string $operator, mixed $val, string $prefix): Query { - if (!isset($this->columnTypes[$colName])) - throw new InvalidArgumentException("Unknown column: $colName"); + private function addCondition(string $col, string $operator, mixed $val, string $prefix): Query { + if ($this->table->existsColumn($col)) + throw new InvalidArgumentException("Unknown column: $col"); - $columnType = $this->columnTypes[$colName]; + $columnType = $this->table->columnType($col); $castedValue = $columnType->dbCast($val); if (!empty($this->conditions)) $this->conditions[] = $prefix; - $this->conditions[] = "$colName $operator $castedValue"; + $this->conditions[] = "$col $operator $castedValue"; return $this; } public function toSql(): string { $columns = implode(", ", $this->columns); - $table = $this->table->tableName; + $table = $this->table->name; $whereClause = !empty($this->conditions) ? " WHERE " . implode(" ", $this->conditions) : ""; return esc_sql("SELECT $columns FROM $table$whereClause"); } diff --git a/Schema.php b/Schema.php index b22d265..d812cdd 100644 --- a/Schema.php +++ b/Schema.php @@ -17,7 +17,19 @@ class Schema public CharsetTypes $charset = CharsetTypes::UTF8; public CollationTypes $collation = CollationTypes::UTF8_GENERAL_CI; - public function __construct(string $tableName) { - $this->name = $tableName; + public function __construct(string $name) { + $this->name = $name; + } + + public function existsColumn(string $col): bool { + return isset($this->columns[$col]); + } + + public function columnType(string $col) { + return $this->columns[$col]['type']; + } + + public function primaryKey() { + return $this->columns['primary']['name']; } } \ No newline at end of file diff --git a/Table.php b/Table.php index f299572..353d8fa 100644 --- a/Table.php +++ b/Table.php @@ -17,47 +17,46 @@ class Table $this->table = new Schema($tableName); } - public function column(string $colName, ColumnTypes $colType, mixed $default = null, bool $nullable = false, bool $unique = false): Table { - if(isset($this->columns[$colName])) + public function column(string $name, ColumnTypes $type, mixed $default = null, bool $isNullable = false, bool $isUnique = false): Table { + if(isset($this->columns[$name])) throw new InvalidArgumentException('Column name already exists.'); - $this->table->columns[$colName] = [ - 'colName' => $colName, - 'defaultVal' => $default, - 'colType' => $colType, - 'nullable' => $nullable, - 'unique' => $unique + $this->table->columns[$name] = [ + 'name' => $name, + 'default' => $default, + 'type' => $type, + 'isNullable' => $isNullable, + 'isUnique' => $isUnique ]; return $this; } - public function primary(string $colName, ColumnTypes $colType, bool $autoInc = false): Table { + public function primary(string $name, ColumnTypes $type, bool $autoInc = false): Table { if(isset($this->primaryKey)) throw new InvalidArgumentException('Primary column already exists.'); $this->table->primaryKey = [ - 'colName' => $colName, - 'colType' => $colType, - 'autoincrement' => $autoInc + 'name' => $name, + 'autoInc' => $autoInc ]; - return $this->column($colName, $colType); + return $this->column($name, $type); } public function reference(Schema $foreignTable, CascadeTypes $onDelete = CascadeTypes::CASCADE, CascadeTypes $onUpdate = CascadeTypes::CASCADE): Table { - $colName = $foreignTable->primaryKey['colName']; - if(isset($this->columns[$colName])) + $name = $foreignTable->primaryKey(); + if(isset($this->columns[$name])) throw new InvalidArgumentException('Column name already exists.'); $this->table->foreignKeys[] = [ - 'colName' => $colName, - 'tableName' => $foreignTable->name, + 'name' => $name, + 'table' => $foreignTable->name, 'onDelete' => $onDelete, 'onUpdate' => $onUpdate ]; - $this->table->columns[$colName] = $foreignTable->columns[$colName]; + $this->table->columns[$name] = $foreignTable->columns[$name]; return $this; } @@ -77,23 +76,21 @@ class Table } public function toSql(): string { + $primaryKey = $this->table->primaryKey(); + $sql = "CREATE TABLE `{$this->table->name}` (\n"; + $sql .= " PRIMARY KEY (`$primaryKey`),\n"; - // Add primary key constraint if present - if (!empty($this->primaryKey)) - $sql .= " PRIMARY KEY (`{$this->primaryKey['colName']}`),\n"; - - foreach ($this->table->columns as $column) { - if ($column['colName'] !== $this->table->primaryKey['colName']) { - $sql .= " `{$column['colName']}` {$column['colType']->value}"; - + foreach ($this->table->columns as $col) { + if ($col['name'] !== $primaryKey) { + $sql .= " `{$col['name']}` {$col['type']->toString()}"; // Handle nulls, uniqueness, and defaults - if (!$column['nullable']) + if (!$col['isNullable']) $sql .= " NOT NULL"; - if ($column['unique']) + if ($col['isUnique']) $sql .= " UNIQUE"; - if ($column['defaultVal'] !== null) { - $default = is_string($column['defaultVal']) ? "'{$column['defaultVal']}'" : $column['defaultVal']; + if ($col['default'] !== null) { + $default = is_string($col['default']) ? "'{$col['default']}'" : $col['default']; $sql .= " DEFAULT $default"; } @@ -102,15 +99,16 @@ class Table } // Add secondary constraints if present - foreach ($this->table->foreignKeys as $foreignKey) { - $sql .= " FOREIGN KEY (`{$foreignKey['colName']}`) REFERENCES `{$foreignKey['tableName']}` (`{$foreignKey['colName']}`)"; - $sql .= " ON DELETE {$foreignKey['onDelete']->toString()} ON UPDATE {$foreignKey['onUpdate']->toString()},\n"; + foreach ($this->table->foreignKeys as $key) { + $sql .= " FOREIGN KEY (`{$key['name']}`) REFERENCES `{$key['table']}` (`{$key['name']}`)"; + $sql .= " ON DELETE {$key['onDelete']->toString()} ON UPDATE {$key['onUpdate']->toString()},\n"; } // Close the SQL string and add constraints - $sql = rtrim($sql, ",\n") . "\n"; - $sql .= ") ENGINE={$this->table->engine->toString()} CHARSET={$this->table->charset->toString()} COLLATE={$this->table->collation->toString()};"; - + $sql = rtrim($sql, ",\n") . "\n) "; + $sql .= "ENGINE={$this->table->engine->toString()} "; + $sql .= "CHARSET={$this->table->charset->toString()} "; + $sql -= "COLLATE={$this->table->collation->toString()};"; return esc_sql($sql); }