1 | package felix.dstruct; |
2 | |
3 | |
4 | import java.sql.Array; |
5 | import java.sql.PreparedStatement; |
6 | import java.sql.ResultSet; |
7 | import java.sql.SQLException; |
8 | import java.util.ArrayList; |
9 | import java.util.Arrays; |
10 | import java.util.HashSet; |
11 | import java.util.List; |
12 | |
13 | |
14 | import felix.util.FelixStringMan; |
15 | import felix.util.FelixUIMan; |
16 | |
17 | import tuffy.db.RDB; |
18 | import tuffy.mln.Literal; |
19 | import tuffy.ra.ConjunctiveQuery; |
20 | import tuffy.util.ExceptionMan; |
21 | import tuffy.util.UIMan; |
22 | |
23 | |
24 | /** |
25 | * A Data Movement Operator (DMO) is a bridge from physical database |
26 | * objects (e.g., view, relational table etc.) to logical |
27 | * requirements of the data. A statistical operator (e.g., CRF, Coref etc.) |
28 | * only knows the logic of DMO instead of the physical execution |
29 | * plan. The physical execution plan of the DMO is instantiated by |
30 | * the Optimizer. The logic definition of the DMO is instantiated by |
31 | * corresponding statistical operators. |
32 | * |
33 | * @author Ce Zhang |
34 | * |
35 | */ |
36 | public class DataMovementOperator { |
37 | |
38 | /** |
39 | * RDB object on which this DMO works on. |
40 | */ |
41 | public RDB db; |
42 | |
43 | /** |
44 | * Estimated number of Bound-Bound invocations. |
45 | */ |
46 | public int predictedBB = 0; |
47 | |
48 | /** |
49 | * Estimated number of Bound-Free invocations. |
50 | */ |
51 | public int PredictedBF = 0; |
52 | |
53 | /** |
54 | * Estimated number of Free-Free invocations. |
55 | */ |
56 | public int PredictedFF = 0; |
57 | |
58 | /** |
59 | * Whether this DMO can be used as view/table by other DMOs. |
60 | */ |
61 | public boolean isIntermediaDMO = false; |
62 | |
63 | /** |
64 | * Name of table/view generated by this DMO. This name |
65 | * can be used by other DMOs as a view/table directly. |
66 | */ |
67 | public String name = ""; |
68 | |
69 | /** |
70 | * Counter for DMO ID. |
71 | */ |
72 | public static int globalID = 1; |
73 | |
74 | /** |
75 | * Whether this DMO allowing optimizations from the optimizer. |
76 | */ |
77 | public boolean allowOptimization = true; |
78 | |
79 | /** |
80 | * Whether this DMO allows pre-fetching. |
81 | */ |
82 | public boolean hasKnownFetchingOrder = false; |
83 | |
84 | /** |
85 | * Parameter for pre-fetching optimization. |
86 | */ |
87 | public int preFetchFactor = -1; |
88 | |
89 | /** |
90 | * The statistical operator who instantiates this DMO. |
91 | */ |
92 | public StatOperator parentStatOperator = null; |
93 | |
94 | /** |
95 | * Conjunctive query or prepared statement acting as the *logic* |
96 | * description of this DMO. This plan cannot be executed by |
97 | * the executor. |
98 | */ |
99 | public QuerySet logicQueryPlan = null; |
100 | |
101 | /** |
102 | * How the result of this DMO is ordered? |
103 | */ |
104 | public ArrayList<String> orderBy = new ArrayList<String>(); |
105 | |
106 | /** |
107 | * Do we need to build index for this DMO's output/intermediate |
108 | * results? |
109 | */ |
110 | public boolean needIndex = false; |
111 | |
112 | /** |
113 | * Datalog, Conjunctive query or prepared statement acting as the *physical* |
114 | * description of this DMO. When this DMO is executed, it first |
115 | * evaluates all Datalog rules (only evaluate once), and then evaluate |
116 | * the conjunctive query or prepared statement (which may have been optimized). |
117 | * This variable cannot be touched by any ad hoc statistical operator. |
118 | */ |
119 | public QuerySet physicalQueryPlan = null; |
120 | |
121 | /** |
122 | * The schema for the output of this DMO. |
123 | */ |
124 | public ArrayList<String> finalSelList = new ArrayList<String>(); |
125 | |
126 | /** |
127 | * Part of the schema of the output of this DMO, which is from the |
128 | * conjunctive queries or prepared statement in {@link DataMovementOperator#logicQueryPlan}. |
129 | */ |
130 | public ArrayList<String> selListFromRule = new ArrayList<String>(); |
131 | |
132 | /** |
133 | * Part of the schema of the output of this DMO, which is additionally |
134 | * assigned (i.e., may not be founded in the conjunctive query or |
135 | * prepared statement in {@link DataMovementOperator#logicQueryPlan}). |
136 | */ |
137 | public ArrayList<String> additionalSelList = new ArrayList<String>(); |
138 | |
139 | /** |
140 | * Whether prepare() method has been invoked. |
141 | */ |
142 | public boolean hasPrepared = false; |
143 | |
144 | /** |
145 | * Whether the output is a {@link ResultSet} object or others. This is maintained |
146 | * by DMO, and is not visible to others. |
147 | * |
148 | */ |
149 | boolean isResultSet = true; |
150 | |
151 | /** |
152 | * Whether the output (if any) of this DMO should be regarded as view or materialized |
153 | * table. |
154 | */ |
155 | public boolean asView = true; |
156 | |
157 | /** |
158 | * Set of variables which will be bounded while evaluating this DMO. |
159 | */ |
160 | public HashSet<String> whichToBound = new HashSet<String>(); |
161 | |
162 | /** |
163 | * Object as the output of this DMO. This can be a {@link ResultSet} object or other. |
164 | * This variable is not visible to other class. Other class must use specified data-exchange |
165 | * interface of DMO instead of trying to fetching data from this variable directly. |
166 | */ |
167 | Object resultSet = null; |
168 | |
169 | /** |
170 | * Get the union of results from a set of DMOs. Here each DMO must share exactly the same output schema. |
171 | * @param db |
172 | * @param _parentStatOperator |
173 | * @param toBeUnioned set of DMOs to be unioned. |
174 | * @param bindingPattern bindingPattern of the resulting union. See {@link ConjunctiveQuery#psMap}. |
175 | * @param bindings |
176 | * @return |
177 | */ |
178 | @SuppressWarnings("unchecked") |
179 | public static DataMovementOperator UnionAll(RDB db, StatOperator _parentStatOperator, |
180 | List<DataMovementOperator> toBeUnioned, String bindingPattern, ArrayList<Integer> bindings, int... cid){ |
181 | |
182 | //return a dummy dmo for unionAll |
183 | DataMovementOperator ret = new DataMovementOperator(db, _parentStatOperator); |
184 | ret.allowOptimization = false; |
185 | ret.predictedBB = 0; |
186 | ret.PredictedBF = 0; |
187 | ret.PredictedFF = 0; |
188 | |
189 | String sql = ""; |
190 | ArrayList<String> subqueries = new ArrayList<String>(); |
191 | ArrayList<String> unionAllSelList = null; |
192 | |
193 | for(DataMovementOperator dmo : toBeUnioned){ |
194 | subqueries.add(" SELECT * FROM " + dmo.getAllFreeViewName()); |
195 | // we assume all sub-DMOs should have the same selList. |
196 | if(unionAllSelList == null){ |
197 | ret.selListFromRule = (ArrayList<String>) dmo.selListFromRule.clone(); |
198 | ret.additionalSelList = (ArrayList<String>) dmo.additionalSelList.clone(); |
199 | ret.finalSelList = (ArrayList<String>) dmo.finalSelList.clone(); |
200 | unionAllSelList = (ArrayList<String>) dmo.finalSelList.clone(); |
201 | } |
202 | } |
203 | |
204 | sql = "SELECT " + FelixStringMan.commaList(unionAllSelList) + " FROM ( " + |
205 | FelixStringMan.join(" UNION ALL ", subqueries) + ") TMPTMPTMP WHERE "; |
206 | |
207 | ArrayList<String> whereList = new ArrayList<String>(); |
208 | for(int i=0; i < unionAllSelList.size(); i++){ |
209 | if(bindingPattern.charAt(i) == '1'){ |
210 | whereList.add("(" + unionAllSelList.get(i) + " = ?" + ")"); |
211 | } |
212 | } |
213 | whereList.add("(1=1)"); |
214 | sql += FelixStringMan.join(" AND ", whereList); |
215 | |
216 | ret.logicQueryPlan.addQuery(db.getPrepareStatement(sql), ret.selListFromRule, ret.additionalSelList); |
217 | |
218 | |
219 | return ret; |
220 | } |
221 | |
222 | /** |
223 | * Generate a DMO which is a SELECT on the given DMO. |
224 | * @param db |
225 | * @param _parentStatOperator |
226 | * @param fromDMO the given DMO. |
227 | * @param bindings variables in the WHERE list. |
228 | * @return |
229 | */ |
230 | @SuppressWarnings("unchecked") |
231 | public static DataMovementOperator Select(RDB db, StatOperator _parentStatOperator, |
232 | DataMovementOperator fromDMO, ArrayList<String> bindings, int... cid){ |
233 | |
234 | //return a dummy dmo for unionAll |
235 | DataMovementOperator ret = new DataMovementOperator(db, _parentStatOperator); |
236 | ret.allowOptimization = false; |
237 | ret.predictedBB = 0; |
238 | ret.PredictedBF = 0; |
239 | ret.PredictedFF = 0; |
240 | |
241 | ret.selListFromRule = (ArrayList<String>) fromDMO.selListFromRule.clone(); |
242 | ret.additionalSelList = (ArrayList<String>) fromDMO.additionalSelList.clone(); |
243 | ret.finalSelList = (ArrayList<String>) fromDMO.finalSelList.clone(); |
244 | |
245 | String sql = "SELECT " + FelixStringMan.commaList(ret.finalSelList) + " FROM " + |
246 | fromDMO.getAllFreeViewName() + " WHERE "; |
247 | |
248 | ArrayList<String> whereList = new ArrayList<String>(); |
249 | for(int i=0; i < bindings.size(); i++){ |
250 | whereList.add("(" + bindings.get(i) + " = ?" + ")"); |
251 | } |
252 | whereList.add("(1=1)"); |
253 | sql += FelixStringMan.join(" AND ", whereList); |
254 | |
255 | ret.logicQueryPlan.addQuery(db.getPrepareStatement(sql), ret.selListFromRule, ret.additionalSelList); |
256 | |
257 | return ret; |
258 | } |
259 | |
260 | /** |
261 | * Generate a DMO which is a SELECT ... ORDER BY on the given DMO. |
262 | * @param db |
263 | * @param _parentStatOperator |
264 | * @param fromDMO the given DMO. |
265 | * @param bindings variables in the WHERE list. |
266 | * @param orderby |
267 | * @param cid |
268 | * @return |
269 | */ |
270 | @SuppressWarnings("unchecked") |
271 | public static DataMovementOperator SelectOrderBy(RDB db, StatOperator _parentStatOperator, |
272 | DataMovementOperator fromDMO, ArrayList<String> bindings, String orderby, int... cid){ |
273 | |
274 | //return a dummy dmo for unionAll |
275 | DataMovementOperator ret = new DataMovementOperator(db, _parentStatOperator); |
276 | ret.allowOptimization = false; |
277 | ret.predictedBB = 0; |
278 | ret.PredictedBF = 0; |
279 | ret.PredictedFF = 0; |
280 | |
281 | ret.selListFromRule = (ArrayList<String>) fromDMO.selListFromRule.clone(); |
282 | ret.additionalSelList = (ArrayList<String>) fromDMO.additionalSelList.clone(); |
283 | ret.finalSelList = (ArrayList<String>) fromDMO.finalSelList.clone(); |
284 | |
285 | String sql = "SELECT " + FelixStringMan.commaList(ret.finalSelList) + " FROM " + |
286 | fromDMO.getAllFreeViewName() + " WHERE "; |
287 | |
288 | ArrayList<String> whereList = new ArrayList<String>(); |
289 | for(int i=0; i < bindings.size(); i++){ |
290 | whereList.add("(" + bindings.get(i) + " = ?" + ")"); |
291 | } |
292 | whereList.add("(1=1)"); |
293 | sql += FelixStringMan.join(" AND ", whereList); |
294 | sql += orderby; |
295 | |
296 | ret.logicQueryPlan.addQuery(db.getPrepareStatement(sql), ret.selListFromRule, ret.additionalSelList); |
297 | |
298 | return ret; |
299 | } |
300 | |
301 | /** |
302 | * the constructor. |
303 | * @param _db |
304 | * @param _parentStatOperator |
305 | */ |
306 | public DataMovementOperator(RDB _db, StatOperator _parentStatOperator){ |
307 | |
308 | db = _db; |
309 | parentStatOperator = _parentStatOperator; |
310 | logicQueryPlan = new QuerySet(); |
311 | physicalQueryPlan = new QuerySet(); |
312 | |
313 | this.name = "pred_DMO_" + (globalID++); |
314 | } |
315 | |
316 | /** |
317 | * Methods that prepares for the physical execution of this DMO. Invocation |
318 | * of this method will: 1) execute all Datalog rules in the physical |
319 | * plan; 2) build indices for evaluating conjunctive queries; and 3) create |
320 | * view/table for this DMO. This function can be only called once in |
321 | * each Dual decomposition iteration. |
322 | * |
323 | */ |
324 | public void prepare(){ |
325 | |
326 | |
327 | if(hasPrepared){ |
328 | for(ConjunctiveQuery cq : physicalQueryPlan.datalogQueries){ |
329 | //db.dropTable(cq.head.getPred().getRelName()); |
330 | String ss = "DELETE FROM " + cq.head.getPred().getRelName(); |
331 | db.execute(ss); |
332 | } |
333 | |
334 | db.commit(); |
335 | } |
336 | |
337 | // if(hasPrepared == false){ |
338 | for(ConjunctiveQuery cq : physicalQueryPlan.datalogQueries){ |
339 | FelixUIMan.println(2, "Materailizing " + cq); |
340 | cq.buildIndexes(db, null, null, null, false, new ArrayList<String>()); |
341 | cq.materialize(db, true, orderBy); |
342 | } |
343 | |
344 | // TODO: do we need to build indices for PreparedStatement? |
345 | if(physicalQueryPlan.objectConjunctiveQuery != null){ |
346 | physicalQueryPlan.objectConjunctiveQuery.buildIndexes(db, null, null, null, false, |
347 | this.additionalSelList); |
348 | |
349 | db.analyze(physicalQueryPlan.objectConjunctiveQuery.head.getPred().getRelName()); |
350 | |
351 | for(Literal l : physicalQueryPlan.objectConjunctiveQuery.body){ |
352 | db.analyze(l.getPred().getRelName()); |
353 | } |
354 | } |
355 | |
356 | // create view/table for this DMO |
357 | if(!isIntermediaDMO && asView){ |
358 | |
359 | db.dropTable(this.getAllFreeViewName()); |
360 | db.dropView(this.getAllFreeViewName()); |
361 | db.commit(); |
362 | |
363 | String sql = "CREATE VIEW " + this.getAllFreeViewName() + " AS " + |
364 | this.getPS(null, new ArrayList<Integer>()).toString(); |
365 | |
366 | FelixUIMan.println(2, "CREATE VIEW " + this.getAllFreeViewName() + " AS " + |
367 | this.getPS(null, new ArrayList<Integer>()).toString()); |
368 | |
369 | db.execute(sql); |
370 | }else if(!isIntermediaDMO && !asView){ |
371 | |
372 | db.dropTable(this.getAllFreeViewName()); |
373 | db.dropView(this.getAllFreeViewName()); |
374 | db.commit(); |
375 | |
376 | FelixUIMan.println(2, "CREATE TABLE "+ this.getAllFreeViewName() + " AS " + this.getPS(null, new ArrayList<Integer>()).toString()); |
377 | String sql = "CREATE TABLE " + this.getAllFreeViewName() + " AS " + |
378 | this.getPS(null, new ArrayList<Integer>()).toString(); |
379 | db.execute(sql); |
380 | |
381 | // needIndex should go back to the optimizer? |
382 | needIndex = true; |
383 | if(needIndex){ |
384 | for(String s : this.selListFromRule){ |
385 | FelixUIMan.println(2, "CREATE INDEX " + this.getAllFreeViewName() + "_" + s |
386 | + " ON " + this.getAllFreeViewName() + "(" + s + ")"); |
387 | db.execute("CREATE INDEX " + this.getAllFreeViewName() + "_" + s |
388 | + " ON " + this.getAllFreeViewName() + "(" + s + ")"); |
389 | } |
390 | } |
391 | |
392 | db.analyze(this.getAllFreeViewName()); |
393 | } |
394 | |
395 | hasPrepared = true; |
396 | // } |
397 | } |
398 | |
399 | /** |
400 | * Execute this DMO given bindings of variables. This method need to be invoked before |
401 | * {@link DataMovementOperator#next()}, {@link DataMovementOperator#getNext(int)}, |
402 | * {@link DataMovementOperator#getNext(String)} etc. can be invoked. This interface |
403 | * is similar to ResultSet in JDBC. |
404 | * |
405 | * @param bindingPattern binding patterns. If this DMO is a conjunctive query (in logic plan), |
406 | * use format as {@link ConjunctiveQuery#psMap} (a null value will correspond to all-free case). |
407 | * If this DMO is a prepared statement (in logic plan), this value should be set as null. |
408 | * @param bindings ordered list of constants that will be used to bind variables. |
409 | * @return PreparedStatement that will be used to execute this DMO. |
410 | */ |
411 | public PreparedStatement execute(String bindingPattern, ArrayList<Integer> bindings){ |
412 | |
413 | //TODO: add pre-fetch for CRF operator |
414 | try{ |
415 | |
416 | if(resultSet != null && resultSet.getClass().equals(ResultSet.class)){ |
417 | ResultSet rs = (ResultSet) resultSet; |
418 | rs.close(); |
419 | } |
420 | |
421 | resultSet = null; |
422 | |
423 | //this.prepare(); |
424 | |
425 | if(bindingPattern == null && physicalQueryPlan.objectPreparedStatement != null){ |
426 | |
427 | for(int i=0;i<bindings.size();i++){ |
428 | physicalQueryPlan.objectPreparedStatement.setInt(i+1, bindings.get(i)); |
429 | } |
430 | |
431 | physicalQueryPlan.objectPreparedStatement.execute(); |
432 | |
433 | resultSet = physicalQueryPlan.objectPreparedStatement.getResultSet(); |
434 | |
435 | isResultSet = true; |
436 | |
437 | return physicalQueryPlan.objectPreparedStatement; |
438 | |
439 | }else if(bindingPattern != null && physicalQueryPlan.objectConjunctiveQuery != null){ |
440 | |
441 | PreparedStatement ps = physicalQueryPlan.objectConjunctiveQuery.psMap.get(bindingPattern); |
442 | |
443 | for(int i=0;i<bindings.size();i++){ |
444 | physicalQueryPlan.objectPreparedStatement.setInt(i+1, bindings.get(i)); |
445 | } |
446 | |
447 | ps.execute(); |
448 | |
449 | resultSet = ps.getResultSet(); |
450 | |
451 | isResultSet = true; |
452 | |
453 | return ps; |
454 | |
455 | }else if(bindingPattern == null && physicalQueryPlan.objectConjunctiveQuery != null){ |
456 | |
457 | PreparedStatement ps = physicalQueryPlan.objectConjunctiveQuery.psMap.get( |
458 | physicalQueryPlan.objectConjunctiveQuery.getAllFreeBinding()); |
459 | |
460 | ps.execute(); |
461 | |
462 | resultSet = ps.getResultSet(); |
463 | |
464 | isResultSet = true; |
465 | |
466 | return ps; |
467 | }else{ |
468 | throw new Exception("Errors when trying to binding non-existing queries!"); |
469 | } |
470 | }catch(Exception e){ |
471 | e.printStackTrace(); |
472 | } |
473 | return null; |
474 | |
475 | } |
476 | |
477 | /** |
478 | * Get the prepared statement that will be used to execute this DMO. |
479 | * See {@link DataMovementOperator#execute(String, ArrayList)} (the only difference |
480 | * is this method does not actually execute this DMO). |
481 | */ |
482 | public PreparedStatement getPS(String bindingPattern, ArrayList<Integer> bindings){ |
483 | |
484 | //TODO: add pre-fetch for CRF operator |
485 | try{ |
486 | |
487 | if(bindingPattern == null && physicalQueryPlan.objectPreparedStatement != null){ |
488 | |
489 | for(int i=0;i<bindings.size();i++){ |
490 | physicalQueryPlan.objectPreparedStatement.setInt(i+1, bindings.get(i)); |
491 | } |
492 | |
493 | return physicalQueryPlan.objectPreparedStatement; |
494 | |
495 | }else if(bindingPattern != null && physicalQueryPlan.objectConjunctiveQuery != null){ |
496 | |
497 | PreparedStatement ps = physicalQueryPlan.objectConjunctiveQuery.psMap.get(bindingPattern); |
498 | |
499 | for(int i=0;i<bindings.size();i++){ |
500 | physicalQueryPlan.objectPreparedStatement.setInt(i+1, bindings.get(i)); |
501 | } |
502 | |
503 | return ps; |
504 | |
505 | }else if(bindingPattern == null && physicalQueryPlan.objectConjunctiveQuery != null){ |
506 | |
507 | PreparedStatement ps = physicalQueryPlan.objectConjunctiveQuery.psMap.get( |
508 | physicalQueryPlan.objectConjunctiveQuery.getAllFreeBinding()); |
509 | |
510 | return ps; |
511 | }else{ |
512 | throw new Exception("Errors when trying to binding non-existing queries!"); |
513 | } |
514 | }catch(Exception e){ |
515 | |
516 | } |
517 | return null; |
518 | |
519 | } |
520 | |
521 | /** |
522 | * Gets the view/table name of this DMO in Free-free case. This name can be referred |
523 | * by other DMO directly w/o aware of the physical plan of this DMO. |
524 | */ |
525 | public String getAllFreeViewName(){ |
526 | try{ |
527 | if(this.isIntermediaDMO){ |
528 | throw new Exception("Requesting view name for intermedia relation!"); |
529 | } |
530 | return this.name; |
531 | }catch(Exception e){ |
532 | e.printStackTrace(); |
533 | } |
534 | return null; |
535 | } |
536 | |
537 | /** |
538 | * Whether there are more tuples in the result of this DMO. See {@link DataMovementOperator#execute(String, ArrayList)}. |
539 | * @return |
540 | */ |
541 | public Boolean next(){ |
542 | |
543 | try{ |
544 | if(isResultSet){ |
545 | |
546 | ResultSet rs = (ResultSet) resultSet; |
547 | |
548 | boolean aa = rs.next(); |
549 | |
550 | if(aa){ |
551 | return aa; |
552 | }else{ |
553 | rs.close(); |
554 | return aa; |
555 | } |
556 | } |
557 | |
558 | }catch(Exception e){ |
559 | |
560 | } |
561 | |
562 | return null; |
563 | } |
564 | |
565 | /** |
566 | * Get int value in the result of this DMO. See {@link DataMovementOperator#execute(String, ArrayList)}. |
567 | * @return |
568 | */ |
569 | public Integer getNext(String columnName){ |
570 | |
571 | try{ |
572 | if(isResultSet){ |
573 | |
574 | ResultSet rs = (ResultSet) resultSet; |
575 | return rs.getInt(columnName); |
576 | |
577 | } |
578 | |
579 | |
580 | }catch(Exception e){ |
581 | |
582 | } |
583 | |
584 | return null; |
585 | } |
586 | |
587 | /** |
588 | * Get int value in the result of this DMO. See {@link DataMovementOperator#execute(String, ArrayList)}. |
589 | * @return |
590 | */ |
591 | public Array getNextArray(int column){ |
592 | |
593 | try{ |
594 | if(isResultSet){ |
595 | |
596 | ResultSet rs = (ResultSet) resultSet; |
597 | return rs.getArray(column); |
598 | |
599 | } |
600 | |
601 | |
602 | }catch(Exception e){ |
603 | e.printStackTrace(); |
604 | } |
605 | |
606 | return null; |
607 | } |
608 | |
609 | /** |
610 | * Get int value in the result of this DMO. See {@link DataMovementOperator#execute(String, ArrayList)}. |
611 | * @return |
612 | */ |
613 | public Integer getNext(int column){ |
614 | |
615 | try{ |
616 | if(isResultSet){ |
617 | |
618 | ResultSet rs = (ResultSet) resultSet; |
619 | return rs.getInt(column); |
620 | |
621 | } |
622 | |
623 | |
624 | }catch(Exception e){ |
625 | e.printStackTrace(); |
626 | } |
627 | |
628 | return null; |
629 | } |
630 | |
631 | /** |
632 | * Get double value in the result of this DMO. See {@link DataMovementOperator#execute(String, ArrayList)}. |
633 | * @return |
634 | */ |
635 | public Double getNextDouble(String columnName){ |
636 | |
637 | try{ |
638 | if(isResultSet){ |
639 | |
640 | ResultSet rs = (ResultSet) resultSet; |
641 | return rs.getDouble(columnName); |
642 | |
643 | } |
644 | |
645 | |
646 | }catch(Exception e){ |
647 | |
648 | } |
649 | |
650 | return null; |
651 | } |
652 | |
653 | /** |
654 | * Get double value in the result of this DMO. See {@link DataMovementOperator#execute(String, ArrayList)}. |
655 | * @return |
656 | */ |
657 | public Double getNextDouble(int column){ |
658 | |
659 | try{ |
660 | if(isResultSet){ |
661 | |
662 | ResultSet rs = (ResultSet) resultSet; |
663 | return rs.getDouble(column); |
664 | |
665 | } |
666 | |
667 | |
668 | }catch(Exception e){ |
669 | e.printStackTrace(); |
670 | } |
671 | |
672 | return null; |
673 | } |
674 | |
675 | /** |
676 | * Get String value in the result of this DMO. See {@link DataMovementOperator#execute(String, ArrayList)}. |
677 | * @return |
678 | */ |
679 | public String getNextString(int column){ |
680 | |
681 | try{ |
682 | if(isResultSet){ |
683 | |
684 | ResultSet rs = (ResultSet) resultSet; |
685 | return rs.getString(column); |
686 | |
687 | |
688 | } |
689 | |
690 | |
691 | }catch(Exception e){ |
692 | e.printStackTrace(); |
693 | } |
694 | |
695 | return null; |
696 | } |
697 | |
698 | /** |
699 | * Cancels rule of this DMO. |
700 | */ |
701 | public void closePS(){ |
702 | if(this.physicalQueryPlan.objectPreparedStatement != null){ |
703 | try { |
704 | UIMan.println("Cancel PS " + this.physicalQueryPlan.objectPreparedStatement); |
705 | this.physicalQueryPlan.objectPreparedStatement.cancel(); |
706 | } catch (SQLException e) { |
707 | e.printStackTrace(); |
708 | ExceptionMan.die("DMO - 708"); |
709 | } |
710 | } |
711 | } |
712 | |
713 | /** |
714 | * Copy logic plan to physical plan directly. If a DMO does not |
715 | * allow global optimization, its physical plan will be filled |
716 | * in this fashion. Notes: This function can not be called by ad hoc |
717 | * statistical operator, which should only be aware of the logic plan. |
718 | */ |
719 | public void copyLogicPlanToPhysicalPlanDirectly(){ |
720 | physicalQueryPlan.datalogQueries = new ArrayList<ConjunctiveQuery>(); |
721 | physicalQueryPlan.objectConjunctiveQuery = |
722 | logicQueryPlan.objectConjunctiveQuery; |
723 | physicalQueryPlan.objectPreparedStatement = |
724 | logicQueryPlan.objectPreparedStatement; |
725 | } |
726 | |
727 | |
728 | /** |
729 | * A collection containing 1) a set of datalog rules; 2) a conjunctive query |
730 | * or prepared statement. |
731 | * |
732 | * @author Ce Zhang |
733 | * |
734 | */ |
735 | public class QuerySet{ |
736 | |
737 | public ArrayList<ConjunctiveQuery> datalogQueries; |
738 | |
739 | public ConjunctiveQuery objectConjunctiveQuery = null; |
740 | |
741 | public PreparedStatement objectPreparedStatement = null; |
742 | |
743 | /** |
744 | * The constructor. |
745 | */ |
746 | public QuerySet(){ |
747 | datalogQueries = new ArrayList<ConjunctiveQuery>(); |
748 | } |
749 | |
750 | /** |
751 | * Add one query to this collection. |
752 | * @param query |
753 | * @param selList See {@link DataMovementOperator#selListFromRule}. |
754 | * @param _additionalSelList See {@link DataMovementOperator#additionalSelList}. |
755 | */ |
756 | @SuppressWarnings("unchecked") |
757 | public void addQuery(Object query, ArrayList<String> selList, ArrayList<String> _additionalSelList){ |
758 | try{ |
759 | if(objectConjunctiveQuery != null || objectPreparedStatement != null){ |
760 | throw new Exception("You can have only one rule for each DMO."); |
761 | } |
762 | |
763 | additionalSelList = (ArrayList<String>) _additionalSelList; |
764 | |
765 | if(query.getClass().equals(ConjunctiveQuery.class)){ |
766 | objectConjunctiveQuery = (ConjunctiveQuery) query; |
767 | if(selList != null){ |
768 | selListFromRule = (ArrayList<String>) selList.clone(); |
769 | }else{ |
770 | for(String arg : objectConjunctiveQuery.head.getPred().getArgs()){ |
771 | selListFromRule.add(arg); |
772 | } |
773 | } |
774 | }else{ |
775 | if(selList != null){ |
776 | selListFromRule = (ArrayList<String>) selList.clone(); |
777 | }else{ |
778 | throw new Exception("You need to provide the sel-list (the field of resulting table" + |
779 | "for this prepared statement)"); |
780 | } |
781 | objectPreparedStatement = (PreparedStatement) query; |
782 | } |
783 | |
784 | finalSelList.addAll(selListFromRule); |
785 | finalSelList.addAll(additionalSelList); |
786 | }catch(Exception e){ |
787 | e.printStackTrace(); |
788 | } |
789 | } |
790 | } |
791 | |
792 | |
793 | } |
794 | |
795 | |
796 | |
797 | |
798 | |
799 | |
800 | |
801 | |
802 | |
803 | |