basic horde_rdo functionality works on top of horde_db
authorChuck Hagenbuch <chuck@horde.org>
Sat, 10 Jan 2009 16:57:39 +0000 (11:57 -0500)
committerChuck Hagenbuch <chuck@horde.org>
Sat, 10 Jan 2009 16:57:39 +0000 (11:57 -0500)
framework/Rdo/lib/Horde/Rdo/List.php
framework/Rdo/lib/Horde/Rdo/Mapper.php
framework/Rdo/lib/Horde/Rdo/Query.php
framework/Rdo/lib/Horde/Rdo/Query/Builder.php [deleted file]
framework/Rdo/lib/Horde/Rdo/Query/Literal.php
framework/Rdo/package.xml

index b8b56ad..212878e 100644 (file)
@@ -1,7 +1,7 @@
 <?php
 /**
  * @category Horde
- * @package Horde_Rdo
+ * @package  Horde_Rdo
  */
 
 /**
  * @TODO implement ArrayAccess as well?
  *
  * @category Horde
- * @package Horde_Rdo
+ * @package  Horde_Rdo
  */
-class Horde_Rdo_List implements Iterator {
-
+class Horde_Rdo_List implements Iterator
+{
     /**
      * Rdo Mapper
      * @var Horde_Rdo_Mapper
@@ -79,7 +79,7 @@ class Horde_Rdo_List implements Iterator {
 
             // Convert the query into a SQL statement and an array of
             // bind parameters.
-            list($this->_sql, $this->_bindParams) = $mapper->adapter->dml->getQuery($query);
+            list($this->_sql, $this->_bindParams) = $query->getQuery();
         } elseif (is_string($query)) {
             // Straight SQL query, empty bind parameters array.
             $this->_sql = $query;
index 9ad1208..e386c2e 100644 (file)
@@ -3,7 +3,7 @@
  * Rdo Mapper base class.
  *
  * @category Horde
- * @package Horde_Rdo
+ * @package  Horde_Rdo
  */
 
 /**
  *   the main table of this entity.
  *
  * @category Horde
- * @package Horde_Rdo
+ * @package  Horde_Rdo
  */
-abstract class Horde_Rdo_Mapper implements Countable {
-
+abstract class Horde_Rdo_Mapper implements Countable
+{
     /**
      * If this is true and fields named created and updated are
      * present, Rdo will automatically set creation and last updated
@@ -130,9 +130,11 @@ abstract class Horde_Rdo_Mapper implements Countable {
             return $this->table;
 
         case 'tableDefinition':
+            $this->tableDefinition = $this->adapter->table($this->table);
+            return $this->tableDefinition;
 
         case 'fields':
-            $this->fields = array_diff($this->model->listFields(), $this->_lazyFields);
+            $this->fields = array_diff($this->tableDefinition->getColumnNames(), $this->_lazyFields);
             return $this->fields;
 
         case 'lazyFields':
@@ -219,8 +221,8 @@ abstract class Horde_Rdo_Mapper implements Countable {
                     }
                 }
 
-                if (isset($relationships[$m->model->table])) {
-                    $o->$relationship = $m->map($relationships[$m->model->table]);
+                if (isset($relationships[$m->table])) {
+                    $o->$relationship = $m->map($relationships[$m->table]);
                 }
             }
         }
@@ -283,8 +285,8 @@ abstract class Horde_Rdo_Mapper implements Countable {
         $query = Horde_Rdo_Query::create($query, $this);
         $query->setFields('COUNT(*)')
               ->clearSort();
-        list($sql, $bindParams) = $this->adapter->dml->getCount($query);
-        return $this->adapter->selectOne($sql, $bindParams);
+        list($sql, $bindParams) = $query->getQuery();
+        return $this->adapter->selectValue($sql, $bindParams);
     }
 
     /**
@@ -300,8 +302,8 @@ abstract class Horde_Rdo_Mapper implements Countable {
         $query = Horde_Rdo_Query::create($query, $this);
         $query->setFields(1)
               ->clearSort();
-        list($sql, $bindParams) = $this->adapter->dml->getQuery($query);
-        return (bool)$this->adapter->selectOne($sql, $bindParams);
+        list($sql, $bindParams) = $query->getQuery();
+        return (bool)$this->adapter->selectValue($sql, $bindParams);
     }
 
     /**
@@ -323,7 +325,7 @@ abstract class Horde_Rdo_Mapper implements Countable {
         }
 
         // Filter out any extra fields.
-        $fields = array_intersect_key($fields, $this->model->getFields());
+        $fields = array_intersect_key($fields, $this->tableDefinition->getColumnNames());
 
         if (!$fields) {
             throw new Horde_Rdo_Exception('create() requires at least one field value.');
@@ -342,7 +344,7 @@ abstract class Horde_Rdo_Mapper implements Countable {
 
         $id = $this->adapter->insert($sql, $bindParams);
 
-        return $this->map(array_merge(array($this->model->key => $id),
+        return $this->map(array_merge(array($this->tableDefinition->getPrimaryKey() => $id),
                                       $fields));
     }
 
@@ -361,7 +363,7 @@ abstract class Horde_Rdo_Mapper implements Countable {
     public function update($object, $fields = null)
     {
         if ($object instanceof Horde_Rdo_Base) {
-            $key = $this->model->key;
+            $key = $this->tableDefinition->getPrimaryKey();
             $id = $object->$key;
             $fields = iterator_to_array($object);
 
@@ -380,7 +382,7 @@ abstract class Horde_Rdo_Mapper implements Countable {
         }
 
         // Filter out any extra fields.
-        $fields = array_intersect_key($fields, $this->model->getFields());
+        $fields = array_intersect_key($fields, $this->tableDefinition->getColumnNames());
 
         if (!$fields) {
             // Nothing to change.
@@ -393,7 +395,7 @@ abstract class Horde_Rdo_Mapper implements Countable {
             $sql .= ' ' . $this->adapter->quoteColumnName($field) . ' = ?,';
             $bindParams[] = $value;
         }
-        $sql = substr($sql, 0, -1) . ' WHERE ' . $this->model->key . ' = ?';
+        $sql = substr($sql, 0, -1) . ' WHERE ' . $this->tableDefinition->getPrimaryKey() . ' = ?';
         $bindParams[] = $id;
 
         return $this->adapter->update($sql, $bindParams);
@@ -411,13 +413,13 @@ abstract class Horde_Rdo_Mapper implements Countable {
     public function delete($object)
     {
         if ($object instanceof Horde_Rdo_Base) {
-            $key = $this->model->key;
+            $key = $this->tableDefinition->getPrimaryKey();
             $id = $object->$key;
             $query = array($key => $id);
         } elseif ($object instanceof Horde_Rdo_Query) {
             $query = $object;
         } else {
-            $key = $this->model->key;
+            $key = $this->tableDefinition->getPrimaryKey();
             $query = array($key => $object);
         }
 
@@ -467,7 +469,7 @@ abstract class Horde_Rdo_Mapper implements Countable {
             if (is_numeric(key($arg))) {
                 // Numerically indexed arrays are assumed to be an array of
                 // primary keys.
-                $key = $this->model->key;
+                $key = $this->tableDefinition->getPrimaryKey();
                 $query = new Horde_Rdo_Query();
                 $query->combineWith('OR');
                 foreach ($argv[0] as $id) {
@@ -505,7 +507,7 @@ abstract class Horde_Rdo_Mapper implements Countable {
         if (is_null($arg)) {
             $query = null;
         } elseif (is_scalar($arg)) {
-            $query = array($this->model->key => $arg);
+            $query = array($this->tableDefinition->getPrimaryKey() => $arg);
         } else {
             $query = $arg;
         }
index 5ed2353..558778c 100644 (file)
@@ -3,15 +3,15 @@
  * Represent a single query or a tree of many query elements uniformly to clients.
  *
  * @category Horde
- * @package Horde_Rdo
+ * @package  Horde_Rdo
  */
 
 /**
  * @category Horde
- * @package Horde_Rdo
+ * @package  Horde_Rdo
  */
-class Horde_Rdo_Query {
-
+class Horde_Rdo_Query
+{
     /**
      * @var Horde_Rdo_Mapper
      */
@@ -77,7 +77,7 @@ class Horde_Rdo_Query {
         $q = new Horde_Rdo_Query($mapper);
 
         if (is_scalar($query)) {
-            $q->addTest($mapper->model->key, '=', $query);
+            $q->addTest($mapper->tableDefinition->getPrimaryKey(), '=', $query);
         } elseif ($query) {
             $q->combineWith('AND');
             foreach ($query as $key => $value) {
@@ -110,7 +110,7 @@ class Horde_Rdo_Query {
         $this->mapper = $mapper;
 
         // Fetch all non-lazy-loaded fields for the mapper.
-        $this->setFields($mapper->fields, $mapper->model->table . '.');
+        $this->setFields($mapper->fields, $mapper->table . '.');
 
         if (!is_null($mapper)) {
             // Add all non-lazy relationships.
@@ -125,7 +125,7 @@ class Horde_Rdo_Query {
                 }
 
                 // Add the fields for this relationship to the query.
-                $this->addFields($m->fields, $m->model->table . '.@');
+                $this->addFields($m->fields, $m->table . '.@');
 
                 switch ($rel['type']) {
                 case Horde_Rdo::ONE_TO_ONE:
@@ -133,7 +133,7 @@ class Horde_Rdo_Query {
                     if (isset($rel['query'])) {
                         $query = $this->_fillJoinPlaceholders($m, $mapper, $rel['query']);
                     } else {
-                        $query = array($mapper->model->table . '.' . $rel['foreignKey'] => new Horde_Rdo_Query_Literal($m->model->table . '.' . $m->model->key));
+                        $query = array($mapper->table . '.' . $rel['foreignKey'] => new Horde_Rdo_Query_Literal($m->table . '.' . $m->tableDefinition->getPrimaryKey()));
                     }
                     $this->addRelationship($relationship, array('mapper' => $m,
                                                                 'type' => $rel['type'],
@@ -203,7 +203,7 @@ class Horde_Rdo_Query {
             throw new InvalidArgumentException('Relationships must contain a Horde_Rdo_Mapper object.');
         }
         if (!isset($args['table'])) {
-            $args['table'] = $args['mapper']->model->table;
+            $args['table'] = $args['mapper']->table;
         }
         if (!isset($args['type'])) {
             $args['type'] = Horde_Rdo::MANY_TO_MANY;
@@ -277,6 +277,138 @@ class Horde_Rdo_Query {
     }
 
     /**
+     * Query generator.
+     *
+     * @return array A two-element array of the SQL query and an array
+     * of bind parameters.
+     */
+    public function getQuery()
+    {
+        $bindParams = array();
+        $sql = '';
+
+        $this->_select($sql, $bindParams);
+        $this->_from($sql, $bindParams);
+        $this->_join($sql, $bindParams);
+        $this->_where($sql, $bindParams);
+        $this->_orderBy($sql, $bindParams);
+        $this->_limit($sql, $bindParams);
+
+        return array($sql, $bindParams);
+    }
+
+    /**
+     */
+    protected function _select(&$sql, &$bindParams)
+    {
+        $fields = array();
+        foreach ($this->fields as $field) {
+            $parts = explode('.@', $field, 2);
+            if (count($parts) == 1) {
+                $fields[] = $field;
+            } else {
+                $fields[] = str_replace('.@', '.', $field) . ' AS ' . $this->mapper->adapter->quoteColumnName($parts[0] . '@' . $parts[1]);
+            }
+        }
+
+        $sql = 'SELECT ' . implode(', ', $fields);
+    }
+
+    /**
+     */
+    protected function _from(&$sql, &$bindParams)
+    {
+        $sql .= ' FROM ' . $this->mapper->table;
+    }
+
+    /**
+     */
+    protected function _join(&$sql, &$bindParams)
+    {
+        foreach ($this->relationships as $relationship) {
+            $relsql = array();
+            foreach ($relationship['query'] as $key => $value) {
+                if ($value instanceof Horde_Rdo_Query_Literal) {
+                    $relsql[] = $key . ' = ' . (string)$value;
+                } else {
+                    $relsql[] = $key . ' = ?';
+                    $bindParams[] = $value;
+                }
+            }
+
+            $sql .= ' ' . $relationship['join_type'] . ' ' . $relationship['table'] . ' ON ' . implode(' AND ', $relsql);
+        }
+    }
+
+    /**
+     */
+    protected function _where(&$sql, &$bindParams)
+    {
+        $clauses = array();
+        foreach ($this->tests as $test) {
+            if (strpos($test['field'], '@') !== false) {
+                list($rel, $field) = explode('@', $test['field']);
+                if (!isset($this->relationships[$rel])) {
+                    continue;
+                }
+                $clause = $this->relationships[$rel]['table'] . '.' . $field . ' ' . $test['test'];
+            } else {
+                $clause = $this->mapper->table . '.' . $this->mapper->adapter->quoteColumnName($test['field']) . ' ' . $test['test'];
+            }
+
+            if ($test['value'] instanceof Horde_Rdo_Query_Literal) {
+                $clauses[] = $clause . ' ' . (string)$test['value'];
+            } else {
+                if ($test['test'] == 'IN' && is_array($test['value'])) {
+                    $clauses[] = $clause . '(?' . str_repeat(',?', count($test['value']) - 1) . ')';
+                    $bindParams = array_merge($bindParams, array_values($test['value']));
+                } else {
+                    $clauses[] = $clause . ' ?';
+                    $bindParams[] = $test['value'];
+                }
+            }
+        }
+
+        if ($clauses) {
+            $sql .= ' WHERE ' . implode(' ' . $this->conjunction . ' ', $clauses);
+        }
+    }
+
+    /**
+     */
+    protected function _orderBy(&$sql, &$bindParams)
+    {
+        if ($this->sortby) {
+            $sql .= ' ORDER BY';
+            foreach ($this->sortby as $sort) {
+                if (strpos($sort, '@') !== false) {
+                    /* @TODO parse these placeholders out, or drop them */
+                    list($field, $direction) = $sort;
+                    list($rel, $field) = explode('@', $field);
+                    if (!isset($this->relationships[$rel])) {
+                        continue;
+                    }
+                    $sql .= ' ' . $this->relationships[$rel]['table'] . '.' . $field . ' ' . $direction . ',';
+                } else {
+                    $sql .= " $sort,";
+                }
+            }
+
+            $sql = substr($sql, 0, -1);
+        }
+    }
+
+    /**
+     */
+    protected function _limit(&$sql, &$bindParams)
+    {
+        if ($this->limit) {
+            $opts = array('limit' => $this->limit, 'offset' => $this->limitOffset);
+            $sql = $this->mapper->adapter->addLimitOffset($sql, $opts);
+        }
+    }
+
+    /**
      * Callback for array_walk to prefix all elements of an array with
      * a given prefix.
      */
@@ -301,9 +433,9 @@ class Horde_Rdo_Query {
         foreach (array_keys($query) as $field) {
             $value = $query[$field];
             if (preg_match('/^@(.*)@$/', $value, $matches)) {
-                $q[$m1->model->table . '.' . $field] = new Horde_Rdo_Query_Literal($m2->model->table . '.' . $matches[1]);
+                $q[$m1->table . '.' . $field] = new Horde_Rdo_Query_Literal($m2->table . '.' . $matches[1]);
             } else {
-                $q[$m1->model->table . '.' . $field] = $value;
+                $q[$m1->table . '.' . $field] = $value;
             }
         }
 
diff --git a/framework/Rdo/lib/Horde/Rdo/Query/Builder.php b/framework/Rdo/lib/Horde/Rdo/Query/Builder.php
deleted file mode 100644 (file)
index 1623e06..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-<?php
-/**
- * @category Horde
- * @package Horde_Rdo
- */
-
-/**
- * Horde_Rdo query building abstract base
- *
- * @category Horde
- * @package Horde_Rdo
- */
-abstract class Horde_Rdo_Query_Builder {
-
-    /**
-     */
-    public function getCount($query)
-    {
-        return $this->getQuery($query);
-    }
-
-    /**
-     * Query generator.
-     *
-     * @param Horde_Rdo_Query $query The query object to turn into SQL.
-     *
-     * @return array A two-element array of the SQL query and an array
-     * of bind parameters.
-     */
-    public function getQuery($query)
-    {
-        if ($query instanceof Horde_Rdo_Query_Literal) {
-            return array((string)$query, array());
-        }
-
-        $bindParams = array();
-        $sql = '';
-
-        $this->_select($query, $sql, $bindParams);
-        $this->_from($query, $sql, $bindParams);
-        $this->_join($query, $sql, $bindParams);
-        $this->_where($query, $sql, $bindParams);
-        $this->_orderBy($query, $sql, $bindParams);
-        $this->_limit($query, $sql, $bindParams);
-
-        return array($sql, $bindParams);
-    }
-
-    /**
-     * Return the database-specific version of a test.
-     *
-     * @param string $test The test to "localize"
-     */
-    public function getTest($test)
-    {
-        return $test;
-    }
-
-    /**
-     */
-    protected function _select($query, &$sql, &$bindParams)
-    {
-        $fields = array();
-        foreach ($query->fields as $field) {
-            $parts = explode('.@', $field, 2);
-            if (count($parts) == 1) {
-                $fields[] = $field;
-            } else {
-                $fields[] = str_replace('.@', '.', $field) . ' AS ' . $query->mapper->adapter->quoteColumnName($parts[0] . '@' . $parts[1]);
-            }
-        }
-
-        $sql = 'SELECT ' . implode(', ', $fields);
-    }
-
-    /**
-     */
-    protected function _from($query, &$sql, &$bindParams)
-    {
-        $sql .= ' FROM ' . $query->mapper->model->table;
-    }
-
-    /**
-     */
-    protected function _join($query, &$sql, &$bindParams)
-    {
-        foreach ($query->relationships as $relationship) {
-            $relsql = array();
-            foreach ($relationship['query'] as $key => $value) {
-                if ($value instanceof Horde_Rdo_Query_Literal) {
-                    $relsql[] = $key . ' = ' . (string)$value;
-                } else {
-                    $relsql[] = $key . ' = ?';
-                    $bindParams[] = $value;
-                }
-            }
-
-            $sql .= ' ' . $relationship['join_type'] . ' ' . $relationship['table'] . ' ON ' . implode(' AND ', $relsql);
-        }
-    }
-
-    /**
-     */
-    protected function _where($query, &$sql, &$bindParams)
-    {
-        $clauses = array();
-        foreach ($query->tests as $test) {
-            if (strpos($test['field'], '@') !== false) {
-                list($rel, $field) = explode('@', $test['field']);
-                if (!isset($query->relationships[$rel])) {
-                    continue;
-                }
-                $clause = $query->relationships[$rel]['table'] . '.' . $field . ' ' . $this->getTest($test['test']);
-            } else {
-                $clause = $query->mapper->model->table . '.' . $query->mapper->adapter->quoteColumnName($test['field']) . ' ' . $this->getTest($test['test']);
-            }
-
-            if ($test['value'] instanceof Horde_Rdo_Query_Literal) {
-                $clauses[] = $clause . ' ' . (string)$test['value'];
-            } else {
-                if ($test['test'] == 'IN' && is_array($test['value'])) {
-                    $clauses[] = $clause . '(?' . str_repeat(',?', count($test['value']) - 1) . ')';
-                    $bindParams = array_merge($bindParams, array_values($test['value']));
-                } else {
-                    $clauses[] = $clause . ' ?';
-                    $bindParams[] = $test['value'];
-                }
-            }
-        }
-
-        if ($clauses) {
-            $sql .= ' WHERE ' . implode(' ' . $query->conjunction . ' ', $clauses);
-        }
-    }
-
-    /**
-     */
-    protected function _orderBy($query, &$sql, &$bindParams)
-    {
-        if ($query->sortby) {
-            $sql .= ' ORDER BY';
-            foreach ($query->sortby as $sort) {
-                if (strpos($sort, '@') !== false) {
-                    /*@TODO parse these placeholders out, or drop them*/
-                    list($field, $direction) = $sort;
-                    list($rel, $field) = explode('@', $field);
-                    if (!isset($query->relationships[$rel])) {
-                        continue;
-                    }
-                    $sql .= ' ' . $query->relationships[$rel]['table'] . '.' . $field . ' ' . $direction . ',';
-                } else {
-                    $sql .= " $sort,";
-                }
-            }
-
-            $sql = substr($sql, 0, -1);
-        }
-    }
-
-    /**
-     */
-    protected function _limit($query, &$sql, &$bindParams)
-    {
-        if ($query->limit) {
-            $sql .= ' LIMIT ' . $query->limit;
-            if (!is_null($query->limitOffset)) {
-                $sql .= ' OFFSET ' . $query->limitOffset;
-            }
-        }
-    }
-
-}
index 1703e77..035a4f8 100644 (file)
@@ -1,7 +1,7 @@
 <?php
 /**
  * @category Horde
- * @package Horde_Rdo
+ * @package  Horde_Rdo
  */
 
 /**
  *   $literal = new Horde_Rdo_Query_Literal('MAX(column_name)');
  *
  * @category Horde
- * @package Horde_Rdo
+ * @package  Horde_Rdo
  */
-class Horde_Rdo_Query_Literal {
-
+class Horde_Rdo_Query_Literal
+{
     /**
      * SQL literal string.
      *
@@ -56,16 +56,12 @@ class Horde_Rdo_Query_Literal {
 
     /**
      * @param Horde_Rdo_Mapper $mapper Rdo mapper base class
-     *
-     * @return Horde_Rdo_Query Return the query object for fluent chaining.
      */
     public function setMapper($mapper)
     {
-        if ($mapper === $this->mapper) {
-            return $this;
+        if ($mapper !== $this->mapper) {
+            $this->mapper = $mapper;
         }
-
-        $this->mapper = $mapper;
     }
 
 }
index 5ca5fa3..0c77330 100644 (file)
@@ -33,7 +33,6 @@ http://pear.php.net/dtd/package-2.0.xsd">
     <dir name="Horde">
      <dir name="Rdo">
       <dir name="Query">
-       <file name="Builder.php" role="php" />
        <file name="Literal.php" role="php" />
       </dir> <!-- /lib/Horde/Rdo/Query -->
       <file name="Base.php" role="php" />
@@ -59,7 +58,6 @@ http://pear.php.net/dtd/package-2.0.xsd">
  </dependencies>
  <phprelease>
   <filelist>
-   <install name="lib/Horde/Rdo/Query/Builder.php" as="Horde/Rdo/Query/Builder.php" />
    <install name="lib/Horde/Rdo/Query/Literal.php" as="Horde/Rdo/Query/Literal.php" />
    <install name="lib/Horde/Rdo/Base.php" as="Horde/Rdo/Base.php" />
    <install name="lib/Horde/Rdo/Iterator.php" as="Horde/Rdo/Iterator.php" />