/** * return collection of arrays representing all of the constraints on a table * this is more than just the <constraint> discret children of a table element * this is also primary key, inline column foreign keys, and inline column unique constraints * everything comparing the constraints of a table should be calling this */ public static function get_table_constraints($db_doc, $node_schema, $node_table, $type = 'all') { if (!is_object($node_table)) { var_dump($node_table); throw new Exception("node_table is not an object, check trace for bad table pointer"); } switch ($type) { case 'all': case 'primaryKey': case 'constraint': case 'foreignKey': break; default: throw new Exception("unknown type " . $type . " encountered"); } $constraints = array(); if ($type == 'all' || $type == 'primaryKey') { if (!empty($node_table['primaryKey'])) { $pk_name = static::get_primary_key_name($node_table); $pk_def = static::get_primary_key_definition($node_table); $constraints[] = array('name' => $pk_name, 'schema_name' => (string) $node_schema['name'], 'table_name' => (string) $node_table['name'], 'type' => 'PRIMARY KEY', 'definition' => $pk_def); } else { if (!dbsteward::$ignore_primary_key_errors) { throw new Exception("Table {$node_schema['name']}.{$node_table['name']} does not have a primaryKey!"); } } } if ($type == 'all' || $type == 'constraint' || $type == 'foreignKey') { // look for constraints in <constraint> elements foreach ($node_table->constraint as $node_constraint) { // sanity check node definition constraint types switch (strtoupper((string) $node_constraint['type'])) { case 'PRIMARY KEY': throw new Exception("Primary keys are not allowed to be defined in a <constraint>"); break; default: throw new Exception('unknown constraint type ' . $node_constraint['type'] . ' encountered'); break; case 'CHECK': case 'UNIQUE': // if we're ONLY looking for foreign keys, ignore everything else if ($type == 'foreignKey') { continue; } // fallthru // fallthru case 'FOREIGN KEY': $constraints[] = array('name' => (string) $node_constraint['name'], 'schema_name' => (string) $node_schema['name'], 'table_name' => (string) $node_table['name'], 'type' => strtoupper((string) $node_constraint['type']), 'definition' => (string) $node_constraint['definition']); break; } } // look for explicit <foreignKey> elements foreach ($node_table->foreignKey as $node_fkey) { $foreign = self::foreign_key_lookup_compound($db_doc, $node_schema, $node_table, $node_fkey); $local_cols = preg_split('/[\\s,]+/', $node_fkey['columns'], -1, PREG_SPLIT_NO_EMPTY); $quoted_cols = implode(', ', array_map('format::get_quoted_column_name', $local_cols)); $constraint = array('name' => (string) $node_fkey['constraintName'], 'schema_name' => (string) $node_schema['name'], 'table_name' => (string) $node_table['name'], 'type' => 'FOREIGN KEY', 'definition' => "({$quoted_cols}) REFERENCES {$foreign['references']}", 'foreign_key_data' => $foreign); if (isset($node_fkey['onDelete'])) { $constraint['foreignOnDelete'] = (string) $node_fkey['onDelete']; } if (isset($node_fkey['onUpdate'])) { $constraint['foreignOnUpdate'] = (string) $node_fkey['onUpdate']; } if (isset($node_fkey['indexName'])) { $constraint['foreignIndexName'] = (string) $node_fkey['foreignIndexName']; } $constraints[] = $constraint; } // look for constraints in columns: foreign key and unique foreach ($node_table->column as $column) { if (isset($column['foreignTable'])) { if (empty($column['foreignTable'])) { throw new Exception("Invalid foreignSchema|foreignTable pair for {$node_schema['name']}.{$node_table['name']}.{$column['name']}"); } if (!empty($column['type'])) { throw new exception("Foreign-Keyed columns should not specify a type for {$node_schema['name']}.{$node_table['name']}.{$column['name']}"); } $foreign = static::foreign_key_lookup($db_doc, $node_schema, $node_table, $column); if (!empty($column['foreignKeyName']) > 0) { // explicitly name the foreign key if specified in the node $foreign['name'] = (string) $column['foreignKeyName']; } $column_fkey_constraint = array('name' => (string) $foreign['name'], 'schema_name' => (string) $node_schema['name'], 'table_name' => (string) $node_table['name'], 'type' => 'FOREIGN KEY', 'definition' => '(' . dbsteward::quote_column_name($column['name']) . ') REFERENCES ' . $foreign['references'], 'foreign_key_data' => $foreign); if (!empty($column['foreignIndexName'])) { $column_fkey_constraint['foreignIndexName'] = (string) $column['foreignIndexName']; } if (!empty($column['foreignOnDelete'])) { $column_fkey_constraint['foreignOnDelete'] = strtoupper((string) $column['foreignOnDelete']); } if (!empty($column['foreignOnUpdate'])) { $column_fkey_constraint['foreignOnUpdate'] = strtoupper((string) $column['foreignOnUpdate']); } $constraints[] = $column_fkey_constraint; } } } if ($type == 'all' || $type == 'constraint' || $type == 'check') { foreach ($node_table->column as $column) { // add column check constraints to the list if (isset($column['check'])) { $column_check_constraint = array('name' => $column['name'] . '_check', 'schema_name' => (string) $node_schema['name'], 'table_name' => (string) $node_table['name'], 'type' => 'CHECK', 'definition' => $column['check']); $constraints[] = $column_check_constraint; } } } return $constraints; }