/** * Parses definition of the column * * @param definition definition of the column */ public static function parse_definition(&$node_schema, &$node_table, &$node_column, $definition) { $type = $definition; if (preg_match(self::PATTERN_NOT_NULL, $type, $matches) > 0) { $type = trim($matches[1]); dbx::set_attribute($node_column, 'null', 'false'); } else { if (preg_match(self::PATTERN_NULL, $type, $matches) > 0 && preg_match(self::PATTERN_DEFAULT_NULL, $type) == 0) { // PATTERN_NULL match only if it is not a trailing DEFAULT NULL // as that is not a null designation just a default designation $type = trim($matches[1]); dbx::set_attribute($node_column, 'null', 'true'); } } if (preg_match(self::PATTERN_DEFAULT, $type, $matches) > 0) { $type = trim($matches[1]); dbx::set_attribute($node_column, 'default', trim($matches[2])); } // post-parsing sanity checks if (preg_match('/[\\s]+/', $type) > 0) { // type contains whitespace // split the type and look for bad tokens $bad_keywords = array('DEFAULT', 'UNIQUE'); $tokens = preg_split("/[\\s]+/", $type, -1, PREG_SPLIT_NO_EMPTY); foreach ($tokens as $token) { foreach ($bad_keywords as $bad_keyword) { if (strcasecmp($token, $bad_keyword) == 0) { var_dump($definition); throw new exception($node_column['name'] . " column definition parse fail: type '" . $type . "' still contains '" . $bad_keyword . "' keyword -- look at callers for mis-handling of definition parameter"); } } } } dbx::set_attribute($node_column, 'type', $type); // for serial and bigserials, create the accompanying sequence that powers the serial if (preg_match(pgsql8::PATTERN_TABLE_LINKED_TYPES, $type) > 0) { $sequence_name = pgsql8::identifier_name($node_schema['name'], $node_table['name'], $node_column['name'], '_seq'); $node_sequence =& dbx::get_sequence($node_schema, $sequence_name, TRUE); dbx::set_attribute($node_sequence, 'owner', $node_table['owner']); dbx::set_attribute($node_sequence, 'start', '1'); dbx::set_attribute($node_sequence, 'min', '1'); dbx::set_attribute($node_sequence, 'inc', '1'); dbx::set_attribute($node_sequence, 'cycle', 'false'); } }
/** * Modify sequence values if they have changed * * @param $ofs output file pointer * @param $old_schema original schema * @param $new_schema new schema */ private static function add_modified_sequences($ofs, $old_schema, $new_schema) { foreach (dbx::get_sequences($new_schema) as $new_sequence) { if ($old_schema != null && pgsql8_schema::contains_sequence($old_schema, $new_sequence['name'])) { $old_sequence = dbx::get_sequence($old_schema, $new_sequence['name']); $sql = ''; if ($new_sequence['inc'] != null && strcasecmp($new_sequence['inc'], $old_sequence['inc']) != 0) { $sql .= "\n\tINCREMENT BY " . $new_sequence['inc']; } if ($new_sequence['min'] == null && $old_sequence['min'] != null) { $sql .= "\n\tNO MINVALUE"; } else { if ($new_sequence['min'] != null && strcasecmp($new_sequence['min'], $old_sequence['min']) != 0) { $sql .= "\n\tMINVALUE " . $new_sequence['min']; } } if ($new_sequence['max'] == null && $old_sequence['max'] != null) { $sql .= "\n\tNO MAXVALUE"; } else { if ($new_sequence['max'] != null && strcasecmp($new_sequence['max'], $old_sequence['max']) != 0) { $sql .= "\n\tMAXVALUE " . $new_sequence['max']; } } if (!pgsql8_diff::$ignore_start_with) { if ($new_sequence['start'] != null && strcasecmp($new_sequence['start'], $old_sequence['start']) != 0) { $sql .= "\n\tRESTART WITH " . $new_sequence['start']; } } if ($new_sequence['cache'] != null && strcasecmp($new_sequence['cache'], $old_sequence['cache']) != 0) { $sql .= "\n\tCACHE " . $new_sequence['cache']; } if ($old_sequence['cycle'] && !$new_sequence['cycle']) { $sql .= "\n\tNO CYCLE"; } else { if (!$old_sequence['cycle'] && $new_sequence['cycle']) { $sql .= "\n\tCYCLE"; } } if (strlen($sql) > 0) { $ofs->write("ALTER SEQUENCE " . pgsql8::get_quoted_schema_name($new_schema['name']) . '.' . pgsql8::get_quoted_object_name($new_sequence['name']) . $sql . ";\n"); } } } }
/** * Parses CREATE SEQUENCE command. * * @param database database * @param command CREATE SEQUENCE command */ public static function parse($database, $command) { $line = $command; if (preg_match(self::PATTERN_SEQUENCE_NAME, $line, $matches) > 0) { $sequence_name = trim($matches[1]); $line = preg_replace(self::PATTERN_SEQUENCE_NAME, '', $line); } else { throw new exception("Cannot parse line: " . $line); } $node_schema =& dbx::get_schema($database, sql_parser::get_schema_name($sequence_name, $database)); $node_sequence =& dbx::get_sequence($node_schema, sql_parser::get_object_name($sequence_name), true); $line = sql_parser::remove_last_semicolon($line); $line = self::processMaxValue($node_sequence, $line); $line = self::processMinValue($node_sequence, $line); $line = self::processCycle($node_sequence, $line); $line = self::processCache($node_sequence, $line); $line = self::processIncrement($node_sequence, $line); $line = self::processstart_with($node_sequence, $line); $line = trim($line); if (strlen($line) > 0) { throw new exception("Cannot parse commmand '" . $command . "', string '" . $line . "'"); } }
protected static function update_permissions($ofs1, $ofs3) { foreach (dbx::get_schemas(dbsteward::$new_database) as $new_schema) { $old_schema = dbx::get_schema(dbsteward::$old_database, $new_schema['name']); foreach (dbx::get_permissions($new_schema) as $new_permission) { if ($old_schema == NULL || !mssql10_permission::has_permission($old_schema, $new_permission)) { $ofs1->write(mssql10_permission::get_sql(dbsteward::$new_database, $new_schema, $new_schema, $new_permission) . "\n"); } } foreach (dbx::get_tables($new_schema) as $new_table) { $old_table = NULL; if ($old_schema != NULL) { $old_table = dbx::get_table($old_schema, $new_table['name']); } if (!dbsteward::$ignore_oldnames && mssql10_diff_tables::is_renamed_table($new_schema, $new_table)) { // oldTableName renamed table ? skip permission diffing on it, it is the same continue; } foreach (dbx::get_permissions($new_table) as $new_permission) { if ($old_table == NULL || !mssql10_permission::has_permission($old_table, $new_permission)) { $ofs1->write(mssql10_permission::get_sql(dbsteward::$new_database, $new_schema, $new_table, $new_permission) . "\n"); } } } foreach (dbx::get_sequences($new_schema) as $new_sequence) { $old_sequence = NULL; if ($old_schema != NULL) { $old_sequence = dbx::get_sequence($old_schema, $new_sequence['name']); } foreach (dbx::get_permissions($new_sequence) as $new_permission) { if ($old_sequence == NULL || !mssql10_permission::has_permission($old_sequence, $new_permission)) { $ofs1->write(mssql10_permission::get_sql(dbsteward::$new_database, $new_schema, $new_sequence, $new_permission) . "\n"); } } } foreach (dbx::get_functions($new_schema) as $new_function) { $old_function = NULL; if ($old_schema != NULL) { $old_function = dbx::get_function($old_schema, $new_function['name'], mssql10_function::get_declaration($new_schema, $new_function)); } foreach (dbx::get_permissions($new_function) as $new_permission) { if ($old_function == NULL || !mssql10_permission::has_permission($old_function, $new_permission)) { $ofs1->write(mssql10_permission::get_sql(dbsteward::$new_database, $new_schema, $new_function, $new_permission) . "\n"); } } } foreach (dbx::get_views($new_schema) as $new_view) { $old_view = NULL; if ($old_schema != NULL) { $old_view = dbx::get_view($old_schema, $new_view['name']); } foreach (dbx::get_permissions($new_view) as $new_permission) { // if always_recreate_views flag is on, always grant all view permissions, as the view was recreated if (dbsteward::$always_recreate_views || $old_view == NULL || !mssql10_permission::has_permission($old_view, $new_permission) || mssql10_diff_views::is_view_modified($old_view, $new_view)) { // view permissions are in schema stage 3 file because views are (re)created in that stage for SELECT * expansion $ofs3->write(mssql10_permission::get_sql(dbsteward::$new_database, $new_schema, $new_view, $new_permission) . "\n"); } } } } }
public static function slony_diff($old_files, $new_files) { if (!is_array($old_files)) { $old_files = array($old_files); } $old_output_prefix = dirname($old_files[0]) . '/' . substr(basename($old_files[0]), 0, -4); if (!is_array($new_files)) { $new_files = array($new_files); } $new_output_prefix = dirname($new_files[0]) . '/' . substr(basename($new_files[0]), 0, -4); $old_db_doc = xml_parser::xml_composite($old_output_prefix, $old_files, $old_slony_composite_file); $new_db_doc = xml_parser::xml_composite($new_output_prefix, $new_files, $new_slony_composite_file); foreach ($old_db_doc->schema as $old_schema) { $new_schema = dbx::get_schema($new_db_doc, $old_schema['name']); if (!$new_schema) { dbsteward::warning("new definition missing schema " . $old_schema['name']); continue 1; } foreach ($old_schema->table as $old_table) { $new_table = dbx::get_table($new_schema, $old_table['name']); if (!$new_table) { dbsteward::warning("new definition missing table " . $old_schema['name'] . "." . $old_table['name']); continue 1; } if (strcmp($old_table['slonyId'], $new_table['slonyId']) != 0) { dbsteward::info("table " . $old_schema['name'] . "." . $old_table['name'] . "\told slonyId " . $old_table['slonyId'] . " new slonyId " . $new_table['slonyId']); continue 1; } } foreach ($old_schema->sequence as $old_sequence) { $new_sequence = dbx::get_sequence($new_schema, $old_sequence['name']); if (!$new_sequence) { dbsteward::warning("new definition missing sequence " . $old_schema['name'] . "." . $old_sequence['name']); continue 1; } if (strcmp($old_sequence['slonyId'], $new_sequence['slonyId']) != 0) { dbsteward::info("sequence " . $old_schema['name'] . "." . $old_sequence['name'] . "\told slonyId " . $old_sequence['slonyId'] . " new slonyId " . $new_sequence['slonyId']); continue 1; } } } }
/** * Parses GRANT and REVOKE commands * * @param database database * @param command REVOKE command * */ public static function parse($database, $command) { $command = sql_parser::remove_last_semicolon($command); if (preg_match(self::PATTERN_GRANT_REVOKE, $command, $matches) > 0) { if (count($matches) != 5) { throw new exception("GRANT/REVOKE definition preg exploded into " . count($matches) . ", panic!"); } $action = strtoupper($matches[1]); switch ($action) { case 'GRANT': case 'REVOKE': break; default: throw new exception("permission action " . $action . " is unknown, panic!"); break; } $operations = preg_split("/[\\,\\s]+/", $matches[2], -1, PREG_SPLIT_NO_EMPTY); if (!is_array($operations)) { $permission = array($operations); } for ($i = 0; $i < count($operations); $i++) { $operations[$i] = strtoupper($operations[$i]); switch ($operations[$i]) { case 'ALL': case 'SELECT': case 'INSERT': case 'UPDATE': case 'DELETE': case 'USAGE': case 'REFERENCES': case 'TRIGGER': break; default: var_dump($operations); throw new exception("the operation " . $operations[$i] . " is unknown, panic!"); break; } } $object = $matches[3]; $chunks = preg_split("/[\\s]+/", $object, -1, PREG_SPLIT_NO_EMPTY); if (count($chunks) == 1) { // if there is no white space separating this bit // then let postgresql decide what it is when the grant is run $object_type = ''; $object_name = $chunks[0]; } else { if (count($chunks) == 2) { // SEQUENCE schema.table_table_id_seq // TABLE schema.table $object_type = $chunks[0]; $object_name = $chunks[1]; // if it's a schema, don't try to explode / default the schema prefix if (strcasecmp($object_type, 'SCHEMA') == 0) { $schema =& dbx::get_schema($database, $object_name); } else { $object_name = sql_parser::get_schema_name($object_name, $database) . '.' . sql_parser::get_object_name($object_name); $schema =& dbx::get_schema($database, sql_parser::get_schema_name($object_name, $database)); } if ($schema == null) { throw new exception("Failed to find schema for grant/revoke: " . sql_parser::get_schema_name($object_name, $database)); } } else { throw new exception("object definition exploded into " . count($chunks) . " chunks, panic!"); } } $role = $matches[4]; // find the node_object, swtich'd on $object_type // based on http://www.postgresql.org/docs/8.4/static/sql-grant.html // empty object_type should be considered a TABLE GRANT/REVOKE if (strlen($object_type) == 0) { $object_type = 'TABLE'; } /* var_dump($command); var_dump(sql_parser::get_schema_name($object_name, $database)); var_dump(sql_parser::get_object_name($object_name)); /**/ switch (strtoupper($object_type)) { case 'SCHEMA': $node_object =& dbx::get_schema($database, $object_name); break; case 'SEQUENCE': $node_schema =& dbx::get_schema($database, sql_parser::get_schema_name($object_name, $database)); $node_object =& dbx::get_sequence($node_schema, sql_parser::get_object_name($object_name)); break; case 'TABLE': $node_schema =& dbx::get_schema($database, sql_parser::get_schema_name($object_name, $database)); $node_object =& dbx::get_table($node_schema, sql_parser::get_object_name($object_name)); break; default: throw new exception("unknown object_type " . $object_type . " encountered, panic!"); break; } dbx::set_permission($node_object, $action, $operations, $role); } else { throw new exception("Cannot parse command: " . $command); } }