danielebarchiesi@4
|
1 <?php
|
danielebarchiesi@4
|
2 /**
|
danielebarchiesi@4
|
3 * ARC2 RDF Store SELECT Query Handler
|
danielebarchiesi@4
|
4 *
|
danielebarchiesi@4
|
5 * @author Benjamin Nowack
|
danielebarchiesi@4
|
6 * @license http://arc.semsol.org/license
|
danielebarchiesi@4
|
7 * @homepage <http://arc.semsol.org/>
|
danielebarchiesi@4
|
8 * @package ARC2
|
danielebarchiesi@4
|
9 * @version 2010-11-16
|
danielebarchiesi@4
|
10 *
|
danielebarchiesi@4
|
11 */
|
danielebarchiesi@4
|
12
|
danielebarchiesi@4
|
13 ARC2::inc('StoreQueryHandler');
|
danielebarchiesi@4
|
14
|
danielebarchiesi@4
|
15 class ARC2_StoreSelectQueryHandler extends ARC2_StoreQueryHandler {
|
danielebarchiesi@4
|
16
|
danielebarchiesi@4
|
17 function __construct($a, &$caller) {/* caller has to be a store */
|
danielebarchiesi@4
|
18 parent::__construct($a, $caller);
|
danielebarchiesi@4
|
19 }
|
danielebarchiesi@4
|
20
|
danielebarchiesi@4
|
21 function __init() {/* db_con */
|
danielebarchiesi@4
|
22 parent::__init();
|
danielebarchiesi@4
|
23 $this->store = $this->caller;
|
danielebarchiesi@4
|
24 $con = $this->store->getDBCon();
|
danielebarchiesi@4
|
25 $this->handler_type = 'select';
|
danielebarchiesi@4
|
26 $this->engine_type = $this->v('store_engine_type', 'MyISAM', $this->a);
|
danielebarchiesi@4
|
27 $this->cache_results = $this->v('store_cache_results', 0, $this->a);
|
danielebarchiesi@4
|
28 }
|
danielebarchiesi@4
|
29
|
danielebarchiesi@4
|
30 /* */
|
danielebarchiesi@4
|
31
|
danielebarchiesi@4
|
32 function runQuery($infos) {
|
danielebarchiesi@4
|
33 $con = $this->store->getDBCon();
|
danielebarchiesi@4
|
34 $rf = $this->v('result_format', '', $infos);
|
danielebarchiesi@4
|
35 $this->infos = $infos;
|
danielebarchiesi@4
|
36 $this->infos['null_vars'] = array();
|
danielebarchiesi@4
|
37 $this->indexes = array();
|
danielebarchiesi@4
|
38 $this->pattern_order_offset = 0;
|
danielebarchiesi@4
|
39 $q_sql = $this->getSQL();
|
danielebarchiesi@4
|
40
|
danielebarchiesi@4
|
41 /* debug result formats */
|
danielebarchiesi@4
|
42 if ($rf == 'sql') return $q_sql;
|
danielebarchiesi@4
|
43 if ($rf == 'structure') return $this->infos;
|
danielebarchiesi@4
|
44 if ($rf == 'index') return $this->indexes;
|
danielebarchiesi@4
|
45 /* create intermediate results (ID-based) */
|
danielebarchiesi@4
|
46 $tmp_tbl = $this->createTempTable($q_sql);
|
danielebarchiesi@4
|
47 /* join values */
|
danielebarchiesi@4
|
48 $r = $this->getFinalQueryResult($q_sql, $tmp_tbl);
|
danielebarchiesi@4
|
49 /* remove intermediate results */
|
danielebarchiesi@4
|
50 if (!$this->cache_results) {
|
danielebarchiesi@4
|
51 $this->queryDB('DROP TABLE IF EXISTS ' . $tmp_tbl, $con);
|
danielebarchiesi@4
|
52 }
|
danielebarchiesi@4
|
53 return $r;
|
danielebarchiesi@4
|
54 }
|
danielebarchiesi@4
|
55
|
danielebarchiesi@4
|
56 function getSQL() {
|
danielebarchiesi@4
|
57 $r = '';
|
danielebarchiesi@4
|
58 $nl = "\n";
|
danielebarchiesi@4
|
59 $this->buildInitialIndexes();
|
danielebarchiesi@4
|
60 foreach ($this->indexes as $i => $index) {
|
danielebarchiesi@4
|
61 $this->index = array_merge($this->getEmptyIndex(), $index);
|
danielebarchiesi@4
|
62 $this->analyzeIndex($this->getPattern('0'));
|
danielebarchiesi@4
|
63 $sub_r = $this->getQuerySQL();
|
danielebarchiesi@4
|
64 $r .= $r ? $nl . 'UNION' . $this->getDistinctSQL() . $nl : '';
|
danielebarchiesi@4
|
65 $r .= $this->is_union_query ? '(' . $sub_r . ')' : $sub_r;
|
danielebarchiesi@4
|
66 $this->indexes[$i] = $this->index;
|
danielebarchiesi@4
|
67 }
|
danielebarchiesi@4
|
68 $r .= $this->is_union_query ? $this->getLIMITSQL() : '';
|
danielebarchiesi@4
|
69 if ($this->v('order_infos', 0, $this->infos['query'])) {
|
danielebarchiesi@4
|
70 $r = preg_replace('/SELECT(\s+DISTINCT)?\s*/', 'SELECT\\1 NULL AS `_pos_`, ', $r);
|
danielebarchiesi@4
|
71 }
|
danielebarchiesi@4
|
72 $pd_count = $this->problematicDependencies();
|
danielebarchiesi@4
|
73 if ($pd_count) {
|
danielebarchiesi@4
|
74 /* re-arranging the patterns sometimes reduces the LEFT JOIN dependencies */
|
danielebarchiesi@4
|
75 $set_sql = 0;
|
danielebarchiesi@4
|
76 if (!$this->pattern_order_offset) $set_sql = 1;
|
danielebarchiesi@4
|
77 if (!$set_sql && ($pd_count < $this->opt_sql_pd_count)) $set_sql = 1;
|
danielebarchiesi@4
|
78 if (!$set_sql && ($pd_count == $this->opt_sql_pd_count) && (strlen($r) < strlen($this->opt_sql))) $set_sql = 1;
|
danielebarchiesi@4
|
79 if ($set_sql) {
|
danielebarchiesi@4
|
80 $this->opt_sql = $r;
|
danielebarchiesi@4
|
81 $this->opt_sql_pd_count = $pd_count;
|
danielebarchiesi@4
|
82 }
|
danielebarchiesi@4
|
83 $this->pattern_order_offset++;
|
danielebarchiesi@4
|
84 if ($this->pattern_order_offset > 5) {
|
danielebarchiesi@4
|
85 return $this->opt_sql;
|
danielebarchiesi@4
|
86 }
|
danielebarchiesi@4
|
87 return $this->getSQL();
|
danielebarchiesi@4
|
88 }
|
danielebarchiesi@4
|
89 return $r;
|
danielebarchiesi@4
|
90 }
|
danielebarchiesi@4
|
91
|
danielebarchiesi@4
|
92 function buildInitialIndexes() {
|
danielebarchiesi@4
|
93 $this->dependency_log = array();
|
danielebarchiesi@4
|
94 $this->index = $this->getEmptyIndex();
|
danielebarchiesi@4
|
95 $this->buildIndex($this->infos['query']['pattern'], 0);
|
danielebarchiesi@4
|
96 $tmp = $this->index;
|
danielebarchiesi@4
|
97 $this->analyzeIndex($this->getPattern('0'));
|
danielebarchiesi@4
|
98 $this->initial_index = $this->index;
|
danielebarchiesi@4
|
99 $this->index = $tmp;
|
danielebarchiesi@4
|
100 $this->is_union_query = $this->index['union_branches'] ? 1 : 0;
|
danielebarchiesi@4
|
101 $this->indexes = $this->is_union_query ? $this->getUnionIndexes($this->index) : array($this->index);
|
danielebarchiesi@4
|
102 }
|
danielebarchiesi@4
|
103
|
danielebarchiesi@4
|
104 function createTempTable($q_sql) {
|
danielebarchiesi@4
|
105 $con = $this->store->getDBCon();
|
danielebarchiesi@4
|
106 $v = $this->store->getDBVersion();
|
danielebarchiesi@4
|
107 if ($this->cache_results) {
|
danielebarchiesi@4
|
108 $tbl = $this->store->getTablePrefix() . 'Q' . md5($q_sql);
|
danielebarchiesi@4
|
109 }
|
danielebarchiesi@4
|
110 else {
|
danielebarchiesi@4
|
111 $tbl = $this->store->getTablePrefix() . 'Q' . md5($q_sql . time() . uniqid(rand()));
|
danielebarchiesi@4
|
112 }
|
danielebarchiesi@4
|
113 if (strlen($tbl) > 64) $tbl = 'Q' . md5($tbl);
|
danielebarchiesi@4
|
114 $tmp_sql = 'CREATE TEMPORARY TABLE ' . $tbl . ' ( ' . $this->getTempTableDef($tbl, $q_sql) . ') ';
|
danielebarchiesi@4
|
115 $tmp_sql .= (($v < '04-01-00') && ($v >= '04-00-18')) ? 'ENGINE' : (($v >= '04-01-02') ? 'ENGINE' : 'TYPE');
|
danielebarchiesi@4
|
116 $tmp_sql .= '=' . $this->engine_type;/* HEAP doesn't support AUTO_INCREMENT, and MySQL breaks on MEMORY sometimes */
|
danielebarchiesi@4
|
117 if (!$this->queryDB($tmp_sql, $con) && !$this->queryDB(str_replace('CREATE TEMPORARY', 'CREATE', $tmp_sql), $con)) {
|
danielebarchiesi@4
|
118 return $this->addError(mysql_error($con));
|
danielebarchiesi@4
|
119 }
|
danielebarchiesi@4
|
120 mysql_unbuffered_query('INSERT INTO ' . $tbl . ' ' . "\n" . $q_sql, $con);
|
danielebarchiesi@4
|
121 if ($er = mysql_error($con)) $this->addError($er);
|
danielebarchiesi@4
|
122 return $tbl;
|
danielebarchiesi@4
|
123 }
|
danielebarchiesi@4
|
124
|
danielebarchiesi@4
|
125 function getEmptyIndex() {
|
danielebarchiesi@4
|
126 return array(
|
danielebarchiesi@4
|
127 'from' => array(),
|
danielebarchiesi@4
|
128 'join' => array(),
|
danielebarchiesi@4
|
129 'left_join' => array(),
|
danielebarchiesi@4
|
130 'vars' => array(), 'graph_vars' => array(), 'graph_uris' => array(),
|
danielebarchiesi@4
|
131 'bnodes' => array(),
|
danielebarchiesi@4
|
132 'triple_patterns' => array(),
|
danielebarchiesi@4
|
133 'sub_joins' => array(),
|
danielebarchiesi@4
|
134 'constraints' => array(),
|
danielebarchiesi@4
|
135 'union_branches'=> array(),
|
danielebarchiesi@4
|
136 'patterns' => array(),
|
danielebarchiesi@4
|
137 'havings' => array()
|
danielebarchiesi@4
|
138 );
|
danielebarchiesi@4
|
139 }
|
danielebarchiesi@4
|
140
|
danielebarchiesi@4
|
141 function getTempTableDef($tmp_tbl, $q_sql) {
|
danielebarchiesi@4
|
142 $col_part = preg_replace('/^SELECT\s*(DISTINCT)?(.*)FROM.*$/s', '\\2', $q_sql);
|
danielebarchiesi@4
|
143 $parts = explode(',', $col_part);
|
danielebarchiesi@4
|
144 $has_order_infos = $this->v('order_infos', 0, $this->infos['query']);
|
danielebarchiesi@4
|
145 $r = '';
|
danielebarchiesi@4
|
146 $added = array();
|
danielebarchiesi@4
|
147 foreach ($parts as $part) {
|
danielebarchiesi@4
|
148 if (preg_match('/\.?(.+)\s+AS\s+`(.+)`/U', trim($part), $m) && !isset($added[$m[2]])) {
|
danielebarchiesi@4
|
149 $col = $m[1];
|
danielebarchiesi@4
|
150 $alias = $m[2];
|
danielebarchiesi@4
|
151 if ($alias == '_pos_') continue;
|
danielebarchiesi@4
|
152 $r .= $r ? ',' : '';
|
danielebarchiesi@4
|
153 $r .= "\n `" . $alias . "` int UNSIGNED";
|
danielebarchiesi@4
|
154 $added[$alias] = 1;
|
danielebarchiesi@4
|
155 }
|
danielebarchiesi@4
|
156 }
|
danielebarchiesi@4
|
157 if ($has_order_infos) {
|
danielebarchiesi@4
|
158 $r = "\n" . '`_pos_` mediumint NOT NULL AUTO_INCREMENT PRIMARY KEY, ' . $r;
|
danielebarchiesi@4
|
159 }
|
danielebarchiesi@4
|
160 return $r ? $r . "\n" : '';
|
danielebarchiesi@4
|
161 }
|
danielebarchiesi@4
|
162
|
danielebarchiesi@4
|
163 function getFinalQueryResult($q_sql, $tmp_tbl) {
|
danielebarchiesi@4
|
164 /* var names */
|
danielebarchiesi@4
|
165 $vars = array();
|
danielebarchiesi@4
|
166 $aggregate_vars = array();
|
danielebarchiesi@4
|
167 foreach ($this->infos['query']['result_vars'] as $entry) {
|
danielebarchiesi@4
|
168 if ($entry['aggregate']) {
|
danielebarchiesi@4
|
169 $vars[] = $entry['alias'];
|
danielebarchiesi@4
|
170 $aggregate_vars[] = $entry['alias'];
|
danielebarchiesi@4
|
171 }
|
danielebarchiesi@4
|
172 else {
|
danielebarchiesi@4
|
173 $vars[] = $entry['var'];
|
danielebarchiesi@4
|
174 }
|
danielebarchiesi@4
|
175 }
|
danielebarchiesi@4
|
176 /* result */
|
danielebarchiesi@4
|
177 $r = array('variables' => $vars);
|
danielebarchiesi@4
|
178 $v_sql = $this->getValueSQL($tmp_tbl, $q_sql);
|
danielebarchiesi@4
|
179 //echo "\n\n" . $v_sql;
|
danielebarchiesi@4
|
180 $t1 = ARC2::mtime();
|
danielebarchiesi@4
|
181 $con = $this->store->getDBCon();
|
danielebarchiesi@4
|
182 $rs = mysql_unbuffered_query($v_sql, $con);
|
danielebarchiesi@4
|
183 if ($er = mysql_error($con)) {
|
danielebarchiesi@4
|
184 $this->addError($er);
|
danielebarchiesi@4
|
185 }
|
danielebarchiesi@4
|
186 $t2 = ARC2::mtime();
|
danielebarchiesi@4
|
187 $rows = array();
|
danielebarchiesi@4
|
188 $types = array(0 => 'uri', 1 => 'bnode', 2 => 'literal');
|
danielebarchiesi@4
|
189 if ($rs) {
|
danielebarchiesi@4
|
190 while ($pre_row = mysql_fetch_array($rs)) {
|
danielebarchiesi@4
|
191 $row = array();
|
danielebarchiesi@4
|
192 foreach ($vars as $var) {
|
danielebarchiesi@4
|
193 if (isset($pre_row[$var])) {
|
danielebarchiesi@4
|
194 $row[$var] = $pre_row[$var];
|
danielebarchiesi@4
|
195 $row[$var . ' type'] = isset($pre_row[$var . ' type']) ? $types[$pre_row[$var . ' type']] : (in_array($var, $aggregate_vars) ? 'literal' : 'uri');
|
danielebarchiesi@4
|
196 if (isset($pre_row[$var . ' lang_dt']) && ($lang_dt = $pre_row[$var . ' lang_dt'])) {
|
danielebarchiesi@4
|
197 if (preg_match('/^([a-z]+(\-[a-z0-9]+)*)$/i', $lang_dt)) {
|
danielebarchiesi@4
|
198 $row[$var . ' lang'] = $lang_dt;
|
danielebarchiesi@4
|
199 }
|
danielebarchiesi@4
|
200 else {
|
danielebarchiesi@4
|
201 $row[$var . ' datatype'] = $lang_dt;
|
danielebarchiesi@4
|
202 }
|
danielebarchiesi@4
|
203 }
|
danielebarchiesi@4
|
204 }
|
danielebarchiesi@4
|
205 }
|
danielebarchiesi@4
|
206 if ($row || !$vars) {
|
danielebarchiesi@4
|
207 $rows[] = $row;
|
danielebarchiesi@4
|
208 }
|
danielebarchiesi@4
|
209 }
|
danielebarchiesi@4
|
210 }
|
danielebarchiesi@4
|
211 $r['rows'] = $rows;
|
danielebarchiesi@4
|
212 return $r;
|
danielebarchiesi@4
|
213 }
|
danielebarchiesi@4
|
214
|
danielebarchiesi@4
|
215 /* */
|
danielebarchiesi@4
|
216
|
danielebarchiesi@4
|
217 function buildIndex($pattern, $id) {
|
danielebarchiesi@4
|
218 $pattern['id'] = $id;
|
danielebarchiesi@4
|
219 $type = $this->v('type', '', $pattern);
|
danielebarchiesi@4
|
220 if (($type == 'filter') && $this->v('constraint', 0, $pattern)) {
|
danielebarchiesi@4
|
221 $sub_pattern = $pattern['constraint'];
|
danielebarchiesi@4
|
222 $sub_pattern['parent_id'] = $id;
|
danielebarchiesi@4
|
223 $sub_id = $id . '_0';
|
danielebarchiesi@4
|
224 $this->buildIndex($sub_pattern, $sub_id);
|
danielebarchiesi@4
|
225 $pattern['constraint'] = $sub_id;
|
danielebarchiesi@4
|
226 }
|
danielebarchiesi@4
|
227 else {
|
danielebarchiesi@4
|
228 $sub_patterns = $this->v('patterns', array(), $pattern);
|
danielebarchiesi@4
|
229 $keys = array_keys($sub_patterns);
|
danielebarchiesi@4
|
230 $spc = count($sub_patterns);
|
danielebarchiesi@4
|
231 if (($spc > 4) && $this->pattern_order_offset) {
|
danielebarchiesi@4
|
232 $keys = array();
|
danielebarchiesi@4
|
233 for ($i = 0 ; $i < $spc; $i++) {
|
danielebarchiesi@4
|
234 $keys[$i] = $i + $this->pattern_order_offset;
|
danielebarchiesi@4
|
235 while ($keys[$i] >= $spc) $keys[$i] -= $spc;
|
danielebarchiesi@4
|
236 }
|
danielebarchiesi@4
|
237 }
|
danielebarchiesi@4
|
238 foreach ($keys as $i => $key) {
|
danielebarchiesi@4
|
239 $sub_pattern = $sub_patterns[$key];
|
danielebarchiesi@4
|
240 $sub_pattern['parent_id'] = $id;
|
danielebarchiesi@4
|
241 $sub_id = $id . '_' . $key;
|
danielebarchiesi@4
|
242 $this->buildIndex($sub_pattern, $sub_id);
|
danielebarchiesi@4
|
243 $pattern['patterns'][$i] = $sub_id;
|
danielebarchiesi@4
|
244 if ($type == 'union') {
|
danielebarchiesi@4
|
245 $this->index['union_branches'][] = $sub_id;
|
danielebarchiesi@4
|
246 }
|
danielebarchiesi@4
|
247 }
|
danielebarchiesi@4
|
248 }
|
danielebarchiesi@4
|
249 $this->index['patterns'][$id] = $pattern;
|
danielebarchiesi@4
|
250 }
|
danielebarchiesi@4
|
251
|
danielebarchiesi@4
|
252 /* */
|
danielebarchiesi@4
|
253
|
danielebarchiesi@4
|
254 function analyzeIndex($pattern) {
|
danielebarchiesi@4
|
255 $type = $this->v('type', '', $pattern);
|
danielebarchiesi@4
|
256 if (!$type) {
|
danielebarchiesi@4
|
257 //echo '<!-- ' . var_export($this->infos, 1) . ' -->';
|
danielebarchiesi@4
|
258 return false;
|
danielebarchiesi@4
|
259 }
|
danielebarchiesi@4
|
260 $type = $pattern['type'];
|
danielebarchiesi@4
|
261 $id = $pattern['id'];
|
danielebarchiesi@4
|
262 /* triple */
|
danielebarchiesi@4
|
263 if ($type == 'triple') {
|
danielebarchiesi@4
|
264 foreach (array('s', 'p', 'o') as $term) {
|
danielebarchiesi@4
|
265 if ($pattern[$term . '_type'] == 'var') {
|
danielebarchiesi@4
|
266 $val = $pattern[$term];
|
danielebarchiesi@4
|
267 $this->index['vars'][$val] = array_merge($this->v($val, array(), $this->index['vars']), array(array('table' => $pattern['id'], 'col' =>$term)));
|
danielebarchiesi@4
|
268 }
|
danielebarchiesi@4
|
269 if ($pattern[$term . '_type'] == 'bnode') {
|
danielebarchiesi@4
|
270 $val = $pattern[$term];
|
danielebarchiesi@4
|
271 $this->index['bnodes'][$val] = array_merge($this->v($val, array(), $this->index['bnodes']), array(array('table' => $pattern['id'], 'col' =>$term)));
|
danielebarchiesi@4
|
272 }
|
danielebarchiesi@4
|
273 }
|
danielebarchiesi@4
|
274 $this->index['triple_patterns'][] = $pattern['id'];
|
danielebarchiesi@4
|
275 /* joins */
|
danielebarchiesi@4
|
276 if ($this->isOptionalPattern($id)) {
|
danielebarchiesi@4
|
277 $this->index['left_join'][] = $id;
|
danielebarchiesi@4
|
278 }
|
danielebarchiesi@4
|
279 elseif (!$this->index['from']) {
|
danielebarchiesi@4
|
280 $this->index['from'][] = $id;
|
danielebarchiesi@4
|
281 }
|
danielebarchiesi@4
|
282 elseif (!$this->getJoinInfos($id)) {
|
danielebarchiesi@4
|
283 $this->index['from'][] = $id;
|
danielebarchiesi@4
|
284 }
|
danielebarchiesi@4
|
285 else {
|
danielebarchiesi@4
|
286 $this->index['join'][] = $id;
|
danielebarchiesi@4
|
287 }
|
danielebarchiesi@4
|
288 /* graph infos, graph vars */
|
danielebarchiesi@4
|
289 $this->index['patterns'][$id]['graph_infos'] = $this->getGraphInfos($id);
|
danielebarchiesi@4
|
290 foreach ($this->index['patterns'][$id]['graph_infos'] as $info) {
|
danielebarchiesi@4
|
291 if ($info['type'] == 'graph') {
|
danielebarchiesi@4
|
292 if ($info['var']) {
|
danielebarchiesi@4
|
293 $val = $info['var']['value'];
|
danielebarchiesi@4
|
294 $this->index['graph_vars'][$val] = array_merge($this->v($val, array(), $this->index['graph_vars']), array(array('table' => $id)));
|
danielebarchiesi@4
|
295 }
|
danielebarchiesi@4
|
296 elseif ($info['uri']) {
|
danielebarchiesi@4
|
297 $val = $info['uri'];
|
danielebarchiesi@4
|
298 $this->index['graph_uris'][$val] = array_merge($this->v($val, array(), $this->index['graph_uris']), array(array('table' => $id)));
|
danielebarchiesi@4
|
299 }
|
danielebarchiesi@4
|
300 }
|
danielebarchiesi@4
|
301 }
|
danielebarchiesi@4
|
302 }
|
danielebarchiesi@4
|
303 $sub_ids = $this->v('patterns', array(), $pattern);
|
danielebarchiesi@4
|
304 foreach ($sub_ids as $sub_id) {
|
danielebarchiesi@4
|
305 $this->analyzeIndex($this->getPattern($sub_id));
|
danielebarchiesi@4
|
306 }
|
danielebarchiesi@4
|
307 }
|
danielebarchiesi@4
|
308
|
danielebarchiesi@4
|
309 /* */
|
danielebarchiesi@4
|
310
|
danielebarchiesi@4
|
311 function getGraphInfos($id) {
|
danielebarchiesi@4
|
312 $r = array();
|
danielebarchiesi@4
|
313 if ($id) {
|
danielebarchiesi@4
|
314 $pattern = $this->index['patterns'][$id];
|
danielebarchiesi@4
|
315 $type = $pattern['type'];
|
danielebarchiesi@4
|
316 /* graph */
|
danielebarchiesi@4
|
317 if ($type == 'graph') {
|
danielebarchiesi@4
|
318 $r[] = array('type' => 'graph', 'var' => $pattern['var'], 'uri' => $pattern['uri']);
|
danielebarchiesi@4
|
319 }
|
danielebarchiesi@4
|
320 $p_pattern = $this->index['patterns'][$pattern['parent_id']];
|
danielebarchiesi@4
|
321 if (isset($p_pattern['graph_infos'])) {
|
danielebarchiesi@4
|
322 return array_merge($p_pattern['graph_infos'], $r);
|
danielebarchiesi@4
|
323 }
|
danielebarchiesi@4
|
324 return array_merge($this->getGraphInfos($pattern['parent_id']), $r);
|
danielebarchiesi@4
|
325 }
|
danielebarchiesi@4
|
326 /* FROM / FROM NAMED */
|
danielebarchiesi@4
|
327 else {
|
danielebarchiesi@4
|
328 if (isset($this->infos['query']['dataset'])) {
|
danielebarchiesi@4
|
329 foreach ($this->infos['query']['dataset'] as $set) {
|
danielebarchiesi@4
|
330 $r[] = array_merge(array('type' => 'dataset'), $set);
|
danielebarchiesi@4
|
331 }
|
danielebarchiesi@4
|
332 }
|
danielebarchiesi@4
|
333 }
|
danielebarchiesi@4
|
334 return $r;
|
danielebarchiesi@4
|
335 }
|
danielebarchiesi@4
|
336
|
danielebarchiesi@4
|
337 /* */
|
danielebarchiesi@4
|
338
|
danielebarchiesi@4
|
339 function getPattern($id) {
|
danielebarchiesi@4
|
340 if (is_array($id)) {
|
danielebarchiesi@4
|
341 return $id;
|
danielebarchiesi@4
|
342 }
|
danielebarchiesi@4
|
343 return $this->v($id, array(), $this->index['patterns']);
|
danielebarchiesi@4
|
344 }
|
danielebarchiesi@4
|
345
|
danielebarchiesi@4
|
346 function getInitialPattern($id) {
|
danielebarchiesi@4
|
347 return $this->v($id, array(), $this->initial_index['patterns']);
|
danielebarchiesi@4
|
348 }
|
danielebarchiesi@4
|
349
|
danielebarchiesi@4
|
350 /* */
|
danielebarchiesi@4
|
351
|
danielebarchiesi@4
|
352 function getUnionIndexes($pre_index) {
|
danielebarchiesi@4
|
353 $r = array();
|
danielebarchiesi@4
|
354 $branches = array();
|
danielebarchiesi@4
|
355 $min_depth = 1000;
|
danielebarchiesi@4
|
356 /* only process branches with minimum depth */
|
danielebarchiesi@4
|
357 foreach ($pre_index['union_branches'] as $id) {
|
danielebarchiesi@4
|
358 $branches[$id] = count(preg_split('/\_/', $id));
|
danielebarchiesi@4
|
359 $min_depth = min($min_depth, $branches[$id]);
|
danielebarchiesi@4
|
360 }
|
danielebarchiesi@4
|
361 foreach ($branches as $branch_id => $depth) {
|
danielebarchiesi@4
|
362 if ($depth == $min_depth) {
|
danielebarchiesi@4
|
363 $union_id = preg_replace('/\_[0-9]+$/', '', $branch_id);
|
danielebarchiesi@4
|
364 $index = array('keeping' => $branch_id, 'union_branches' => array(), 'patterns' => $pre_index['patterns']);
|
danielebarchiesi@4
|
365 $old_branches = $index['patterns'][$union_id]['patterns'];
|
danielebarchiesi@4
|
366 $skip_id = ($old_branches[0] == $branch_id) ? $old_branches[1] : $old_branches[0];
|
danielebarchiesi@4
|
367 $index['patterns'][$union_id]['type'] = 'group';
|
danielebarchiesi@4
|
368 $index['patterns'][$union_id]['patterns'] = array($branch_id);
|
danielebarchiesi@4
|
369 $has_sub_unions = 0;
|
danielebarchiesi@4
|
370 foreach ($index['patterns'] as $pattern_id => $pattern) {
|
danielebarchiesi@4
|
371 if (preg_match('/^' .$skip_id. '/', $pattern_id)) {
|
danielebarchiesi@4
|
372 unset($index['patterns'][$pattern_id]);
|
danielebarchiesi@4
|
373 }
|
danielebarchiesi@4
|
374 elseif ($pattern['type'] == 'union') {
|
danielebarchiesi@4
|
375 foreach ($pattern['patterns'] as $sub_union_branch_id) {
|
danielebarchiesi@4
|
376 $index['union_branches'][] = $sub_union_branch_id;
|
danielebarchiesi@4
|
377 }
|
danielebarchiesi@4
|
378 }
|
danielebarchiesi@4
|
379 }
|
danielebarchiesi@4
|
380 if ($index['union_branches']) {
|
danielebarchiesi@4
|
381 $r = array_merge($r, $this->getUnionIndexes($index));
|
danielebarchiesi@4
|
382 }
|
danielebarchiesi@4
|
383 else {
|
danielebarchiesi@4
|
384 $r[] = $index;
|
danielebarchiesi@4
|
385 }
|
danielebarchiesi@4
|
386 }
|
danielebarchiesi@4
|
387 }
|
danielebarchiesi@4
|
388 return $r;
|
danielebarchiesi@4
|
389 }
|
danielebarchiesi@4
|
390
|
danielebarchiesi@4
|
391 /* */
|
danielebarchiesi@4
|
392
|
danielebarchiesi@4
|
393 function isOptionalPattern($id) {
|
danielebarchiesi@4
|
394 $pattern = $this->getPattern($id);
|
danielebarchiesi@4
|
395 if ($this->v('type', '', $pattern) == 'optional') {
|
danielebarchiesi@4
|
396 return 1;
|
danielebarchiesi@4
|
397 }
|
danielebarchiesi@4
|
398 if ($this->v('parent_id', '0', $pattern) == '0') {
|
danielebarchiesi@4
|
399 return 0;
|
danielebarchiesi@4
|
400 }
|
danielebarchiesi@4
|
401 return $this->isOptionalPattern($pattern['parent_id']);
|
danielebarchiesi@4
|
402 }
|
danielebarchiesi@4
|
403
|
danielebarchiesi@4
|
404 function getOptionalPattern($id) {
|
danielebarchiesi@4
|
405 $pn = $this->getPattern($id);
|
danielebarchiesi@4
|
406 do {
|
danielebarchiesi@4
|
407 $pn = $this->getPattern($pn['parent_id']);
|
danielebarchiesi@4
|
408 } while ($pn['parent_id'] && ($pn['type'] != 'optional'));
|
danielebarchiesi@4
|
409 return $pn['id'];
|
danielebarchiesi@4
|
410 }
|
danielebarchiesi@4
|
411
|
danielebarchiesi@4
|
412 function sameOptional($id, $id2) {
|
danielebarchiesi@4
|
413 return $this->getOptionalPattern($id) == $this->getOptionalPattern($id2);
|
danielebarchiesi@4
|
414 }
|
danielebarchiesi@4
|
415
|
danielebarchiesi@4
|
416 /* */
|
danielebarchiesi@4
|
417
|
danielebarchiesi@4
|
418 function isUnionPattern($id) {
|
danielebarchiesi@4
|
419 $pattern = $this->getPattern($id);
|
danielebarchiesi@4
|
420 if ($this->v('type', '', $pattern) == 'union') {
|
danielebarchiesi@4
|
421 return 1;
|
danielebarchiesi@4
|
422 }
|
danielebarchiesi@4
|
423 if ($this->v('parent_id', '0', $pattern) == '0') {
|
danielebarchiesi@4
|
424 return 0;
|
danielebarchiesi@4
|
425 }
|
danielebarchiesi@4
|
426 return $this->isUnionPattern($pattern['parent_id']);
|
danielebarchiesi@4
|
427 }
|
danielebarchiesi@4
|
428
|
danielebarchiesi@4
|
429 /* */
|
danielebarchiesi@4
|
430
|
danielebarchiesi@4
|
431 function getValueTable($col) {
|
danielebarchiesi@4
|
432 return $this->store->getTablePrefix() . (preg_match('/^(s|o)$/', $col) ? $col . '2val' : 'id2val');
|
danielebarchiesi@4
|
433 }
|
danielebarchiesi@4
|
434
|
danielebarchiesi@4
|
435 function getGraphTable() {
|
danielebarchiesi@4
|
436 return $this->store->getTablePrefix() . 'g2t';
|
danielebarchiesi@4
|
437 }
|
danielebarchiesi@4
|
438
|
danielebarchiesi@4
|
439 /* */
|
danielebarchiesi@4
|
440
|
danielebarchiesi@4
|
441 function getQuerySQL() {
|
danielebarchiesi@4
|
442 $nl = "\n";
|
danielebarchiesi@4
|
443 $where_sql = $this->getWHERESQL(); /* pre-fills $index['sub_joins'] $index['constraints'] */
|
danielebarchiesi@4
|
444 $order_sql = $this->getORDERSQL(); /* pre-fills $index['sub_joins'] $index['constraints'] */
|
danielebarchiesi@4
|
445 return '' .
|
danielebarchiesi@4
|
446 ($this->is_union_query ? 'SELECT' : 'SELECT' . $this->getDistinctSQL()) . $nl .
|
danielebarchiesi@4
|
447 $this->getResultVarsSQL() . $nl . /* fills $index['sub_joins'] */
|
danielebarchiesi@4
|
448 $this->getFROMSQL() .
|
danielebarchiesi@4
|
449 $this->getAllJoinsSQL() .
|
danielebarchiesi@4
|
450 $this->getWHERESQL() .
|
danielebarchiesi@4
|
451 $this->getGROUPSQL() .
|
danielebarchiesi@4
|
452 $this->getORDERSQL() .
|
danielebarchiesi@4
|
453 ($this->is_union_query ? '' : $this->getLIMITSQL()) .
|
danielebarchiesi@4
|
454 $nl .
|
danielebarchiesi@4
|
455 '';
|
danielebarchiesi@4
|
456 }
|
danielebarchiesi@4
|
457
|
danielebarchiesi@4
|
458 /* */
|
danielebarchiesi@4
|
459
|
danielebarchiesi@4
|
460 function getDistinctSQL() {
|
danielebarchiesi@4
|
461 if ($this->is_union_query) {
|
danielebarchiesi@4
|
462 return ($this->v('distinct', 0, $this->infos['query']) || $this->v('reduced', 0, $this->infos['query'])) ? '' : ' ALL';
|
danielebarchiesi@4
|
463 }
|
danielebarchiesi@4
|
464 return ($this->v('distinct', 0, $this->infos['query']) || $this->v('reduced', 0, $this->infos['query'])) ? ' DISTINCT' : '';
|
danielebarchiesi@4
|
465 }
|
danielebarchiesi@4
|
466
|
danielebarchiesi@4
|
467 /* */
|
danielebarchiesi@4
|
468
|
danielebarchiesi@4
|
469 function getResultVarsSQL() {
|
danielebarchiesi@4
|
470 $r = '';
|
danielebarchiesi@4
|
471 $vars = $this->infos['query']['result_vars'];
|
danielebarchiesi@4
|
472 $nl = "\n";
|
danielebarchiesi@4
|
473 $added = array();
|
danielebarchiesi@4
|
474 foreach ($vars as $var) {
|
danielebarchiesi@4
|
475 $var_name = $var['var'];
|
danielebarchiesi@4
|
476 $tbl_alias = '';
|
danielebarchiesi@4
|
477 if ($tbl_infos = $this->getVarTableInfos($var_name, 0)) {
|
danielebarchiesi@4
|
478 $tbl = $tbl_infos['table'];
|
danielebarchiesi@4
|
479 $col = $tbl_infos['col'];
|
danielebarchiesi@4
|
480 $tbl_alias = $tbl_infos['table_alias'];
|
danielebarchiesi@4
|
481 }
|
danielebarchiesi@4
|
482 elseif ($var_name == 1) {/* ASK query */
|
danielebarchiesi@4
|
483 $r .= '1 AS `success`';
|
danielebarchiesi@4
|
484 }
|
danielebarchiesi@4
|
485 else {
|
danielebarchiesi@4
|
486 $this->addError('Result variable "' .$var_name. '" not used in query.');
|
danielebarchiesi@4
|
487 }
|
danielebarchiesi@4
|
488 if ($tbl_alias) {
|
danielebarchiesi@4
|
489 /* aggregate */
|
danielebarchiesi@4
|
490 if ($var['aggregate']) {
|
danielebarchiesi@4
|
491 $conv_code = '';
|
danielebarchiesi@4
|
492 if (strtolower($var['aggregate']) != 'count') {
|
danielebarchiesi@4
|
493 $tbl_alias = 'V_' . $tbl . '_' . $col . '.val';
|
danielebarchiesi@4
|
494 $conv_code = '0 + ';
|
danielebarchiesi@4
|
495 }
|
danielebarchiesi@4
|
496 if (!isset($added[$var['alias']])) {
|
danielebarchiesi@4
|
497 $r .= $r ? ',' . $nl . ' ' : ' ';
|
danielebarchiesi@4
|
498 $distinct_code = (strtolower($var['aggregate']) == 'count') && $this->v('distinct', 0, $this->infos['query']) ? 'DISTINCT ' : '';
|
danielebarchiesi@4
|
499 $r .= $var['aggregate'] . '(' . $conv_code . $distinct_code . $tbl_alias. ') AS `' . $var['alias'] . '`';
|
danielebarchiesi@4
|
500 $added[$var['alias']] = 1;
|
danielebarchiesi@4
|
501 }
|
danielebarchiesi@4
|
502 }
|
danielebarchiesi@4
|
503 /* normal var */
|
danielebarchiesi@4
|
504 else {
|
danielebarchiesi@4
|
505 if (!isset($added[$var_name])) {
|
danielebarchiesi@4
|
506 $r .= $r ? ',' . $nl . ' ' : ' ';
|
danielebarchiesi@4
|
507 $r .= $tbl_alias . ' AS `' . $var_name . '`';
|
danielebarchiesi@4
|
508 $is_s = ($col == 's');
|
danielebarchiesi@4
|
509 $is_p = ($col == 'p');
|
danielebarchiesi@4
|
510 $is_o = ($col == 'o');
|
danielebarchiesi@4
|
511 if ($tbl_alias == 'NULL') {
|
danielebarchiesi@4
|
512 /* type / add in UNION queries? */
|
danielebarchiesi@4
|
513 if ($is_s || $is_o) {
|
danielebarchiesi@4
|
514 $r .= ', ' . $nl . ' NULL AS `' . $var_name . ' type`';
|
danielebarchiesi@4
|
515 }
|
danielebarchiesi@4
|
516 /* lang_dt / always add it in UNION queries, the var may be used as s/p/o */
|
danielebarchiesi@4
|
517 if ($is_o || $this->is_union_query) {
|
danielebarchiesi@4
|
518 $r .= ', ' . $nl . ' NULL AS `' . $var_name . ' lang_dt`';
|
danielebarchiesi@4
|
519 }
|
danielebarchiesi@4
|
520 }
|
danielebarchiesi@4
|
521 else {
|
danielebarchiesi@4
|
522 /* type */
|
danielebarchiesi@4
|
523 if ($is_s || $is_o) {
|
danielebarchiesi@4
|
524 $r .= ', ' . $nl . ' ' .$tbl_alias . '_type AS `' . $var_name . ' type`';
|
danielebarchiesi@4
|
525 }
|
danielebarchiesi@4
|
526 /* lang_dt / always add it in UNION queries, the var may be used as s/p/o */
|
danielebarchiesi@4
|
527 if ($is_o) {
|
danielebarchiesi@4
|
528 $r .= ', ' . $nl . ' ' .$tbl_alias . '_lang_dt AS `' . $var_name . ' lang_dt`';
|
danielebarchiesi@4
|
529 }
|
danielebarchiesi@4
|
530 elseif ($this->is_union_query) {
|
danielebarchiesi@4
|
531 $r .= ', ' . $nl . ' NULL AS `' . $var_name . ' lang_dt`';
|
danielebarchiesi@4
|
532 }
|
danielebarchiesi@4
|
533 }
|
danielebarchiesi@4
|
534 $added[$var_name] = 1;
|
danielebarchiesi@4
|
535 }
|
danielebarchiesi@4
|
536 }
|
danielebarchiesi@4
|
537 if (!in_array($tbl_alias, $this->index['sub_joins'])) {
|
danielebarchiesi@4
|
538 $this->index['sub_joins'][] = $tbl_alias;
|
danielebarchiesi@4
|
539 }
|
danielebarchiesi@4
|
540 }
|
danielebarchiesi@4
|
541 }
|
danielebarchiesi@4
|
542 return $r ? $r : '1 AS `success`';
|
danielebarchiesi@4
|
543 }
|
danielebarchiesi@4
|
544
|
danielebarchiesi@4
|
545 function getVarTableInfos($var, $ignore_initial_index = 1) {
|
danielebarchiesi@4
|
546 if ($var == '*') {
|
danielebarchiesi@4
|
547 return array('table' => '', 'col' => '', 'table_alias' => '*');
|
danielebarchiesi@4
|
548 }
|
danielebarchiesi@4
|
549 if ($infos = $this->v($var, 0, $this->index['vars'])) {
|
danielebarchiesi@4
|
550 $infos[0]['table_alias'] = 'T_' . $infos[0]['table'] . '.' . $infos[0]['col'];
|
danielebarchiesi@4
|
551 return $infos[0];
|
danielebarchiesi@4
|
552 }
|
danielebarchiesi@4
|
553 if ($infos = $this->v($var, 0, $this->index['graph_vars'])) {
|
danielebarchiesi@4
|
554 $infos[0]['col'] = 'g';
|
danielebarchiesi@4
|
555 $infos[0]['table_alias'] = 'G_' . $infos[0]['table'] . '.' . $infos[0]['col'];
|
danielebarchiesi@4
|
556 return $infos[0];
|
danielebarchiesi@4
|
557 }
|
danielebarchiesi@4
|
558 if ($this->is_union_query && !$ignore_initial_index) {
|
danielebarchiesi@4
|
559 if (($infos = $this->v($var, 0, $this->initial_index['vars'])) || ($infos = $this->v($var, 0, $this->initial_index['graph_vars']))) {
|
danielebarchiesi@4
|
560 if (!in_array($var, $this->infos['null_vars'])) {
|
danielebarchiesi@4
|
561 $this->infos['null_vars'][] = $var;
|
danielebarchiesi@4
|
562 }
|
danielebarchiesi@4
|
563 $infos[0]['table_alias'] = 'NULL';
|
danielebarchiesi@4
|
564 $infos[0]['col'] = !isset($infos[0]['col']) ? '' : $infos[0]['col'];
|
danielebarchiesi@4
|
565 return $infos[0];
|
danielebarchiesi@4
|
566 }
|
danielebarchiesi@4
|
567 }
|
danielebarchiesi@4
|
568 return 0;
|
danielebarchiesi@4
|
569 }
|
danielebarchiesi@4
|
570
|
danielebarchiesi@4
|
571 /* */
|
danielebarchiesi@4
|
572
|
danielebarchiesi@4
|
573 function getFROMSQL() {
|
danielebarchiesi@4
|
574 $from_ids = $this->index['from'];
|
danielebarchiesi@4
|
575 $r = '';
|
danielebarchiesi@4
|
576 foreach ($from_ids as $from_id) {
|
danielebarchiesi@4
|
577 $r .= $r ? ', ' : '';
|
danielebarchiesi@4
|
578 $r .= $this->getTripleTable($from_id) . ' T_' . $from_id;
|
danielebarchiesi@4
|
579 }
|
danielebarchiesi@4
|
580 /* MySQL 5 requires parentheses in case of multiple tables */
|
danielebarchiesi@4
|
581 /* MySQL >5.5 (?) does not allow parentheses in case of a single table anymore! */
|
danielebarchiesi@4
|
582 $r = (count($from_ids) > 1) ? '(' . $r . ')' : $r;
|
danielebarchiesi@4
|
583 return $r ? 'FROM ' . $r : '';
|
danielebarchiesi@4
|
584 }
|
danielebarchiesi@4
|
585
|
danielebarchiesi@4
|
586 /* */
|
danielebarchiesi@4
|
587
|
danielebarchiesi@4
|
588 function getOrderedJoinIDs() {
|
danielebarchiesi@4
|
589 return array_merge($this->index['from'], $this->index['join'], $this->index['left_join']);
|
danielebarchiesi@4
|
590 }
|
danielebarchiesi@4
|
591
|
danielebarchiesi@4
|
592 function getJoinInfos($id) {
|
danielebarchiesi@4
|
593 $r = array();
|
danielebarchiesi@4
|
594 $tbl_ids = $this->getOrderedJoinIDs();
|
danielebarchiesi@4
|
595 $pattern = $this->getPattern($id);
|
danielebarchiesi@4
|
596 foreach ($tbl_ids as $tbl_id) {
|
danielebarchiesi@4
|
597 $tbl_pattern = $this->getPattern($tbl_id);
|
danielebarchiesi@4
|
598 if ($tbl_id != $id) {
|
danielebarchiesi@4
|
599 foreach (array('s', 'p', 'o') as $tbl_term) {
|
danielebarchiesi@4
|
600 foreach (array('var', 'bnode', 'uri') as $term_type) {
|
danielebarchiesi@4
|
601 if ($tbl_pattern[$tbl_term . '_type'] == $term_type) {
|
danielebarchiesi@4
|
602 foreach (array('s', 'p', 'o') as $term) {
|
danielebarchiesi@4
|
603 if (($pattern[$term . '_type'] == $term_type) && ($tbl_pattern[$tbl_term] == $pattern[$term])) {
|
danielebarchiesi@4
|
604 $r[] = array('term' => $term, 'join_tbl' => $tbl_id, 'join_term' => $tbl_term);
|
danielebarchiesi@4
|
605 }
|
danielebarchiesi@4
|
606 }
|
danielebarchiesi@4
|
607 }
|
danielebarchiesi@4
|
608 }
|
danielebarchiesi@4
|
609 }
|
danielebarchiesi@4
|
610 }
|
danielebarchiesi@4
|
611 }
|
danielebarchiesi@4
|
612 return $r;
|
danielebarchiesi@4
|
613 }
|
danielebarchiesi@4
|
614
|
danielebarchiesi@4
|
615 function getAllJoinsSQL() {
|
danielebarchiesi@4
|
616 $js = $this->getJoins();
|
danielebarchiesi@4
|
617 $ljs = $this->getLeftJoins();
|
danielebarchiesi@4
|
618 $entries = array_merge($js, $ljs);
|
danielebarchiesi@4
|
619 $id2code = array();
|
danielebarchiesi@4
|
620 foreach ($entries as $entry) {
|
danielebarchiesi@4
|
621 if (preg_match('/([^\s]+) ON (.*)/s', $entry, $m)) {
|
danielebarchiesi@4
|
622 $id2code[$m[1]] = $entry;
|
danielebarchiesi@4
|
623 }
|
danielebarchiesi@4
|
624 }
|
danielebarchiesi@4
|
625 $deps = array();
|
danielebarchiesi@4
|
626 foreach ($id2code as $id => $code) {
|
danielebarchiesi@4
|
627 $deps[$id]['rank'] = 0;
|
danielebarchiesi@4
|
628 foreach ($id2code as $other_id => $other_code) {
|
danielebarchiesi@4
|
629 $deps[$id]['rank'] += ($id != $other_id) && preg_match('/' . $other_id . '/', $code) ? 1 : 0;
|
danielebarchiesi@4
|
630 $deps[$id][$other_id] = ($id != $other_id) && preg_match('/' . $other_id . '/', $code) ? 1 : 0;
|
danielebarchiesi@4
|
631 }
|
danielebarchiesi@4
|
632 }
|
danielebarchiesi@4
|
633 $r = '';
|
danielebarchiesi@4
|
634 do {
|
danielebarchiesi@4
|
635 /* get next 0-rank */
|
danielebarchiesi@4
|
636 $next_id = 0;
|
danielebarchiesi@4
|
637 foreach ($deps as $id => $infos) {
|
danielebarchiesi@4
|
638 if ($infos['rank'] == 0) {
|
danielebarchiesi@4
|
639 $next_id = $id;
|
danielebarchiesi@4
|
640 break;
|
danielebarchiesi@4
|
641 }
|
danielebarchiesi@4
|
642 }
|
danielebarchiesi@4
|
643 if ($next_id) {
|
danielebarchiesi@4
|
644 $r .= "\n" . $id2code[$next_id];
|
danielebarchiesi@4
|
645 unset($deps[$next_id]);
|
danielebarchiesi@4
|
646 foreach ($deps as $id => $infos) {
|
danielebarchiesi@4
|
647 $deps[$id]['rank'] = 0;
|
danielebarchiesi@4
|
648 unset($deps[$id][$next_id]);
|
danielebarchiesi@4
|
649 foreach ($infos as $k => $v) {
|
danielebarchiesi@4
|
650 if (!in_array($k, array('rank', $next_id))) {
|
danielebarchiesi@4
|
651 $deps[$id]['rank'] += $v;
|
danielebarchiesi@4
|
652 $deps[$id][$k] = $v;
|
danielebarchiesi@4
|
653 }
|
danielebarchiesi@4
|
654 }
|
danielebarchiesi@4
|
655 }
|
danielebarchiesi@4
|
656 }
|
danielebarchiesi@4
|
657 }
|
danielebarchiesi@4
|
658 while ($next_id);
|
danielebarchiesi@4
|
659 if ($deps) {
|
danielebarchiesi@4
|
660 $this->addError('Not all patterns could be rewritten to SQL JOINs');
|
danielebarchiesi@4
|
661 }
|
danielebarchiesi@4
|
662 return $r;
|
danielebarchiesi@4
|
663 }
|
danielebarchiesi@4
|
664
|
danielebarchiesi@4
|
665 function getJoins() {
|
danielebarchiesi@4
|
666 $r = array();
|
danielebarchiesi@4
|
667 $nl = "\n";
|
danielebarchiesi@4
|
668 foreach ($this->index['join'] as $id) {
|
danielebarchiesi@4
|
669 $sub_r = $this->getJoinConditionSQL($id);
|
danielebarchiesi@4
|
670 $r[] = 'JOIN ' . $this->getTripleTable($id) . ' T_' . $id . ' ON (' . $sub_r . $nl . ')';
|
danielebarchiesi@4
|
671 }
|
danielebarchiesi@4
|
672 foreach (array_merge($this->index['from'], $this->index['join']) as $id) {
|
danielebarchiesi@4
|
673 if ($sub_r = $this->getRequiredSubJoinSQL($id)) {
|
danielebarchiesi@4
|
674 $r[] = $sub_r;
|
danielebarchiesi@4
|
675 }
|
danielebarchiesi@4
|
676 }
|
danielebarchiesi@4
|
677 return $r;
|
danielebarchiesi@4
|
678 }
|
danielebarchiesi@4
|
679
|
danielebarchiesi@4
|
680 function getLeftJoins() {
|
danielebarchiesi@4
|
681 $r = array();
|
danielebarchiesi@4
|
682 $nl = "\n";
|
danielebarchiesi@4
|
683 foreach ($this->index['left_join'] as $id) {
|
danielebarchiesi@4
|
684 $sub_r = $this->getJoinConditionSQL($id);
|
danielebarchiesi@4
|
685 $r[] = 'LEFT JOIN ' . $this->getTripleTable($id) . ' T_' . $id . ' ON (' . $sub_r . $nl . ')';
|
danielebarchiesi@4
|
686 }
|
danielebarchiesi@4
|
687 foreach ($this->index['left_join'] as $id) {
|
danielebarchiesi@4
|
688 if ($sub_r = $this->getRequiredSubJoinSQL($id, 'LEFT')) {
|
danielebarchiesi@4
|
689 $r[] = $sub_r;
|
danielebarchiesi@4
|
690 }
|
danielebarchiesi@4
|
691 }
|
danielebarchiesi@4
|
692 return $r;
|
danielebarchiesi@4
|
693 }
|
danielebarchiesi@4
|
694
|
danielebarchiesi@4
|
695 function getJoinConditionSQL($id) {
|
danielebarchiesi@4
|
696 $r = '';
|
danielebarchiesi@4
|
697 $nl = "\n";
|
danielebarchiesi@4
|
698 $infos = $this->getJoinInfos($id);
|
danielebarchiesi@4
|
699 $pattern = $this->getPattern($id);
|
danielebarchiesi@4
|
700
|
danielebarchiesi@4
|
701 $tbl = 'T_' . $id;
|
danielebarchiesi@4
|
702 /* core dependency */
|
danielebarchiesi@4
|
703 $d_tbls = $this->getDependentJoins($id);
|
danielebarchiesi@4
|
704 foreach ($d_tbls as $d_tbl) {
|
danielebarchiesi@4
|
705 if (preg_match('/^T_([0-9\_]+)\.[spo]+/', $d_tbl, $m) && ($m[1] != $id)) {
|
danielebarchiesi@4
|
706 if ($this->isJoinedBefore($m[1], $id) && !in_array($m[1], array_merge($this->index['from'], $this->index['join']))) {
|
danielebarchiesi@4
|
707 $r .= $r ? $nl . ' AND ' : $nl . ' ';
|
danielebarchiesi@4
|
708 $r .= '(' . $d_tbl . ' IS NOT NULL)';
|
danielebarchiesi@4
|
709 }
|
danielebarchiesi@4
|
710 $this->logDependency($id, $d_tbl);
|
danielebarchiesi@4
|
711 }
|
danielebarchiesi@4
|
712 }
|
danielebarchiesi@4
|
713 /* triple-based join info */
|
danielebarchiesi@4
|
714 foreach ($infos as $info) {
|
danielebarchiesi@4
|
715 if ($this->isJoinedBefore($info['join_tbl'], $id) && $this->joinDependsOn($id, $info['join_tbl'])) {
|
danielebarchiesi@4
|
716 $r .= $r ? $nl . ' AND ' : $nl . ' ';
|
danielebarchiesi@4
|
717 $r .= '(' . $tbl . '.' . $info['term'] . ' = T_' . $info['join_tbl'] . '.' . $info['join_term'] . ')';
|
danielebarchiesi@4
|
718 }
|
danielebarchiesi@4
|
719 }
|
danielebarchiesi@4
|
720 /* filters etc */
|
danielebarchiesi@4
|
721 if ($sub_r = $this->getPatternSQL($pattern, 'join__T_' . $id)) {
|
danielebarchiesi@4
|
722 $r .= $r ? $nl . ' AND ' . $sub_r : $nl . ' ' . '(' . $sub_r . ')';
|
danielebarchiesi@4
|
723 }
|
danielebarchiesi@4
|
724 return $r;
|
danielebarchiesi@4
|
725 }
|
danielebarchiesi@4
|
726
|
danielebarchiesi@4
|
727 /**
|
danielebarchiesi@4
|
728 * A log of identified table join dependencies in getJoinConditionSQL
|
danielebarchiesi@4
|
729 *
|
danielebarchiesi@4
|
730 */
|
danielebarchiesi@4
|
731
|
danielebarchiesi@4
|
732 function logDependency($id, $tbl) {
|
danielebarchiesi@4
|
733 if (!isset($this->dependency_log[$id])) $this->dependency_log[$id] = array();
|
danielebarchiesi@4
|
734 if (!in_array($tbl, $this->dependency_log[$id])) {
|
danielebarchiesi@4
|
735 $this->dependency_log[$id][] = $tbl;
|
danielebarchiesi@4
|
736 }
|
danielebarchiesi@4
|
737 }
|
danielebarchiesi@4
|
738
|
danielebarchiesi@4
|
739 /**
|
danielebarchiesi@4
|
740 * checks whether entries in the dependecy log could perhaps be optimized
|
danielebarchiesi@4
|
741 * (triggers re-ordering of patterns
|
danielebarchiesi@4
|
742 */
|
danielebarchiesi@4
|
743
|
danielebarchiesi@4
|
744 function problematicDependencies() {
|
danielebarchiesi@4
|
745 foreach ($this->dependency_log as $id => $tbls) {
|
danielebarchiesi@4
|
746 if (count($tbls) > 1) return count($tbls);
|
danielebarchiesi@4
|
747 }
|
danielebarchiesi@4
|
748 return 0;
|
danielebarchiesi@4
|
749 }
|
danielebarchiesi@4
|
750
|
danielebarchiesi@4
|
751 function isJoinedBefore($tbl_1, $tbl_2) {
|
danielebarchiesi@4
|
752 $tbl_ids = $this->getOrderedJoinIDs();
|
danielebarchiesi@4
|
753 foreach ($tbl_ids as $id) {
|
danielebarchiesi@4
|
754 if ($id == $tbl_1) {
|
danielebarchiesi@4
|
755 return 1;
|
danielebarchiesi@4
|
756 }
|
danielebarchiesi@4
|
757 if ($id == $tbl_2) {
|
danielebarchiesi@4
|
758 return 0;
|
danielebarchiesi@4
|
759 }
|
danielebarchiesi@4
|
760 }
|
danielebarchiesi@4
|
761 }
|
danielebarchiesi@4
|
762
|
danielebarchiesi@4
|
763 function joinDependsOn($id, $id2) {
|
danielebarchiesi@4
|
764 if (in_array($id2, array_merge($this->index['from'], $this->index['join']))) {
|
danielebarchiesi@4
|
765 return 1;
|
danielebarchiesi@4
|
766 }
|
danielebarchiesi@4
|
767 $d_tbls = $this->getDependentJoins($id2);
|
danielebarchiesi@4
|
768 //echo $id . ' :: ' . $id2 . '=>' . print_r($d_tbls, 1);
|
danielebarchiesi@4
|
769 foreach ($d_tbls as $d_tbl) {
|
danielebarchiesi@4
|
770 if (preg_match('/^T_' .$id. '\./', $d_tbl)) {
|
danielebarchiesi@4
|
771 return 1;
|
danielebarchiesi@4
|
772 }
|
danielebarchiesi@4
|
773 }
|
danielebarchiesi@4
|
774 return 0;
|
danielebarchiesi@4
|
775 }
|
danielebarchiesi@4
|
776
|
danielebarchiesi@4
|
777 function getDependentJoins($id) {
|
danielebarchiesi@4
|
778 $r = array();
|
danielebarchiesi@4
|
779 /* sub joins */
|
danielebarchiesi@4
|
780 foreach ($this->index['sub_joins'] as $alias) {
|
danielebarchiesi@4
|
781 if (preg_match('/^(T|V|G)_' . $id . '/', $alias)) {
|
danielebarchiesi@4
|
782 $r[] = $alias;
|
danielebarchiesi@4
|
783 }
|
danielebarchiesi@4
|
784 }
|
danielebarchiesi@4
|
785 /* siblings in shared optional */
|
danielebarchiesi@4
|
786 $o_id = $this->getOptionalPattern($id);
|
danielebarchiesi@4
|
787 foreach ($this->index['sub_joins'] as $alias) {
|
danielebarchiesi@4
|
788 if (preg_match('/^(T|V|G)_' . $o_id . '/', $alias) && !in_array($alias, $r)) {
|
danielebarchiesi@4
|
789 $r[] = $alias;
|
danielebarchiesi@4
|
790 }
|
danielebarchiesi@4
|
791 }
|
danielebarchiesi@4
|
792 foreach ($this->index['left_join'] as $alias) {
|
danielebarchiesi@4
|
793 if (preg_match('/^' . $o_id . '/', $alias) && !in_array($alias, $r)) {
|
danielebarchiesi@4
|
794 $r[] = 'T_' . $alias . '.s';
|
danielebarchiesi@4
|
795 }
|
danielebarchiesi@4
|
796 }
|
danielebarchiesi@4
|
797 return $r;
|
danielebarchiesi@4
|
798 }
|
danielebarchiesi@4
|
799
|
danielebarchiesi@4
|
800 /* */
|
danielebarchiesi@4
|
801
|
danielebarchiesi@4
|
802 function getRequiredSubJoinSQL($id, $prefix = '') {/* id is a triple pattern id. Optional FILTERS and GRAPHs are getting added to the join directly */
|
danielebarchiesi@4
|
803 $nl = "\n";
|
danielebarchiesi@4
|
804 $r = '';
|
danielebarchiesi@4
|
805 foreach ($this->index['sub_joins'] as $alias) {
|
danielebarchiesi@4
|
806 if (preg_match('/^V_' . $id . '_([a-z\_]+)\.val$/', $alias, $m)) {
|
danielebarchiesi@4
|
807 $col = $m[1];
|
danielebarchiesi@4
|
808 $sub_r = '';
|
danielebarchiesi@4
|
809 if ($this->isOptionalPattern($id)) {
|
danielebarchiesi@4
|
810 $pattern = $this->getPattern($id);
|
danielebarchiesi@4
|
811 do {
|
danielebarchiesi@4
|
812 $pattern = $this->getPattern($pattern['parent_id']);
|
danielebarchiesi@4
|
813 } while ($pattern['parent_id'] && ($pattern['type'] != 'optional'));
|
danielebarchiesi@4
|
814 $sub_r = $this->getPatternSQL($pattern, 'sub_join__V_' . $id);
|
danielebarchiesi@4
|
815 }
|
danielebarchiesi@4
|
816 $sub_r = $sub_r ? $nl . ' AND (' . $sub_r . ')' : '';
|
danielebarchiesi@4
|
817 /* lang dt only on literals */
|
danielebarchiesi@4
|
818 if ($col == 'o_lang_dt') {
|
danielebarchiesi@4
|
819 $sub_sub_r = 'T_' . $id . '.o_type = 2';
|
danielebarchiesi@4
|
820 $sub_r .= $nl . ' AND (' . $sub_sub_r . ')';
|
danielebarchiesi@4
|
821 }
|
danielebarchiesi@4
|
822 //$cur_prefix = $prefix ? $prefix . ' ' : 'STRAIGHT_';
|
danielebarchiesi@4
|
823 $cur_prefix = $prefix ? $prefix . ' ' : '';
|
danielebarchiesi@4
|
824 if ($col == 'g') {
|
danielebarchiesi@4
|
825 $r .= trim($cur_prefix . 'JOIN '. $this->getValueTable($col) . ' V_' .$id . '_' . $col. ' ON (' .$nl. ' (G_' . $id . '.' . $col. ' = V_' . $id. '_' . $col. '.id) ' . $sub_r . $nl . ')');
|
danielebarchiesi@4
|
826 }
|
danielebarchiesi@4
|
827 else {
|
danielebarchiesi@4
|
828 $r .= trim($cur_prefix . 'JOIN '. $this->getValueTable($col) . ' V_' .$id . '_' . $col. ' ON (' .$nl. ' (T_' . $id . '.' . $col. ' = V_' . $id. '_' . $col. '.id) ' . $sub_r . $nl . ')');
|
danielebarchiesi@4
|
829 }
|
danielebarchiesi@4
|
830 }
|
danielebarchiesi@4
|
831 elseif (preg_match('/^G_' . $id . '\.g$/', $alias, $m)) {
|
danielebarchiesi@4
|
832 $pattern = $this->getPattern($id);
|
danielebarchiesi@4
|
833 $sub_r = $this->getPatternSQL($pattern, 'graph_sub_join__G_' . $id);
|
danielebarchiesi@4
|
834 $sub_r = $sub_r ? $nl . ' AND ' . $sub_r : '';
|
danielebarchiesi@4
|
835 /* dataset restrictions */
|
danielebarchiesi@4
|
836 $gi = $this->getGraphInfos($id);
|
danielebarchiesi@4
|
837 $sub_sub_r = '';
|
danielebarchiesi@4
|
838 $added_gts = array();
|
danielebarchiesi@4
|
839 foreach ($gi as $set) {
|
danielebarchiesi@4
|
840 if (isset($set['graph']) && !in_array($set['graph'], $added_gts)) {
|
danielebarchiesi@4
|
841 $sub_sub_r .= $sub_sub_r !== '' ? ',' : '';
|
danielebarchiesi@4
|
842 $sub_sub_r .= $this->getTermID($set['graph'], 'g');
|
danielebarchiesi@4
|
843 $added_gts[] = $set['graph'];
|
danielebarchiesi@4
|
844 }
|
danielebarchiesi@4
|
845 }
|
danielebarchiesi@4
|
846 $sub_r .= ($sub_sub_r !== '') ? $nl . ' AND (G_' . $id . '.g IN (' . $sub_sub_r . '))' : ''; // /* ' . str_replace('#' , '::', $set['graph']) . ' */';
|
danielebarchiesi@4
|
847 /* other graph join conditions */
|
danielebarchiesi@4
|
848 foreach ($this->index['graph_vars'] as $var => $occurs) {
|
danielebarchiesi@4
|
849 $occur_tbls = array();
|
danielebarchiesi@4
|
850 foreach ($occurs as $occur) {
|
danielebarchiesi@4
|
851 $occur_tbls[] = $occur['table'];
|
danielebarchiesi@4
|
852 if ($occur['table'] == $id) break;
|
danielebarchiesi@4
|
853 }
|
danielebarchiesi@4
|
854 foreach($occur_tbls as $tbl) {
|
danielebarchiesi@4
|
855 if (($tbl != $id) && in_array($id, $occur_tbls) && $this->isJoinedBefore($tbl, $id)) {
|
danielebarchiesi@4
|
856 $sub_r .= $nl . ' AND (G_' .$id. '.g = G_' .$tbl. '.g)';
|
danielebarchiesi@4
|
857 }
|
danielebarchiesi@4
|
858 }
|
danielebarchiesi@4
|
859 }
|
danielebarchiesi@4
|
860 //$cur_prefix = $prefix ? $prefix . ' ' : 'STRAIGHT_';
|
danielebarchiesi@4
|
861 $cur_prefix = $prefix ? $prefix . ' ' : '';
|
danielebarchiesi@4
|
862 $r .= trim($cur_prefix . 'JOIN '. $this->getGraphTable() . ' G_' .$id . ' ON (' .$nl. ' (T_' . $id . '.t = G_' .$id. '.t)' . $sub_r . $nl . ')');
|
danielebarchiesi@4
|
863 }
|
danielebarchiesi@4
|
864 }
|
danielebarchiesi@4
|
865 return $r;
|
danielebarchiesi@4
|
866 }
|
danielebarchiesi@4
|
867
|
danielebarchiesi@4
|
868 /* */
|
danielebarchiesi@4
|
869
|
danielebarchiesi@4
|
870 function getWHERESQL() {
|
danielebarchiesi@4
|
871 $r = '';
|
danielebarchiesi@4
|
872 $nl = "\n";
|
danielebarchiesi@4
|
873 /* standard constraints */
|
danielebarchiesi@4
|
874 $sub_r = $this->getPatternSQL($this->getPattern('0'), 'where');
|
danielebarchiesi@4
|
875 /* additional constraints */
|
danielebarchiesi@4
|
876 foreach ($this->index['from'] as $id) {
|
danielebarchiesi@4
|
877 if ($sub_sub_r = $this->getConstraintSQL($id)) {
|
danielebarchiesi@4
|
878 $sub_r .= $sub_r ? $nl . ' AND ' . $sub_sub_r : $sub_sub_r;
|
danielebarchiesi@4
|
879 }
|
danielebarchiesi@4
|
880 }
|
danielebarchiesi@4
|
881 $r .= $sub_r ? $sub_r : '';
|
danielebarchiesi@4
|
882 /* left join dependencies */
|
danielebarchiesi@4
|
883 foreach ($this->index['left_join'] as $id) {
|
danielebarchiesi@4
|
884 $d_joins = $this->getDependentJoins($id);
|
danielebarchiesi@4
|
885 $added = array();
|
danielebarchiesi@4
|
886 $d_aliases = array();
|
danielebarchiesi@4
|
887 //echo $id . ' =>' . print_r($d_joins, 1);
|
danielebarchiesi@4
|
888 $id_alias = 'T_' . $id . '.s';
|
danielebarchiesi@4
|
889 foreach ($d_joins as $alias) {
|
danielebarchiesi@4
|
890 if (preg_match('/^(T|V|G)_([0-9\_]+)(_[spo])?\.([a-z\_]+)/', $alias, $m)) {
|
danielebarchiesi@4
|
891 $tbl_type = $m[1];
|
danielebarchiesi@4
|
892 $tbl_pattern_id = $m[2];
|
danielebarchiesi@4
|
893 $suffix = $m[3];
|
danielebarchiesi@4
|
894 if (($tbl_pattern_id >= $id) && $this->sameOptional($tbl_pattern_id, $id)) {/* get rid of dependency permutations and nested optionals */
|
danielebarchiesi@4
|
895 if (!in_array($tbl_type . '_' . $tbl_pattern_id . $suffix, $added)) {
|
danielebarchiesi@4
|
896 $sub_r .= $sub_r ? ' AND ' : '';
|
danielebarchiesi@4
|
897 $sub_r .= $alias . ' IS NULL';
|
danielebarchiesi@4
|
898 $d_aliases[] = $alias;
|
danielebarchiesi@4
|
899 $added[] = $tbl_type . '_' . $tbl_pattern_id . $suffix;
|
danielebarchiesi@4
|
900 $id_alias = ($tbl_pattern_id == $id) ? $alias : $id_alias;
|
danielebarchiesi@4
|
901 }
|
danielebarchiesi@4
|
902 }
|
danielebarchiesi@4
|
903 }
|
danielebarchiesi@4
|
904 }
|
danielebarchiesi@4
|
905 if (count($d_aliases) > 2) {/* @@todo fix this! */
|
danielebarchiesi@4
|
906 $sub_r1 = ' /* '.$id_alias.' dependencies */';
|
danielebarchiesi@4
|
907 $sub_r2 = '((' . $id_alias . ' IS NULL) OR (CONCAT(' . join(', ', $d_aliases) . ') IS NOT NULL))';
|
danielebarchiesi@4
|
908 $r .= $r ? $nl . $sub_r1 . $nl . ' AND ' .$sub_r2 : $sub_r1 . $nl . $sub_r2;
|
danielebarchiesi@4
|
909 }
|
danielebarchiesi@4
|
910 }
|
danielebarchiesi@4
|
911 return $r ? $nl . 'WHERE ' . $r : '';
|
danielebarchiesi@4
|
912 }
|
danielebarchiesi@4
|
913
|
danielebarchiesi@4
|
914 /* */
|
danielebarchiesi@4
|
915
|
danielebarchiesi@4
|
916 function addConstraintSQLEntry($id, $sql) {
|
danielebarchiesi@4
|
917 if (!isset($this->index['constraints'][$id])) {
|
danielebarchiesi@4
|
918 $this->index['constraints'][$id] = array();
|
danielebarchiesi@4
|
919 }
|
danielebarchiesi@4
|
920 if (!in_array($sql, $this->index['constraints'][$id])) {
|
danielebarchiesi@4
|
921 $this->index['constraints'][$id][] = $sql;
|
danielebarchiesi@4
|
922 }
|
danielebarchiesi@4
|
923 }
|
danielebarchiesi@4
|
924
|
danielebarchiesi@4
|
925 function getConstraintSQL($id) {
|
danielebarchiesi@4
|
926 $r = '';
|
danielebarchiesi@4
|
927 $nl = "\n";
|
danielebarchiesi@4
|
928 $constraints = $this->v($id, array(), $this->index['constraints']);
|
danielebarchiesi@4
|
929 foreach ($constraints as $constraint) {
|
danielebarchiesi@4
|
930 $r .= $r ? $nl . ' AND ' . $constraint : $constraint;
|
danielebarchiesi@4
|
931 }
|
danielebarchiesi@4
|
932 return $r;
|
danielebarchiesi@4
|
933 }
|
danielebarchiesi@4
|
934
|
danielebarchiesi@4
|
935 /* */
|
danielebarchiesi@4
|
936
|
danielebarchiesi@4
|
937 function getPatternSQL($pattern, $context) {
|
danielebarchiesi@4
|
938 $type = $this->v('type', '', $pattern);
|
danielebarchiesi@4
|
939 if (!$type) {
|
danielebarchiesi@4
|
940 return '';
|
danielebarchiesi@4
|
941 }
|
danielebarchiesi@4
|
942 $m = 'get' . ucfirst($type) . 'PatternSQL';
|
danielebarchiesi@4
|
943 return method_exists($this, $m) ? $this->$m($pattern, $context) : $this->getDefaultPatternSQL($pattern, $context);
|
danielebarchiesi@4
|
944 }
|
danielebarchiesi@4
|
945
|
danielebarchiesi@4
|
946 function getDefaultPatternSQL($pattern, $context) {
|
danielebarchiesi@4
|
947 $r = '';
|
danielebarchiesi@4
|
948 $nl = "\n";
|
danielebarchiesi@4
|
949 $sub_ids = $this->v('patterns', array(), $pattern);
|
danielebarchiesi@4
|
950 foreach ($sub_ids as $sub_id) {
|
danielebarchiesi@4
|
951 $sub_r = $this->getPatternSQL($this->getPattern($sub_id), $context);
|
danielebarchiesi@4
|
952 $r .= ($r && $sub_r) ? $nl . ' AND (' . $sub_r . ')' : ($sub_r ? $sub_r : '');
|
danielebarchiesi@4
|
953 }
|
danielebarchiesi@4
|
954 return $r ? $r : '';
|
danielebarchiesi@4
|
955 }
|
danielebarchiesi@4
|
956
|
danielebarchiesi@4
|
957 function getTriplePatternSQL($pattern, $context) {
|
danielebarchiesi@4
|
958 $r = '';
|
danielebarchiesi@4
|
959 $nl = "\n";
|
danielebarchiesi@4
|
960 $id = $pattern['id'];
|
danielebarchiesi@4
|
961 /* s p o */
|
danielebarchiesi@4
|
962 $vars = array();
|
danielebarchiesi@4
|
963 foreach (array('s', 'p', 'o') as $term) {
|
danielebarchiesi@4
|
964 $sub_r = '';
|
danielebarchiesi@4
|
965 $type = $pattern[$term . '_type'];
|
danielebarchiesi@4
|
966 if ($type == 'uri') {
|
danielebarchiesi@4
|
967 $term_id = $this->getTermID($pattern[$term], $term);
|
danielebarchiesi@4
|
968 $sub_r = '(T_' . $id . '.' . $term . ' = ' . $term_id . ') /* ' . preg_replace('/[\#\*\>]/' , '::', $pattern[$term]) . ' */';
|
danielebarchiesi@4
|
969 }
|
danielebarchiesi@4
|
970 elseif ($type == 'literal') {
|
danielebarchiesi@4
|
971 $term_id = $this->getTermID($pattern[$term], $term);
|
danielebarchiesi@4
|
972 $sub_r = '(T_' . $id . '.' . $term . ' = ' . $term_id . ') /* ' . preg_replace('/[\#\n\*\>]/' , ' ', $pattern[$term]) . ' */';
|
danielebarchiesi@4
|
973 if (($lang_dt = $this->v1($term . '_lang', '', $pattern)) || ($lang_dt = $this->v1($term . '_datatype', '', $pattern))) {
|
danielebarchiesi@4
|
974 $lang_dt_id = $this->getTermID($lang_dt);
|
danielebarchiesi@4
|
975 $sub_r .= $nl . ' AND (T_' . $id . '.' .$term. '_lang_dt = ' . $lang_dt_id . ') /* ' . preg_replace('/[\#\*\>]/' , '::', $lang_dt) . ' */';
|
danielebarchiesi@4
|
976 }
|
danielebarchiesi@4
|
977 }
|
danielebarchiesi@4
|
978 elseif ($type == 'var') {
|
danielebarchiesi@4
|
979 $val = $pattern[$term];
|
danielebarchiesi@4
|
980 if (isset($vars[$val])) {/* repeated var in pattern */
|
danielebarchiesi@4
|
981 $sub_r = '(T_' . $id . '.' . $term . '=' . 'T_' . $id . '.' . $vars[$val] . ')';
|
danielebarchiesi@4
|
982 }
|
danielebarchiesi@4
|
983 $vars[$val] = $term;
|
danielebarchiesi@4
|
984 if ($infos = $this->v($val, 0, $this->index['graph_vars'])) {/* graph var in triple pattern */
|
danielebarchiesi@4
|
985 $sub_r .= $sub_r ? $nl . ' AND ' : '';
|
danielebarchiesi@4
|
986 $tbl = $infos[0]['table'];
|
danielebarchiesi@4
|
987 $sub_r .= 'G_' . $tbl . '.g = T_' . $id . '.' . $term;
|
danielebarchiesi@4
|
988 }
|
danielebarchiesi@4
|
989 }
|
danielebarchiesi@4
|
990 if ($sub_r) {
|
danielebarchiesi@4
|
991 if (preg_match('/^(join)/', $context) || (preg_match('/^where/', $context) && in_array($id, $this->index['from']))) {
|
danielebarchiesi@4
|
992 $r .= $r ? $nl . ' AND ' . $sub_r : $sub_r;
|
danielebarchiesi@4
|
993 }
|
danielebarchiesi@4
|
994 }
|
danielebarchiesi@4
|
995 }
|
danielebarchiesi@4
|
996 /* g */
|
danielebarchiesi@4
|
997 if ($infos = $pattern['graph_infos']) {
|
danielebarchiesi@4
|
998 $tbl_alias = 'G_' . $id . '.g';
|
danielebarchiesi@4
|
999 if (!in_array($tbl_alias, $this->index['sub_joins'])) {
|
danielebarchiesi@4
|
1000 $this->index['sub_joins'][] = $tbl_alias;
|
danielebarchiesi@4
|
1001 }
|
danielebarchiesi@4
|
1002 $sub_r = array('graph_var' => '', 'graph_uri' => '', 'from' => '', 'from_named' => '');
|
danielebarchiesi@4
|
1003 foreach ($infos as $info) {
|
danielebarchiesi@4
|
1004 $type = $info['type'];
|
danielebarchiesi@4
|
1005 if ($type == 'graph') {
|
danielebarchiesi@4
|
1006 if ($info['uri']) {
|
danielebarchiesi@4
|
1007 $term_id = $this->getTermID($info['uri'], 'g');
|
danielebarchiesi@4
|
1008 $sub_r['graph_uri'] .= $sub_r['graph_uri'] ? $nl . ' AND ' : '';
|
danielebarchiesi@4
|
1009 $sub_r['graph_uri'] .= '(' .$tbl_alias. ' = ' . $term_id . ') /* ' . preg_replace('/[\#\*\>]/' , '::', $info['uri']) . ' */';
|
danielebarchiesi@4
|
1010 }
|
danielebarchiesi@4
|
1011 }
|
danielebarchiesi@4
|
1012 }
|
danielebarchiesi@4
|
1013 if ($sub_r['from'] && $sub_r['from_named']) {
|
danielebarchiesi@4
|
1014 $sub_r['from_named'] = '';
|
danielebarchiesi@4
|
1015 }
|
danielebarchiesi@4
|
1016 if (!$sub_r['from'] && !$sub_r['from_named']) {
|
danielebarchiesi@4
|
1017 $sub_r['graph_var'] = '';
|
danielebarchiesi@4
|
1018 }
|
danielebarchiesi@4
|
1019 if (preg_match('/^(graph_sub_join)/', $context)) {
|
danielebarchiesi@4
|
1020 foreach ($sub_r as $g_type => $g_sql) {
|
danielebarchiesi@4
|
1021 if ($g_sql) {
|
danielebarchiesi@4
|
1022 $r .= $r ? $nl . ' AND ' . $g_sql : $g_sql;
|
danielebarchiesi@4
|
1023 }
|
danielebarchiesi@4
|
1024 }
|
danielebarchiesi@4
|
1025 }
|
danielebarchiesi@4
|
1026 }
|
danielebarchiesi@4
|
1027 /* optional sibling filters? */
|
danielebarchiesi@4
|
1028 if (preg_match('/^(join|sub_join)/', $context) && $this->isOptionalPattern($id)) {
|
danielebarchiesi@4
|
1029 $o_pattern = $pattern;
|
danielebarchiesi@4
|
1030 do {
|
danielebarchiesi@4
|
1031 $o_pattern = $this->getPattern($o_pattern['parent_id']);
|
danielebarchiesi@4
|
1032 } while ($o_pattern['parent_id'] && ($o_pattern['type'] != 'optional'));
|
danielebarchiesi@4
|
1033 if ($sub_r = $this->getPatternSQL($o_pattern, 'optional_filter' . preg_replace('/^(.*)(__.*)$/', '\\2', $context))) {
|
danielebarchiesi@4
|
1034 $r .= $r ? $nl . ' AND ' . $sub_r : $sub_r;
|
danielebarchiesi@4
|
1035 }
|
danielebarchiesi@4
|
1036 /* created constraints */
|
danielebarchiesi@4
|
1037 if ($sub_r = $this->getConstraintSQL($id)) {
|
danielebarchiesi@4
|
1038 $r .= $r ? $nl . ' AND ' . $sub_r : $sub_r;
|
danielebarchiesi@4
|
1039 }
|
danielebarchiesi@4
|
1040 }
|
danielebarchiesi@4
|
1041 /* result */
|
danielebarchiesi@4
|
1042 if (preg_match('/^(where)/', $context) && $this->isOptionalPattern($id)) {
|
danielebarchiesi@4
|
1043 return '';
|
danielebarchiesi@4
|
1044 }
|
danielebarchiesi@4
|
1045 return $r;
|
danielebarchiesi@4
|
1046 }
|
danielebarchiesi@4
|
1047
|
danielebarchiesi@4
|
1048 /* */
|
danielebarchiesi@4
|
1049
|
danielebarchiesi@4
|
1050 function getFilterPatternSQL($pattern, $context) {
|
danielebarchiesi@4
|
1051 $r = '';
|
danielebarchiesi@4
|
1052 $id = $pattern['id'];
|
danielebarchiesi@4
|
1053 $constraint_id = $this->v1('constraint', '', $pattern);
|
danielebarchiesi@4
|
1054 $constraint = $this->getPattern($constraint_id);
|
danielebarchiesi@4
|
1055 $constraint_type = $constraint['type'];
|
danielebarchiesi@4
|
1056 if ($constraint_type == 'built_in_call') {
|
danielebarchiesi@4
|
1057 $r = $this->getBuiltInCallSQL($constraint, $context);
|
danielebarchiesi@4
|
1058 }
|
danielebarchiesi@4
|
1059 elseif ($constraint_type == 'expression') {
|
danielebarchiesi@4
|
1060 $r = $this->getExpressionSQL($constraint, $context, '', 'filter');
|
danielebarchiesi@4
|
1061 }
|
danielebarchiesi@4
|
1062 else {
|
danielebarchiesi@4
|
1063 $m = 'get' . ucfirst($constraint_type) . 'ExpressionSQL';
|
danielebarchiesi@4
|
1064 if (method_exists($this, $m)) {
|
danielebarchiesi@4
|
1065 $r = $this->$m($constraint, $context, '', 'filter');
|
danielebarchiesi@4
|
1066 }
|
danielebarchiesi@4
|
1067 }
|
danielebarchiesi@4
|
1068 if ($this->isOptionalPattern($id) && !preg_match('/^(join|optional_filter)/', $context)) {
|
danielebarchiesi@4
|
1069 return '';
|
danielebarchiesi@4
|
1070 }
|
danielebarchiesi@4
|
1071 /* unconnected vars in FILTERs eval to false */
|
danielebarchiesi@4
|
1072 $sub_r = $this->hasUnconnectedFilterVars($id);
|
danielebarchiesi@4
|
1073 if ($sub_r) {
|
danielebarchiesi@4
|
1074 if ($sub_r == 'alias') {
|
danielebarchiesi@4
|
1075 if (!in_array($r, $this->index['havings'])) $this->index['havings'][] = $r;
|
danielebarchiesi@4
|
1076 return '';
|
danielebarchiesi@4
|
1077 }
|
danielebarchiesi@4
|
1078 elseif (preg_match('/^T([^\s]+\.)g (.*)$/s', $r, $m)) {/* graph filter */
|
danielebarchiesi@4
|
1079 return 'G' . $m[1] . 't ' . $m[2];
|
danielebarchiesi@4
|
1080 }
|
danielebarchiesi@4
|
1081 elseif (preg_match('/^\(*V[^\s]+_g\.val .*$/s', $r, $m)) {/* graph value filter, @@improveMe */
|
danielebarchiesi@4
|
1082 //return $r;
|
danielebarchiesi@4
|
1083 }
|
danielebarchiesi@4
|
1084 else {
|
danielebarchiesi@4
|
1085 return 'FALSE';
|
danielebarchiesi@4
|
1086 }
|
danielebarchiesi@4
|
1087 }
|
danielebarchiesi@4
|
1088 /* some really ugly tweaks */
|
danielebarchiesi@4
|
1089 /* empty language filter: FILTER ( lang(?v) = '' ) */
|
danielebarchiesi@4
|
1090 $r = preg_replace('/\(\/\* language call \*\/ ([^\s]+) = ""\)/s', '((\\1 = "") OR (\\1 LIKE "%:%"))', $r);
|
danielebarchiesi@4
|
1091 return $r;
|
danielebarchiesi@4
|
1092 }
|
danielebarchiesi@4
|
1093
|
danielebarchiesi@4
|
1094 /**
|
danielebarchiesi@4
|
1095 * Checks if vars in the given (filter) pattern are used within the filter's scope.
|
danielebarchiesi@4
|
1096 */
|
danielebarchiesi@4
|
1097
|
danielebarchiesi@4
|
1098 function hasUnconnectedFilterVars($filter_pattern_id) {
|
danielebarchiesi@4
|
1099 $scope_id = $this->getFilterScope($filter_pattern_id);
|
danielebarchiesi@4
|
1100 $vars = $this->getFilterVars($filter_pattern_id);
|
danielebarchiesi@4
|
1101 $r = 0;
|
danielebarchiesi@4
|
1102 foreach ($vars as $var_name) {
|
danielebarchiesi@4
|
1103 if ($this->isUsedTripleVar($var_name, $scope_id)) continue;
|
danielebarchiesi@4
|
1104 if ($this->isAliasVar($var_name)) {
|
danielebarchiesi@4
|
1105 $r = 'alias';
|
danielebarchiesi@4
|
1106 break;
|
danielebarchiesi@4
|
1107 }
|
danielebarchiesi@4
|
1108 $r = 1;
|
danielebarchiesi@4
|
1109 break;
|
danielebarchiesi@4
|
1110 }
|
danielebarchiesi@4
|
1111 return $r;
|
danielebarchiesi@4
|
1112 }
|
danielebarchiesi@4
|
1113
|
danielebarchiesi@4
|
1114 /**
|
danielebarchiesi@4
|
1115 * Returns the given filter pattern's scope (the id of the parent group pattern).
|
danielebarchiesi@4
|
1116 */
|
danielebarchiesi@4
|
1117
|
danielebarchiesi@4
|
1118 function getFilterScope($filter_pattern_id) {
|
danielebarchiesi@4
|
1119 $patterns = $this->initial_index['patterns'];
|
danielebarchiesi@4
|
1120 $r = '';
|
danielebarchiesi@4
|
1121 foreach ($patterns as $id => $p) {
|
danielebarchiesi@4
|
1122 /* the id has to be sub-part of the given filter id */
|
danielebarchiesi@4
|
1123 if (!preg_match('/^' . $id . '.+/', $filter_pattern_id)) continue;
|
danielebarchiesi@4
|
1124 /* we are looking for a group or union */
|
danielebarchiesi@4
|
1125 if (!preg_match('/^(group|union)$/', $p['type'])) continue;
|
danielebarchiesi@4
|
1126 /* we are looking for the longest/deepest match */
|
danielebarchiesi@4
|
1127 if (strlen($id) > strlen($r)) $r = $id;
|
danielebarchiesi@4
|
1128 }
|
danielebarchiesi@4
|
1129 return $r;
|
danielebarchiesi@4
|
1130 }
|
danielebarchiesi@4
|
1131
|
danielebarchiesi@4
|
1132 /**
|
danielebarchiesi@4
|
1133 * Builds a list of vars used in the given (filter) pattern.
|
danielebarchiesi@4
|
1134 */
|
danielebarchiesi@4
|
1135
|
danielebarchiesi@4
|
1136 function getFilterVars($filter_pattern_id) {
|
danielebarchiesi@4
|
1137 $r = array();
|
danielebarchiesi@4
|
1138 $patterns = $this->initial_index['patterns'];
|
danielebarchiesi@4
|
1139 /* find vars in the given filter (i.e. the given id is part of their pattern id) */
|
danielebarchiesi@4
|
1140 foreach ($patterns as $id => $p) {
|
danielebarchiesi@4
|
1141 if (!preg_match('/^' . $filter_pattern_id . '.+/', $id)) continue;
|
danielebarchiesi@4
|
1142 $var_name = '';
|
danielebarchiesi@4
|
1143 if ($p['type'] == 'var') {
|
danielebarchiesi@4
|
1144 $var_name = $p['value'];
|
danielebarchiesi@4
|
1145 }
|
danielebarchiesi@4
|
1146 elseif (($p['type'] == 'built_in_call') && ($p['call'] == 'bound')) {
|
danielebarchiesi@4
|
1147 $var_name = $p['args'][0]['value'];
|
danielebarchiesi@4
|
1148 }
|
danielebarchiesi@4
|
1149 if ($var_name && !in_array($var_name, $r)) {
|
danielebarchiesi@4
|
1150 $r[] = $var_name;
|
danielebarchiesi@4
|
1151 }
|
danielebarchiesi@4
|
1152 }
|
danielebarchiesi@4
|
1153 return $r;
|
danielebarchiesi@4
|
1154 }
|
danielebarchiesi@4
|
1155
|
danielebarchiesi@4
|
1156 /**
|
danielebarchiesi@4
|
1157 * Checks if $var_name appears as result projection alias.
|
danielebarchiesi@4
|
1158 */
|
danielebarchiesi@4
|
1159
|
danielebarchiesi@4
|
1160 function isAliasVar($var_name) {
|
danielebarchiesi@4
|
1161 foreach ($this->infos['query']['result_vars'] as $r_var) {
|
danielebarchiesi@4
|
1162 if ($r_var['alias'] == $var_name) return 1;
|
danielebarchiesi@4
|
1163 }
|
danielebarchiesi@4
|
1164 return 0;
|
danielebarchiesi@4
|
1165 }
|
danielebarchiesi@4
|
1166
|
danielebarchiesi@4
|
1167 /**
|
danielebarchiesi@4
|
1168 * Checks if $var_name is used in a triple pattern in the given scope
|
danielebarchiesi@4
|
1169 */
|
danielebarchiesi@4
|
1170
|
danielebarchiesi@4
|
1171 function isUsedTripleVar($var_name, $scope_id = '0') {
|
danielebarchiesi@4
|
1172 $patterns = $this->initial_index['patterns'];
|
danielebarchiesi@4
|
1173 foreach ($patterns as $id => $p) {
|
danielebarchiesi@4
|
1174 if ($p['type'] != 'triple') continue;
|
danielebarchiesi@4
|
1175 if (!preg_match('/^' . $scope_id . '.+/', $id)) continue;
|
danielebarchiesi@4
|
1176 foreach (array('s', 'p', 'o') as $term) {
|
danielebarchiesi@4
|
1177 if ($p[$term . '_type'] != 'var') continue;
|
danielebarchiesi@4
|
1178 if ($p[$term] == $var_name) return 1;
|
danielebarchiesi@4
|
1179 }
|
danielebarchiesi@4
|
1180 }
|
danielebarchiesi@4
|
1181 }
|
danielebarchiesi@4
|
1182
|
danielebarchiesi@4
|
1183 /* */
|
danielebarchiesi@4
|
1184
|
danielebarchiesi@4
|
1185 function getExpressionSQL($pattern, $context, $val_type = '', $parent_type = '') {
|
danielebarchiesi@4
|
1186 $r = '';
|
danielebarchiesi@4
|
1187 $nl = "\n";
|
danielebarchiesi@4
|
1188 $type = $this->v1('type', '', $pattern);
|
danielebarchiesi@4
|
1189 $sub_type = $this->v1('sub_type', $type, $pattern);
|
danielebarchiesi@4
|
1190 if (preg_match('/^(and|or)$/', $sub_type)) {
|
danielebarchiesi@4
|
1191 foreach ($pattern['patterns'] as $sub_id) {
|
danielebarchiesi@4
|
1192 $sub_pattern = $this->getPattern($sub_id);
|
danielebarchiesi@4
|
1193 $sub_pattern_type = $sub_pattern['type'];
|
danielebarchiesi@4
|
1194 if ($sub_pattern_type == 'built_in_call') {
|
danielebarchiesi@4
|
1195 $sub_r = $this->getBuiltInCallSQL($sub_pattern, $context, '', $parent_type);
|
danielebarchiesi@4
|
1196 }
|
danielebarchiesi@4
|
1197 else {
|
danielebarchiesi@4
|
1198 $sub_r = $this->getExpressionSQL($sub_pattern, $context, '', $parent_type);
|
danielebarchiesi@4
|
1199 }
|
danielebarchiesi@4
|
1200 if ($sub_r) {
|
danielebarchiesi@4
|
1201 $r .= $r ? ' ' . strtoupper($sub_type). ' (' .$sub_r. ')' : '(' . $sub_r . ')';
|
danielebarchiesi@4
|
1202 }
|
danielebarchiesi@4
|
1203 }
|
danielebarchiesi@4
|
1204 }
|
danielebarchiesi@4
|
1205 elseif ($sub_type == 'built_in_call') {
|
danielebarchiesi@4
|
1206 $r = $this->getBuiltInCallSQL($pattern, $context, $val_type, $parent_type);
|
danielebarchiesi@4
|
1207 }
|
danielebarchiesi@4
|
1208 elseif (preg_match('/literal/', $sub_type)) {
|
danielebarchiesi@4
|
1209 $r = $this->getLiteralExpressionSQL($pattern, $context, $val_type, $parent_type);
|
danielebarchiesi@4
|
1210 }
|
danielebarchiesi@4
|
1211 elseif ($sub_type) {
|
danielebarchiesi@4
|
1212 $m = 'get' . ucfirst($sub_type) . 'ExpressionSQL';
|
danielebarchiesi@4
|
1213 if (method_exists($this, $m)) {
|
danielebarchiesi@4
|
1214 $r = $this->$m($pattern, $context, '', $parent_type);
|
danielebarchiesi@4
|
1215 }
|
danielebarchiesi@4
|
1216 }
|
danielebarchiesi@4
|
1217 /* skip expressions that reference non-yet-joined tables */
|
danielebarchiesi@4
|
1218 if (preg_match('/__(T|V|G)_(.+)$/', $context, $m)) {
|
danielebarchiesi@4
|
1219 $context_pattern_id = $m[2];
|
danielebarchiesi@4
|
1220 $context_table_type = $m[1];
|
danielebarchiesi@4
|
1221 if (preg_match_all('/((T|V|G)(\_[0-9])+)/', $r, $m)) {
|
danielebarchiesi@4
|
1222 $aliases = $m[1];
|
danielebarchiesi@4
|
1223 $keep = 1;
|
danielebarchiesi@4
|
1224 foreach ($aliases as $alias) {
|
danielebarchiesi@4
|
1225 if (preg_match('/(T|V|G)_(.*)$/', $alias, $m)) {
|
danielebarchiesi@4
|
1226 $tbl_type = $m[1];
|
danielebarchiesi@4
|
1227 $tbl = $m[2];
|
danielebarchiesi@4
|
1228 if (!$this->isJoinedBefore($tbl, $context_pattern_id)) {
|
danielebarchiesi@4
|
1229 $keep = 0;
|
danielebarchiesi@4
|
1230 }
|
danielebarchiesi@4
|
1231 elseif (($context_pattern_id == $tbl) && preg_match('/(TV)/', $context_table_type . $tbl_type)) {
|
danielebarchiesi@4
|
1232 $keep = 0;
|
danielebarchiesi@4
|
1233 }
|
danielebarchiesi@4
|
1234 }
|
danielebarchiesi@4
|
1235 }
|
danielebarchiesi@4
|
1236 $r = $keep ? $r : '';
|
danielebarchiesi@4
|
1237 }
|
danielebarchiesi@4
|
1238 }
|
danielebarchiesi@4
|
1239 return $r ? '(' . $r . ')' : $r;
|
danielebarchiesi@4
|
1240 }
|
danielebarchiesi@4
|
1241
|
danielebarchiesi@4
|
1242 function detectExpressionValueType($pattern_ids) {
|
danielebarchiesi@4
|
1243 foreach ($pattern_ids as $id) {
|
danielebarchiesi@4
|
1244 $pattern = $this->getPattern($id);
|
danielebarchiesi@4
|
1245 $type = $this->v('type', '', $pattern);
|
danielebarchiesi@4
|
1246 if (($type == 'literal') && isset($pattern['datatype'])) {
|
danielebarchiesi@4
|
1247 if (in_array($pattern['datatype'], array($this->xsd . 'integer', $this->xsd . 'float', $this->xsd . 'double'))) {
|
danielebarchiesi@4
|
1248 return 'numeric';
|
danielebarchiesi@4
|
1249 }
|
danielebarchiesi@4
|
1250 }
|
danielebarchiesi@4
|
1251 }
|
danielebarchiesi@4
|
1252 return '';
|
danielebarchiesi@4
|
1253 }
|
danielebarchiesi@4
|
1254
|
danielebarchiesi@4
|
1255 /* */
|
danielebarchiesi@4
|
1256
|
danielebarchiesi@4
|
1257 function getRelationalExpressionSQL($pattern, $context, $val_type = '', $parent_type = '') {
|
danielebarchiesi@4
|
1258 $r = '';
|
danielebarchiesi@4
|
1259 $val_type = $this->detectExpressionValueType($pattern['patterns']);
|
danielebarchiesi@4
|
1260 $op = $pattern['operator'];
|
danielebarchiesi@4
|
1261 foreach ($pattern['patterns'] as $sub_id) {
|
danielebarchiesi@4
|
1262 $sub_pattern = $this->getPattern($sub_id);
|
danielebarchiesi@4
|
1263 $sub_pattern['parent_op'] = $op;
|
danielebarchiesi@4
|
1264 $sub_type = $sub_pattern['type'];
|
danielebarchiesi@4
|
1265 $m = ($sub_type == 'built_in_call') ? 'getBuiltInCallSQL' : 'get' . ucfirst($sub_type) . 'ExpressionSQL';
|
danielebarchiesi@4
|
1266 $m = str_replace('ExpressionExpression', 'Expression', $m);
|
danielebarchiesi@4
|
1267 $sub_r = method_exists($this, $m) ? $this->$m($sub_pattern, $context, $val_type, 'relational') : '';
|
danielebarchiesi@4
|
1268 $r .= $r ? ' ' . $op . ' ' . $sub_r : $sub_r;
|
danielebarchiesi@4
|
1269 }
|
danielebarchiesi@4
|
1270 return $r ? '(' . $r . ')' : $r;
|
danielebarchiesi@4
|
1271 }
|
danielebarchiesi@4
|
1272
|
danielebarchiesi@4
|
1273 function getAdditiveExpressionSQL($pattern, $context, $val_type = '', $parent_type = '') {
|
danielebarchiesi@4
|
1274 $r = '';
|
danielebarchiesi@4
|
1275 $val_type = $this->detectExpressionValueType($pattern['patterns']);
|
danielebarchiesi@4
|
1276 foreach ($pattern['patterns'] as $sub_id) {
|
danielebarchiesi@4
|
1277 $sub_pattern = $this->getPattern($sub_id);
|
danielebarchiesi@4
|
1278 $sub_type = $this->v('type', '', $sub_pattern);
|
danielebarchiesi@4
|
1279 $m = ($sub_type == 'built_in_call') ? 'getBuiltInCallSQL' : 'get' . ucfirst($sub_type) . 'ExpressionSQL';
|
danielebarchiesi@4
|
1280 $m = str_replace('ExpressionExpression', 'Expression', $m);
|
danielebarchiesi@4
|
1281 $sub_r = method_exists($this, $m) ? $this->$m($sub_pattern, $context, $val_type, 'additive') : '';
|
danielebarchiesi@4
|
1282 $r .= $r ? ' ' . $sub_r : $sub_r;
|
danielebarchiesi@4
|
1283 }
|
danielebarchiesi@4
|
1284 return $r;
|
danielebarchiesi@4
|
1285 }
|
danielebarchiesi@4
|
1286
|
danielebarchiesi@4
|
1287 function getMultiplicativeExpressionSQL($pattern, $context, $val_type = '', $parent_type = '') {
|
danielebarchiesi@4
|
1288 $r = '';
|
danielebarchiesi@4
|
1289 $val_type = $this->detectExpressionValueType($pattern['patterns']);
|
danielebarchiesi@4
|
1290 foreach ($pattern['patterns'] as $sub_id) {
|
danielebarchiesi@4
|
1291 $sub_pattern = $this->getPattern($sub_id);
|
danielebarchiesi@4
|
1292 $sub_type = $sub_pattern['type'];
|
danielebarchiesi@4
|
1293 $m = ($sub_type == 'built_in_call') ? 'getBuiltInCallSQL' : 'get' . ucfirst($sub_type) . 'ExpressionSQL';
|
danielebarchiesi@4
|
1294 $m = str_replace('ExpressionExpression', 'Expression', $m);
|
danielebarchiesi@4
|
1295 $sub_r = method_exists($this, $m) ? $this->$m($sub_pattern, $context, $val_type, 'multiplicative') : '';
|
danielebarchiesi@4
|
1296 $r .= $r ? ' ' . $sub_r : $sub_r;
|
danielebarchiesi@4
|
1297 }
|
danielebarchiesi@4
|
1298 return $r;
|
danielebarchiesi@4
|
1299 }
|
danielebarchiesi@4
|
1300
|
danielebarchiesi@4
|
1301 /* */
|
danielebarchiesi@4
|
1302
|
danielebarchiesi@4
|
1303 function getVarExpressionSQL($pattern, $context, $val_type = '', $parent_type = '') {
|
danielebarchiesi@4
|
1304 $var = $pattern['value'];
|
danielebarchiesi@4
|
1305 $info = $this->getVarTableInfos($var);
|
danielebarchiesi@4
|
1306 if (!$tbl = $info['table']) {
|
danielebarchiesi@4
|
1307 /* might be an aggregate var */
|
danielebarchiesi@4
|
1308 $vars = $this->infos['query']['result_vars'];
|
danielebarchiesi@4
|
1309 foreach ($vars as $test_var) {
|
danielebarchiesi@4
|
1310 if ($test_var['alias'] == $pattern['value']) {
|
danielebarchiesi@4
|
1311 return '`' . $pattern['value'] . '`';
|
danielebarchiesi@4
|
1312 }
|
danielebarchiesi@4
|
1313 }
|
danielebarchiesi@4
|
1314 return '';
|
danielebarchiesi@4
|
1315 }
|
danielebarchiesi@4
|
1316 $col = $info['col'];
|
danielebarchiesi@4
|
1317 if (($context == 'order') && ($col == 'o')) {
|
danielebarchiesi@4
|
1318 $tbl_alias = 'T_' . $tbl . '.o_comp';
|
danielebarchiesi@4
|
1319 }
|
danielebarchiesi@4
|
1320 elseif ($context == 'sameterm') {
|
danielebarchiesi@4
|
1321 $tbl_alias = 'T_' . $tbl . '.' . $col;
|
danielebarchiesi@4
|
1322 }
|
danielebarchiesi@4
|
1323 elseif (($parent_type == 'relational') && ($col == 'o') && (preg_match('/[\<\>]/', $this->v('parent_op', '', $pattern)))) {
|
danielebarchiesi@4
|
1324 $tbl_alias = 'T_' . $tbl . '.o_comp';
|
danielebarchiesi@4
|
1325 }
|
danielebarchiesi@4
|
1326 else {
|
danielebarchiesi@4
|
1327 $tbl_alias = 'V_' . $tbl . '_' . $col . '.val';
|
danielebarchiesi@4
|
1328 if (!in_array($tbl_alias, $this->index['sub_joins'])) {
|
danielebarchiesi@4
|
1329 $this->index['sub_joins'][] = $tbl_alias;
|
danielebarchiesi@4
|
1330 }
|
danielebarchiesi@4
|
1331 }
|
danielebarchiesi@4
|
1332 $op = $this->v('operator', '', $pattern);
|
danielebarchiesi@4
|
1333 if (preg_match('/^(filter|and)/', $parent_type)) {
|
danielebarchiesi@4
|
1334 if ($op == '!') {
|
danielebarchiesi@4
|
1335 $r = '(((' . $tbl_alias . ' = 0) AND (CONCAT("1", ' . $tbl_alias . ') != 1))'; /* 0 and no string */
|
danielebarchiesi@4
|
1336 $r .= ' OR (' . $tbl_alias . ' IN ("", "false")))'; /* or "", or "false" */
|
danielebarchiesi@4
|
1337 }
|
danielebarchiesi@4
|
1338 else {
|
danielebarchiesi@4
|
1339 $r = '((' . $tbl_alias . ' != 0)'; /* not null */
|
danielebarchiesi@4
|
1340 $r .= ' OR ((CONCAT("1", ' . $tbl_alias . ') = 1) AND (' . $tbl_alias . ' NOT IN ("", "false"))))'; /* string, and not "" or "false" */
|
danielebarchiesi@4
|
1341 }
|
danielebarchiesi@4
|
1342 }
|
danielebarchiesi@4
|
1343 else {
|
danielebarchiesi@4
|
1344 $r = trim($op . ' ' . $tbl_alias);
|
danielebarchiesi@4
|
1345 if ($val_type == 'numeric') {
|
danielebarchiesi@4
|
1346 if (preg_match('/__(T|V|G)_(.+)$/', $context, $m)) {
|
danielebarchiesi@4
|
1347 $context_pattern_id = $m[2];
|
danielebarchiesi@4
|
1348 $context_table_type = $m[1];
|
danielebarchiesi@4
|
1349 }
|
danielebarchiesi@4
|
1350 else {
|
danielebarchiesi@4
|
1351 $context_pattern_id = $pattern['id'];
|
danielebarchiesi@4
|
1352 $context_table_type = 'T';
|
danielebarchiesi@4
|
1353 }
|
danielebarchiesi@4
|
1354 if ($this->isJoinedBefore($tbl, $context_pattern_id)) {
|
danielebarchiesi@4
|
1355 $add = ($tbl != $context_pattern_id) ? 1 : 0;
|
danielebarchiesi@4
|
1356 $add = (!$add && ($context_table_type == 'V')) ? 1 : 0;
|
danielebarchiesi@4
|
1357 if ($add) {
|
danielebarchiesi@4
|
1358 $this->addConstraintSQLEntry($context_pattern_id, '(' .$r. ' = "0" OR ' . $r . '*1.0 != 0)');
|
danielebarchiesi@4
|
1359 }
|
danielebarchiesi@4
|
1360 }
|
danielebarchiesi@4
|
1361 }
|
danielebarchiesi@4
|
1362 }
|
danielebarchiesi@4
|
1363 return $r;
|
danielebarchiesi@4
|
1364 }
|
danielebarchiesi@4
|
1365
|
danielebarchiesi@4
|
1366 /* */
|
danielebarchiesi@4
|
1367
|
danielebarchiesi@4
|
1368 function getUriExpressionSQL($pattern, $context, $val_type = '') {
|
danielebarchiesi@4
|
1369 $val = $pattern['uri'];
|
danielebarchiesi@4
|
1370 $r = $pattern['operator'];
|
danielebarchiesi@4
|
1371 $r .= is_numeric($val) ? ' ' . $val : ' "' . mysql_real_escape_string($val, $this->store->getDBCon()) . '"';
|
danielebarchiesi@4
|
1372 return $r;
|
danielebarchiesi@4
|
1373 }
|
danielebarchiesi@4
|
1374
|
danielebarchiesi@4
|
1375 /* */
|
danielebarchiesi@4
|
1376
|
danielebarchiesi@4
|
1377 function getLiteralExpressionSQL($pattern, $context, $val_type = '', $parent_type = '') {
|
danielebarchiesi@4
|
1378 $val = $pattern['value'];
|
danielebarchiesi@4
|
1379 $r = $pattern['operator'];
|
danielebarchiesi@4
|
1380 if (is_numeric($val) && $this->v('datatype', 0, $pattern)) {
|
danielebarchiesi@4
|
1381 $r .= ' ' . $val;
|
danielebarchiesi@4
|
1382 }
|
danielebarchiesi@4
|
1383 elseif (preg_match('/^(true|false)$/i', $val) && ($this->v1('datatype', '', $pattern) == 'http://www.w3.org/2001/XMLSchema#boolean')) {
|
danielebarchiesi@4
|
1384 $r .= ' ' . strtoupper($val);
|
danielebarchiesi@4
|
1385 }
|
danielebarchiesi@4
|
1386 elseif ($parent_type == 'regex') {
|
danielebarchiesi@4
|
1387 $sub_r = mysql_real_escape_string($val, $this->store->getDBCon());
|
danielebarchiesi@4
|
1388 $r .= ' "' . preg_replace('/\x5c\x5c/', '\\', $sub_r) . '"';
|
danielebarchiesi@4
|
1389 }
|
danielebarchiesi@4
|
1390 else {
|
danielebarchiesi@4
|
1391 $r .= ' "' . mysql_real_escape_string($val, $this->store->getDBCon()) . '"';
|
danielebarchiesi@4
|
1392 }
|
danielebarchiesi@4
|
1393 if (($lang_dt = $this->v1('lang', '', $pattern)) || ($lang_dt = $this->v1('datatype', '', $pattern))) {
|
danielebarchiesi@4
|
1394 /* try table/alias via var in siblings */
|
danielebarchiesi@4
|
1395 if ($var = $this->findSiblingVarExpression($pattern['id'])) {
|
danielebarchiesi@4
|
1396 if (isset($this->index['vars'][$var])) {
|
danielebarchiesi@4
|
1397 $infos = $this->index['vars'][$var];
|
danielebarchiesi@4
|
1398 foreach ($infos as $info) {
|
danielebarchiesi@4
|
1399 if ($info['col'] == 'o') {
|
danielebarchiesi@4
|
1400 $tbl = $info['table'];
|
danielebarchiesi@4
|
1401 $term_id = $this->getTermID($lang_dt);
|
danielebarchiesi@4
|
1402 if ($pattern['operator'] != '!=') {
|
danielebarchiesi@4
|
1403 if (preg_match('/__(T|V|G)_(.+)$/', $context, $m)) {
|
danielebarchiesi@4
|
1404 $context_pattern_id = $m[2];
|
danielebarchiesi@4
|
1405 $context_table_type = $m[1];
|
danielebarchiesi@4
|
1406 }
|
danielebarchiesi@4
|
1407 elseif ($context == 'where') {
|
danielebarchiesi@4
|
1408 $context_pattern_id = $tbl;
|
danielebarchiesi@4
|
1409 }
|
danielebarchiesi@4
|
1410 else {
|
danielebarchiesi@4
|
1411 $context_pattern_id = $pattern['id'];
|
danielebarchiesi@4
|
1412 }
|
danielebarchiesi@4
|
1413 if ($tbl == $context_pattern_id) {/* @todo better dependency check */
|
danielebarchiesi@4
|
1414 if ($term_id || ($lang_dt != 'http://www.w3.org/2001/XMLSchema#integer')) {/* skip if simple int, but no id */
|
danielebarchiesi@4
|
1415 $this->addConstraintSQLEntry($context_pattern_id, 'T_' . $tbl . '.o_lang_dt = ' . $term_id . ' /* ' . preg_replace('/[\#\*\>]/' , '::', $lang_dt) . ' */');
|
danielebarchiesi@4
|
1416 }
|
danielebarchiesi@4
|
1417 }
|
danielebarchiesi@4
|
1418 }
|
danielebarchiesi@4
|
1419 break;
|
danielebarchiesi@4
|
1420 }
|
danielebarchiesi@4
|
1421 }
|
danielebarchiesi@4
|
1422 }
|
danielebarchiesi@4
|
1423 }
|
danielebarchiesi@4
|
1424 }
|
danielebarchiesi@4
|
1425 return trim($r);
|
danielebarchiesi@4
|
1426 }
|
danielebarchiesi@4
|
1427
|
danielebarchiesi@4
|
1428 function findSiblingVarExpression($id) {
|
danielebarchiesi@4
|
1429 $pattern = $this->getPattern($id);
|
danielebarchiesi@4
|
1430 do {
|
danielebarchiesi@4
|
1431 $pattern = $this->getPattern($pattern['parent_id']);
|
danielebarchiesi@4
|
1432 } while ($pattern['parent_id'] && ($pattern['type'] != 'expression'));
|
danielebarchiesi@4
|
1433 $sub_patterns = $this->v('patterns', array(), $pattern);
|
danielebarchiesi@4
|
1434 foreach ($sub_patterns as $sub_id) {
|
danielebarchiesi@4
|
1435 $sub_pattern = $this->getPattern($sub_id);
|
danielebarchiesi@4
|
1436 if ($sub_pattern['type'] == 'var') {
|
danielebarchiesi@4
|
1437 return $sub_pattern['value'];
|
danielebarchiesi@4
|
1438 }
|
danielebarchiesi@4
|
1439 }
|
danielebarchiesi@4
|
1440 return '';
|
danielebarchiesi@4
|
1441 }
|
danielebarchiesi@4
|
1442
|
danielebarchiesi@4
|
1443 /* */
|
danielebarchiesi@4
|
1444
|
danielebarchiesi@4
|
1445 function getFunctionExpressionSQL($pattern, $context, $val_type = '', $parent_type = '') {
|
danielebarchiesi@4
|
1446 $fnc_uri = $pattern['uri'];
|
danielebarchiesi@4
|
1447 $op = $this->v('operator', '', $pattern);
|
danielebarchiesi@4
|
1448 if ($op) $op .= ' ';
|
danielebarchiesi@4
|
1449 if ($this->allow_extension_functions) {
|
danielebarchiesi@4
|
1450 /* mysql functions */
|
danielebarchiesi@4
|
1451 if (preg_match('/^http\:\/\/web\-semantics\.org\/ns\/mysql\/(.*)$/', $fnc_uri, $m)) {
|
danielebarchiesi@4
|
1452 $fnc_name = strtoupper($m[1]);
|
danielebarchiesi@4
|
1453 $sub_r = '';
|
danielebarchiesi@4
|
1454 foreach ($pattern['args'] as $arg) {
|
danielebarchiesi@4
|
1455 $sub_r .= $sub_r ? ', ' : '';
|
danielebarchiesi@4
|
1456 $sub_r .= $this->getExpressionSQL($arg, $context, $val_type, $parent_type);
|
danielebarchiesi@4
|
1457 }
|
danielebarchiesi@4
|
1458 return $op . $fnc_name . '(' . $sub_r . ')';
|
danielebarchiesi@4
|
1459 }
|
danielebarchiesi@4
|
1460 /* any other: ignore */
|
danielebarchiesi@4
|
1461 }
|
danielebarchiesi@4
|
1462 /* simple type conversions */
|
danielebarchiesi@4
|
1463 if (strpos($fnc_uri, 'http://www.w3.org/2001/XMLSchema#') === 0) {
|
danielebarchiesi@4
|
1464 return $op . $this->getExpressionSQL($pattern['args'][0], $context, $val_type, $parent_type);
|
danielebarchiesi@4
|
1465 }
|
danielebarchiesi@4
|
1466 return '';
|
danielebarchiesi@4
|
1467 }
|
danielebarchiesi@4
|
1468
|
danielebarchiesi@4
|
1469 /* */
|
danielebarchiesi@4
|
1470
|
danielebarchiesi@4
|
1471 function getBuiltInCallSQL($pattern, $context) {
|
danielebarchiesi@4
|
1472 $call = $pattern['call'];
|
danielebarchiesi@4
|
1473 $m = 'get' . ucfirst($call) . 'CallSQL';
|
danielebarchiesi@4
|
1474 if (method_exists($this, $m)) {
|
danielebarchiesi@4
|
1475 return $this->$m($pattern, $context);
|
danielebarchiesi@4
|
1476 }
|
danielebarchiesi@4
|
1477 else {
|
danielebarchiesi@4
|
1478 $this->addError('Unknown built-in call "' . $call . '"');
|
danielebarchiesi@4
|
1479 }
|
danielebarchiesi@4
|
1480 return '';
|
danielebarchiesi@4
|
1481 }
|
danielebarchiesi@4
|
1482
|
danielebarchiesi@4
|
1483 function getBoundCallSQL($pattern, $context) {
|
danielebarchiesi@4
|
1484 $r = '';
|
danielebarchiesi@4
|
1485 $var = $pattern['args'][0]['value'];
|
danielebarchiesi@4
|
1486 $info = $this->getVarTableInfos($var);
|
danielebarchiesi@4
|
1487 if (!$tbl = $info['table']) {
|
danielebarchiesi@4
|
1488 return '';
|
danielebarchiesi@4
|
1489 }
|
danielebarchiesi@4
|
1490 $col = $info['col'];
|
danielebarchiesi@4
|
1491 $tbl_alias = 'T_' . $tbl . '.' . $col;
|
danielebarchiesi@4
|
1492 if ($pattern['operator'] == '!') {
|
danielebarchiesi@4
|
1493 return $tbl_alias . ' IS NULL';
|
danielebarchiesi@4
|
1494 }
|
danielebarchiesi@4
|
1495 return $tbl_alias . ' IS NOT NULL';
|
danielebarchiesi@4
|
1496 }
|
danielebarchiesi@4
|
1497
|
danielebarchiesi@4
|
1498 function getHasTypeCallSQL($pattern, $context, $type) {
|
danielebarchiesi@4
|
1499 $r = '';
|
danielebarchiesi@4
|
1500 $var = $pattern['args'][0]['value'];
|
danielebarchiesi@4
|
1501 $info = $this->getVarTableInfos($var);
|
danielebarchiesi@4
|
1502 if (!$tbl = $info['table']) {
|
danielebarchiesi@4
|
1503 return '';
|
danielebarchiesi@4
|
1504 }
|
danielebarchiesi@4
|
1505 $col = $info['col'];
|
danielebarchiesi@4
|
1506 $tbl_alias = 'T_' . $tbl . '.' . $col . '_type';
|
danielebarchiesi@4
|
1507 return $tbl_alias . ' ' .$this->v('operator', '', $pattern) . '= ' . $type;
|
danielebarchiesi@4
|
1508 }
|
danielebarchiesi@4
|
1509
|
danielebarchiesi@4
|
1510 function getIsliteralCallSQL($pattern, $context) {
|
danielebarchiesi@4
|
1511 return $this->getHasTypeCallSQL($pattern, $context, 2);
|
danielebarchiesi@4
|
1512 }
|
danielebarchiesi@4
|
1513
|
danielebarchiesi@4
|
1514 function getIsblankCallSQL($pattern, $context) {
|
danielebarchiesi@4
|
1515 return $this->getHasTypeCallSQL($pattern, $context, 1);
|
danielebarchiesi@4
|
1516 }
|
danielebarchiesi@4
|
1517
|
danielebarchiesi@4
|
1518 function getIsiriCallSQL($pattern, $context) {
|
danielebarchiesi@4
|
1519 return $this->getHasTypeCallSQL($pattern, $context, 0);
|
danielebarchiesi@4
|
1520 }
|
danielebarchiesi@4
|
1521
|
danielebarchiesi@4
|
1522 function getIsuriCallSQL($pattern, $context) {
|
danielebarchiesi@4
|
1523 return $this->getHasTypeCallSQL($pattern, $context, 0);
|
danielebarchiesi@4
|
1524 }
|
danielebarchiesi@4
|
1525
|
danielebarchiesi@4
|
1526 function getStrCallSQL($pattern, $context) {
|
danielebarchiesi@4
|
1527 $sub_pattern = $pattern['args'][0];
|
danielebarchiesi@4
|
1528 $sub_type = $sub_pattern['type'];
|
danielebarchiesi@4
|
1529 $m = 'get' . ucfirst($sub_type) . 'ExpressionSQL';
|
danielebarchiesi@4
|
1530 if (method_exists($this, $m)) {
|
danielebarchiesi@4
|
1531 return $this->$m($sub_pattern, $context);
|
danielebarchiesi@4
|
1532 }
|
danielebarchiesi@4
|
1533 }
|
danielebarchiesi@4
|
1534
|
danielebarchiesi@4
|
1535 function getFunctionCallSQL($pattern, $context) {
|
danielebarchiesi@4
|
1536 $f_uri = $pattern['uri'];
|
danielebarchiesi@4
|
1537 if (preg_match('/(integer|double|float|string)$/', $f_uri)) {/* skip conversions */
|
danielebarchiesi@4
|
1538 $sub_pattern = $pattern['args'][0];
|
danielebarchiesi@4
|
1539 $sub_type = $sub_pattern['type'];
|
danielebarchiesi@4
|
1540 $m = 'get' . ucfirst($sub_type) . 'ExpressionSQL';
|
danielebarchiesi@4
|
1541 if (method_exists($this, $m)) {
|
danielebarchiesi@4
|
1542 return $this->$m($sub_pattern, $context);
|
danielebarchiesi@4
|
1543 }
|
danielebarchiesi@4
|
1544 }
|
danielebarchiesi@4
|
1545 }
|
danielebarchiesi@4
|
1546
|
danielebarchiesi@4
|
1547 function getLangDatatypeCallSQL($pattern, $context) {
|
danielebarchiesi@4
|
1548 $r = '';
|
danielebarchiesi@4
|
1549 if (isset($pattern['patterns'])) { /* proceed with first argument only (assumed as base type for type promotion) */
|
danielebarchiesi@4
|
1550 $sub_pattern = array('args' => array($pattern['patterns'][0]));
|
danielebarchiesi@4
|
1551 return $this->getLangDatatypeCallSQL($sub_pattern, $context);
|
danielebarchiesi@4
|
1552 }
|
danielebarchiesi@4
|
1553 if (!isset($pattern['args'])) {
|
danielebarchiesi@4
|
1554 return 'FALSE';
|
danielebarchiesi@4
|
1555 }
|
danielebarchiesi@4
|
1556 $sub_type = $pattern['args'][0]['type'];
|
danielebarchiesi@4
|
1557 if ($sub_type != 'var') {
|
danielebarchiesi@4
|
1558 return $this->getLangDatatypeCallSQL($pattern['args'][0], $context);
|
danielebarchiesi@4
|
1559 }
|
danielebarchiesi@4
|
1560 $var = $pattern['args'][0]['value'];
|
danielebarchiesi@4
|
1561 $info = $this->getVarTableInfos($var);
|
danielebarchiesi@4
|
1562 if (!$tbl = $info['table']) {
|
danielebarchiesi@4
|
1563 return '';
|
danielebarchiesi@4
|
1564 }
|
danielebarchiesi@4
|
1565 $col = 'o_lang_dt';
|
danielebarchiesi@4
|
1566 $tbl_alias = 'V_' . $tbl . '_' . $col . '.val';
|
danielebarchiesi@4
|
1567 if (!in_array($tbl_alias, $this->index['sub_joins'])) {
|
danielebarchiesi@4
|
1568 $this->index['sub_joins'][] = $tbl_alias;
|
danielebarchiesi@4
|
1569 }
|
danielebarchiesi@4
|
1570 $op = $this->v('operator', '', $pattern);
|
danielebarchiesi@4
|
1571 $r = trim($op . ' ' . $tbl_alias);
|
danielebarchiesi@4
|
1572 return $r;
|
danielebarchiesi@4
|
1573 }
|
danielebarchiesi@4
|
1574
|
danielebarchiesi@4
|
1575 function getDatatypeCallSQL($pattern, $context) {
|
danielebarchiesi@4
|
1576 return '/* datatype call */ ' . $this->getLangDatatypeCallSQL($pattern, $context);
|
danielebarchiesi@4
|
1577 }
|
danielebarchiesi@4
|
1578
|
danielebarchiesi@4
|
1579 function getLangCallSQL($pattern, $context) {
|
danielebarchiesi@4
|
1580 return '/* language call */ ' . $this->getLangDatatypeCallSQL($pattern, $context);
|
danielebarchiesi@4
|
1581 }
|
danielebarchiesi@4
|
1582
|
danielebarchiesi@4
|
1583 function getLangmatchesCallSQL($pattern, $context) {
|
danielebarchiesi@4
|
1584 if (count($pattern['args']) == 2) {
|
danielebarchiesi@4
|
1585 $arg_1 = $pattern['args'][0];
|
danielebarchiesi@4
|
1586 $arg_2 = $pattern['args'][1];
|
danielebarchiesi@4
|
1587 $sub_r_1 = $this->getBuiltInCallSQL($arg_1, $context);/* adds value join */
|
danielebarchiesi@4
|
1588 $sub_r_2 = $this->getExpressionSQL($arg_2, $context);
|
danielebarchiesi@4
|
1589 $op = $this->v('operator', '', $pattern);
|
danielebarchiesi@4
|
1590 if (preg_match('/^([\"\'])([^\'\"]+)/', $sub_r_2, $m)) {
|
danielebarchiesi@4
|
1591 if ($m[2] == '*') {
|
danielebarchiesi@4
|
1592 $r = ($op == '!') ? 'NOT (' . $sub_r_1 . ' REGEXP "^[a-zA-Z\-]+$"' . ')' : $sub_r_1 . ' REGEXP "^[a-zA-Z\-]+$"';
|
danielebarchiesi@4
|
1593 }
|
danielebarchiesi@4
|
1594 else {
|
danielebarchiesi@4
|
1595 $r = ($op == '!') ? $sub_r_1 . ' NOT LIKE ' . $m[1] . $m[2] . '%' . $m[1] : $sub_r_1 . ' LIKE ' . $m[1] . $m[2] . '%' . $m[1];
|
danielebarchiesi@4
|
1596 }
|
danielebarchiesi@4
|
1597 }
|
danielebarchiesi@4
|
1598 else {
|
danielebarchiesi@4
|
1599 $r = ($op == '!') ? $sub_r_1 . ' NOT LIKE CONCAT(' . $sub_r_2 . ', "%")' : $sub_r_1 . ' LIKE CONCAT(' . $sub_r_2 . ', "%")';
|
danielebarchiesi@4
|
1600 }
|
danielebarchiesi@4
|
1601 return $r;
|
danielebarchiesi@4
|
1602 }
|
danielebarchiesi@4
|
1603 return '';
|
danielebarchiesi@4
|
1604 }
|
danielebarchiesi@4
|
1605
|
danielebarchiesi@4
|
1606 function getSametermCallSQL($pattern, $context) {
|
danielebarchiesi@4
|
1607 if (count($pattern['args']) == 2) {
|
danielebarchiesi@4
|
1608 $arg_1 = $pattern['args'][0];
|
danielebarchiesi@4
|
1609 $arg_2 = $pattern['args'][1];
|
danielebarchiesi@4
|
1610 $sub_r_1 = $this->getExpressionSQL($arg_1, 'sameterm');
|
danielebarchiesi@4
|
1611 $sub_r_2 = $this->getExpressionSQL($arg_2, 'sameterm');
|
danielebarchiesi@4
|
1612 $op = $this->v('operator', '', $pattern);
|
danielebarchiesi@4
|
1613 $r = $sub_r_1 . ' ' . $op . '= ' . $sub_r_2;
|
danielebarchiesi@4
|
1614 return $r;
|
danielebarchiesi@4
|
1615 }
|
danielebarchiesi@4
|
1616 return '';
|
danielebarchiesi@4
|
1617 }
|
danielebarchiesi@4
|
1618
|
danielebarchiesi@4
|
1619 function getRegexCallSQL($pattern, $context) {
|
danielebarchiesi@4
|
1620 $ac = count($pattern['args']);
|
danielebarchiesi@4
|
1621 if ($ac >= 2) {
|
danielebarchiesi@4
|
1622 foreach ($pattern['args'] as $i => $arg) {
|
danielebarchiesi@4
|
1623 $var = 'sub_r_' . ($i + 1);
|
danielebarchiesi@4
|
1624 $$var = $this->getExpressionSQL($arg, $context, '', 'regex');
|
danielebarchiesi@4
|
1625 }
|
danielebarchiesi@4
|
1626 $sub_r_3 = (isset($sub_r_3) && preg_match('/[\"\'](.+)[\"\']/', $sub_r_3, $m)) ? strtolower($m[1]) : '';
|
danielebarchiesi@4
|
1627 $op = ($this->v('operator', '', $pattern) == '!') ? ' NOT' : '';
|
danielebarchiesi@4
|
1628 if (!$sub_r_1 || !$sub_r_2) return '';
|
danielebarchiesi@4
|
1629 $is_simple_search = preg_match('/^[\(\"]+(\^)?([a-z0-9\_\-\s]+)(\$)?[\)\"]+$/is', $sub_r_2, $m);
|
danielebarchiesi@4
|
1630 $is_simple_search = preg_match('/^[\(\"]+(\^)?([^\\\*\[\]\}\{\(\)\"\'\?\+\.]+)(\$)?[\)\"]+$/is', $sub_r_2, $m);
|
danielebarchiesi@4
|
1631 $is_o_search = preg_match('/o\.val\)*$/', $sub_r_1);
|
danielebarchiesi@4
|
1632 /* fulltext search (may have "|") */
|
danielebarchiesi@4
|
1633 if ($is_simple_search && $is_o_search && !$op && (strlen($m[2]) > 8) && $this->store->hasFulltextIndex()) {
|
danielebarchiesi@4
|
1634 /* MATCH variations */
|
danielebarchiesi@4
|
1635 if (($val_parts = preg_split('/\|/', $m[2]))) {
|
danielebarchiesi@4
|
1636 return 'MATCH(' . trim($sub_r_1, '()') . ') AGAINST("' . join(' ', $val_parts) . '")';
|
danielebarchiesi@4
|
1637 }
|
danielebarchiesi@4
|
1638 else {
|
danielebarchiesi@4
|
1639 return 'MATCH(' . trim($sub_r_1, '()') . ') AGAINST("' . $m[2] . '")';
|
danielebarchiesi@4
|
1640 }
|
danielebarchiesi@4
|
1641 }
|
danielebarchiesi@4
|
1642 if (preg_match('/\|/', $sub_r_2)) $is_simple_search = 0;
|
danielebarchiesi@4
|
1643 /* LIKE */
|
danielebarchiesi@4
|
1644 if ($is_simple_search && ($sub_r_3 == 'i')) {
|
danielebarchiesi@4
|
1645 $sub_r_2 = $m[1] ? $m[2] : '%' . $m[2];
|
danielebarchiesi@4
|
1646 $sub_r_2 .= isset($m[3]) && $m[3] ? '' : '%';
|
danielebarchiesi@4
|
1647 return $sub_r_1 . $op . ' LIKE "' . $sub_r_2 . '"';
|
danielebarchiesi@4
|
1648 }
|
danielebarchiesi@4
|
1649 /* REGEXP */
|
danielebarchiesi@4
|
1650 $opt = ($sub_r_3 == 'i') ? '' : 'BINARY ';
|
danielebarchiesi@4
|
1651 return $sub_r_1 . $op . ' REGEXP ' . $opt . $sub_r_2;
|
danielebarchiesi@4
|
1652 }
|
danielebarchiesi@4
|
1653 return '';
|
danielebarchiesi@4
|
1654 }
|
danielebarchiesi@4
|
1655
|
danielebarchiesi@4
|
1656 /* */
|
danielebarchiesi@4
|
1657
|
danielebarchiesi@4
|
1658 function getGROUPSQL() {
|
danielebarchiesi@4
|
1659 $r = '';
|
danielebarchiesi@4
|
1660 $nl = "\n";
|
danielebarchiesi@4
|
1661 $infos = $this->v('group_infos', array(), $this->infos['query']);
|
danielebarchiesi@4
|
1662 foreach ($infos as $info) {
|
danielebarchiesi@4
|
1663 $var = $info['value'];
|
danielebarchiesi@4
|
1664 if ($tbl_infos = $this->getVarTableInfos($var, 0)) {
|
danielebarchiesi@4
|
1665 $tbl_alias = $tbl_infos['table_alias'];
|
danielebarchiesi@4
|
1666 $r .= $r ? ', ' : 'GROUP BY ';
|
danielebarchiesi@4
|
1667 $r .= $tbl_alias;
|
danielebarchiesi@4
|
1668 }
|
danielebarchiesi@4
|
1669 }
|
danielebarchiesi@4
|
1670 $hr = '';
|
danielebarchiesi@4
|
1671 foreach ($this->index['havings'] as $having) {
|
danielebarchiesi@4
|
1672 $hr .= $hr ? ' AND' : ' HAVING';
|
danielebarchiesi@4
|
1673 $hr .= '(' . $having . ')';
|
danielebarchiesi@4
|
1674 }
|
danielebarchiesi@4
|
1675 $r .= $hr;
|
danielebarchiesi@4
|
1676 return $r ? $nl . $r : $r;
|
danielebarchiesi@4
|
1677 }
|
danielebarchiesi@4
|
1678
|
danielebarchiesi@4
|
1679 /* */
|
danielebarchiesi@4
|
1680
|
danielebarchiesi@4
|
1681 function getORDERSQL() {
|
danielebarchiesi@4
|
1682 $r = '';
|
danielebarchiesi@4
|
1683 $nl = "\n";
|
danielebarchiesi@4
|
1684 $infos = $this->v('order_infos', array(), $this->infos['query']);
|
danielebarchiesi@4
|
1685 foreach ($infos as $info) {
|
danielebarchiesi@4
|
1686 $type = $info['type'];
|
danielebarchiesi@4
|
1687 $ms = array('expression' => 'getExpressionSQL', 'built_in_call' => 'getBuiltInCallSQL', 'function_call' => 'getFunctionCallSQL');
|
danielebarchiesi@4
|
1688 $m = isset($ms[$type]) ? $ms[$type] : 'get' . ucfirst($type) . 'ExpressionSQL';
|
danielebarchiesi@4
|
1689 if (method_exists($this, $m)) {
|
danielebarchiesi@4
|
1690 $sub_r = '(' . $this->$m($info, 'order') . ')';
|
danielebarchiesi@4
|
1691 $sub_r .= $this->v('direction', '', $info) == 'desc' ? ' DESC' : '';
|
danielebarchiesi@4
|
1692 $r .= $r ? ',' .$nl . $sub_r : $sub_r;
|
danielebarchiesi@4
|
1693 }
|
danielebarchiesi@4
|
1694 }
|
danielebarchiesi@4
|
1695 return $r ? $nl . 'ORDER BY ' . $r : '';
|
danielebarchiesi@4
|
1696 }
|
danielebarchiesi@4
|
1697
|
danielebarchiesi@4
|
1698 /* */
|
danielebarchiesi@4
|
1699
|
danielebarchiesi@4
|
1700 function getLIMITSQL() {
|
danielebarchiesi@4
|
1701 $r = '';
|
danielebarchiesi@4
|
1702 $nl = "\n";
|
danielebarchiesi@4
|
1703 $limit = $this->v('limit', -1, $this->infos['query']);
|
danielebarchiesi@4
|
1704 $offset = $this->v('offset', -1, $this->infos['query']);
|
danielebarchiesi@4
|
1705 if ($limit != -1) {
|
danielebarchiesi@4
|
1706 $offset = ($offset == -1) ? 0 : mysql_real_escape_string($offset, $this->store->getDBCon());
|
danielebarchiesi@4
|
1707 $r = 'LIMIT ' . $offset . ',' . $limit;
|
danielebarchiesi@4
|
1708 }
|
danielebarchiesi@4
|
1709 elseif ($offset != -1) {
|
danielebarchiesi@4
|
1710 $r = 'LIMIT ' . mysql_real_escape_string($offset, $this->store->getDBCon()) . ',999999999999'; /* mysql doesn't support stand-alone offsets .. */
|
danielebarchiesi@4
|
1711 }
|
danielebarchiesi@4
|
1712 return $r ? $nl . $r : '';
|
danielebarchiesi@4
|
1713 }
|
danielebarchiesi@4
|
1714
|
danielebarchiesi@4
|
1715 /* */
|
danielebarchiesi@4
|
1716
|
danielebarchiesi@4
|
1717 function getValueSQL($q_tbl, $q_sql) {
|
danielebarchiesi@4
|
1718 $r = '';
|
danielebarchiesi@4
|
1719 /* result vars */
|
danielebarchiesi@4
|
1720 $vars = $this->infos['query']['result_vars'];
|
danielebarchiesi@4
|
1721 $nl = "\n";
|
danielebarchiesi@4
|
1722 $v_tbls = array('JOIN' => array(), 'LEFT JOIN' => array());
|
danielebarchiesi@4
|
1723 $vc = 1;
|
danielebarchiesi@4
|
1724 foreach ($vars as $var) {
|
danielebarchiesi@4
|
1725 $var_name = $var['var'];
|
danielebarchiesi@4
|
1726 $r .= $r ? ',' . $nl . ' ' : ' ';
|
danielebarchiesi@4
|
1727 $col = '';
|
danielebarchiesi@4
|
1728 $tbl = '';
|
danielebarchiesi@4
|
1729 if ($var_name != '*') {
|
danielebarchiesi@4
|
1730 if (in_array($var_name, $this->infos['null_vars'])) {
|
danielebarchiesi@4
|
1731 if (isset($this->initial_index['vars'][$var_name])) {
|
danielebarchiesi@4
|
1732 $col = $this->initial_index['vars'][$var_name][0]['col'];
|
danielebarchiesi@4
|
1733 $tbl = $this->initial_index['vars'][$var_name][0]['table'];
|
danielebarchiesi@4
|
1734 }
|
danielebarchiesi@4
|
1735 if (isset($this->initial_index['graph_vars'][$var_name])) {
|
danielebarchiesi@4
|
1736 $col = 'g';
|
danielebarchiesi@4
|
1737 $tbl = $this->initial_index['graph_vars'][$var_name][0]['table'];
|
danielebarchiesi@4
|
1738 }
|
danielebarchiesi@4
|
1739 }
|
danielebarchiesi@4
|
1740 elseif (isset($this->index['vars'][$var_name])) {
|
danielebarchiesi@4
|
1741 $col = $this->index['vars'][$var_name][0]['col'];
|
danielebarchiesi@4
|
1742 $tbl = $this->index['vars'][$var_name][0]['table'];
|
danielebarchiesi@4
|
1743 }
|
danielebarchiesi@4
|
1744 }
|
danielebarchiesi@4
|
1745 if ($var['aggregate']) {
|
danielebarchiesi@4
|
1746 $r .= 'TMP.`' . $var['alias'] . '`';
|
danielebarchiesi@4
|
1747 }
|
danielebarchiesi@4
|
1748 else {
|
danielebarchiesi@4
|
1749 $join_type = in_array($tbl, array_merge($this->index['from'], $this->index['join'])) ? 'JOIN' : 'LEFT JOIN';/* val may be NULL */
|
danielebarchiesi@4
|
1750 $v_tbls[$join_type][] = array('t_col' => $col, 'q_col' => $var_name, 'vc' => $vc);
|
danielebarchiesi@4
|
1751 $r .= 'V' . $vc . '.val AS `' . $var_name . '`';
|
danielebarchiesi@4
|
1752 if (in_array($col, array('s', 'o'))) {
|
danielebarchiesi@4
|
1753 if (strpos($q_sql, '`' . $var_name . ' type`')) {
|
danielebarchiesi@4
|
1754 $r .= ', ' . $nl . ' TMP.`' . $var_name . ' type` AS `' . $var_name . ' type`';
|
danielebarchiesi@4
|
1755 //$r .= ', ' . $nl . ' CASE TMP.`' . $var_name . ' type` WHEN 2 THEN "literal" WHEN 1 THEN "bnode" ELSE "uri" END AS `' . $var_name . ' type`';
|
danielebarchiesi@4
|
1756 }
|
danielebarchiesi@4
|
1757 else {
|
danielebarchiesi@4
|
1758 $r .= ', ' . $nl . ' NULL AS `' . $var_name . ' type`';
|
danielebarchiesi@4
|
1759 }
|
danielebarchiesi@4
|
1760 }
|
danielebarchiesi@4
|
1761 $vc++;
|
danielebarchiesi@4
|
1762 if ($col == 'o') {
|
danielebarchiesi@4
|
1763 $v_tbls[$join_type][] = array('t_col' => 'id', 'q_col' => $var_name . ' lang_dt', 'vc' => $vc);
|
danielebarchiesi@4
|
1764 if (strpos($q_sql, '`' . $var_name . ' lang_dt`')) {
|
danielebarchiesi@4
|
1765 $r .= ', ' .$nl. ' V' . $vc . '.val AS `' . $var_name . ' lang_dt`';
|
danielebarchiesi@4
|
1766 $vc++;
|
danielebarchiesi@4
|
1767 }
|
danielebarchiesi@4
|
1768 else {
|
danielebarchiesi@4
|
1769 $r .= ', ' .$nl. ' NULL AS `' . $var_name . ' lang_dt`';
|
danielebarchiesi@4
|
1770 }
|
danielebarchiesi@4
|
1771 }
|
danielebarchiesi@4
|
1772 }
|
danielebarchiesi@4
|
1773 }
|
danielebarchiesi@4
|
1774 if (!$r) $r = '*';
|
danielebarchiesi@4
|
1775 /* from */
|
danielebarchiesi@4
|
1776 $r .= $nl . 'FROM (' . $q_tbl . ' TMP)';
|
danielebarchiesi@4
|
1777 foreach (array('JOIN', 'LEFT JOIN') as $join_type) {
|
danielebarchiesi@4
|
1778 foreach ($v_tbls[$join_type] as $v_tbl) {
|
danielebarchiesi@4
|
1779 $tbl = $this->getValueTable($v_tbl['t_col']);
|
danielebarchiesi@4
|
1780 $var_name = preg_replace('/^([^\s]+)(.*)$/', '\\1', $v_tbl['q_col']);
|
danielebarchiesi@4
|
1781 $cur_join_type = in_array($var_name, $this->infos['null_vars']) ? 'LEFT JOIN' : $join_type;
|
danielebarchiesi@4
|
1782 if (!strpos($q_sql, '`' . $v_tbl['q_col'].'`')) continue;
|
danielebarchiesi@4
|
1783 $r .= $nl . ' ' . $cur_join_type . ' ' . $tbl . ' V' . $v_tbl['vc'] . ' ON (
|
danielebarchiesi@4
|
1784 (V' . $v_tbl['vc'] . '.id = TMP.`' . $v_tbl['q_col'].'`)
|
danielebarchiesi@4
|
1785 )';
|
danielebarchiesi@4
|
1786 }
|
danielebarchiesi@4
|
1787 }
|
danielebarchiesi@4
|
1788 /* create pos columns, id needed */
|
danielebarchiesi@4
|
1789 if ($this->v('order_infos', array(), $this->infos['query'])) {
|
danielebarchiesi@4
|
1790 $r .= $nl . ' ORDER BY _pos_';
|
danielebarchiesi@4
|
1791 }
|
danielebarchiesi@4
|
1792 return 'SELECT' . $nl . $r;
|
danielebarchiesi@4
|
1793 }
|
danielebarchiesi@4
|
1794
|
danielebarchiesi@4
|
1795 /* */
|
danielebarchiesi@4
|
1796
|
danielebarchiesi@4
|
1797 }
|
danielebarchiesi@4
|
1798
|
danielebarchiesi@4
|
1799
|