[dev] Category_sql & PostgreSQL

Jason M. Felice jfelice at cronosys.com
Fri May 30 07:05:24 PDT 2003


Here is a patch that solves the issue with the Category sql
driver <-> PostgreSQL.  It introduces a Horde_SQL::buildTest() method
which can be used to build various comparisons in a database-independent
manner.

I'm not sure how common a boolean '&' operator is for different SQL platforms,
and I'm not sure what Chuck is using, but I coded the PostgreSQL method to
be SQL99-compliant.  Perhaps the case and default should be reversed?

-Jay 'Eraserhead' Felice

Index: SQL.php
===================================================================
RCS file: /repository/horde/lib/SQL.php,v
retrieving revision 1.13
diff -u -u -r1.13 SQL.php
--- SQL.php	28 May 2003 21:22:36 -0000	1.13
+++ SQL.php	30 May 2003 13:47:30 -0000
@@ -204,4 +204,38 @@
         return $dbh->execute($stmt, $values);
     }
 
+    /**
+     * Return a boolean expression using the specified operator.  Uses
+     * database-specific casting, if necessary.
+     *
+     * @access public
+     *
+     * @param         object $db         The database object.
+     * @param         string $lhs        The column or expression to test.
+     * @param         string $op         The operator.
+     * @param         string $rhs        The comparison value.
+     *
+     * @returns string  The SQL test expression.
+     */
+    function buildTest (&$db, $lhs, $op, $rhs)
+    {
+        switch ($op) {
+        case '&':
+            switch ($db->phptype) {
+            case 'pgsql':
+                // This should conform completely to SQL99
+                return sprintf("CASE WHEN CAST(%s AS VARCHAR) SIMILAR TO '(-[0-9]+|[0-9]+)' THEN (CAST(%s AS INTEGER) & %d) <> 0 ELSE FALSE END", $lhs, $lhs, $rhs);
+
+            default:
+                return sprintf('%s & %d', $lhs, $rhs);
+            }
+
+        case 'IN':
+            return sprintf('%s IN %s', $lhs, $rhs);
+
+        default:
+            return sprintf('%s %s %s', $lhs, $op, $db->quote($rhs));
+        }
+    }
+
 }
Index: Category/sql.php
===================================================================
RCS file: /repository/horde/lib/Category/sql.php,v
retrieving revision 1.71
diff -u -u -r1.71 sql.php
--- Category/sql.php	29 May 2003 17:58:50 -0000	1.71
+++ Category/sql.php	30 May 2003 13:47:31 -0000
@@ -623,47 +623,34 @@
     function _buildAttributeQuery($glue, $criteria)
     {
         $clause = '';
-        foreach ($criteria as $key => $vals) {
-            if (!empty($vals['OR']) || !empty($vals['AND'])) {
-                if (!empty($clause)) {
-                    $clause .= ' ' . $glue . ' ';
-                }
-                $clause .= '(' . $this->_buildAttributeQuery($glue, $vals) . ')';
-            } else {
-                if (isset($vals['field'])) {
-                    if (!empty($clause)) {
-                        $clause .= ' ' . $glue . ' ';
-                    }
-                    $value = $this->_quoteByOp($vals['op'], $vals['test']);
-                    $clause .= 'attribute_' . $vals['field'] . ' ' . $vals['op'] . ' ' . $value;
-                } else {
-                    foreach ($vals as $test) {
-                        if (!empty($clause)) {
-                            $clause .= ' ' . $key . ' ';
-                        }
 
-                        $value = $this->_quoteByOp($test['op'], $test['test']);
-                        $clause .= 'attribute_' . $test['field'] . ' ' . $test['op'] . ' ' . $value;
-                    }
+        require_once HORDE_BASE . '/lib/SQL.php';
+
+        foreach ($criteria as $key => $vals) {
+            if (!empty($vals['OR']))
+                $clauses[] = '(' . $this->_buildAttributeQuery('OR', $vals) . ')';
+            elseif (!empty($vals['AND']))
+                $clauses[] = '(' . $this->_buildAttributeQuery('AND', $vals) . ')';
+            else {
+                if (isset($vals['field']))
+                    $clauses[] = Horde_SQL::buildTest(
+                        $this->_db,
+                        'attribute_'.$vals['field'],
+                        $vals['op'],
+                        $vals['test']
+                        );
+                else {
+                    foreach ($vals as $test)
+                        $clauses[] = Horde_SQL::buildTest(
+                            $this->_db,
+                            'attribute_'.$test['field'],
+                            $test['op'],
+                            $test['test']
+                            );
                 }
             }
         }
-
-        return $clause;
-    }
-
-    function _quoteByOp($op, $value)
-    {
-        switch($op) {
-        case '&':
-            return (int)$value;
-
-        case 'IN':
-            return $value;
-
-        default:
-            return $this->_db->quote($value);
-        }
+        return join(' '.$glue.' ',$clauses);
     }
 
     /**


More information about the dev mailing list