postgres7.class.php
来自「很棒的在线教学系统」· PHP 代码 · 共 575 行 · 第 1/2 页
PHP
575 行
($xmldb_field->getType() == XMLDB_TYPE_CHAR) || ($xmldb_field->getType() == XMLDB_TYPE_TEXT) || ($xmldb_field->getType() == XMLDB_TYPE_BINARY) || (!$xmldb_field->getDecimals()) || (!$olddecimals) || ($xmldb_field->getDecimals() == $olddecimals)) { $decimalchanged = false; } /// Detect if we are changing the default if (($xmldb_field->getDefault() === null && $olddefault === null) || ($xmldb_field->getDefault() === $olddefault) || //Check both equality and ("'" . $xmldb_field->getDefault() . "'" === $olddefault)) { //Equality with quotes because ADOdb returns the default with quotes $defaultchanged = false; } /// Detect if we are changing the nullability if (($xmldb_field->getNotnull() === $oldnotnull)) { $notnullchanged = false; } /// TODO: Some combinations like /// TODO: integer->integer /// TODO: integer->text /// TODO: number->text /// TODO: text->text /// TODO: do not require the use of temp columns, because PG 8.0 supports them automatically /// TODO: with a simple "alter table zzz alter column yyy type new specs" /// TODO: Must be implemented that way. Eloy 09/2007 /// If the type or the precision or the decimals have changed, then we need to: /// - create one temp column with the new specs /// - fill the new column with the values from the old one (casting if needed) /// - drop the old column /// - rename the temp column to the original name if ($typechanged || $precisionchanged || $decimalchanged) { $tempcolname = $xmldb_field->getName() . '_alter_column_tmp'; /// Prevent temp field to have both NULL/NOT NULL and DEFAULT constraints $this->alter_column_skip_notnull = true; $this->alter_column_skip_default = true; $xmldb_field->setName($tempcolname); /// Create the temporal column $results = array_merge($results, $this->getAddFieldSQL($xmldb_table, $xmldb_field)); /// Detect some basic casting options if ((substr($oldmetatype, 0, 1) == 'C' && $xmldb_field->getType() == XMLDB_TYPE_NUMBER) || (substr($oldmetatype, 0, 1) == 'C' && $xmldb_field->getType() == XMLDB_TYPE_FLOAT)) { $copyorigin = 'CAST(CAST('.$fieldname.' AS TEXT) AS REAL)'; //From char to number or float } else if ((substr($oldmetatype, 0, 1) == 'C' && $xmldb_field->getType() == XMLDB_TYPE_INTEGER)) { $copyorigin = 'CAST(CAST('.$fieldname.' AS TEXT) AS INTEGER)'; //From char to integer } else { $copyorigin = $fieldname; //Direct copy between columns } /// Copy contents from original col to the temporal one $results[] = 'UPDATE ' . $tablename . ' SET ' . $tempcolname . ' = ' . $copyorigin; /// Drop the old column $xmldb_field->setName($fieldname); //Set back the original field name $results = array_merge($results, $this->getDropFieldSQL($xmldb_table, $xmldb_field)); /// Rename the temp column to the original one $results[] = 'ALTER TABLE ' . $tablename . ' RENAME COLUMN ' . $tempcolname . ' TO ' . $fieldname; /// Mark we have performed one change based in temp fields $from_temp_fields = true; } /// If the default has changed or we have used one temp field if ($defaultchanged || $from_temp_fields) { if ($default_clause = $this->getDefaultClause($xmldb_field)) { $results[] = 'ALTER TABLE ' . $tablename . ' ALTER COLUMN ' . $fieldname . ' SET' . $default_clause; /// Add default clause } else { if (!$from_temp_fields) { /// Only drop default if we haven't used the temp field, i.e. old column $results[] = 'ALTER TABLE ' . $tablename . ' ALTER COLUMN ' . $fieldname . ' DROP DEFAULT'; /// Drop default clause } } } /// If the not null has changed or we have used one temp field if ($notnullchanged || $from_temp_fields) { if ($xmldb_field->getNotnull()) { $results[] = 'ALTER TABLE ' . $tablename . ' ALTER COLUMN ' . $fieldname . ' SET NOT NULL'; } else { $results[] = 'ALTER TABLE ' . $tablename . ' ALTER COLUMN ' . $fieldname . ' DROP NOT NULL'; } } /// Return the results return $results; } /** * Returns the code (array of statements) needed to execute extra statements on field rename */ function getRenameFieldExtraSQL ($xmldb_table, $xmldb_field, $newname) { $results = array(); /// If the field is enum, drop and re-create the check constraint if ($xmldb_field->getEnum()) { /// Drop the current enum $results = array_merge($results, $this->getDropEnumSQL($xmldb_table, $xmldb_field)); /// Change field name (over a clone to avoid some potential problems later) $new_xmldb_field = clone($xmldb_field); $new_xmldb_field->setName($newname); /// Recreate the enum $results = array_merge($results, $this->getCreateEnumSQL($xmldb_table, $new_xmldb_field)); } return $results; } /** * Given one XMLDBTable and one XMLDBField, return the SQL statements needded to create its enum * (usually invoked from getModifyEnumSQL() */ function getCreateEnumSQL($xmldb_table, $xmldb_field) { /// All we have to do is to create the check constraint return array('ALTER TABLE ' . $this->getTableName($xmldb_table) . ' ADD ' . $this->getEnumExtraSQL($xmldb_table, $xmldb_field)); } /** * Given one XMLDBTable and one XMLDBField, return the SQL statements needded to drop its enum * (usually invoked from getModifyEnumSQL() */ function getDropEnumSQL($xmldb_table, $xmldb_field) { /// Let's introspect to know the real name of the check constraint if ($check_constraints = $this->getCheckConstraintsFromDB($xmldb_table, $xmldb_field)) { $check_constraint = array_shift($check_constraints); /// Get the 1st (should be only one) $constraint_name = strtolower($check_constraint->name); /// Extract the REAL name /// All we have to do is to drop the check constraint return array('ALTER TABLE ' . $this->getTableName($xmldb_table) . ' DROP CONSTRAINT ' . $constraint_name); } else { /// Constraint not found. Nothing to do return array(); } } /** * Given one XMLDBTable and one XMLDBField, return the SQL statements needded to create its default * (usually invoked from getModifyDefaultSQL() */ function getCreateDefaultSQL($xmldb_table, $xmldb_field) { /// Just a wrapper over the getAlterFieldSQL() function for PostgreSQL that /// is capable of handling defaults return $this->getAlterFieldSQL($xmldb_table, $xmldb_field); } /** * Given one XMLDBTable and one XMLDBField, return the SQL statements needded to drop its default * (usually invoked from getModifyDefaultSQL() */ function getDropDefaultSQL($xmldb_table, $xmldb_field) { /// Just a wrapper over the getAlterFieldSQL() function for PostgreSQL that /// is capable of handling defaults return $this->getAlterFieldSQL($xmldb_table, $xmldb_field); } /** * Given one XMLDBTable returns one array with all the check constrainsts * in the table (fetched from DB) * Optionally the function allows one xmldb_field to be specified in * order to return only the check constraints belonging to one field. * Each element contains the name of the constraint and its description * If no check constraints are found, returns an empty array */ function getCheckConstraintsFromDB($xmldb_table, $xmldb_field = null) { $results = array(); $tablename = $this->getTableName($xmldb_table); if ($constraints = get_records_sql("SELECT co.conname AS name, co.consrc AS description FROM pg_constraint co, pg_class cl WHERE co.conrelid = cl.oid AND co.contype = 'c' AND cl.relname = '{$tablename}'")) { foreach ($constraints as $constraint) { $results[$constraint->name] = $constraint; } } /// Filter by the required field if specified if ($xmldb_field) { $filtered_results = array(); $filter = $xmldb_field->getName(); /// Lets clean a bit each constraint description, looking for the filtered field foreach ($results as $key => $result) { $description = preg_replace('/\("(.*?)"\)/', '($1)', $result->description);// Double quotes out $description = preg_replace('/[\(\)]/', '', $description); // Parenthesis out $description = preg_replace('/::[a-z]+/i', '', $description); // Casts out $description = preg_replace("/({$filter})/i", '@$1@', $description); $description = trim(preg_replace('/ or /i', ' OR ', $description)); // Uppercase or & trim /// description starts by @$filter@ assume it's a constraint beloging to the field if (preg_match("/^@{$filter}@/i", $description)) { $filtered_results[$key] = $result; } } /// Assign filtered results to the final results array $results = $filtered_results; } return $results; }/** * Given one XMLDBTable returns one string with the sequence of the table * in the table (fetched from DB) * The sequence name for Postgres has one standard name convention: * tablename_fieldname_seq * so we just calculate it and confirm it's present in pg_class * If no sequence is found, returns false */function getSequenceFromDB($xmldb_table) { $tablename = $this->getTableName($xmldb_table); $sequencename = $tablename . '_id_seq'; if (!get_record_sql("SELECT * FROM pg_class WHERE relname = '{$sequencename}' AND relkind = 'S'")) { $sequencename = false; } return $sequencename;} /** * Given one object name and it's type (pk, uk, fk, ck, ix, uix, seq, trg) * return if such name is currently in use (true) or no (false) * (invoked from getNameForObject() */ function isNameInUse($object_name, $type, $table_name) { switch($type) { case 'ix': case 'uix': case 'seq': if ($check = get_records_sql("SELECT relname FROM pg_class WHERE lower(relname) = '" . strtolower($object_name) . "'")) { return true; } break; case 'pk': case 'uk': case 'fk': case 'ck': if ($check = get_records_sql("SELECT conname FROM pg_constraint WHERE lower(conname) = '" . strtolower($object_name) . "'")) { return true; } break; case 'trg': if ($check = get_records_sql("SELECT tgname FROM pg_trigger WHERE lower(tgname) = '" . strtolower($object_name) . "'")) { return true; } break; } return false; //No name in use found } /** * Returns an array of reserved words (lowercase) for this DB */ function getReservedWords() { /// This file contains the reserved words for PostgreSQL databases /// http://www.postgresql.org/docs/current/static/sql-keywords-appendix.html $reserved_words = array ( 'all', 'analyse', 'analyze', 'and', 'any', 'array', 'as', 'asc', 'asymmetric', 'authorization', 'between', 'binary', 'both', 'case', 'cast', 'check', 'collate', 'column', 'constraint', 'create', 'cross', 'current_date', 'current_role', 'current_time', 'current_timestamp', 'current_user', 'default', 'deferrable', 'desc', 'distinct', 'do', 'else', 'end', 'except', 'false', 'for', 'foreign', 'freeze', 'from', 'full', 'grant', 'group', 'having', 'ilike', 'in', 'initially', 'inner', 'intersect', 'into', 'is', 'isnull', 'join', 'leading', 'left', 'like', 'limit', 'localtime', 'localtimestamp', 'natural', 'new', 'not', 'notnull', 'null', 'off', 'offset', 'old', 'on', 'only', 'or', 'order', 'outer', 'overlaps', 'placing', 'primary', 'references', 'returning', 'right', 'select', 'session_user', 'similar', 'some', 'symmetric', 'table', 'then', 'to', 'trailing', 'true', 'union', 'unique', 'user', 'using', 'verbose', 'when', 'where', 'with' ); return $reserved_words; }}?>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?