%PDF-1.4
Directory : /var/www/vhosts/lautnusantara.com/httpdocs/web/system/Database/OCI8/ |
<?php /** * This file is part of CodeIgniter 4 framework. * * (c) CodeIgniter Foundation <admin@codeigniter.com> * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace CodeIgniter\Database\OCI8; use CodeIgniter\Database\Forge as BaseForge; /** * Forge for OCI8 */ class Forge extends BaseForge { /** * DROP INDEX statement * * @var string */ protected $dropIndexStr = 'DROP INDEX %s'; /** * CREATE DATABASE statement * * @var false */ protected $createDatabaseStr = false; /** * CREATE TABLE IF statement * * @var false * * @deprecated This is no longer used. */ protected $createTableIfStr = false; /** * DROP TABLE IF EXISTS statement * * @var false */ protected $dropTableIfStr = false; /** * DROP DATABASE statement * * @var false */ protected $dropDatabaseStr = false; /** * UNSIGNED support * * @var array|bool */ protected $unsigned = false; /** * NULL value representation in CREATE/ALTER TABLE statements * * @var string */ protected $null = 'NULL'; /** * RENAME TABLE statement * * @var string */ protected $renameTableStr = 'ALTER TABLE %s RENAME TO %s'; /** * DROP CONSTRAINT statement * * @var string */ protected $dropConstraintStr = 'ALTER TABLE %s DROP CONSTRAINT %s'; /** * ALTER TABLE * * @param string $alterType ALTER type * @param string $table Table name * @param array|string $field Column definition * * @return string|string[] */ protected function _alterTable(string $alterType, string $table, $field) { $sql = 'ALTER TABLE ' . $this->db->escapeIdentifiers($table); if ($alterType === 'DROP') { $fields = array_map(fn ($field) => $this->db->escapeIdentifiers(trim($field)), is_string($field) ? explode(',', $field) : $field); return $sql . ' DROP (' . implode(',', $fields) . ') CASCADE CONSTRAINT INVALIDATE'; } if ($alterType === 'CHANGE') { $alterType = 'MODIFY'; } $nullableMap = array_column($this->db->getFieldData($table), 'nullable', 'name'); $sqls = []; for ($i = 0, $c = count($field); $i < $c; $i++) { if ($alterType === 'MODIFY') { // If a null constraint is added to a column with a null constraint, // ORA-01451 will occur, // so add null constraint is used only when it is different from the current null constraint. $isWantToAddNull = strpos($field[$i]['null'], ' NOT') === false; $currentNullAddable = $nullableMap[$field[$i]['name']]; if ($isWantToAddNull === $currentNullAddable) { $field[$i]['null'] = ''; } } if ($field[$i]['_literal'] !== false) { $field[$i] = "\n\t" . $field[$i]['_literal']; } else { $field[$i]['_literal'] = "\n\t" . $this->_processColumn($field[$i]); if (! empty($field[$i]['comment'])) { $sqls[] = 'COMMENT ON COLUMN ' . $this->db->escapeIdentifiers($table) . '.' . $this->db->escapeIdentifiers($field[$i]['name']) . ' IS ' . $field[$i]['comment']; } if ($alterType === 'MODIFY' && ! empty($field[$i]['new_name'])) { $sqls[] = $sql . ' RENAME COLUMN ' . $this->db->escapeIdentifiers($field[$i]['name']) . ' TO ' . $this->db->escapeIdentifiers($field[$i]['new_name']); } $field[$i] = "\n\t" . $field[$i]['_literal']; } } $sql .= ' ' . $alterType . ' '; $sql .= count($field) === 1 ? $field[0] : '(' . implode(',', $field) . ')'; // RENAME COLUMN must be executed after MODIFY array_unshift($sqls, $sql); return $sqls; } /** * Field attribute AUTO_INCREMENT * * @return void */ protected function _attributeAutoIncrement(array &$attributes, array &$field) { if (! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === true && stripos($field['type'], 'NUMBER') !== false && version_compare($this->db->getVersion(), '12.1', '>=') ) { $field['auto_increment'] = ' GENERATED BY DEFAULT AS IDENTITY'; } } /** * Process column */ protected function _processColumn(array $field): string { $constraint = ''; // @todo: can’t cover multi pattern when set type. if ($field['type'] === 'VARCHAR2' && strpos($field['length'], "('") === 0) { $constraint = ' CHECK(' . $this->db->escapeIdentifiers($field['name']) . ' IN ' . $field['length'] . ')'; $field['length'] = '(' . max(array_map('mb_strlen', explode("','", mb_substr($field['length'], 2, -2)))) . ')' . $constraint; } elseif (count($this->primaryKeys) === 1 && $field['name'] === $this->primaryKeys[0]) { $field['unique'] = ''; } return $this->db->escapeIdentifiers($field['name']) . ' ' . $field['type'] . $field['length'] . $field['unsigned'] . $field['default'] . $field['auto_increment'] . $field['null'] . $field['unique']; } /** * Performs a data type mapping between different databases. * * @return void */ protected function _attributeType(array &$attributes) { // Reset field lengths for data types that don't support it // Usually overridden by drivers switch (strtoupper($attributes['TYPE'])) { case 'TINYINT': $attributes['CONSTRAINT'] ??= 3; // no break case 'SMALLINT': $attributes['CONSTRAINT'] ??= 5; // no break case 'MEDIUMINT': $attributes['CONSTRAINT'] ??= 7; // no break case 'INT': case 'INTEGER': $attributes['CONSTRAINT'] ??= 11; // no break case 'BIGINT': $attributes['CONSTRAINT'] ??= 19; // no break case 'NUMERIC': $attributes['TYPE'] = 'NUMBER'; return; case 'BOOLEAN': $attributes['TYPE'] = 'NUMBER'; $attributes['CONSTRAINT'] = 1; $attributes['UNSIGNED'] = true; $attributes['NULL'] = false; return; case 'DOUBLE': $attributes['TYPE'] = 'FLOAT'; $attributes['CONSTRAINT'] ??= 126; return; case 'DATETIME': case 'TIME': $attributes['TYPE'] = 'DATE'; return; case 'SET': case 'ENUM': case 'VARCHAR': $attributes['CONSTRAINT'] ??= 255; // no break case 'TEXT': case 'MEDIUMTEXT': $attributes['CONSTRAINT'] ??= 4000; $attributes['TYPE'] = 'VARCHAR2'; } } /** * Generates a platform-specific DROP TABLE string * * @return bool|string */ protected function _dropTable(string $table, bool $ifExists, bool $cascade) { $sql = parent::_dropTable($table, $ifExists, $cascade); if ($sql !== true && $cascade === true) { $sql .= ' CASCADE CONSTRAINTS PURGE'; } elseif ($sql !== true) { $sql .= ' PURGE'; } return $sql; } protected function _processForeignKeys(string $table): string { $sql = ''; $allowActions = [ 'CASCADE', 'SET NULL', 'NO ACTION', ]; foreach ($this->foreignKeys as $fkey) { $nameIndex = $table . '_' . implode('_', $fkey['field']) . '_fk'; $nameIndexFilled = $this->db->escapeIdentifiers($nameIndex); $foreignKeyFilled = implode(', ', $this->db->escapeIdentifiers($fkey['field'])); $referenceTableFilled = $this->db->escapeIdentifiers($this->db->DBPrefix . $fkey['referenceTable']); $referenceFieldFilled = implode(', ', $this->db->escapeIdentifiers($fkey['referenceField'])); $formatSql = ",\n\tCONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s(%s)"; $sql .= sprintf($formatSql, $nameIndexFilled, $foreignKeyFilled, $referenceTableFilled, $referenceFieldFilled); if ($fkey['onDelete'] !== false && in_array($fkey['onDelete'], $allowActions, true)) { $sql .= ' ON DELETE ' . $fkey['onDelete']; } } return $sql; } }