]> git.mxchange.org Git - quix0rs-gnu-social.git/commitdiff
add some more methods to Schema
authorEvan Prodromou <evan@status.net>
Thu, 1 Oct 2009 19:00:54 +0000 (15:00 -0400)
committerEvan Prodromou <evan@status.net>
Thu, 1 Oct 2009 19:00:54 +0000 (15:00 -0400)
lib/schema.php

index f49075690593476dd3c7814ffc724c200eb93229..056c2093d6594ef6d295004f2ed67a4e8a767f18 100644 (file)
@@ -193,32 +193,161 @@ class Schema
         return true;
     }
 
-    public function createIndex($name, $table, $columns)
+    public function createIndex($table, $columnNames, $name = null)
     {
+        if (!is_array($columnNames)) {
+            $columnNames = array($columnNames);
+        }
+
+        if (empty($name)) {
+            $name = "$table_".implode("_", $columnNames)."_idx";
+        }
+
+        $res =& $this->conn->query("ALTER TABLE $table ADD INDEX $name (".implode(",", $columnNames).")");
+
+        if (PEAR::isError($res)) {
+            throw new Exception($res->getMessage());
+        }
+
+        return true;
     }
 
-    public function dropIndex($name, $table)
+    public function dropIndex($table, $name)
     {
+        $res =& $this->conn->query("ALTER TABLE $table DROP INDEX $name");
+
+        if (PEAR::isError($res)) {
+            throw new Exception($res->getMessage());
+        }
+
+        return true;
     }
 
     public function addColumn($table, $columndef)
     {
+        $sql = "ALTER TABLE $table ADD COLUMN " . $this->_columnSql($columndef);
+
+        $res =& $this->conn->query($sql);
+
+        if (PEAR::isError($res)) {
+            throw new Exception($res->getMessage());
+        }
+
+        return true;
+    }
+
+    public function modifyColumn($table, $columndef)
+    {
+        $sql = "ALTER TABLE $table MODIFY COLUMN " . $this->_columnSql($columndef);
+
+        $res =& $this->conn->query($sql);
+
+        if (PEAR::isError($res)) {
+            throw new Exception($res->getMessage());
+        }
+
+        return true;
+    }
+
+    public function dropColumn($table, $columnName)
+    {
+        $sql = "ALTER TABLE $table DROP COLUMN $columnName";
+
+        $res =& $this->conn->query($sql);
+
+        if (PEAR::isError($res)) {
+            throw new Exception($res->getMessage());
+        }
+
+        return true;
     }
 
-    public function modifyColumn($table, $column, $columndef)
+    public function ensureTable($tableName, $columns, $indices=null)
     {
+        // XXX: DB engine portability -> toilet
+
+        try {
+            $td = $this->getTableDef($tableName);
+        } catch (Exception $e) {
+            if (preg_match('/no such table/', $e->getMessage())) {
+                return $this->createTable($tableName, $columns, $indices);
+            } else {
+                throw $e;
+            }
+        }
+
+        $cur = $this->_names($td->columns);
+        $new = $this->_names($columns);
+
+        $toadd  = array_diff($new, $cur);
+        $todrop = array_diff($cur, $new);
+
+        $same  = array_intersect($new, $cur);
+
+        foreach ($same as $m) {
+            $curCol = $this->_byName($td->columns, $m);
+            $newCol = $this->_byName($columns, $m);
+
+            if (!$newCol->equals($curCol)) {
+                $tomod[] = $newCol->name;
+            }
+        }
+
+        if (count($toadd) + count($todrop) + count($tomod) == 0) {
+            // nothing to do
+            return true;
+        }
+
+        // For efficiency, we want this all in one
+        // query, instead of using our methods.
+
+        $phrase = array();
+
+        foreach ($toadd as $columnName) {
+            $cd = $this->_byName($columns, $columnName);
+            $phrase[] = 'ADD COLUMN ' . $this->_columnSql($cd);
+        }
+
+        foreach ($todrop as $columnName) {
+            $phrase[] = 'DROP COLUMN ' . $columnName;
+        }
+
+        foreach ($tomod as $columnName) {
+            $cd = $this->_byName($columns, $columnName);
+            $phrase[] = 'MODIFY COLUMN ' . $this->_columnSql($cd);
+        }
+
+        $sql = 'ALTER TABLE ' . $tableName . ' ' . implode(', ', $phrase);
+
+        $res =& $this->conn->query($sql);
+
+        if (PEAR::isError($res)) {
+            throw new Exception($res->getMessage());
+        }
+
+        return true;
     }
 
-    public function dropColumn($table, $column)
+    function _names($cds)
     {
+        $names = array();
+
+        foreach ($cds as $cd) {
+            $names[] = $cd->name;
+        }
+
+        return $names;
     }
 
-    public function ensureTable($name, $columns, $indices)
+    function _byName($cds, $name)
     {
-        $def = $this->tableDef($name);
-        if (empty($def)) {
-            return $this->createTable($name, $columns, $indices);
+        foreach ($cds as $cd) {
+            if ($cd->name == $name) {
+                return $cd;
+            }
         }
+
+        return null;
     }
 
     function _columnSql($cd)
@@ -257,16 +386,52 @@ class ColumnDef
     public $default;
     public $extra;
 
-    function __construct($name, $type, $size=null, $nullable=null,
+    function __construct($name, $type, $size=null, $nullable=true,
                          $key=null, $default=null, $extra=null) {
-        $this->name     = $name;
-        $this->type     = $type;
-        $this->size     = $size;
+        $this->name     = strtolower($name);
+        $this->type     = strtolower($type);
+        $this->size     = $size+0;
         $this->nullable = $nullable;
         $this->key      = $key;
         $this->default  = $default;
         $this->extra    = $extra;
     }
+
+    function equals($other)
+    {
+        return ($this->name == $other->name &&
+                $this->_typeMatch($other) &&
+                $this->_defaultMatch($other) &&
+                $this->_nullMatch($other) &&
+                $this->key == $other->key);
+    }
+
+    function _typeMatch($other)
+    {
+        switch ($this->type) {
+         case 'integer':
+         case 'int':
+            return ($other->type == 'integer' ||
+                    $other->type == 'int');
+            break;
+         default:
+            return ($this->type == $other->type &&
+                    $this->size == $other->size);
+        }
+    }
+
+    function _defaultMatch($other)
+    {
+        return ((is_null($this->default) && is_null($other->default)) ||
+                ($this->default == $other->default));
+    }
+
+    function _nullMatch($other)
+    {
+        return ((!is_null($this->default) && !is_null($other->default) &&
+                 $this->default == $other->default) ||
+                ($this->nullable == $other->nullable));
+    }
 }
 
 class IndexDef