summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrion Vibber <brion@pobox.com>2010-10-08 16:36:32 -0700
committerBrion Vibber <brion@pobox.com>2010-10-08 16:36:32 -0700
commit2d0807bc1c72c1351f57d7f65386ad7be9d19e83 (patch)
tree158de9dbf8294a3989c576023572aa0bf7ce912d
parentefa8ff82f4a364f6ba183a683431e9d83652cd9f (diff)
Starting on adapting postgresql schema class to look stuff up in the new drupalish format...
Fetching basic column data and unique indexes. Still needs detail work, multi-value indexes, foreign keys, and distinguishing the primary key. Since we don't get comments and such, for cleaner comparisons we should probably do a filtering on supported features.
-rw-r--r--lib/mysqlschema.php23
-rw-r--r--lib/pgsqlschema.php131
-rw-r--r--lib/schema.php35
3 files changed, 135 insertions, 54 deletions
diff --git a/lib/mysqlschema.php b/lib/mysqlschema.php
index 696b2b8d2..98e276a40 100644
--- a/lib/mysqlschema.php
+++ b/lib/mysqlschema.php
@@ -244,29 +244,6 @@ class MysqlSchema extends Schema
}
/**
- * Pull info from the query into a fun-fun array of dooooom
- *
- * @param string $sql
- * @return array of arrays
- */
- protected function fetchQueryData($sql)
- {
- $res = $this->conn->query($sql);
- if (PEAR::isError($res)) {
- throw new Exception($res->getMessage());
- }
-
- $out = array();
- $row = array();
- while ($res->fetchInto($row, DB_FETCHMODE_ASSOC)) {
- $out[] = $row;
- }
- $res->free();
-
- return $out;
- }
-
- /**
* Creates a table with the given names and columns.
*
* @param string $name Name of the table
diff --git a/lib/pgsqlschema.php b/lib/pgsqlschema.php
index 2d0f60983..1c6d12b94 100644
--- a/lib/pgsqlschema.php
+++ b/lib/pgsqlschema.php
@@ -42,6 +42,7 @@ if (!defined('STATUSNET')) {
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @author Brenda Wallace <shiny@cpan.org>
+ * @author Brion Vibber <brion@status.net>
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*/
@@ -50,57 +51,104 @@ class PgsqlSchema extends Schema
{
/**
- * Returns a TableDef object for the table
+ * Returns a table definition array for the table
* in the schema with the given name.
*
* Throws an exception if the table is not found.
*
- * @param string $name Name of the table to get
+ * @param string $table Name of the table to get
*
- * @return TableDef tabledef for that table.
+ * @return array tabledef for that table.
*/
- public function getTableDef($name)
+ public function getTableDef($table)
{
- $res = $this->conn->query("SELECT *, column_default as default, is_nullable as Null,
- udt_name as Type, column_name AS Field from INFORMATION_SCHEMA.COLUMNS where table_name = '$name'");
+ $def = array();
+ $hasKeys = false;
- if (PEAR::isError($res)) {
- throw new Exception($res->getMessage());
+ // Pull column data from INFORMATION_SCHEMA
+ $columns = $this->fetchMetaInfo($table, 'columns', 'ordinal_position');
+ if (count($columns) == 0) {
+ throw new SchemaTableMissingException("No such table: $table");
}
- $td = new TableDef();
+ foreach ($columns as $row) {
- $td->name = $name;
- $td->columns = array();
-
- if ($res->numRows() == 0 ) {
- throw new Exception('no such table'); //pretend to be the msyql error. yeah, this sucks.
- }
- $row = array();
+ $name = $row['column_name'];
+ $field = array();
- while ($res->fetchInto($row, DB_FETCHMODE_ASSOC)) {
- $cd = new ColumnDef();
+ // ??
+ list($type, $size) = $this->reverseMapType($row['udt_name']);
+ $field['type'] = $type;
+ if ($size !== null) {
+ $field['size'] = $size;
+ }
- $cd->name = $row['field'];
+ if ($type == 'char' || $type == 'varchar') {
+ if ($row['character_maximum_length'] !== null) {
+ $field['length'] = intval($row['character_maximum_length']);
+ }
+ }
+ if ($type == 'numeric') {
+ // Other int types may report these values, but they're irrelevant.
+ // Just ignore them!
+ if ($row['numeric_precision'] !== null) {
+ $field['precision'] = intval($row['numeric_precision']);
+ }
+ if ($row['numeric_scale'] !== null) {
+ $field['scale'] = intval($row['numeric_scale']);
+ }
+ }
+ if ($row['is_nullable'] == 'NO') {
+ $field['not null'] = true;
+ }
+ if ($row['column_default'] !== null) {
+ $field['default'] = $row['column_default'];
+ if ($this->isNumericType($type)) {
+ $field['default'] = intval($field['default']);
+ }
+ }
- $packed = $row['type'];
+ $def['fields'][$name] = $field;
+ }
- if (preg_match('/^(\w+)\((\d+)\)$/', $packed, $match)) {
- $cd->type = $match[1];
- $cd->size = $match[2];
- } else {
- $cd->type = $packed;
+ // Pull constraint data from INFORMATION_SCHEMA
+ // @fixme also find multi-val indexes
+ // @fixme distinguish the primary key
+ // @fixme pull foreign key references
+ $keyColumns = $this->fetchMetaInfo($table, 'key_column_usage', 'constraint_name,ordinal_position');
+ $keys = array();
+
+ foreach ($keyColumns as $row) {
+ $keyName = $row['constraint_name'];
+ $keyCol = $row['column_name'];
+ if (!isset($keys[$keyName])) {
+ $keys[$keyName] = array();
}
+ $keys[$keyName][] = $keyCol;
+ }
- $cd->nullable = ($row['null'] == 'YES') ? true : false;
- $cd->key = $row['Key'];
- $cd->default = $row['default'];
- $cd->extra = $row['Extra'];
+ foreach ($keys as $keyName => $cols) {
+ $def['unique indexes'][$keyName] = $cols;
+ }
+ return $def;
+ }
- $td->columns[] = $cd;
+ /**
+ * Pull some INFORMATION.SCHEMA data for the given table.
+ *
+ * @param string $table
+ * @return array of arrays
+ */
+ function fetchMetaInfo($table, $infoTable, $orderBy=null)
+ {
+ $query = "SELECT * FROM information_schema.%s " .
+ "WHERE table_name='%s'";
+ $sql = sprintf($query, $infoTable, $table);
+ if ($orderBy) {
+ $sql .= ' ORDER BY ' . $orderBy;
}
- return $td;
+ return $this->fetchQueryData($sql);
}
/**
@@ -360,4 +408,25 @@ class PgsqlSchema extends Schema
}
}
+ /**
+ * Map a native type back to an independent type + size
+ *
+ * @param string $type
+ * @return array ($type, $size) -- $size may be null
+ */
+ protected function reverseMapType($type)
+ {
+ $type = strtolower($type);
+ $map = array(
+ 'int4' => array('int', null),
+ 'int8' => array('int', 'big'),
+ 'bytea' => array('blob', null),
+ );
+ if (isset($map[$type])) {
+ return $map[$type];
+ } else {
+ return array($type, null);
+ }
+ }
+
}
diff --git a/lib/schema.php b/lib/schema.php
index 5868627ed..5085ab6fe 100644
--- a/lib/schema.php
+++ b/lib/schema.php
@@ -516,6 +516,17 @@ class Schema
}
/**
+ * Map a native type back to an independent type + size
+ *
+ * @param string $type
+ * @return array ($type, $size) -- $size may be null
+ */
+ protected function reverseMapType($type)
+ {
+ return array($type, null);
+ }
+
+ /**
* Convert an old-style set of ColumnDef objects into the current
* Drupal-style schema definition array, for backwards compatibility
* with plugins written for 0.9.x.
@@ -590,6 +601,30 @@ class Schema
$known = array('int', 'serial', 'numeric');
return in_array($type, $known);
}
+
+ /**
+ * Pull info from the query into a fun-fun array of dooooom
+ *
+ * @param string $sql
+ * @return array of arrays
+ */
+ protected function fetchQueryData($sql)
+ {
+ $res = $this->conn->query($sql);
+ if (PEAR::isError($res)) {
+ throw new Exception($res->getMessage());
+ }
+
+ $out = array();
+ $row = array();
+ while ($res->fetchInto($row, DB_FETCHMODE_ASSOC)) {
+ $out[] = $row;
+ }
+ $res->free();
+
+ return $out;
+ }
+
}
class SchemaTableMissingException extends Exception