KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > daffodilwoods > daffodildb > server > sql99 > dql > tableexpression > fromclause > ViewAbstract


1 package com.daffodilwoods.daffodildb.server.sql99.dql.tableexpression.fromclause;
2
3 import java.util.*;
4
5 import com.daffodilwoods.daffodildb.server.datadictionarysystem.*;
6 import com.daffodilwoods.daffodildb.server.serversystem.*;
7 import com.daffodilwoods.daffodildb.server.sql99.common.*;
8 import com.daffodilwoods.daffodildb.server.sql99.dql.common.*;
9 import com.daffodilwoods.daffodildb.server.sql99.dql.execution.*;
10 import com.daffodilwoods.daffodildb.server.sql99.dql.plan.*;
11 import com.daffodilwoods.daffodildb.server.sql99.dql.plan.condition.*;
12 import com.daffodilwoods.daffodildb.server.sql99.dql.plan.order.*;
13 import com.daffodilwoods.daffodildb.server.sql99.dql.plan.table.*;
14 import com.daffodilwoods.daffodildb.server.sql99.dql.queryexpression.*;
15 import com.daffodilwoods.daffodildb.server.sql99.expression.booleanvalueexpression.*;
16 import com.daffodilwoods.database.resource.*;
17 import com.daffodilwoods.database.sqlinitiator.*;
18 import com.daffodilwoods.database.utility.P;
19
20 /**
21  * Abstract Class containing common methods for <from SubQuery> and view.
22  * It provides the functionality of obtaining plan for select query contained
23  * in view or 'from subquery'.
24  *
25  * <p>Title: </p>
26  * <p>Description: </p>
27  * <p>Copyright: Copyright (c) 2003</p>
28  * <p>Company: </p>
29  * @author not attributable
30  * @version 1.0
31  */

