Completed
Push — master ( 790ba1...b96a42 )
by Auke
121:15 queued 112:29
created

postgresql_compiler::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 2
dl 0
loc 5
ccs 5
cts 5
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
include($this->code."stores/modules/sql_compiler.php");
3
4
class postgresql_compiler extends sql_compiler {
5
	protected $tbl_prefix;
6
	protected $in_orderby;
7
	protected $nls_join;
8
	protected $select_tables;
9
	protected $used_tables;
10
	protected $custom_id;
11
	protected $custom_ref;
12
	protected $used_custom_fields;
13
	protected $where_s_ext;
14
	protected $where_s;
15
	protected $limit_s;
16
	protected $orderby_s;
17
	protected $select_list;
18
19 14
	function __construct(&$store, $tbl_prefix="") {
20 14
		debug("postgresql_compiler($tbl_prefix)", "store");
21 14
		$this->tbl_prefix=$tbl_prefix;
22 14
		$this->store=$store;
23 14
	}
24
25 14
	function test_for_lowercase(&$node){
26 14
		$ret = false;
27 14
		switch ((string)$node["id"]) {
28 14
			case 'ident':
29
				if ( $node["table"] == "nodes" ) {
30
					if ( $node["field"] == "path" or $node["field"] == "parent" ) {
31
						$ret = true;
32
					}
33
				}
34
				break;
35
		}
36 14
		return $ret;
37
	}
38
39 14
	function compile_tree(&$node) {
40 14
		switch ((string)$node["id"]) {
41 14
			case 'property':
42 14
				$table=$this->tbl_prefix.$node["table"];
43 14
				$field=$node["field"];
44 14
				$record_id=$node["record_id"];
45 14
				if (!$record_id) {
46 14
					if (!$this->in_orderby) {
47 14
						$result=" $table.object = ".$this->tbl_prefix."objects.id and $table.$field ";
48 14
						$this->used_tables[$table]=$table;
49 14 View Code Duplication
					} else {
50
						if ($this->in_orderby && $node["nls"]) {
51
							/*
52
								we do a left join so that we will also find non
53
								matching objects
54
							*/
55
							$objects_table = $this->tbl_prefix."objects";
56
							$this->nls_join[$table] = "left join $table as order_$table on $objects_table.id=order_$table.object and order_$table.AR_nls='".$node["nls"]."' ";
57
58
							$result = " order_$table.$field ";
59
							$this->select_list["order_".$table.".".$field] = "order_$table.$field";
60
61
						} else {
62
							/*
63
								if we are parsing 'orderby' properties we have
64
								to join our tables for the whole query
65
							*/
66
							$this->select_tables[$table]=$table;
67
							$this->used_tables[$table]=$table;
68
							$result=" $table.$field ";
69
						}
70
					}
71 14
				} else {
72
					$this->used_tables["$table as $table$record_id"] = $table.$record_id;
73
					if (!$this->in_orderby) {
74
						$result=" $table$record_id.object = ".$this->tbl_prefix."objects.id and $table$record_id.$field ";
75
					} else {
76
						$this->select_tables["$table as $table$record_id"] = $table.$record_id;
77
						$result=" $table$record_id.$field ";
78
					}
79
				}
80 14
			break;
81 14 View Code Duplication
			case 'ident':
82
				$table=$this->tbl_prefix.$node["table"];
83
				$field=$node["field"];
84
				$this->used_tables[$table]=$table;
85
				$result=" $table.$field ";
86
			break;
87 14 View Code Duplication
			case 'custom':
88
				$table = $this->tbl_prefix."prop_custom";
89
				$field = $node["field"];
90
				$nls = $node["nls"];
91
				$record_id = $node["record_id"];
92
				/*
93
					when we are compiling orderby properties we always want
94
					to assign it to a new table alias
95
				*/
96
				if ($this->in_orderby) {
97
					$this->custom_id++;
98
				}
99
				$this->custom_ref++;
100
				if (!$record_id) {
101
					$this->used_tables[$table." as $table".$this->custom_id] = $table.$this->custom_id;
102
					$this->select_tables[$table." as $table".$this->custom_id] = 1;
103
104
					$this->used_custom_fields[$field] = true;
105
					$result = " $table".$this->custom_id.".AR_name = '$field' ";
106
					if ($nls) {
107
						$result = " $result and $table".$this->custom_id.".AR_nls = '$nls' ";
108
					}
109
110
					if (!$this->in_orderby) {
111
						$result = " $result and $table".$this->custom_id.".AR_value ";
112
					} else {
113
						$this->where_s_ext = $result;
114
						$result = " $table".$this->custom_id.".AR_value ";
115
					}
116
				} else {
117
					$this->used_tables["$table as $table$record_id"] = $table.$record_id;
118
			//		$this->select_tables[$table." as $table$record_id"] = 1;
119
120
					$result = " $table$record_id.AR_name = '$field' ";
121
					if (!$this->in_orderby ) {
122
						if ($this->join_target_properties["prop_my"][":$record_id"]) {
123
							$result=" $result and $table$record_id.object = target.object and $table$record_id.AR_value ";
124
						} else {
125
							$result=" $table$record_id.object = ".$this->tbl_prefix."objects.id and $table$record_id.AR_value ";
126
						}
127
					} else {
128
						if ($this->join_target_properties[$node["table"]]) {
129
							$this->join_target_properties["$table as $table$record_id"] = $table.$record_id;
130
						}
131
						$this->select_tables["$table as $table$record_id"] = $table.$record_id;
132
						$result=" $table$record_id.AR_value ";
133
					}
134
				}
135
			break;
136 14
			case 'string':
137 14
				$result=" '".pg_escape_string($node["value"])."' ";
138 14
			break;
139 14
			case 'float':
140 14
			case 'int':
141
				$result=" ".$node["value"]." ";
142
			break;
143 14 View Code Duplication
			case 'and':
144
				$cr = $this->custom_ref;
145
				$left=$this->compile_tree($node["left"]);
146
				if ($this->custom_ref > $cr) {
147
					$this->custom_id++;
148
				}
149
150
				$right=$this->compile_tree($node["right"]);
151
				$cr = $this->custom_ref;
152
				if ($this->custom_ref > $cr) {
153
					$this->custom_id++;
154
				}
155
				$result=" $left and $right ";
156
			break;
157 14 View Code Duplication
			case 'or':
158
				$left=$this->compile_tree($node["left"]);
159
				$right=$this->compile_tree($node["right"]);
160
				$result=" $left or $right ";
161
			break;
162 14
			case 'cmp':
163 14
				$not = '';
164 14
				switch ($node["operator"]) {
165 14
					case '=':
166 14
					case '==':
167 14
						$operator="=";
168 14
					break;
169
					case '!=':
170
					case '<=':
171
					case '>=':
172
					case '<':
173
					case '>':
174
						$operator=$node["operator"];
175
					break;
176
					case '!~':
177
					case '!~~':
178
						$not="NOT ";
179
 					case '~=':
180
					case '=~':
181 View Code Duplication
					case '=~~':
182
						if (!strlen($node["operator"])==3) {
183
							$not.="I";
184
						}
185
						$operator=$not."LIKE";
186
					break;
187
					case '!/':
188
					case '!//':
189
						$not="!";
190
					case '=/':
191 View Code Duplication
					case '=//':
192
						$operator=$not."~";
193
						if (strlen($node["operator"])==3) {
194
							$operator.="*";
195
						}
196
						break;
197 14
				}
198 14
				if ($node["left"]["id"]!=="implements") {
199 14
					$left=$this->compile_tree($node["left"]);
200 14
					$right=$this->compile_tree($node["right"]);
201 14
					if($this->test_for_lowercase($node["left"])){
202
						// lowercase compile
203
						$result=" lower($left) $operator lower($right) ";
0 ignored issues
show
Bug introduced by
The variable $operator does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
204
					} else {
205
						// normal compile
206
						/* lastchanged == unixtimestamp -> lastchanged == 200201.. */
207 14
						if ($node["left"]["field"]=="lastchanged") {
208
							$right = "to_timestamp($right)";
209
						}
210 14
						$result=" $left $operator $right ";
211
					}
212 14
				} else {
213
					$table=$this->tbl_prefix."types";
214
					$type=$this->compile_tree($node["right"]);
215
					switch ($operator) {
216 View Code Duplication
						case '!=':
217
							$result=" (".$this->tbl_prefix."objects.type not in (select type from ".$this->tbl_prefix."types where implements = $type )) ";
218
						break;
219
						default:
220
							$this->used_tables[$table]=$table;
221
							$result=" (".$this->tbl_prefix."types.implements $operator $type and ".$this->tbl_prefix."objects.vtype = ".$this->tbl_prefix."types.type ) ";
222
						break;
223
					}
224
				}
225 14
			break;
226 14 View Code Duplication
			case 'group':
227
				$left=$this->compile_tree($node["left"]);
228
				if ($left) {
229
					$result=" ( $left ) ";
230
				}
231
			break;
232
233 14 View Code Duplication
			case 'orderby':
234 12
				$result=$this->compile_tree($node["left"]);
235 12
				$this->orderby_s=$this->compile_tree($node["right"]);
236 12
			break;
237
238 14
			case 'orderbyfield':
239 12
				$this->in_orderby = true;
240 12
				$left=$this->compile_tree($node["left"]);
241 12
				if ( $node["right"]["field"] != "none" ) {
242
					$right=$this->compile_tree($node["right"]);
243
					if ($left) {
244
						$result=" $left ,  $right ".$node["type"]." ";
245 View Code Duplication
						if($node["left"]['id'] == 'property' && !$node["right"]['nls']){
246
							$lefttablefield = $this->tbl_prefix.$node["left"]['table'].".".$node["left"]['field'];
247
							$this->select_list[$lefttablefield] = $lefttablefield;
248
						}
249
					} else {
250
						$result=" $right ".$node["type"]." ";
251
					}
252 View Code Duplication
					if($node["right"]['id'] == 'property' && !$node["right"]['nls']){
253
						$righttablefield = $this->tbl_prefix.$node["right"]['table'].".".$node["right"]['field'];
254
						$this->select_list[$righttablefield] = $righttablefield;
255
					}
256
				} else {
257 12
					$result = "";
258 12
					if ($left) {
259
						$result = " $left ";
260 View Code Duplication
						if($node["left"]['id'] == 'property' && !$node["right"]['nls']){
261
							$lefttablefield = $this->tbl_prefix.$node["left"]['table'].".".$node["left"]['field'];
262
							$this->select_list[$lefttablefield] = $lefttablefield;
263
						}
264
					}
265 12
					$this->skipDefaultOrderBy = true;
266
				}
267 12
			break;
268
269 14 View Code Duplication
			case 'limit':
270 14
				$this->where_s=$this->compile_tree($node["left"]);
271 14
				$this->limit_s="";
272 14
				if ($node["limit"]) {
273 2
					$this->limit_s=" offset ".(int)$node["offset"]." limit ".$node["limit"]." ";
274 2
				} else
275 12
				if ($node["offset"]) {
276
					$this->limit_s=" limit ".(int)$node["offset"]." ";
277
				} else {
278 12
					if ($this->limit) {
279
						$offset = (int)$this->offset;
280
						$this->limit_s=" offset $offset limit ".(int)$this->limit." ";
281
					}
282
				}
283 14
			break;
284
		}
285 14
		return $result;
0 ignored issues
show
Bug introduced by
The variable $result does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
286
	}
287
288
	// postgresql specific compiler function
289 14
	function priv_sql_compile($tree) {
290 14
		$this->custom_ref = 0;
291 14
		$this->custom_id = 0;
292 14
		$this->used_tables=array();
293 14
		$this->compile_tree($tree);
294
295 14
		if ( $this->error ) {
296
			return null;
297
		}
298
299 14
		$nodes=$this->tbl_prefix."nodes";
300 14
		$objects=$this->tbl_prefix."objects";
301 14
		$this->used_tables[$nodes]=$nodes;
302 14
		$this->used_tables[$objects]=$objects;
303 14
		@reset($this->used_tables);
304 14
		while (list($key, $val)=each($this->used_tables)) {
305 14
			if ($tables) {
306 14
				$tables.=", $key";
0 ignored issues
show
Bug introduced by
The variable $tables does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
307 14
			} else {
308 14
				$tables="$key";
309
			}
310 14
			if ($this->select_tables[$key]) {
311
				$prop_dep.=" and $val.object=$objects.id ";
0 ignored issues
show
Bug introduced by
The variable $prop_dep does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
312
			}
313 14
		}
314 14
		if (is_array($this->nls_join)) {
315
			$join = join($this->nls_join);
316
		}
317 14
		if(is_array($this->select_list)){
318
			$select = join(", ", $this->select_list);
319
		}
320
321 14
		$query ="where $nodes.object=$objects.id $prop_dep";
322 14
		$query.=" and $nodes.path like '".str_replace('_','\\_',pg_escape_string($this->path))."%' ";
323 14
		if ($this->where_s) {
324 14
			$query.=" and ( $this->where_s ) ";
325 14
		}
326 14
		if ($this->where_s_ext) {
327
			$query .= " and ($this->where_s_ext) ";
328
		}
329 14
		$order = '';
330 14
		if ($this->orderby_s) {
331 View Code Duplication
			if ($this->skipDefaultOrderBy) {
332
				$order .= "order by $this->orderby_s";
333
			} else {
334
				$order .= "order by $this->orderby_s, $nodes.parent ASC, $nodes.priority DESC, $nodes.path ASC ";
335
			}
336 14
		} else if (!$this->skipDefaultOrderBy) {
337 2
			$order .= "order by $nodes.parent ASC, $nodes.priority DESC, $nodes.path ASC ";
338 2
		}
339
340 14
		$order .= " $this->limit_s ";
341
342 14
		$select_query  = "select distinct($nodes.path), $nodes.parent, $nodes.priority, ";
343 14
		$select_query .= " $objects.id, $objects.type, $objects.object, date_part('epoch', $objects.lastchanged) as lastchanged, $objects.vtype ";
344
345 14
		if($select){
346
			$select_query .= ", " . $select;
0 ignored issues
show
Bug introduced by
The variable $select does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
347
		}
348
349 14
		$select_query .= " from $tables $join $query $order";
0 ignored issues
show
Bug introduced by
The variable $join does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
350 14
		$count_query = "select count(distinct($nodes.path)) as count from $tables ".$query;
351
352 14
		return Array("select_query" => $select_query, "count_query" => $count_query);
353
	}
354
355
  }
356