/**
  * 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;
 }