From 1bdc7cd5c95561622103cc470dba0af041996c28 Mon Sep 17 00:00:00 2001 From: lsces Date: Thu, 5 Mar 2026 10:18:56 +0000 Subject: Shuffle the driver into an Illuminate namespace to allow other elements to be added later, if required. Just using a Firebird namespace did not fell right? --- src/illuminate/FirebirdConnection.php | 171 ++++++ src/illuminate/FirebirdConnector.php | 58 ++ src/illuminate/FirebirdServiceProvider.php | 23 + src/illuminate/Query/FirebirdBuilder.php | 126 ++++ src/illuminate/Query/Grammars/FirebirdGrammar.php | 256 ++++++++ .../Query/Processors/FirebirdProcessor.php | 40 ++ src/illuminate/Schema/FirebirdBuilder.php | 10 + src/illuminate/Schema/Grammars/FirebirdGrammar.php | 665 +++++++++++++++++++++ 8 files changed, 1349 insertions(+) create mode 100755 src/illuminate/FirebirdConnection.php create mode 100755 src/illuminate/FirebirdConnector.php create mode 100755 src/illuminate/FirebirdServiceProvider.php create mode 100755 src/illuminate/Query/FirebirdBuilder.php create mode 100755 src/illuminate/Query/Grammars/FirebirdGrammar.php create mode 100644 src/illuminate/Query/Processors/FirebirdProcessor.php create mode 100755 src/illuminate/Schema/FirebirdBuilder.php create mode 100755 src/illuminate/Schema/Grammars/FirebirdGrammar.php diff --git a/src/illuminate/FirebirdConnection.php b/src/illuminate/FirebirdConnection.php new file mode 100755 index 0000000..b279632 --- /dev/null +++ b/src/illuminate/FirebirdConnection.php @@ -0,0 +1,171 @@ +schemaGrammar)) { + $this->useDefaultSchemaGrammar(); + } + + return new FirebirdSchemaBuilder($this); + } + + /** + * Get the default schema grammar instance. + * + * @return \Firebird\Illuminate\Schema\Grammars\FirebirdGrammar + */ + protected function getDefaultSchemaGrammar() + { + return new FirebirdSchemaGrammar($this); // $this->withTablePrefix() + } + + /** + * Get the connection's last insert ID. + * + * @return string|int|null + */ + public function getLastInsertId() + { + return $this->lastInsertId; + } + + /** + * Get a new query builder instance. + * + * @return \Firebird\IlluminateQuery\FirebirdBuilder + */ + public function query() + { + return new FirebirdQueryBuilder( + $this, $this->getQueryGrammar(), $this->getPostProcessor() + ); + } + + /** + * Run an insert statement against the database. + * + * @param string $query + * @param array $bindings + * @param string|null $sequence + * @return array + */ + public function insert($query, $bindings = [], $sequence = null) + { + return $this->run($query, $bindings, function ($query, $bindings) use ($sequence) { + if ($this->pretending()) { + return true; + } + + $statement = $this->getPdo()->prepare($query); + + $this->bindValues($statement, $this->prepareBindings($bindings)); + + $this->recordsHaveBeenModified(); + + $result = $statement->execute(); + + // Fetch the RETURNING clause result to get the actual ID used + if ($result) { + $row = $statement->fetch(\PDO::FETCH_ASSOC); + if ($row) { + // Get the first (and typically only) returned value + $this->lastInsertId = reset($row); + } + } + + return $result; + }); + } + + /** + * Run a select statement against the database. + * + * @param string $query + * @param array $bindings + * @param bool $useReadPdo + * @return array + */ + public function select($query, $bindings = [], $useReadPdo = true) + { + return $this->run($query, $bindings, function ($query, $bindings) use ($useReadPdo) { + if ($this->pretending()) { + return []; + } + + // For select statements, we'll simply execute the query and return an array + // of the database result set. Each element in the array will be a single + // row from the database table, and will either be an array or objects. + $statement = $this->prepared( + $this->getPdoForSelect($useReadPdo)->prepare($query) + ); + + $this->bindValues($statement, $this->prepareBindings($bindings)); + + $statement->execute(); + + $result = []; + while ($row = $statement->fetch(\PDO::FETCH_ASSOC)) { + $lowerCaseRow = array_change_key_case((array) $row, CASE_LOWER); + $result[] = (object) $lowerCaseRow; + } + return count($result) > 0 ? $result : []; + }); + } + + /** + * Execute a stored procedure. + * + * @param string $procedure + * @param array $values + * @return Collection + */ + public function executeProcedure($procedure, array $values = []): Collection + { + return $this->query()->fromProcedure($procedure, $values)->get(); + } +} diff --git a/src/illuminate/FirebirdConnector.php b/src/illuminate/FirebirdConnector.php new file mode 100755 index 0000000..3517f34 --- /dev/null +++ b/src/illuminate/FirebirdConnector.php @@ -0,0 +1,58 @@ +createConnection( + $this->getDsn($config), + $config, + $this->getOptions($config) + ); + } + + /** + * Create a DSN string from the configuration. + * + * @param array $config + * @return string + */ + protected function getDsn(array $config): string + { + extract($config); + + if (! isset($host) || ! isset($database)) { + trigger_error('Cannot connect to Firebird Database, no host or database supplied'); + } + + $dsn = "firebird:dbname={$host}"; + + if (isset($port)) { + $dsn .= "/{$port}"; + } + + $dsn .= ":{$database};"; + + if (isset($role)) { + $dsn .= "role={$role};"; + } + + if (isset($charset)) { + $dsn .= "charset={$charset};"; + } + + return $dsn; + } +} diff --git a/src/illuminate/FirebirdServiceProvider.php b/src/illuminate/FirebirdServiceProvider.php new file mode 100755 index 0000000..a78889f --- /dev/null +++ b/src/illuminate/FirebirdServiceProvider.php @@ -0,0 +1,23 @@ +app->bind('db.connector.firebird', FirebirdConnector::class); + } +} diff --git a/src/illuminate/Query/FirebirdBuilder.php b/src/illuminate/Query/FirebirdBuilder.php new file mode 100755 index 0000000..119e804 --- /dev/null +++ b/src/illuminate/Query/FirebirdBuilder.php @@ -0,0 +1,126 @@ + 0; + } + + /** + * Add a from stored procedure clause to the query builder. + * + * @param string $procedure + * @param array $values + * @return \Illuminate\Database\Query\Builder|static + */ + public function fromProcedure(string $procedure, array $values = []) + { + $compiledProcedure = $this->grammar->compileProcedure($this, $procedure, $values); + + // Remove any expressions from the values array, as they will have + // already been evaluated by the grammar's parameterize() function. + $values = array_filter($values, function($value) { + return ! $this->grammar->isExpression($value); + }); + + $this->fromRaw($compiledProcedure, array_values($values)); + + return $this; + } + + /** + * Insert new records into the database. + * + * @return bool + */ + public function insert(array $values) + { + // Handle multi-row inserts by looping + if (count($values) > 1 && is_array(reset($values))) { + $results = []; + foreach ($values as $row) { + $results[] = parent::insert($row); + } + return end($results); + } + + // Single row or already formatted correctly + return parent::insert($values); + } + public function where($column, $operator = NULL, $value = NULL, $boolean = 'and') + { + // Not sure what this was intended to fix, but target hidden for now + if (! str($operator)->contains('hide', true)) { + return parent::where($column, $operator, $value, $boolean); + } + + // when is search covert to upper case column and value at database level + $wrapped = $this->grammar->wrap($column); + return $boolean === 'and' + ? parent::whereRaw("UPPER($wrapped) LIKE UPPER(?)", [$value]) + : parent::orWhereRaw("UPPER($wrapped) LIKE UPPER(?)", [$value]); + } + + /** + * Retrieve column values from rows represented as objects. + * + * @param array $queryResult + * @param string $column + * @param string $key + * @return Collection + */ + protected function pluckFromObjectColumn($queryResult, $column, $key) + { + $results = []; + $column = str_replace('"', '', $column); + foreach ($queryResult as $item) { + if (is_null($key)) { + foreach ($queryResult as $row) { + $results[] = $row->$column; + } + } else { + foreach ($queryResult as $row) { + $results[$row->$key] = $row->$column; + } + } + } + + return new Collection($results); + } + + /** + * Retrieve column values from rows represented as arrays. + * + * @param array $queryResult + * @param string $column + * @param string $key + * @return Collection + */ + protected function pluckFromArrayColumn($queryResult, $column, $key) + { + $results = []; + + if (is_null($key)) { + foreach ($queryResult as $row) { + $results[] = $row[$column]; + } + } else { + foreach ($queryResult as $row) { + $results[$row[$key]] = $row[$column]; + } + } + + return new Collection($results); + } +} diff --git a/src/illuminate/Query/Grammars/FirebirdGrammar.php b/src/illuminate/Query/Grammars/FirebirdGrammar.php new file mode 100755 index 0000000..efd03f4 --- /dev/null +++ b/src/illuminate/Query/Grammars/FirebirdGrammar.php @@ -0,0 +1,256 @@ +', '<=', '>=', '<>', '!=', + 'like', 'not like', 'between', 'not between', + 'containing', 'not containing', 'starting with', 'not starting with', + 'similar to', 'not similar to', 'is distinct from', 'is not distinct from', + ]; + + /** + * @param Builder $query + * @param array $columns + * @return string|null + */ + protected function compileColumns(Builder $query, $columns) + { + // See superclass. + if (! is_null($query->aggregate)) { + return; + } + + // In Firebird, the correct syntax for limiting and offsetting rows is + // "select first [num_rows] skip [start_row] * from table". Laravel does + // not support adding components between the "select" keyword and the + // column names, so compile the limit and offset components here. Note + // that they are commented out in the $selectComponents class variable. + // Reference: http://mc-computing.com/Databases/Firebird/SQL.html + + $select = 'select '; + + if ($query->limit) { + $select .= $this->compileLimit($query, $query->limit).' '; + } + + if ($query->offset) { + $select .= $this->compileOffset($query, $query->offset).' '; + } + + if ($query->distinct) { + $select .= 'distinct '; + } + + return $select.$this->columnize($columns); + } + + /** + * Compile a delete statement into SQL. + * + * @param \Illuminate\Database\Query\Builder $query + * @return string + */ + public function compileDelete(Builder $query) + { + if (isset($query->joins) ) { // || isset($query->limit)) { + return $this->compileDeleteWithJoinsOrLimit($query); + } + + return parent::compileDelete($query); + } + + /** + * Compile a delete statement with joins or limit into SQL. + * + * @param \Illuminate\Database\Query\Builder $query + * @return string + */ + protected function compileDeleteWithJoinsOrLimit(Builder $query) + { + $table = $this->wrapTable($query->from); + $alias = last(preg_split('/\s+as\s+/i', $query->from)); + switch ($alias) { + case 'block_setting' : $field = 'block_id'; break; + case 'places' : $field = 'p_id'; break; + default : $field = $alias.'_id'; + } + $selectSql = $this->compileSelect($query->select($alias.'.'.$field)); + + return "delete from {$table} where {$this->wrap($field)} in ({$selectSql})"; + } + + /** + * Compile the "limit" portions of the query. + * + * @param \Illuminate\Database\Query\Builder $query + * @param int $limit + * @return string + */ + protected function compileLimit(Builder $query, $limit) + { + return 'first '.(int) $limit; + } + + /** + * Compile the "offset" portions of the query. + * + * @param \Illuminate\Database\Query\Builder $query + * @param int $offset + * @return string + */ + protected function compileOffset(Builder $query, $offset) + { + return 'skip '.(int) $offset; + } + + /** + * Compile the random statement into SQL. + * + * @param string $seed + * @return string + */ + public function compileRandom($seed) + { + return 'RAND()'; + } + + /** + * Compile an insert statement into SQL. + * + * @param \Illuminate\Database\Query\Builder $query + * @param array $values + * @return string + */ + public function compileInsert(Builder $query, array $values) + { + $table = $this->wrapTable($query->from); + + if (empty($values)) { + return "insert into {$table} default values"; + } + + if (! is_array(array_first($values))) { + $values = [$values]; + } + + $columns = $this->columnize(array_keys(array_first($values))); + + // We need to build a list of parameter place-holders of values that are bound + // to the query. Each insert should have the exact same number of parameter + // bindings so we will loop through the record and parameterize them all. + $parameters = (new Collection($values)) + ->map(fn ($record) => '('.$this->parameterize($record).')') + ->implode(', '); + + return "insert into $table ($columns) values $parameters returning *"; + } + + /** + * Wrap a single string in keyword identifiers. + * + * @param string $value + * @return string + */ + protected function wrapValue($value) + { + // wrap reserved words in firebird + if ($value == 'year' or $value == 'pending' or $value == 'value') { + return '"'.$value.'"'; + } + + // Currently just return unwrapped + return $value; + } + + /** + * Wrap a union subquery in parentheses. + * + * @param string $sql + * @return string + */ + protected function wrapUnion($sql) + { + return $sql; + } + + /** + * Compile a date based where clause. + * + * @param string $type + * @param \Illuminate\Database\Query\Builder $query + * @param array $where + * @return string + */ + protected function dateBasedWhere($type, Builder $query, $where) + { + $value = $this->parameter($where['value']); + + return 'EXTRACT('.$type.' FROM '.$this->wrap($where['column']).') '.$where['operator'].' '.$value; + } + + /** + * Compile SQL statement for a stored procedure. + * + * @param \Illuminate\Database\Query\Builder $query + * @param string $procedure + * @param array $values + * @return string + */ + public function compileProcedure(Builder $query, $procedure, ?array $values = null) + { + $procedure = $this->wrap($procedure); + + return $procedure.' ('.$this->parameterize($values).')'; + } + + /** + * Compile an aggregated select clause. + * + * @param \Illuminate\Database\Query\Builder $query + * @param array $aggregate + * @return string + */ + protected function compileAggregate(Builder $query, $aggregate) + { + // Wrap `aggregate` in double quotes to ensure the resultset returns the + // column name as a lowercase string. This resolves compatibility with + // the framework's paginator. + return Str::replaceLast( + 'as aggregate', 'as "aggregate"', parent::compileAggregate($query, $aggregate) + ); + } +} diff --git a/src/illuminate/Query/Processors/FirebirdProcessor.php b/src/illuminate/Query/Processors/FirebirdProcessor.php new file mode 100644 index 0000000..577ebf7 --- /dev/null +++ b/src/illuminate/Query/Processors/FirebirdProcessor.php @@ -0,0 +1,40 @@ +column_name; + }, $results); + } + + /** + * Process an "insert get ID" query. + * + * @param \Illuminate\Database\Query\Builder $query + * @param string $sql + * @param array $values + * @param string|null $sequence + * @return int + */ + public function processInsertGetId(Builder $query, $sql, $values, $sequence = null) + { + $query->getConnection()->insert($sql, $values); + + $id = $query->getConnection()->getLastInsertId(); + + return is_numeric($id) ? (int) $id : $id; + } +} diff --git a/src/illuminate/Schema/FirebirdBuilder.php b/src/illuminate/Schema/FirebirdBuilder.php new file mode 100755 index 0000000..7b804a4 --- /dev/null +++ b/src/illuminate/Schema/FirebirdBuilder.php @@ -0,0 +1,10 @@ +quoteString(strtoupper($table) ).' ' + .'order by rdb$relation_name'; + } + + /** + * Compile the query to determine the list of columns. + * + * @param string $table + * @return string + */ + public function compileColumnListing($table) + { + return "select trim(rdb\$field_name) as \"column_name\" from rdb\$relation_fields where rdb\$relation_name = '$table'"; + } + + /** + * Compile a create table command. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $command + * @return string + */ + public function compileCreate(Blueprint $blueprint, Fluent $command) + { + if ($blueprint->temporary) { + throw new \LogicException('This database driver does not support temporary tables.'); + } + + $columns = implode(', ', $this->getColumns($blueprint)); + + $sql = 'create table '.$this->wrapTable($blueprint->getTable())." ($columns)"; + + return $sql; + } + + /** + * Compile a drop table command. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $command + * @return string + */ + public function compileDrop(Blueprint $blueprint, Fluent $command) + { + return 'drop table '.$this->wrapTable($blueprint->getTable()); + } + + /** + * Compile a drop table (if exists) command. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $command + * @return string + */ + public function compileDropIfExists(Blueprint $blueprint, Fluent $command) + { + // Replace the double quotes with single quotes. + $table = str_replace('"', "'", $this->wrapTable($blueprint->getTable())); + + return sprintf( + "set term #; execute block as begin if (exists(%s)) then execute statement '%s'; end set term ;#", + $this->compileTableExists( '', $table), + $this->compileDrop($blueprint, $command) + ); + } + + /** + * Compile a column addition command. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $command + * @return string + */ + public function compileAdd(Blueprint $blueprint, Fluent $command) + { + $table = $this->wrapTable($blueprint->getTable()); + + $columns = $this->prefixArray('ADD', $this->getColumns($blueprint)); + + return 'ALTER TABLE '.$table.' '.implode(', ', $columns); + } + + /** + * Compile a primary key command. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $command + * @return string + */ + public function compilePrimary(Blueprint $blueprint, Fluent $command) + { + $columns = $this->columnize($command->columns); + + return 'ALTER TABLE '.$this->wrapTable($blueprint->getTable())." ADD PRIMARY KEY ({$columns})"; + } + + /** + * Compile a unique key command. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $command + * @return string + */ + public function compileUnique(Blueprint $blueprint, Fluent $command) + { + $table = $this->wrapTable($blueprint->getTable()); + + $index = $this->wrap(substr($command->index, 0, 31)); + + $columns = $this->columnize($command->columns); +// need to skip if the columns are already part of the primary key + return "ALTER TABLE {$table} ADD CONSTRAINT {$index} UNIQUE ({$columns})"; + } + + /** + * Compile a plain index key command. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $command + * @return string + */ + public function compileIndex(Blueprint $blueprint, Fluent $command) + { + $columns = $this->columnize($command->columns); + + $index = $this->wrap(substr($command->index, 0, 31)); + + $table = $this->wrapTable($blueprint->getTable()); + + return "CREATE INDEX {$index} ON {$table} ($columns)"; + } + + /** + * Compile a foreign key command. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $command + * @return string + */ + public function compileForeign(Blueprint $blueprint, Fluent $command) + { + $table = $this->wrapTable($blueprint->getTable()); + + $on = $this->wrapTable($command->on); + + // We need to prepare several of the elements of the foreign key definition + // before we can create the SQL, such as wrapping the tables and convert + // an array of columns to comma-delimited strings for the SQL queries. + $columns = $this->columnize($command->columns); + + $onColumns = $this->columnize((array) $command->references); + + $fkName = substr($command->index, 0, 31); + + $sql = "ALTER TABLE {$table} ADD CONSTRAINT {$fkName} "; + + $sql .= "FOREIGN KEY ({$columns}) REFERENCES {$on} ({$onColumns})"; + + // Once we have the basic foreign key creation statement constructed we can + // build out the syntax for what should happen on an update or delete of + // the affected columns, which will get something like "cascade", etc. + if (! is_null($command->onDelete)) { + $sql .= " ON DELETE {$command->onDelete}"; + } + + if (! is_null($command->onUpdate)) { + $sql .= " ON UPDATE {$command->onUpdate}"; + } + + return $sql; + } + + /** + * Compile a drop foreign key command. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $command + * @return string + */ + public function compileDropForeign(Blueprint $blueprint, Fluent $command) + { + $table = $this->wrapTable($blueprint->getTable()); + + return "ALTER TABLE {$table} DROP CONSTRAINT {$command->index}"; + } + + /** + * Get the SQL for a character set column modifier. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $column + * @return string|null + */ + protected function modifyCharset(Blueprint $blueprint, Fluent $column) + { + if (! is_null($column->charset)) { + return ' CHARACTER SET '.$column->charset; + } + } + + /** + * Get the SQL for a collation column modifier. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $column + * @return string|null + */ + protected function modifyCollate(Blueprint $blueprint, Fluent $column) + { + if (! is_null($column->collation)) { + return ' COLLATE '.$column->collation; + } + } + + /** + * Get the SQL for a nullable column modifier. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $column + * @return string|null + */ + protected function modifyNullable(Blueprint $blueprint, Fluent $column) + { + return $column->nullable ? '' : ' NOT NULL'; + } + + /** + * Get the SQL for a default column modifier. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $column + * @return string|null + */ + protected function modifyDefault(Blueprint $blueprint, Fluent $column) + { + if (! is_null($column->default)) { + return ' DEFAULT '.$this->getDefaultValue($column->default); + } + } + + /** + * Get the SQL for an auto-increment column modifier. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $column + * @return string|null + */ + protected function modifyIncrement(Blueprint $blueprint, Fluent $column) + { + if (in_array($column->type, $this->serials) && $column->autoIncrement) { + return $this->hasCommand($blueprint, 'primary') || ($column->change && ! $column->primary) + ? ' unique' + : ' generated BY DEFAULT as identity primary key'; + } + } + + /** + * Create the column definition for a char type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeChar(Fluent $column) + { + return "CHAR({$column->length})"; + } + + /** + * Create the column definition for a string type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeString(Fluent $column) + { + return "VARCHAR({$column->length})"; + } + + /** + * Create the column definition for a text type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeText(Fluent $column) + { + return 'BLOB SUB_TYPE TEXT'; + } + + /** + * Create the column definition for a medium text type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeMediumText(Fluent $column) + { + return 'BLOB SUB_TYPE TEXT'; + } + + /** + * Create the column definition for a long text type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeLongText(Fluent $column) + { + return 'BLOB SUB_TYPE TEXT'; + } + + /** + * Create the column definition for a integer type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeInteger(Fluent $column) + { + return 'INTEGER'; + } + + /** + * Create the column definition for a big integer type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeBigInteger(Fluent $column) + { + return 'BIGINT'; + } + + /** + * Create the column definition for a medium integer type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeMediumInteger(Fluent $column) + { + return 'INTEGER'; + } + + /** + * Create the column definition for a tiny integer type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeTinyInteger(Fluent $column) + { + return 'SMALLINT'; + } + + /** + * Create the column definition for a small integer type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeSmallInteger(Fluent $column) + { + return 'SMALLINT'; + } + + /** + * Create the column definition for a float type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeFloat(Fluent $column) + { + return 'FLOAT'; + } + + /** + * Create the column definition for a double type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeDouble(Fluent $column) + { + return 'DOUBLE PRECISION'; + } + + /** + * Create the column definition for a decimal type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeDecimal(Fluent $column) + { + return "DECIMAL({$column->total}, {$column->places})"; + } + + /** + * Create the column definition for a boolean type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeBoolean(Fluent $column) + { + return 'CHAR(1)'; + } + + /** + * Create the column definition for an enum type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeEnum(Fluent $column) + { + $allowed = array_map(function ($a) { + return "'".$a."'"; + }, $column->allowed); + $default = ''; + if (! is_null($column->default)) { + $default .= ' DEFAULT '.$this->getDefaultValue($column->default); + $column->default = null; + } + + return "VARCHAR(255) $default CHECK ({$column->name} IN (".implode(', ', $allowed).'))'; + } + + /** + * Create the column definition for a json type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeJson(Fluent $column) + { + return 'VARCHAR(8191)'; + } + + /** + * Create the column definition for a jsonb type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeJsonb(Fluent $column) + { + return 'VARCHAR(8191) CHARACTER SET OCTETS'; + } + + /** + * Create the column definition for a date type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeDate(Fluent $column) + { + return 'DATE'; + } + + /** + * Create the column definition for a date-time type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeDateTime(Fluent $column) + { + return 'TIMESTAMP'; + } + + /** + * Create the column definition for a date-time type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeDateTimeTz(Fluent $column) + { + // No timezone support, default to plain date time + return $this->typeDateTime($column); + } + + /** + * Create the column definition for a time type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeTime(Fluent $column) + { + return 'TIME'; + } + + /** + * Create the column definition for a time type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeTimeTz(Fluent $column) + { + // No timezone support, default to plain time + return $this->typeTime($column); + } + + /** + * Create the column definition for a timestamp type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeTimestamp(Fluent $column) + { + if ($column->useCurrent) { + return 'TIMESTAMP DEFAULT CURRENT_TIMESTAMP'; + } + + return 'TIMESTAMP'; + } + + /** + * Create the column definition for a timestamp type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeTimestampTz(Fluent $column) + { + // No timezone support, default to plain timestamp + return $this->typeTimestamp($column); + } + + /** + * Create the column definition for a binary type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeBinary(Fluent $column) + { + return 'BLOB SUB_TYPE BINARY'; + } + + /** + * Create the column definition for a uuid type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeUuid(Fluent $column) + { + return 'CHAR(36)'; + } + + /** + * Create the column definition for an IP address type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeIpAddress(Fluent $column) + { + return 'VARCHAR(45)'; + } + + /** + * Create the column definition for a MAC address type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeMacAddress(Fluent $column) + { + return 'VARCHAR(17)'; + } + + /** + * Wrap a single string in keyword identifiers. + * + * @param string $value + * @return string + */ + protected function wrapValue($value) + { + return $value; + } +} -- cgit v1.3