]> git.mxchange.org Git - quix0rs-gnu-social.git/commitdiff
Starting on adapting postgresql schema class to look stuff up in the new drupalish...
authorBrion Vibber <brion@pobox.com>
Fri, 8 Oct 2010 23:36:32 +0000 (16:36 -0700)
committerBrion Vibber <brion@pobox.com>
Fri, 8 Oct 2010 23:36:32 +0000 (16:36 -0700)
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.

lib/mysqlschema.php
lib/pgsqlschema.php
lib/schema.php

index 696b2b8d2a0ac0d9815775dc8d89cd157d6e2c07..98e276a40821ce4b91d299b16d3e245c1a16ce14 100644 (file)
@@ -243,29 +243,6 @@ class MysqlSchema extends Schema
         return $this->fetchQueryData($sql);
     }
 
-    /**
-     * 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.
      *
index 2d0f60983618a87ebaa8026b72599e3602faa441..1c6d12b9447de116b6e13f5b2cb4562e9e0c06de 100644 (file)
@@ -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);
+        }
+    }
+
 }
index 5868627ed74e7ff5bfb02bfbd024d249c3171d65..5085ab6fe58ae126899f716c1a788df32f674fcb 100644 (file)
@@ -515,6 +515,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
@@ -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