32
33 public abstract class ViewAbstract {
34
35    /**
36     * ViewObject represents View Properties and Query Involved in View,
37     * It is initialised with the help of Connection
38     */

39
40    protected ViewObject viewObject; // Query and properties of View
41

42    /**
43     * Represents the table for viewname or 'from subquery'.
44     */

45    protected TableDetails tableDetails;
46
47    /**
48     * It is used to find the dated condition for this view/ 'from subquery'.
49     * @param datedFrameWork
50     * @return
51     * @throws DException
52     */

53    protected abstract _DatedFramework getAdjustedDatedFrameWork(_DatedFramework datedFrameWork) throws DException;
54
55    /**
56     * boolean represents status of thie view, whether it is Optimizable or not,
57     * true means Optimizable and false means Not Optimizable.
58     */

59
60    private boolean viewOptimizable;
61
62    /**
63     * Represents the array of plan representing view or 'from subquery'
64     */

65
66    private _TablePlan[] finalTablePlan;
67
68    /**
69     * int variable representing, order can be shifted to this view/subquery .
70     */

71
72    private int match;
73
74    public ViewAbstract() {
75    }
76
77    /**
78     * This method is used to check whether order present on this table/view can be
79     * shifted to this level. If order is not present in orderplan then a variable
80     * markes as NOTMATCHED is set in resultant object. otherwise if view/'from subquery'
81     * is present then it is marked as Partial matched. Otherwise it is marked as
82     * FULLYMATCHED. For the purpose refer the documentation of tablereferencelist.
83     * @param session
84     * @param orderPlan
85     * @param bvePlan
86     * @param queryColumns
87     * @param conditionArray
88     * @param isUnderLoj
89     * @return
90     * @throws DException
91     */

92
93    public OrderMappingWithTableRefernces[] checkForOrderSequencePlan(_ServerSession session, _OrderPlan orderPlan, _BVEPlan bvePlan, _QueryColumns queryColumns, ConditionArray conditionArray, boolean isUnderLoj) throws DException {
94       _SingleTableOrderPlan[] stops = orderPlan.getSingleTableOrderPlans();
95       match = TableExpressionConstants.FULLYMATCHED;
96       if (viewObject != null) {
97          match = TableExpressionConstants.PARTIALLYMATCHED;
98          finalTablePlan = getViewPlan(session, tableDetails.cc, null, queryColumns, bvePlan, orderPlan, conditionArray);
99       }
100       for (int i = 0; i < stops.length; i++) {
101          _Order order = stops[i].getOrder();
102          TableDetails td = stops[i].getTableDetail();
103          if (td == tableDetails) {
104             TableDetails[] resultant = getAppTableDetails();
105             OrderMappingWithTableRefernces mapping = new OrderMappingWithTableRefernces(new _SingleTableOrderPlan[] {stops[i]}
106                   , match, resultant);
107                   return new OrderMappingWithTableRefernces[] {mapping};
108          }
109       }
110       return null;
111    }
112
113    /**
114     * If plans are initialized then tables present in plans are returned,
115     * otherwise table representin view/'fromsubquery' is returned.
116     * @return
117     * @throws DException
118     */

119
120    private TableDetails[] getAppTableDetails() throws DException {
121       if (finalTablePlan == null) {
122          return new TableDetails[] {tableDetails};
123       }
124       ArrayList list = new ArrayList();
125       for (int i = 0; i < finalTablePlan.length; i++) {
126          list.addAll(Arrays.asList(finalTablePlan[i].getTableDetails()));
127       }
128       return (TableDetails[]) list.toArray(new TableDetails[list.size()]);
129    }
130
131    /**
132     * This method is used to obtain the plan of view/'from subquery'. It returns
133     * either an array of table plans or a view plan depending on the whether the
134     * view is optimizable or not.
135     *
136     * ALGO::
137     * firstly the view is checked if it is optimizable or not
138     * A view is nonoptimizable if
139     * <li> If order/group/distinct is present</li>
140     * <li> If functional/aggregate columns are present</li>
141     * <li> If Set Operators are present</li>
142     * Next we get the BVE plan for this table
143     * then the order for this view is got
144     * then all the columns of the query that belong to the view are got.
145     * then we obtain a mapping of columns of view vs the columns used in view
146     * definition.
147     * If the view is optimizable then
148     * we map all the columns to the corresponding columns used in view.
149     * then all the table plans of are got from the viewobject
150     * if the table plan returned is of the type querySpecification then
151     * the view is not optimizable // case select * from View order by b: view:: select * from A Loj B : b is a col of B
152     * so we remap the columns except the columns of condition and order which
153     * are shifted to view and set the view as unoptimizable.
154     * and return a View plan
155     * else
156     * then array of table plans is obtained for view definition and returned
157     * If view is not optimizable then
158     * we map the columns involved in condition and order to the corresponding
159     * columns used in view. It is done because order and condition is shifted
160     * to view definition.
161     * @param session
162     * @param session
163     * @param columnCharacteristics
164     * @param datedFrameWork
165     * @param queryCols
166     * @param bvePlan
167     * @param orderPlan
168     * @param conditionArray
169     * @return
170     * @throws DException
171     */

172
173    protected _TablePlan[] getViewPlan(_ServerSession session, _ColumnCharacteristics columnCharacteristics, _DatedFramework datedFrameWork,
174                                       _QueryColumns queryCols, _BVEPlan bvePlan,
175                                       _OrderPlan orderPlan,
176                                       ConditionArray conditionArray) throws DException {
177       if (finalTablePlan != null) {
178          return finalTablePlan;
179       }
180       viewOptimizable = viewObject.getQueryExpression().isViewOptimizationPossible();
181       booleanvalueexpression bve = getBveOfThisTable(bvePlan);
182       boolean dummyColumns = viewObject.getQueryExpression().hasConstantSelectedColumn(bve);
183
184 // */
185
if( dummyColumns ){
186         bvePlan.setRemainingCondition(BVEPlanMerger.addAndConditions(bvePlan.getRemainingCondition(),bve));
187         bve = null;
188       }
189
190       _Order order = getOrderOfThisTable(orderPlan);
191       ColumnDetails[] allCD = getAllCD(queryCols, bve,order);
192       Object JavaDoc[] queryCDAndClonedCD = getQueryColumns(allCD, bve, order);
193       Object JavaDoc[][] virtualAndActualColumns = updatePropertiesOfColumnsInVolvedInQuery(allCD, viewObject.getQueryExpression(), columnCharacteristics, (ColumnDetails[]) queryCDAndClonedCD[0]);
194       if (bve != null) {
195          conditionArray.addCondition(bve);
196       }
197       if (viewOptimizable) {
198          _TablePlan[] tPlans = viewObject.getQueryExpression().getTablePlans(session, bve, order, (ColumnDetails[]) queryCDAndClonedCD[0], conditionArray);
199          if (tPlans.length == 1) {
200             if (tPlans[0] instanceof QuerySpecificationPlan) {
201                remapColumns(queryCDAndClonedCD);
202                viewOptimizable = false;
203                return new _TablePlan[] {createViewPlan(tPlans[0], virtualAndActualColumns)};
204             } else {
205                match = TableExpressionConstants.FULLYMATCHED;
206             }
207          }
208          return tPlans;
209       }
210       _TablePlan tablePlan = viewObject.getQueryExpression().getExecutionPlan(session, bve, datedFrameWork, order, (ColumnDetails[]) queryCDAndClonedCD[0], conditionArray);
211       return new _TablePlan[] {createViewPlan(tablePlan, virtualAndActualColumns)};
212    }
213
214
215
216      private boolean checkForConstantColunms(ColumnDetails[] selectedCDs) throws DException{
217           for (int j = 0; j < selectedCDs.length; j++) {
218              if (selectedCDs[j].getType() == ColumnDetails.CONSTANT)
219                 return true;
220           }
221           return false;
222        }
223
224
225    /**
226     * This method returns all the columns of the query that belong to this view
227     * @param queryCols
228     * @param bve
229     * @return
230     * @throws DException
231     */

232    private ColumnDetails[] getAllCD(_QueryColumns queryCols, booleanvalueexpression bve) throws DException {
233       HashMap hashMap = queryCols.getQueryColsHashMap();
234       if (hashMap.containsKey(tableDetails)) {
235          ColumnDetails cd[] = (ColumnDetails[]) hashMap.get(tableDetails);
236          return addBveColumnIfRequired(cd, bve);
237       }
238       return null;
239    }
240
241    /**
242     * This function is needed when Or condition on view exists and which become
243     * single condition of View like (v.a and A.s) Or (V.b and B.s). In this case
244     * clone of v.a and v.b will come. So we've to add their columns in queryColumns.
245     * @param queryColumns
246     * @param bve
247     * @return
248     * @throws DException
249     */

250    private ColumnDetails[] addBveColumnIfRequired(ColumnDetails[] queryColumns, booleanvalueexpression bve) throws DException {
251       if (bve == null) {
252          return queryColumns;
253       }
254       ColumnDetails[] bveCD = GeneralPurposeStaticClass.getAllCoumnDetails( bve.getColumnDetails());
255       ArrayList aList = new ArrayList(Arrays.asList(queryColumns));
256       for (int i = 0; i < bveCD.length; i++) {
257          int j;
258          for (j = 0; j < queryColumns.length; j++) {
259             if (bveCD[i] == queryColumns[j]) {
260                break;
261             }
262          }
263          if (j == queryColumns.length && bveCD[i].getTable()==tableDetails) {
264             aList.add(bveCD[i]);
265          }
266       }
267       return (ColumnDetails[]) aList.toArray(new ColumnDetails[aList.size()]);
268    }
269
270    /**
271     * This method returns an Array of Objects of length two
272     * The first element contains the column details of the columns to be mapped
273     * The second element contains the columns details of the columns to cloned.
274     * If the view is optmizable then
275     * all the columns of the query are to be mapped and clone of the columns
276     * included in condition and order is performed.
277     * else
278     * only the condition and order columns are to be mapped
279     * and no column needs to be cloned
280     * @param allColumns
281     * @param bve
282     * @param order
283     * @return
284     * @throws DException
285     */

286    private Object JavaDoc[] getQueryColumns(ColumnDetails[] allColumns, booleanvalueexpression bve, _Order order) throws DException {
287       if (allColumns == null) {
288          return new Object JavaDoc[] {null, null};
289       }
290       ColumnDetails[] conditionAndorder = GeneralPurposeStaticClass.getCombinedCDArray(bve == null ? null : bve.getColumnDetails(), order == null ? null : order.getColumnDetails());
291       if (viewOptimizable) {
292          return getCDAndClonedCD(allColumns, conditionAndorder);
293       } else {
294          return new Object JavaDoc[] {conditionAndorder, null};
295       }
296    }
297
298    /**
299     * This method is used to return all the columns and the clone of condition
300     * and order.
301     * @param allColumns
302     * @param conditionAndOrder
303     * @return
304     * @throws DException
305     */

306    private Object JavaDoc[] getCDAndClonedCD(ColumnDetails[] allColumns, ColumnDetails[] conditionAndOrder) throws DException {
307       if (allColumns == null) {
308          return new Object JavaDoc[] {null, null};
309       }
310       ColumnDetails[] cloned = new ColumnDetails[allColumns.length];
311       if (conditionAndOrder != null) {
312          for (int i = 0; i < allColumns.length; i++) {
313             int j;
314             for (j = 0; j < conditionAndOrder.length; j++) {
315                if (allColumns[i] == conditionAndOrder[j]) {
316                   break;
317                }
318             }
319             try {
320                if (j == conditionAndOrder.length) {
321                   cloned[i] = (ColumnDetails) allColumns[i].clone();
322                }
323             } catch (CloneNotSupportedException JavaDoc ex) {
324                throw new DException("DSE0", new Object JavaDoc[] {"Clone Not Supported"});
325             }
326          }
327       }
328       return new Object JavaDoc[] {allColumns, cloned};
329    }
330
331    /**
332     * This method returns a new instance of a view plan
333     * @param tablePlan
334     * @param virtualAndActualColumns
335     * @return
336     * @throws DException
337     */

338    private _TablePlan createViewPlan(_TablePlan tablePlan, Object JavaDoc[][] virtualAndActualColumns) throws DException {
339       return new ViewPlan(viewObject.getQueryExpression(), tableDetails, virtualAndActualColumns, tablePlan);
340    }
341
342    /**
343     * This method is called to remap the columns that were mapped earlier,
344     * Such cases may arise when the view seems optimizable at first but
345     * turns out to be unoptimizable later.
346     * e.g.
347     * select * from v1 order by V1.bid
348     * where
349     * view v2 is :: select * from A loj B
350     * and bid columns belong to table B.
351     * in this case it seems that the order column may be sent to the single table order
352     * but later we see that the order has to be solved after the join
353     * So in such cases we need to remap the columns that were mapped below the view
354     * Algo::
355     * WE use the queryColumn and cloned Columns mapping
356     * for each of the cloned column in the mapping we change (map) the column
357     * details i.e. change the column details to thoes that were before mapping
358     *
359     * @param queryCDAndClonedCD
360     * @throws DException
361     */

362    private void remapColumns(Object JavaDoc[] queryCDAndClonedCD) throws DException {
363       ColumnDetails[] queryCD = (ColumnDetails[]) queryCDAndClonedCD[0];
364       if (queryCD == null) {
365          return;
366       }
367       ColumnDetails[] clonedCD = (ColumnDetails[]) queryCDAndClonedCD[1];
368       for (int i = 0; i < queryCD.length; i++) {
369          if (clonedCD[i] != null) {
370             GeneralPurposeStaticClass.updateColumnDetailsProperties(queryCD[i], clonedCD[i]);
371          }
372       }
373    }
374
375    /**
376     * This method returns the condition belonging to this table or view
377     * @param bvePlan
378     * @return
379     * @throws DException
380     */

381
382    protected booleanvalueexpression getBveOfThisTable(_BVEPlan
383          bvePlan) throws DException {
384       if (bvePlan != null) {
385          _BVESingleTablePlan bveSingleTablePlans[] = bvePlan.getBVESingleTablePlans();
386          if (bveSingleTablePlans != null) {
387             int len = bveSingleTablePlans.length;
388             for (int i = 0; i < len; i++) {
389                if (bveSingleTablePlans[i].getTableDetails()[0] == tableDetails) {
390                   return bveSingleTablePlans[i].getCondition();
391                }
392             }
393          }
394       }
395       return null;
396    }
397
398    /**
399     * This method returns the STOP(single table order plan) beloging to this
400     * table or view. Returns Order Shiftable to Lower Level Query of View.
401     * if Order involves functional columns, then order is solved at this level
402     * otherwise order is shifted to low level.
403     * if Order is shifted to low level then this level order shud be null.
404     * @param orderPlan
405     * @return _order single table order plan belonging to this table or view
406     * @throws DException
407     */

408
409    protected _Order getOrderOfThisTable(_OrderPlan orderPlan) throws DException {
410       if (orderPlan == null) {
411          return null;
412       }
413       _SingleTableOrderPlan[] stops = orderPlan.getSingleTableOrderPlans();
414       for (int i = 0; i < stops.length; i++) {
415          if (stops[i].getTableDetail() == tableDetails) {
416             return stops[i].getOrder();
417          }
418       }
419       return null;
420    }
421
422    /**
423     * This method is used to map those columns representing by toMap columns which
424     * belongs to querycolumns with the column used in view. It is done so as
425     * to convert the columns used above view into the column used under view. It
426     * is required when condition and order has to shift under view or when we've
427     * to map the view definition in upward query.
428     *
429     * Detailed documentation is as given -
430     *
431     * Update the properties of ColumnDetails with new Properties of ColumnDetails
432     * The mapping of the column names and columns used in view are
433     * got by calling the MappingOfColumnsAndColumnDetails
434     * Algo:
435     * a) For each Columns Involved in Query we check wthether column involved is foreignKey Column
436     * b) We check For ForeignKeyColumns as fKey Columns needs to be mapped to base level tables so
437     * only table is copied in the column.
438     * Example:
439     * let the view is : create view v1 as select Cid from state.
440     * and the query is : select V.Cid.Cname from v1 as V1;
441     * now here, tableAliasArray in column is [Cid]
442     * and we need to map this column to base level table state as this table iterator is capable of
443     * giving value for this column.
444     * c) If Not FKey Column then normal column, then we chcek for its matching original column to update
445     * its properties.
446     * d) All such FKey Columns if there are added to below query selctList colums as below query, so that it get
447     * included in setQueryColumns so that it reach it shud map to base level tables.
448     * e) if the column with the same name exist in the mapping got from the viewObject
449     * and if the column is to be mapped then we replace the columDetails by the column details
450     * got from the view Object.
451     * It returns the mapping of the columnnames and column details of the columns whoes
452     * column details have been changed
453     * @param columnsInVolvedInQuery
454     * @throws DException
455     */

456    protected Object JavaDoc[][] updatePropertiesOfColumnsInVolvedInQuery(ColumnDetails[]
457          queryColumnDetails, queryexpression queryExpression,
458          _ColumnCharacteristics columnCharacteristics, ColumnDetails[] toMapCD) throws
459    DException {
460       if (queryColumnDetails == null) {
461          return null;
462       }
463       ArrayList listOfKKeyColumns = new ArrayList(5);
464       ArrayList colAndCDMapping = new ArrayList();
465       Object JavaDoc[][] columnNameAndCD = viewObject.getMappingOfColumnsAndColumnDetails(
466             columnCharacteristics.getColumnNames());
467       for (int i = 0, length = queryColumnDetails.length; i < length; ++i) {
468          if (queryColumnDetails[i].getTableAliasArray() != null) { // ForeignKey Column
469
getMergedPropertiesforFKeyColumn(queryColumnDetails[i],
470             listOfKKeyColumns);
471             continue;
472          }
473
474          String JavaDoc columnName = queryColumnDetails[i].getColumn();//Done by Sandeep [this work is done by VIBHA on main.and here it is done to solve compiere problem ]
475
for (int j = 0, length1 = columnNameAndCD.length; j < length1; ++j) {
476             String JavaDoc columnName1 = (String JavaDoc) columnNameAndCD[j][0];
477             if (columnName.equalsIgnoreCase(columnName1)) {
478                ColumnDetails column = (ColumnDetails) columnNameAndCD[j][1];
479                if (toMapCD != null && isExist(queryColumnDetails[i], toMapCD)) {
480                   GeneralPurposeStaticClass.updateColumnDetailsProperties(
481                         queryColumnDetails[i], column);
482                }
483                queryColumnDetails[i].setByteComparison(column.getType() ==
484                      TypeConstants.REFERENCE);
485                colAndCDMapping.add(new Object JavaDoc[] {queryColumnDetails[i], column});
486                break;
487             }
488          }
489       }
490       if (!listOfKKeyColumns.isEmpty()) {
491          queryExpression.setFKeyColumnDetails( (ColumnDetails[]) listOfKKeyColumns.
492                toArray(new ColumnDetails[
493                listOfKKeyColumns.size()]));
494       }
495       return (Object JavaDoc[][]) colAndCDMapping.toArray(new Object JavaDoc[colAndCDMapping.size()][
496             2]);
497    }
498
499    /**
500     * It is used to check whether passed column is present in passed array of
501     * columns.
502     * @param queryCD
503     * @param toMapCD
504     * @return
505     * @throws DException
506     */

507
508    private boolean isExist(ColumnDetails queryCD, ColumnDetails[] toMapCD) throws DException {
509       for (int j = 0; j < toMapCD.length; j++) {
510          if (queryCD == toMapCD[j]) {
511             return true;
512          }
513       }
514       return false;
515    }
516
517    /**
518     * This method is used to initialize the Foreign key column with underlying
519     * table of view.
520     * @param cd
521     * @param list
522     * @throws DException
523     */

524    protected void getMergedPropertiesforFKeyColumn(ColumnDetails cd,
525          ArrayList list) throws
526    DException {
527       String JavaDoc columnName = cd.getTableAliasArray()[0];
528       Object JavaDoc[][] columnNameAndCD = viewObject.getMappingOfColumnsAndColumnDetails();
529       for (int j = 0, selectListLength = columnNameAndCD.length;
530            j < selectListLength; j++) {
531          if ( ( (String JavaDoc) columnNameAndCD[j][0]).equalsIgnoreCase(columnName)) {
532             cd.setTableDetails( ( (ColumnDetails) columnNameAndCD[j][1]).getTable());
533             list.add(cd);
534             break;
535          }
536       }
537    }
538
539    /**
540     * This method returns the condition plan of select query involved in view or
541     * 'from subquery'. It is needed when view is optimizable and we've to map
542     * condition plan of view definition to upward query.
543     * @return
544     * @throws DException
545     */

546
547    public _BVEPlan getBveExecutionPlan() throws DException {
548       if (viewObject != null) {
549          if (viewOptimizable) {
550             return viewObject.getQueryExpression().getBveExecutionPlan();
551          }
552       }
553       return null;
554    }
555
556    /** This method returns the viewObject that represents the upderlying query for view.
557     * this method is used in tablereferencelist.isSimpleQuery() .
558     * @return ViewObject
559     * @author Manoj kr.
560     * <li>date Dec,17 , 2004
561     */

562    public ViewObject getViewObject(){
563      return viewObject;
564    }
565
566
567
568   private ColumnDetails[] addOrderColumnIfRequired(ColumnDetails[] queryColumns, _Order order) throws DException {
569         if (order == null) {
570            return queryColumns;
571         }
572         ColumnDetails[] bveCD = GeneralPurposeStaticClass.getAllCoumnDetails( order.getColumnDetails());
573         ArrayList aList = new ArrayList(Arrays.asList(queryColumns));
574         for (int i = 0; i < bveCD.length; i++) {
575            int j;
576            for (j = 0; j < queryColumns.length; j++) {
577               if (bveCD[i] == queryColumns[j]) {
578                  break;
579               }
580            }
581            if (j == queryColumns.length && bveCD[i].getTable()==tableDetails) {
582               aList.add(bveCD[i]);
583            }
584         }
585         return (ColumnDetails[]) aList.toArray(new ColumnDetails[aList.size()]);
586      }
587      private ColumnDetails[] getAllCD(_QueryColumns queryCols,
588                                       booleanvalueexpression bve, _Order order) throws
589          DException {
590
591        return addOrderColumnIfRequired(getAllCD(queryCols, bve), order);
592
593      }
594    }
595
Popular Tags