/** * Creates a unique cache prefix to help prevent cache conflicts * * @return void */ private function makeCachePrefix() { $prefix = 'fSchema::' . $this->database->getType() . '::'; if ($this->database->getHost()) { $prefix .= $this->database->getHost() . '::'; } if ($this->database->getPort()) { $prefix .= $this->database->getPort() . '::'; } $prefix .= $this->database->getDatabase() . '::'; if ($this->database->getUsername()) { $prefix .= $this->database->getUsername() . '::'; } return $prefix; }
/** * Translates Flourish SQL `ALTER TABLE` statements to the appropriate * statements for Oracle * * @param string $sql The SQL statements that will be executed against the database * @param array &$extra_statements Any extra SQL statements required for Oracle * @param array $data Data parsed from the `ALTER TABLE` statement * @return string The modified SQL statement */ private function translateOracleAlterTableStatements($sql, &$extra_statements, $data) { $data['schema'] = strtolower($this->database->getUsername()); $data['table_without_schema'] = $data['table']; if (strpos($data['table'], '.') !== FALSE) { list($data['schema'], $data['table_without_schema']) = explode('.', $data['table']); } if (in_array($data['type'], array('drop_check_constraint', 'drop_primary_key', 'drop_foreign_key', 'drop_unique'))) { $column_info = $this->database->query("SELECT\n\t\t\t\t\tATC.COLUMN_NAME\n\t\t\t\tFROM\n\t\t\t\t\tALL_TABLES AT LEFT JOIN\n\t\t\t\t\tALL_TAB_COLUMNS ATC ON\n\t\t\t\t\t\tATC.OWNER = AT.OWNER AND\n\t\t\t\t\t\tATC.TABLE_NAME = AT.TABLE_NAME AND\n\t\t\t\t\t\tLOWER(ATC.COLUMN_NAME) = %s\n\t\t\t\tWHERE\n\t\t\t\t\tLOWER(AT.OWNER) = %s AND\n\t\t\t\t\tLOWER(AT.TABLE_NAME) = %s", isset($data['column_name']) ? $data['column_name'] : '', $data['schema'], $data['table_without_schema']); if (!$column_info->countReturnedRows()) { $this->throwException(self::compose('The table "%1$s" does not exist', $data['table']), $sql); } if (isset($data['column_name'])) { $row = $column_info->fetchRow(); if (!strlen($row['column_name'])) { $this->throwException(self::compose('The column "%1$s" does not exist in the table "%2$s"', $data['column_name'], $data['table']), $sql); } } } if ($data['type'] == 'drop_check_constraint' || $data['type'] == 'set_check_constraint') { $constraints = $this->database->query("SELECT\n\t\t\t\t\tAC.CONSTRAINT_NAME,\n\t\t\t\t\tAC.SEARCH_CONDITION\n\t\t\t\tFROM\n\t\t\t\t\tALL_TAB_COLUMNS ATC INNER JOIN\n\t\t\t\t\tALL_CONS_COLUMNS ACC ON\n\t\t\t\t\t\tATC.OWNER = ACC.OWNER AND\n\t\t\t\t\t\tATC.COLUMN_NAME = ACC.COLUMN_NAME AND\n\t\t\t\t\t\tATC.TABLE_NAME = ACC.TABLE_NAME AND\n\t\t\t\t\t\tACC.POSITION IS NULL INNER JOIN\n\t\t\t\t\tALL_CONSTRAINTS AC ON\n\t\t\t\t\t\tAC.OWNER = ACC.OWNER AND\n\t\t\t\t\t\tAC.CONSTRAINT_NAME = ACC.CONSTRAINT_NAME AND\n\t\t\t\t\t\tAC.CONSTRAINT_TYPE = 'C' AND\n\t\t\t\t\t\tAC.STATUS = 'ENABLED'\n\t\t\t\tWHERE\n\t\t\t\t\tLOWER(ATC.OWNER) = %s AND\n\t\t\t\t\tLOWER(ATC.TABLE_NAME) = %s AND\n\t\t\t\t\tLOWER(ATC.COLUMN_NAME) = %s", $data['schema'], $data['table_without_schema'], $data['column_name']); $constraint_name = NULL; foreach ($constraints as $row) { if (preg_match("#^\\s*\"?\\w+\"?\\s+IN\\s+(\\(\\s*(?:(?<!')'(?:''|[^']+)*'|%\\d+\\\$s)(?:\\s*,\\s*(?:(?<!')'(?:''|[^']+)*'|%\\d+\\\$s))*\\s*\\))\\s*\$#i", $row['search_condition'])) { $constraint_name = $row['constraint_name']; break; } elseif (preg_match('/^\\s*"?' . preg_quote($data['column_name'], '/') . '"?\\s*=\\s*\'((\'\'|[^\']+)*)\'(\\s+OR\\s+"?' . preg_quote($data['column_name'], '/') . '"?\\s*=\\s*\'((\'\'|[^\']+)*)\')*\\s*$/i', $row['search_condition'])) { $constraint_name = $row['constraint_name']; break; } } } if ($data['type'] == 'set_not_null' || $data['type'] == 'drop_not_null') { $not_null_result = $this->database->query("SELECT\n\t\t\t\t\tATC.NULLABLE\n\t\t\t\tFROM\n\t\t\t\t\tALL_TAB_COLUMNS ATC\n\t\t\t\tWHERE\n\t\t\t\t\tLOWER(ATC.OWNER) = %s AND\n\t\t\t\t\tLOWER(ATC.TABLE_NAME) = %s AND\n\t\t\t\t\tLOWER(ATC.COLUMN_NAME) = %s", $data['schema'], $data['table_without_schema'], $data['column_name']); $not_null = $not_null_result->countReturnedRows() && $not_null_result->fetchScalar() == 'N'; } if ($data['type'] == 'set_not_null' && isset($data['default']) && $data['default'] == "''") { $data['type'] = 'drop_not_null'; $data['default'] = ' NULL'; } if ($data['type'] == 'column_comment') { // Oracle handles the normalized syntax } elseif ($data['type'] == 'rename_table') { // Oracle handles the normalized syntax } elseif ($data['type'] == 'rename_column') { // When renaming a primary key column we need to check // for triggers that implement autoincrement $res = $this->database->query("SELECT\n\t\t\t\t\tTRIGGER_NAME,\n\t\t\t\t\tTRIGGER_BODY\n\t\t\t\tFROM\n\t\t\t\t\tALL_TRIGGERS\n\t\t\t\tWHERE\n\t\t\t\t\tTRIGGERING_EVENT LIKE 'INSERT%' AND\n\t\t\t\t\tSTATUS = 'ENABLED' AND\n\t\t\t\t\tTRIGGER_NAME NOT LIKE 'BIN\$%' AND\n\t\t\t\t\tLOWER(TABLE_NAME) = %s AND\n\t\t\t\t\tLOWER(OWNER) = %s", $data['table_without_schema'], $data['schema']); foreach ($res as $row) { if (!preg_match('#\\s+:new\\."?' . preg_quote($data['column_name'], '#') . '"?\\s+FROM\\s+DUAL#i', $row['trigger_body'])) { continue; } $trigger = 'CREATE OR REPLACE TRIGGER ' . $row['trigger_name'] . "\n"; $trigger .= "BEFORE INSERT ON " . $data['table_without_schema'] . "\n"; $trigger .= "FOR EACH ROW\n"; $trigger .= preg_replace('#( :new\\.)' . preg_quote($data['column_name'], '#') . '( )#i', '\\1' . $data['new_column_name'] . '\\2', $row['trigger_body']); $extra_statements[] = $trigger; } } elseif ($data['type'] == 'add_column') { // If NOT NULL DEFAULT '' is present, both are removed since Oracle converts '' to NULL $data['column_definition'] = preg_replace('#(\\bNOT\\s+NULL\\s+DEFAULT\\s+\'\'|\\bDEFAULT\\s+\'\'\\s+NOT\\s+NULL)#', '', $data['column_definition']); // Oracle does not support ON UPDATE clauses $data['column_definition'] = preg_replace('#(\\sON\\s+UPDATE\\s+(CASCADE|SET\\s+NULL|NO\\s+ACTION|RESTRICT))#i', '', $data['column_definition']); // Oracle requires NOT NULL to come after the DEFAULT value or UNIQUE constraint $data['column_definition'] = preg_replace('#(\\s+NOT\\s+NULL)((?:\\s+UNIQUE|\\s+DEFAULT\\s+(?:[^, \'\\n]*|\'(?:\'\'|[^\']+)*\'))+)#i', '\\2\\1', $data['column_definition']); $sql = $this->database->escape('ALTER TABLE %r ADD ', $data['table']) . $data['column_definition']; $sql = $this->translateDataTypes($sql); // Create sequences and triggers for Oracle if (stripos($sql, 'autoincrement') !== FALSE && preg_match('#^\\s*(?:[a-z]+)(?:\\((?:\\d+)\\))?.*?\\bAUTOINCREMENT\\b.*$#iD', $sql, $matches)) { // If we are creating a new autoincrementing primary key on an existing // table we have to take some extra steps to pre-populate the // auto-incrementing column, otherwise Oracle will error out if (preg_match('#\\bPRIMARY\\s+KEY\\b#i', $sql)) { $sql = preg_replace('# PRIMARY\\s+KEY\\b#i', '', $sql); $extra_statements[] = $this->database->escape("UPDATE %r SET %r = ROWNUM", $data['table'], $data['column_name']); $extra_statements[] = $this->database->escape("ALTER TABLE %r ADD CONSTRAINT %r PRIMARY KEY (%r)", $data['table'], $this->generateConstraintName($sql, 'pk'), $data['column_name']); } $table_column = substr(str_replace('"', '', $data['table']) . '_' . str_replace('"', '', $data['column_name']), 0, 26); $sequence_name = $table_column . '_seq'; $trigger_name = $table_column . '_trg'; $sequence = "DECLARE\n\t\t\t\t\tcreate_seq_sql VARCHAR2(200);\n \t\t\tBEGIN\n\t\t\t\t\tSELECT\n\t\t\t\t\t\t'CREATE SEQUENCE " . $sequence_name . " START WITH ' || (SQ.TOTAL_ROWS + 1)\n\t\t\t\t\tINTO\n\t\t\t\t\t\tcreate_seq_sql\n\t\t\t\t\tFROM\n\t\t\t\t\t\t(SELECT COUNT(*) TOTAL_ROWS FROM " . $data['table'] . ") SQ \\;\n\t\t\t\t\tEXECUTE IMMEDIATE create_seq_sql\\;\n\t\t\t\tEND\\;"; $trigger = 'CREATE OR REPLACE TRIGGER ' . $trigger_name . "\n"; $trigger .= "BEFORE INSERT ON " . $data['table'] . "\n"; $trigger .= "FOR EACH ROW\n"; $trigger .= "BEGIN\n"; $trigger .= " IF :new." . $data['column_name'] . " IS NULL THEN\n"; $trigger .= "\tSELECT " . $sequence_name . ".nextval INTO :new." . $data['column_name'] . " FROM dual;\n"; $trigger .= " END IF;\n"; $trigger .= "END;"; $extra_statements[] = $sequence; $extra_statements[] = $trigger; $sql = preg_replace('#\\s+autoincrement\\b#i', '', $sql); } } elseif ($data['type'] == 'drop_column') { $sql .= ' CASCADE CONSTRAINTS'; // Drop any triggers and sequences that implement autoincrement for the column $res = $this->database->query("SELECT\n\t\t\t\t\tTRIGGER_NAME,\n\t\t\t\t\tTRIGGER_BODY\n\t\t\t\tFROM\n\t\t\t\t\tALL_TRIGGERS\n\t\t\t\tWHERE\n\t\t\t\t\tTRIGGERING_EVENT LIKE 'INSERT%' AND\n\t\t\t\t\tSTATUS = 'ENABLED' AND\n\t\t\t\t\tTRIGGER_NAME NOT LIKE 'BIN\$%' AND\n\t\t\t\t\tLOWER(TABLE_NAME) = %s AND\n\t\t\t\t\tLOWER(OWNER) = %s", $data['table_without_schema'], $data['schema']); foreach ($res as $row) { if (!preg_match('#SELECT\\s+"?(\\w+)"?\\.nextval\\s+INTO\\s+:new\\."?' . preg_quote($data['column_name'], '#') . '"?\\s+FROM\\s+dual#i', $row['trigger_body'], $match)) { continue; } $extra_statements[] = $this->database->escape("DROP SEQUENCE %r", $match[1]); $extra_statements[] = $this->database->escape("DROP TRIGGER %r", $row['trigger_name']); } } elseif ($data['type'] == 'alter_type') { $data['data_type'] = $this->translateDataTypes($data['data_type']); $sql = $this->database->escape("ALTER TABLE %r MODIFY (%r ", $data['table'], $data['column_name']) . $data['data_type'] . ')'; } elseif ($data['type'] == 'set_default') { $sql = $this->database->escape("ALTER TABLE %r MODIFY (%r DEFAULT ", $data['table'], $data['column_name']) . $data['default_value'] . ')'; } elseif ($data['type'] == 'drop_default') { $sql = $this->database->escape("ALTER TABLE %r MODIFY (%r DEFAULT NULL)", $data['table'], $data['column_name']); } elseif ($data['type'] == 'set_not_null') { // If it is already NOT NULL, don't set it again since it will cause an error if ($not_null_result->countReturnedRows() && $not_null) { if (isset($data['default'])) { $sql = $this->database->escape("ALTER TABLE %r MODIFY (%r DEFAULT ", $data['table'], $data['column_name']) . $data['default'] . ')'; } else { $sql = "SELECT 'noop - no NOT NULL to set' FROM dual"; } } else { $sql = $this->database->escape("ALTER TABLE %r MODIFY (%r", $data['table'], $data['column_name']); if (isset($data['default'])) { $sql .= ' DEFAULT ' . $data['default']; } $sql .= ' NOT NULL)'; } } elseif ($data['type'] == 'drop_not_null') { if (!$not_null_result->countReturnedRows() || $not_null) { $sql = $this->database->escape("ALTER TABLE %r MODIFY (%r", $data['table'], $data['column_name']); if (isset($data['default'])) { $sql .= ' DEFAULT ' . $data['default']; } $sql .= ' NULL)'; // If it is already NULL, don't set it again since it will cause an error } else { if (isset($data['default'])) { $sql = $this->database->escape("ALTER TABLE %r MODIFY (%r DEFAULT", $data['table'], $data['column_name']) . $data['default'] . ')'; } else { $sql = "SELECT 'noop - no NOT NULL to drop' FROM dual"; } } } elseif ($data['type'] == 'drop_check_constraint') { if (!$constraint_name) { $this->throwException(self::compose('The column "%1$s" in the table "%2$s" does not have a check constraint', $data['column_name'], $data['table']), $sql); } $sql = $this->database->escape("ALTER TABLE %r DROP CONSTRAINT %r", $data['table'], $constraint_name); } elseif ($data['type'] == 'set_check_constraint') { if ($constraint_name) { $extra_statements[] = $this->database->escape("ALTER TABLE %r DROP CONSTRAINT %r", $data['table'], $constraint_name); } $sql = $this->database->escape("ALTER TABLE %r ADD CONSTRAINT %r", $data['table'], $this->generateConstraintName($sql, 'ck')) . $data['constraint']; $extra_statements[] = $sql; $sql = array_shift($extra_statements); } elseif ($data['type'] == 'drop_primary_key') { $constraint_columns = $this->database->query("SELECT\n\t\t\t\t\tAC.CONSTRAINT_NAME CONSTRAINT_NAME,\n\t\t\t\t\tLOWER(ACC.COLUMN_NAME) \"COLUMN\",\n\t\t\t\t\tANC.SEARCH_CONDITION\n\t\t\t\tFROM\n\t\t\t\t\tALL_CONSTRAINTS AC INNER JOIN\n\t\t\t\t\tALL_CONS_COLUMNS ACC ON\n\t\t\t\t\t\tAC.CONSTRAINT_NAME = ACC.CONSTRAINT_NAME AND\n\t\t\t\t\t\tAC.OWNER = ACC.OWNER LEFT JOIN\n\t\t\t\t\tALL_CONS_COLUMNS ANCC ON\n\t\t\t\t\t\tACC.OWNER = ANCC.OWNER AND\n\t\t\t\t\t\tACC.TABLE_NAME = ANCC.TABLE_NAME AND\n\t\t\t\t\t\tACC.COLUMN_NAME = ANCC.COLUMN_NAME LEFT JOIN\n\t\t\t\t\tALL_CONSTRAINTS ANC ON\n\t\t\t\t\t\tANC.CONSTRAINT_NAME = ANCC.CONSTRAINT_NAME AND\n\t\t\t\t\t\tANC.OWNER = ANCC.OWNER AND\n\t\t\t\t\t\tANC.CONSTRAINT_TYPE = 'C' AND\n\t\t\t\t\t\tANC.STATUS = 'ENABLED'\n\t\t\t\tWHERE\n\t\t\t\t\tAC.CONSTRAINT_TYPE = 'P' AND\n\t\t\t\t\tLOWER(AC.OWNER) = %s AND\n\t\t\t\t\tLOWER(AC.TABLE_NAME) = %s", $data['schema'], $data['table_without_schema']); $constraint_name = NULL; $primary_key_columns = array(); $nullable = FALSE; foreach ($constraint_columns as $row) { $constraint_name = $row['constraint_name']; $primary_key_columns[] = $row['column']; $nullable = strtolower($row['search_condition']) != '"' . $row['column'] . '" is not null'; } if (!$constraint_name) { $this->throwException(self::compose('The table "%1$s" does not have a primary key constraint', $data['table']), $sql); } $sql = $this->database->escape("ALTER TABLE %r DROP CONSTRAINT %r CASCADE", $data['table'], $constraint_name); // When dropping a primary key we want to drop any trigger // and sequence used to implement autoincrement $res = $this->database->query("SELECT\n\t\t\t\t\tTRIGGER_NAME,\n\t\t\t\t\tTRIGGER_BODY\n\t\t\t\tFROM\n\t\t\t\t\tALL_TRIGGERS\n\t\t\t\tWHERE\n\t\t\t\t\tTRIGGERING_EVENT LIKE 'INSERT%' AND\n\t\t\t\t\tSTATUS = 'ENABLED' AND\n\t\t\t\t\tTRIGGER_NAME NOT LIKE 'BIN\$%' AND\n\t\t\t\t\tLOWER(TABLE_NAME) = %s AND\n\t\t\t\t\tLOWER(OWNER) = %s", $data['table_without_schema'], $data['schema']); foreach ($res as $row) { if (!preg_match('#SELECT\\s+"?(\\w+)"?\\.nextval\\s+INTO\\s+:new\\.("?\\w+"?)\\s+FROM\\s+DUAL#i', $row['trigger_body'], $match)) { continue; } $extra_statements[] = $this->database->escape("DROP TRIGGER %r", $data['schema'] . '.' . $row['trigger_name']); $extra_statements[] = $this->database->escape("DROP SEQUENCE %r", $data['schema'] . '.' . $match[1]); } if (count($primary_key_columns) == 1 && $nullable) { $extra_statements[] = $this->database->escape("ALTER TABLE %r MODIFY (%r NOT NULL)", $data['table'], reset($primary_key_columns)); } } elseif ($data['type'] == 'add_primary_key') { $sql = $this->database->escape("ALTER TABLE %r ADD CONSTRAINT %r PRIMARY KEY (%r)", $data['table'], $this->generateConstraintName($sql, 'pk'), $data['column_names']); if ($data['autoincrement']) { $extra_statements[] = $sql; $sql = $this->database->escape("UPDATE %r SET %r = ROWNUM", $data['table'], $data['column_name']); $table_column = substr(str_replace('"', '', $data['table']) . '_' . str_replace('"', '', $data['column_name']), 0, 26); $sequence_name = $table_column . '_seq'; $trigger_name = $table_column . '_trg'; $sequence = "DECLARE\n\t\t\t\t\tcreate_seq_sql VARCHAR2(200);\n \t\t\tBEGIN\n\t\t\t\t\tSELECT\n\t\t\t\t\t\t'CREATE SEQUENCE " . $sequence_name . " START WITH ' || (SQ.TOTAL_ROWS + 1)\n\t\t\t\t\tINTO\n\t\t\t\t\t\tcreate_seq_sql\n\t\t\t\t\tFROM\n\t\t\t\t\t\t(SELECT COUNT(*) TOTAL_ROWS FROM " . $data['table'] . ") SQ \\;\n\t\t\t\t\tEXECUTE IMMEDIATE create_seq_sql\\;\n\t\t\t\tEND\\;"; $trigger = 'CREATE OR REPLACE TRIGGER ' . $trigger_name . "\n"; $trigger .= "BEFORE INSERT ON " . $data['table'] . "\n"; $trigger .= "FOR EACH ROW\n"; $trigger .= "BEGIN\n"; $trigger .= " IF :new." . $data['column_name'] . " IS NULL THEN\n"; $trigger .= "\tSELECT " . $sequence_name . ".nextval INTO :new." . $data['column_name'] . " FROM dual;\n"; $trigger .= " END IF;\n"; $trigger .= "END;"; $extra_statements[] = $sequence; $extra_statements[] = $trigger; } } elseif ($data['type'] == 'drop_foreign_key') { $constraint = $this->database->query("SELECT\n\t\t\t\t\tAC.CONSTRAINT_NAME CONSTRAINT_NAME\n\t\t\t\tFROM\n\t\t\t\t\tALL_CONSTRAINTS AC INNER JOIN\n\t\t\t\t\tALL_CONS_COLUMNS ACC ON\n\t\t\t\t\t\tAC.CONSTRAINT_NAME = ACC.CONSTRAINT_NAME AND\n\t\t\t\t\t\tAC.OWNER = ACC.OWNER\n\t\t\t\tWHERE\n\t\t\t\t\tAC.CONSTRAINT_TYPE = 'R' AND\n\t\t\t\t\tLOWER(AC.OWNER) = %s AND\n\t\t\t\t\tLOWER(AC.TABLE_NAME) = %s AND\n\t\t\t\t\tLOWER(ACC.COLUMN_NAME) = %s", $data['schema'], $data['table_without_schema'], $data['column_name']); if (!$constraint->countReturnedRows()) { $this->throwException(self::compose('The column "%1$s" in the table "%2$s" does not have a foreign key constraint', $data['column_name'], $data['table']), $sql); } $sql = $this->database->escape("ALTER TABLE %r DROP CONSTRAINT %r", $data['table'], $constraint->fetchScalar()); } elseif ($data['type'] == 'add_foreign_key') { // Oracle does not support ON UPDATE clauses $data['references'] = preg_replace('#(\\sON\\s+UPDATE\\s+(CASCADE|SET\\s+NULL|NO\\s+ACTION|RESTRICT))#i', '', $data['references']); $sql = $this->database->escape("ALTER TABLE %r ADD CONSTRAINT %r FOREIGN KEY (%r) REFERENCES " . $data['references'], $data['table'], $this->generateConstraintName($sql, 'fk'), $data['column_name']); } elseif ($data['type'] == 'drop_unique') { $constraint_rows = $this->database->query("SELECT\n\t\t\t\t\tAC.CONSTRAINT_NAME,\n\t\t\t\t\tLOWER(ACC.COLUMN_NAME) \"COLUMN\"\n\t\t\t\tFROM\n\t\t\t\t\tALL_CONSTRAINTS AC INNER JOIN\n\t\t\t\t\tALL_CONS_COLUMNS ACC ON\n\t\t\t\t\t\tAC.CONSTRAINT_NAME = ACC.CONSTRAINT_NAME AND\n\t\t\t\t\t\tAC.OWNER = ACC.OWNER\n\t\t\t\tWHERE\n\t\t\t\t\tAC.CONSTRAINT_TYPE = 'U' AND\n\t\t\t\t\tLOWER(AC.OWNER) = %s AND\n\t\t\t\t\tLOWER(AC.TABLE_NAME) = %s", $data['schema'], $data['table_without_schema']); $constraints = array(); foreach ($constraint_rows as $row) { if (!isset($constraints[$row['constraint_name']])) { $constraints[$row['constraint_name']] = array(); } $constraints[$row['constraint_name']][] = $row['column']; } $constraint_name = NULL; sort($data['column_names']); foreach ($constraints as $name => $columns) { sort($columns); if ($columns == $data['column_names']) { $constraint_name = $name; break; } } if (!$constraint_name) { if (count($data['column_names']) > 1) { $message = self::compose('The columns "%1$s" in the table "%2$s" do not have a unique constraint', join('", "', $data['column_names']), $data['table']); } else { $message = self::compose('The column "%1$s" in the table "%2$s" does not have a unique constraint', reset($data['column_names']), $data['table']); } $this->throwException($message, $sql); } $sql = $this->database->escape("ALTER TABLE %r DROP CONSTRAINT %r CASCADE", $data['table'], $constraint_name); } elseif ($data['type'] == 'add_unique') { $sql = $this->database->escape("ALTER TABLE %r ADD CONSTRAINT %r UNIQUE (%r)", $data['table'], $this->generateConstraintName($sql, 'uc'), $data['column_names']); } return $sql; }
/** * Creates a unique cache prefix to help prevent cache conflicts * * @return string The cache prefix to use */ private function makeCachePrefix() { if (!$this->cache_prefix) { $prefix = 'fSQLTranslation::' . $this->database->getType() . '::'; if ($this->database->getHost()) { $prefix .= $this->database->getHost() . '::'; } if ($this->database->getPort()) { $prefix .= $this->database->getPort() . '::'; } $prefix .= $this->database->getDatabase() . '::'; if ($this->database->getUsername()) { $prefix .= $this->database->getUsername() . '::'; } $this->cache_prefix = $prefix; } return $this->cache_prefix; }