1 |
cvsjoko |
1.1 |
<? |
2 |
|
|
|
3 |
|
|
// =========================================================== |
4 |
|
|
class AbstractQueryStatement { |
5 |
|
|
|
6 |
|
|
var $sql_in_base; |
7 |
|
|
var $sql_out_build; |
8 |
|
|
var $sql_out_ready; |
9 |
|
|
|
10 |
|
|
var $bool_built; |
11 |
|
|
var $bool_ready_good; |
12 |
|
|
var $bool_hasToBeMapped; |
13 |
|
|
|
14 |
|
|
var $criterias; |
15 |
|
|
var $orders; |
16 |
|
|
var $limits; |
17 |
|
|
|
18 |
|
|
var $map; |
19 |
|
|
var $data; |
20 |
|
|
var $crud; |
21 |
|
|
|
22 |
|
|
|
23 |
|
|
|
24 |
|
|
// ---------------------------------------------------- |
25 |
|
|
function AbstractQueryStatement($map = array()) { |
26 |
|
|
|
27 |
|
|
$this->sql_in_base = ''; |
28 |
|
|
$this->sql_out_build = ''; |
29 |
|
|
$this->sql_out_ready = ''; |
30 |
|
|
|
31 |
|
|
$this->bool_built = 0; |
32 |
|
|
$this->bool_ready_good = 0; |
33 |
|
|
$this->bool_hasToBeMapped = 0; |
34 |
|
|
|
35 |
|
|
$this->criterias = array(); |
36 |
|
|
$this->orders = array(); |
37 |
|
|
$this->limits = array(); |
38 |
|
|
|
39 |
|
|
$this->map = array(); |
40 |
|
|
$this->data = array(); |
41 |
|
|
$this->crud = ''; |
42 |
|
|
/* |
43 |
|
|
if (count($map)) { |
44 |
|
|
$this->setMap($map); |
45 |
|
|
} |
46 |
|
|
*/ |
47 |
|
|
} |
48 |
|
|
|
49 |
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
50 |
|
|
// getter- and setter-methods |
51 |
|
|
|
52 |
|
|
function setQuery($sql) { |
53 |
|
|
|
54 |
|
|
// strip bounding whitespaces |
55 |
|
|
$sql = trim($sql); |
56 |
|
|
|
57 |
|
|
// strip trailing semicolon, if present |
58 |
|
|
if (substr($sql, -1) == ';') { |
59 |
|
|
$sql = substr($sql, 0, -1); |
60 |
|
|
} |
61 |
|
|
|
62 |
|
|
// set sql-string locally |
63 |
|
|
$this->sql_in_base = $sql; |
64 |
|
|
} |
65 |
|
|
|
66 |
|
|
function setMap($map = array()) { |
67 |
|
|
if (count($map)) { |
68 |
|
|
$this->bool_hasToBeMapped = 1; |
69 |
|
|
|
70 |
|
|
// determine type of map, TODO: don't pass PDLAttributes in here any more!!! |
71 |
|
|
reset($map); |
72 |
|
|
if (strtolower(get_class(current($map))) == 'pdlmodelattribute') { |
73 |
|
|
while($attribute =& current($map)) { |
74 |
|
|
$attributename = $attribute->name; |
75 |
|
|
$mapname = $attribute->map_name; |
76 |
|
|
print $attributename . "," . $mapname . "<br>"; |
77 |
|
|
$map_new[$attributename] = $mapname; |
78 |
|
|
next($map); |
79 |
|
|
} |
80 |
|
|
$map = $map_new; |
81 |
|
|
} |
82 |
|
|
$this->map = $map; |
83 |
|
|
} else { |
84 |
|
|
$this->bool_hasToBeMapped = 0; |
85 |
|
|
} |
86 |
|
|
} |
87 |
|
|
|
88 |
|
|
function setData($data = array()) { |
89 |
|
|
if (count($data)) { |
90 |
|
|
$this->bool_data_set = 1; |
91 |
|
|
$this->data = $data; |
92 |
|
|
} else { |
93 |
|
|
$this->bool_data_set = 0; |
94 |
|
|
} |
95 |
|
|
} |
96 |
|
|
|
97 |
|
|
function setSql_createFromMap($map) { |
98 |
|
|
$this->sql_in_base = $sql; |
99 |
|
|
$this->setMap($map); |
100 |
|
|
} |
101 |
|
|
|
102 |
|
|
function getSql() { |
103 |
|
|
if (!$this->bool_built) { $this->_build(); } |
104 |
|
|
if ($this->bool_ready_good) { |
105 |
|
|
return $this->sql_out_ready; |
106 |
|
|
} |
107 |
|
|
} |
108 |
|
|
|
109 |
|
|
|
110 |
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
111 |
|
|
// processor-methods |
112 |
|
|
|
113 |
|
|
function addCriteria($argument, $logicalOperator = 'AND') { |
114 |
|
|
$criteria = array('argument' => $argument, 'logicalOperator' => $logicalOperator); |
115 |
|
|
array_push($this->criterias, $criteria); |
116 |
|
|
} |
117 |
|
|
|
118 |
|
|
function addOrder($argument, $modifier = 'ASC') { |
119 |
|
|
$order = array('argument' => $argument, 'modifier' => $modifier); |
120 |
|
|
array_push($this->orders, $order); |
121 |
|
|
} |
122 |
|
|
|
123 |
|
|
function addLimit($argument) { |
124 |
|
|
$limit = array('argument' => $argument); |
125 |
|
|
array_push($this->limits, $limit); |
126 |
|
|
} |
127 |
|
|
|
128 |
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
129 |
|
|
// builder-methods |
130 |
|
|
|
131 |
|
|
function _build() { |
132 |
|
|
|
133 |
|
|
$this->sql_out_build = $this->sql_in_base; |
134 |
|
|
$bool_whereAppended = 0; |
135 |
|
|
|
136 |
|
|
|
137 |
|
|
// . . . . . . . . . . . . . . . . . . . |
138 |
|
|
// 1. determine type of query (CRUD) |
139 |
|
|
|
140 |
|
|
// determine "CRUD" (create, retrieve, update, delete) |
141 |
|
|
$this->crud = ""; |
142 |
|
|
if (stristr($this->sql_out_build, 'INSERT INTO')) { $this->crud = "C"; } |
143 |
|
|
if (stristr($this->sql_out_build, 'SELECT')) { $this->crud = "R"; } |
144 |
|
|
if (stristr($this->sql_out_build, 'UPDATE')) { $this->crud = "U"; } |
145 |
|
|
if (stristr($this->sql_out_build, 'DELETE')) { $this->crud = "D"; } |
146 |
|
|
|
147 |
|
|
|
148 |
|
|
// . . . . . . . . . . . . . . . . . . . |
149 |
|
|
// 2. decoration |
150 |
|
|
|
151 |
|
|
// --- |
152 |
|
|
// criterias |
153 |
|
|
if (count($this->criterias)) { |
154 |
|
|
|
155 |
|
|
// do we need a "WHERE"? |
156 |
|
|
// HACK: do more sophisticated, for now, no "where" can appear in data regularly!!! :-( |
157 |
|
|
if (!stristr($this->sql_out_build, 'where')) { |
158 |
|
|
$bool_whereAppended = 1; |
159 |
|
|
$this->sql_out_build .= ' WHERE '; |
160 |
|
|
} |
161 |
|
|
|
162 |
|
|
$criteriastring = ''; |
163 |
|
|
$bool_first = 1; |
164 |
|
|
reset($this->criterias); |
165 |
|
|
while($criteria = current($this->criterias)) { |
166 |
|
|
if (!$bool_first || !$bool_whereAppended) { |
167 |
|
|
$criteriastring .= ' ' . $criteria['logicalOperator'] . ' '; |
168 |
|
|
} |
169 |
|
|
$criteriastring .= $criteria['argument']; |
170 |
|
|
next($this->criterias); |
171 |
|
|
$bool_first = 0; |
172 |
|
|
} |
173 |
|
|
$this->sql_out_build .= $criteriastring; |
174 |
|
|
|
175 |
|
|
} |
176 |
|
|
|
177 |
|
|
// --- |
178 |
|
|
// orders |
179 |
|
|
if (count($this->orders)) { |
180 |
|
|
$orderstring = ' order BY '; |
181 |
|
|
$orderlist = array(); |
182 |
|
|
reset($this->orders); |
183 |
|
|
while($order = current($this->orders)) { |
184 |
|
|
array_push($orderlist, $order['argument'] . ' ' . $order['modifier']); |
185 |
|
|
next($this->orders); |
186 |
|
|
} |
187 |
|
|
$orderstring .= join($orderlist, ', '); |
188 |
|
|
$this->sql_out_build .= $orderstring; |
189 |
|
|
} |
190 |
|
|
|
191 |
|
|
// --- |
192 |
|
|
// limits |
193 |
|
|
if (count($this->limits)) { |
194 |
|
|
$limitstring = ' LIMIT '; |
195 |
|
|
$limitlist = array(); |
196 |
|
|
reset($this->limits); |
197 |
|
|
while($limit = current($this->limits)) { |
198 |
|
|
array_push($limitlist, $limit['argument']); |
199 |
|
|
next($this->limits); |
200 |
|
|
} |
201 |
|
|
$limitstring .= join($limitlist, ', '); |
202 |
|
|
$this->sql_out_build .= $limitstring; |
203 |
|
|
} |
204 |
|
|
|
205 |
|
|
|
206 |
|
|
// . . . . . . . . . . . . . . . . . . . |
207 |
|
|
// 3. mapping |
208 |
|
|
|
209 |
|
|
// if we have ... |
210 |
|
|
if ($this->bool_hasToBeMapped) { |
211 |
|
|
// ... we should check for having a map ... |
212 |
|
|
if ($this->map) { |
213 |
|
|
// ... if we do, start mapping! |
214 |
|
|
$this->_doMapping(); |
215 |
|
|
} else { |
216 |
|
|
// ... trigger an error! |
217 |
|
|
print "<font color=\"red\">In \"SqlStatement->_build()\" there is an \"bool_hasToBeMapped\", but no \"map\".</font><br>"; |
218 |
|
|
} |
219 |
|
|
|
220 |
|
|
} |
221 |
|
|
|
222 |
|
|
// finish sql-statement with semicolon |
223 |
|
|
$this->sql_out_build .= ';'; |
224 |
|
|
|
225 |
|
|
// set "ready"-statement |
226 |
|
|
$this->sql_out_ready = $this->sql_out_build; |
227 |
|
|
|
228 |
|
|
// analyze, what we've built |
229 |
|
|
$this->_analyzeOutputQuery(); |
230 |
|
|
|
231 |
|
|
} |
232 |
|
|
|
233 |
|
|
|
234 |
|
|
function _doMapping() { |
235 |
|
|
|
236 |
|
|
// HACK/TODO: |
237 |
|
|
// right now we use here "PDLModelAttribute"-objects for building our map, we should definitely not! |
238 |
|
|
// (logically yes, but not physically, since this is "lib_database_sql.php.inc", |
239 |
|
|
// which has got absolutely nothing to do with "DataStore" or "PDL" - stuff!!!) |
240 |
|
|
|
241 |
|
|
$list_attributes = array(); |
242 |
|
|
$list_columns = array(); |
243 |
|
|
$map = array(); |
244 |
|
|
$map_values = array(); |
245 |
|
|
|
246 |
|
|
// - - - - - - - - - - - - - - - - - - - - - |
247 |
|
|
// 1. build attribute-list, column-list and mapping-table |
248 |
|
|
while(list($attributename, $mapname) = each($this->map)) { |
249 |
|
|
|
250 |
|
|
// bugfix: before we continue, we should check if "$map_value" is valid, else: skip this |
251 |
|
|
if ($mapname) { |
252 |
|
|
// attribute |
253 |
|
|
array_push($list_attributes, $attributename); |
254 |
|
|
// column |
255 |
|
|
//$meta_sql = $attribute['meta_sql']; |
256 |
|
|
array_push($list_columns, $mapname); |
257 |
|
|
// map |
258 |
|
|
// was: |
259 |
|
|
// $map[$map_key] = $mapname; |
260 |
|
|
// is: |
261 |
|
|
// now we have two different kinds of maps here: |
262 |
|
|
// a) the "normal" map, which maps attribute-names to map-names (for "SELECT"s) |
263 |
|
|
$map[$attributename] = $mapname; |
264 |
|
|
// b) the "value" map, which maps attribute-names to attribute-values (for "INSERT"s or "UPDATE"s) |
265 |
|
|
if ( ($this->crud == 'C') || ($this->crud == 'U') ) { |
266 |
|
|
if (!$this->bool_data_set) { |
267 |
|
|
print "<font color=\"red\">_doMapping: \"INSERT\"- or \"UPDATE\"-query requested, but no data was set. Further object-operations will be aborted.</font><br>"; |
268 |
|
|
exit; |
269 |
|
|
} |
270 |
|
|
$map_values[$attributename] = $this->data[$attributename]; |
271 |
|
|
} |
272 |
|
|
} |
273 |
|
|
//next($this->map); |
274 |
|
|
} |
275 |
|
|
|
276 |
|
|
//print "out_build: " . $this->sql_out_build . "<br>"; |
277 |
|
|
|
278 |
|
|
// - - - - - - - - - - - - - - - - - - - - - |
279 |
|
|
// 2. build attribute- and column-list |
280 |
|
|
$wrkString = $this->sql_out_build; |
281 |
|
|
while( list($attribute_name, $map_name) = each($map) ) { |
282 |
|
|
$this->sql_out_build = str_replace(':' . $attribute_name, $map_name, $this->sql_out_build); |
283 |
|
|
} |
284 |
|
|
if ( ($this->crud == 'C') || ($this->crud == 'U') ) { |
285 |
|
|
if (count($map_values)) { |
286 |
|
|
$use_list_attributes = array_keys($map_values); |
287 |
|
|
$use_list_values = array_values($map_values); |
288 |
|
|
|
289 |
|
|
modifyArray($use_list_attributes, array('prefix' => '/(!', 'postfix' => ')(\W)/')); |
290 |
|
|
modifyArray($use_list_values, array('prefix' => "'", 'postfix' => "'\\2")); |
291 |
|
|
|
292 |
|
|
/* |
293 |
|
|
while( list($attribute_name, $attribute_value) = each($map_values) ) { |
294 |
|
|
$map_values_use['!' . $attribute_name] = $attribute_value; |
295 |
|
|
//$this->sql_out_build = str_replace('!' . $attribute_name, "'" . $attribute_value . "'", $this->sql_out_build); |
296 |
|
|
} |
297 |
|
|
*/ |
298 |
|
|
$this->sql_out_build = preg_replace($use_list_attributes, $use_list_values, $this->sql_out_build); |
299 |
|
|
|
300 |
|
|
} |
301 |
|
|
} |
302 |
|
|
|
303 |
|
|
//print "out_build: " . $this->sql_out_build . "<br>"; |
304 |
|
|
|
305 |
|
|
// out now: |
306 |
|
|
//$wrkString = ereg_replace("[[:<:]]" . $key . "[[:>:]]", $value, $wrkString); |
307 |
|
|
|
308 |
|
|
} |
309 |
|
|
|
310 |
|
|
|
311 |
|
|
// ---------------------------------------------------- |
312 |
|
|
function _analyzeOutputQuery() { |
313 |
|
|
|
314 |
|
|
// we assume a "good" query |
315 |
|
|
$bool_good = 1; |
316 |
|
|
|
317 |
|
|
// get ready query |
318 |
|
|
$oq = $this->sql_out_build; |
319 |
|
|
|
320 |
|
|
// replace all value-stuff |
321 |
|
|
//$oq = str_replace('', '', $oq); |
322 |
|
|
|
323 |
|
|
// check for unmapped items |
324 |
|
|
if (preg_match('/(:\w+)/', $oq, $regs)) { |
325 |
|
|
print "<font color=\"red\">_analyzeOutputQuery: Detected unmapped item(s) in query \"$oq\", query will be set invalid.</font><br>"; |
326 |
|
|
print "Item(s) was/were: \"{$regs[1]}\".</font><br>"; |
327 |
|
|
$bool_good = 0; |
328 |
|
|
} |
329 |
|
|
|
330 |
|
|
// check for deletes without criteria ("where") |
331 |
|
|
if ( (stristr($oq, 'DELETE FROM')) && (!stristr($oq, 'WHERE')) ) { |
332 |
|
|
print "<font color=\"red\">_analyzeOutputQuery: Detected \"DELETE\" without \"WHERE\" in query \"$oq\", query will be set invalid.</font><br>"; |
333 |
|
|
$bool_good = 0; |
334 |
|
|
} |
335 |
|
|
|
336 |
|
|
// set "bool_ready_good" if the query is valid |
337 |
|
|
$this->bool_ready_good = $bool_good; |
338 |
|
|
|
339 |
|
|
} |
340 |
|
|
|
341 |
|
|
|
342 |
|
|
} |
343 |
|
|
|
344 |
|
|
?> |