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: JoinCondition.php 7490 2010-03-29 19:53:27Z 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_JoinCondition
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: 7490 $
31
 * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
32
 */
33
class Doctrine_Query_JoinCondition extends Doctrine_Query_Condition
34
{
35
    public function load($condition)
36
    {
37
        $condition = trim($condition);
38
        $e = $this->_tokenizer->sqlExplode($condition);
39
 
40
        foreach ($e as $k => $v) {
41
          if ( ! $v) {
42
            unset($e[$k]);
43
          }
44
        }
45
        $e = array_values($e);
46
 
47
        if (($l = count($e)) > 2) {
48
            $leftExpr = $this->query->parseClause($e[0]);
49
            $operator  = $e[1];
50
 
51
            if ($l == 4) {
52
                // FIX: "field NOT IN (XXX)" issue
53
                // Related to ticket #1329
54
                $operator .= ' ' . $e[2]; // Glue "NOT" and "IN"
55
                $e[2] = $e[3]; // Move "(XXX)" to previous index
56
 
57
                unset($e[3]); // Remove unused index
58
            } else if ($l >= 5) {
59
                // FIX: "field BETWEEN field2 AND field3" issue
60
                // Related to ticket #1488
61
                $e[2] .= ' ' . $e[3] . ' ' . $e[4];
62
 
63
                unset($e[3], $e[4]); // Remove unused indexes
64
            }
65
 
66
            if (substr(trim($e[2]), 0, 1) != '(') {
67
                $expr = new Doctrine_Expression($e[2], $this->query->getConnection());
68
                $e[2] = $expr->getSql();
69
            }
70
 
71
            // We need to check for agg functions here
72
            $rightMatches = array();
73
            $hasRightAggExpression = $this->_processPossibleAggExpression($e[2], $rightMatches);
74
 
75
            // Defining needed information
76
            $value = $e[2];
77
 
78
            if (substr($value, 0, 1) == '(') {
79
                // trim brackets
80
                $trimmed   = $this->_tokenizer->bracketTrim($value);
81
                $trimmed_upper = strtoupper($trimmed);
82
 
83
                if (substr($trimmed_upper, 0, 4) == 'FROM' || substr($trimmed_upper, 0, 6) == 'SELECT') {
84
                    // subquery found
85
                    $q = $this->query->createSubquery()
86
                        ->parseDqlQuery($trimmed, false);
87
                    $value   = '(' . $q->getSqlQuery() . ')';
88
                    $q->free();
89
                } elseif (substr($trimmed_upper, 0, 4) == 'SQL:') {
90
                    // Change due to bug "(" XXX ")"
91
                    //$value = '(' . substr($trimmed, 4) . ')';
92
                    $value = substr($trimmed, 4);
93
                } else {
94
                    // simple in expression found
95
                    $e = $this->_tokenizer->sqlExplode($trimmed, ',');
96
                    $value = array();
97
 
98
                    foreach ($e as $part) {
99
                        $value[] = $this->parseLiteralValue($part);
100
                    }
101
 
102
                    $value = '(' . implode(', ', $value) . ')';
103
                }
104
            } elseif ( ! $hasRightAggExpression) {
105
                // Possible expression found (field1 AND field2)
106
                // In relation to ticket #1488
107
                $e     = $this->_tokenizer->bracketExplode($value, array(' AND ', ' \&\& '), '(', ')');
108
                $value = array();
109
 
110
                foreach ($e as $part) {
111
                    $value[] = $this->parseLiteralValue($part);
112
                }
113
 
114
                $value = implode(' AND ', $value);
115
            }
116
 
117
            if ($hasRightAggExpression) {
118
                $rightExpr = $rightMatches[1] . '(' . $value . ')' . $rightMatches[3];
119
                $rightExpr = $this->query->parseClause($rightExpr);
120
            } else {
121
                $rightExpr = $value;
122
            }
123
 
124
            $condition  = $leftExpr . ' ' . $operator . ' ' . $rightExpr;
125
 
126
            return $condition;
127
        }
128
 
129
        $parser = new Doctrine_Query_Where($this->query, $this->_tokenizer);
130
 
131
        return $parser->parse($condition);
132
    }
133
 
134
 
135
    protected function _processPossibleAggExpression(& $expr, & $matches = array())
136
    {
137
        $hasAggExpr = preg_match('/(.*[^\s\(\=])\(([^\)]*)\)(.*)/', $expr, $matches);
138
 
139
        if ($hasAggExpr) {
140
            $expr = $matches[2];
141
 
142
            // We need to process possible comma separated items
143
            if (substr(trim($matches[3]), 0, 1) == ',') {
144
                $xplod = $this->_tokenizer->sqlExplode(trim($matches[3], ' )'), ',');
145
 
146
                $matches[3] = array();
147
 
148
                foreach ($xplod as $part) {
149
                    if ($part != '') {
150
                        $matches[3][] = $this->parseLiteralValue($part);
151
                    }
152
                }
153
 
154
                $matches[3] = '), ' . implode(', ', $matches[3]);
155
            }
156
        }
157
 
158
        return $hasAggExpr;
159
    }
160
}