Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/*
3
 *  $Id: Where.php 7672 2010-06-08 20:46:54Z jwage $
4
 *
5
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
6
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
7
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
8
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
9
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
10
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
11
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
12
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
13
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
14
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
15
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16
 *
17
 * This software consists of voluntary contributions made by many individuals
18
 * and is licensed under the LGPL. For more information, see
19
 * <http://www.doctrine-project.org>.
20
 */
21
 
22
/**
23
 * Doctrine_Query_Where
24
 *
25
 * @package     Doctrine
26
 * @subpackage  Query
27
 * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
28
 * @link        www.doctrine-project.org
29
 * @since       1.0
30
 * @version     $Revision: 7672 $
31
 * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
32
 */
33
class Doctrine_Query_Where extends Doctrine_Query_Condition
34
{
35
    public function load($where)
36
    {
37
        // Handle operator ("AND" | "OR"), reducing overhead of this method processment
38
        $possibleOp = strtolower($where);
39
 
40
        if ($possibleOp == 'and' || $possibleOp == 'or')
41
        {
42
            return $where;
43
        }
44
 
45
        $where = $this->_tokenizer->bracketTrim(trim($where));
46
        $conn  = $this->query->getConnection();
47
        $terms = $this->_tokenizer->sqlExplode($where);
48
 
49
        if (count($terms) > 1) {
50
            if (substr($where, 0, 6) == 'EXISTS') {
51
                return $this->parseExists($where, true);
52
            } elseif (preg_match('/^NOT\s+EXISTS\b/i', $where) !== 0) {
53
                return $this->parseExists($where, false);
54
            }
55
        }
56
 
57
        if (count($terms) < 3) {
58
            $terms = $this->_tokenizer->sqlExplode($where, array('=', '<', '<>', '>', '!='));
59
        }
60
 
61
        if (count($terms) > 1) {
62
            $leftExpr = array_shift($terms);
63
            $rightExpr = array_pop($terms);
64
            $operator = trim(substr($where, strlen($leftExpr), -strlen($rightExpr)));
65
 
66
            if (strpos($leftExpr, "'") === false && strpos($leftExpr, '(') === false) {
67
                // normal field reference found
68
                $a = explode('.', $leftExpr);
69
                $fieldname = array_pop($a); // Discard the field name (not needed!)
70
                $reference = implode('.', $a);
71
 
72
                if (empty($reference)) {
73
                    $map = $this->query->getRootDeclaration();
74
                    $alias = $this->query->getSqlTableAlias($this->query->getRootAlias());
75
                } else {
76
                    $map = $this->query->load($reference, false);
77
                    $alias = $this->query->getSqlTableAlias($reference);
78
                }
79
 
80
                // DC-843 Modifiy operator for MSSQL
81
                // @TODO apply database dependent parsing
82
                //       list($leftExpr, $operator, $rightExpr) = $conn->modifyWhereCondition($leftExpr, $operator, $rightExpr);
83
                $driverName = strtolower($conn->getDriverName());
84
                if ($driverName == 'mssql' && !empty($reference)) {
85
                    $cmp = $this->query->getQueryComponent($reference);
86
                    $table = $cmp['table'];
87
 
88
                    /* @var $table Doctrine_Table */
89
                    $column = $table->getColumnName($fieldname);
90
                    $columndef = $table->getColumnDefinition($column);
91
 
92
                    if ($columndef['type'] == 'string' && ($columndef['length'] == NULL || $columndef['length'] > $conn->varchar_max_length)) {
93
                        $operator = 'LIKE';
94
                    }
95
                }
96
            }
97
 
98
            $sql = $this->_buildSql($leftExpr, $operator, $rightExpr);
99
 
100
            return $sql;
101
        } else {
102
            return $where;
103
        }
104
    }
105
 
106
 
107
    protected function _buildSql($leftExpr, $operator, $rightExpr)
108
    {
109
        $leftExprOriginal = $leftExpr;
110
        $leftExpr = $this->query->parseClause($leftExpr);
111
 
112
        // BETWEEN operation
113
        if ('BETWEEN' == strtoupper(substr($operator, 0, 7))) {
114
            $midExpr = trim(substr($operator, 7, -3));
115
            $operator = 'BETWEEN ' . $this->query->parseClause($midExpr) . ' AND';
116
        }
117
 
118
        // NOT BETWEEN operation
119
        if ('NOT BETWEEN' == strtoupper(substr($operator, 0, 11))) {
120
            $midExpr = trim(substr($operator, 11, -3));
121
            $operator = 'NOT BETWEEN ' . $this->query->parseClause($midExpr) . ' AND';
122
        }
123
 
124
        $op = strtolower($operator);
125
        $isInX = ($op == 'in' || $op == 'not in');
126
 
127
        // Check if we are not dealing with "obj.field IN :named"
128
        if (substr($rightExpr, 0 , 1) == ':' && $isInX) {
129
            throw new Doctrine_Query_Exception(
130
                'Cannot use ' . $operator . ' with a named parameter in "' .
131
                $leftExprOriginal . ' ' . $operator . ' ' . $rightExpr . '"'
132
            );
133
        }
134
 
135
        // Right Expression
136
        $rightExpr = ($rightExpr == '?' && $isInX)
137
            ? $this->_buildWhereInArraySqlPart($rightExpr)
138
            : $this->query->parseClause($rightExpr);
139
 
140
        return $leftExpr . ' ' . $operator . ' ' . $rightExpr;
141
    }
142
 
143
 
144
    protected function _buildWhereInArraySqlPart($rightExpr)
145
    {
146
        $params = $this->query->getInternalParams();
147
        $value = array();
148
 
149
        for ($i = 0, $l = count($params); $i < $l; $i++) {
150
            if (is_array($params[$i])) {
151
                $value = array_fill(0, count($params[$i]), $rightExpr);
152
                $this->query->adjustProcessedParam($i);
153
 
154
                break;
155
            }
156
        }
157
 
158
        return '(' . (count($value) > 0 ? implode(', ', $value) : $rightExpr) . ')';
159
    }
160
 
161
    /**
162
     * parses an EXISTS expression
163
     *
164
     * @param string $where         query where part to be parsed
165
     * @param boolean $negation     whether or not to use the NOT keyword
166
     * @return string
167
     */
168
    public function parseExists($where, $negation)
169
    {
170
        $operator = ($negation) ? 'EXISTS' : 'NOT EXISTS';
171
 
172
        $pos = strpos($where, '(');
173
 
174
        if ($pos == false) {
175
            throw new Doctrine_Query_Exception('Unknown expression, expected a subquery with () -marks');
176
        }
177
 
178
        $sub = $this->_tokenizer->bracketTrim(substr($where, $pos));
179
 
180
        $q = $this->query->createSubquery()->parseDqlQuery($sub, false);
181
        $sql = $q->getSqlQuery();
182
        $q->free();
183
 
184
        return $operator . ' (' . $sql . ')';
185
    }
186
}