Пример #1
0
 public static function build($output_prefix, $db_doc)
 {
     if (strlen($output_prefix) == 0) {
         throw new exception("pgsql8::build() sanity failure: output_prefix is blank");
     }
     // build full db creation script
     $build_file = $output_prefix . '_build.sql';
     dbsteward::info("Building complete file " . $build_file);
     $build_file_fp = fopen($build_file, 'w');
     if ($build_file_fp === FALSE) {
         throw new exception("failed to open full file " . $build_file . ' for output');
     }
     $build_file_ofs = new output_file_segmenter($build_file, 1, $build_file_fp, $build_file);
     if (count(dbsteward::$limit_to_tables) == 0) {
         $build_file_ofs->write("-- full database definition file generated " . date('r') . "\n");
     }
     if (!dbsteward::$generate_slonik) {
         $build_file_ofs->write("BEGIN;\n\n");
     }
     dbsteward::info("Calculating table foreign key dependency order..");
     $table_dependency = xml_parser::table_dependency_order($db_doc);
     // database-specific implementation code refers to dbsteward::$new_database when looking up roles/values/conflicts etc
     dbsteward::$new_database = $db_doc;
     dbx::set_default_schema($db_doc, 'public');
     // language defintions
     if (dbsteward::$create_languages) {
         foreach ($db_doc->language as $language) {
             $build_file_ofs->write(pgsql8_language::get_creation_sql($language));
         }
     }
     // by default, postgresql will validate the contents of LANGUAGE SQL functions during creation
     // because we are creating all functions before tables, this doesn't work when LANGUAGE SQL functions
     // refer to tables yet to be created.
     // scan language="sql" functions for <functionDefiniton>s that contain FROM (<TABLE>) statements
     $set_check_function_bodies = TRUE;
     // on in default postgresql configs
     dbx::set_default_schema($db_doc, 'public');
     foreach ($db_doc->schema as $schema) {
         foreach ($schema->function as $function) {
             if (pgsql8_function::has_definition($function)) {
                 $definition = pgsql8_function::get_definition($function);
                 if (strcasecmp($definition['language'], 'sql') == 0 && $definition['sqlFormat'] == 'pgsql8' && !is_null($referenced_table_name = static::function_definition_references_table($definition))) {
                     $table_schema_name = sql_parser::get_schema_name($referenced_table_name, $db_doc);
                     $node_schema = dbx::get_schema($db_doc, $table_schema_name);
                     $node_table = dbx::get_table($node_schema, sql_parser::get_object_name($referenced_table_name));
                     if ($node_table) {
                         // the referenced table is in the definition
                         // turn off check_function_bodies
                         $set_check_function_bodies = FALSE;
                         $set_check_function_bodies_info = "Detected LANGUAGE SQL function " . $schema['name'] . '.' . $function['name'] . " referring to table " . $table_schema_name . '.' . $node_table['name'] . " in the database definition";
                         dbsteward::info($set_check_function_bodies_info);
                         break 2;
                     }
                 }
             }
         }
     }
     if (!$set_check_function_bodies) {
         $build_file_ofs->write("\n");
         $build_file_ofs->write("SET check_function_bodies = FALSE; -- DBSteward " . $set_check_function_bodies_info . "\n\n");
     }
     if (dbsteward::$only_schema_sql || !dbsteward::$only_data_sql) {
         dbsteward::info("Defining structure");
         pgsql8::build_schema($db_doc, $build_file_ofs, $table_dependency);
     }
     if (!dbsteward::$only_schema_sql || dbsteward::$only_data_sql) {
         dbsteward::info("Defining data inserts");
         pgsql8::build_data($db_doc, $build_file_ofs, $table_dependency);
     }
     dbsteward::$new_database = NULL;
     if (!dbsteward::$generate_slonik) {
         $build_file_ofs->write("COMMIT;\n\n");
     }
     if (dbsteward::$generate_slonik) {
         $replica_sets = static::get_slony_replica_sets($db_doc);
         foreach ($replica_sets as $replica_set) {
             // output preamble file standalone for tool chains that use the preamble to do additional slonik commands
             pgsql8::build_slonik_preamble($db_doc, $replica_set, $output_prefix . "_slony_replica_set_" . $replica_set['id'] . "_preamble.slonik");
             // output paths specificity standalone for tool chains that use the store path slonik statements separately
             pgsql8::build_slonik_paths($db_doc, $replica_set, $output_prefix . "_slony_replica_set_" . $replica_set['id'] . "_paths.slonik");
             // output create set file standalone for tool chains that use the create_set slonik separately
             $create_set_filename = $output_prefix . '_slony_replica_set_' . $replica_set['id'] . '_create_set.slonik';
             pgsql8::build_slonik_create_set($db_doc, $replica_set, $create_set_filename);
             pgsql8::build_slonik_preamble($db_doc, $replica_set, $output_prefix . "_slony_replica_set_" . $replica_set['id'] . "_create_nodes.slonik");
             pgsql8::build_slonik_store_nodes($db_doc, $replica_set, $output_prefix . "_slony_replica_set_" . $replica_set['id'] . "_create_nodes.slonik");
             pgsql8::build_slonik_paths($db_doc, $replica_set, $output_prefix . "_slony_replica_set_" . $replica_set['id'] . "_create_nodes.slonik");
             // build full subscribe steps that creates sets and subscribes nodes
             $subscribe_filename = $output_prefix . "_slony_replica_set_" . $replica_set['id'] . "_subscribe.slonik";
             pgsql8::build_slonik_preamble($db_doc, $replica_set, $subscribe_filename);
             // create_set does one time slony configuration comparison.
             // so append the content of _create_set into _subscribe built earlier
             file_put_contents($subscribe_filename, file_get_contents($create_set_filename), FILE_APPEND);
             foreach ($replica_set->slonyReplicaSetNode as $replica_set_node) {
                 pgsql8::build_slonik_subscribe_set_node($db_doc, $replica_set, $output_prefix . "_slony_replica_set_" . $replica_set['id'] . "_subscribe.slonik", $replica_set_node);
             }
             static::slony_ids_required_during_build($replica_set, $db_doc);
         }
         $count = 0;
         foreach (array_keys(self::$sequence_slony_ids) as $slony_set_id) {
             $count += count(self::$sequence_slony_ids[$slony_set_id]);
         }
         dbsteward::notice("[slony] ID summary: " . count(self::$table_slony_ids) . " tables " . $count . " sequences");
         dbsteward::notice("[slony] table ID segments: " . static::slony_id_segment_summary(self::$table_slony_ids));
         // keep this from bombing on there being no ids in $sequence_slony_ids
         // if there were none returned (i.e. either there weren't any defined
         // or they were all set to IGNORE_REQUIRED which hopefully doesn't happen
         // because why would you do that for all of them)
         if (!empty(self::$sequence_slony_ids)) {
             foreach (array_keys(self::$sequence_slony_ids) as $slony_set_id) {
                 $console_line = "[slony] sequence ID segments";
                 if ($slony_set_id != 'NoSlonySet') {
                     $console_line .= " for slonySetId {$slony_set_id}";
                 }
                 $console_line .= ": ";
                 dbsteward::notice($console_line . static::slony_id_segment_summary(self::$sequence_slony_ids[$slony_set_id]));
             }
         }
     }
     return $db_doc;
 }