KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > daffodilwoods > daffodildb > server > sql99 > dql > semanticchecker > SemanticChecker


1 package com.daffodilwoods.daffodildb.server.sql99.dql.semanticchecker;
2
3 import java.util.*;
4 import com.daffodilwoods.daffodildb.server.datadictionarysystem.*;
5 import com.daffodilwoods.daffodildb.server.serversystem.*;
6 import com.daffodilwoods.daffodildb.server.sql99.common.*;
7 import com.daffodilwoods.daffodildb.server.sql99.dql.listenerevents.*;
8 import com.daffodilwoods.daffodildb.server.sql99.dql.queryexpression.
9     queryspecification.*;
10 import com.daffodilwoods.daffodildb.server.sql99.expression.expressionprimary.*;
11 import com.daffodilwoods.daffodildb.server.sql99.utils.*;
12 import com.daffodilwoods.daffodildb.utils.field.*;
13 import com.daffodilwoods.database.general.*;
14 import com.daffodilwoods.database.resource.*;
15 import com.daffodilwoods.daffodildb.server.sql99.common.
16
    GeneralPurposeStaticClass;
17 import com.daffodilwoods.daffodildb.server.sql99.dql.queryexpression.
18
    queryspecification.selectlist;
19 import com.daffodilwoods.daffodildb.server.sql99.fulltext.dml.
20
    _FullTextIndexInformation;
21 import com.daffodilwoods.daffodildb.server.sql99.common.Datatypes;
22 import java.util.ArrayList JavaDoc;
23 import com.daffodilwoods.daffodildb.server.sql99.utils._Reference;
24 import com.daffodilwoods.daffodildb.server.sql99.common.ColumnDetails;
25 import com.daffodilwoods.database.utility.P;
26 import com.daffodilwoods.database.resource.DException;
27 import com.daffodilwoods.daffodildb.server.sessionsystem.GlobalSession;
28
29 /**
30  * By semantics we mean to say objects used in query is meaningful to database
31  * or not.For instance, semantic checking ensures that tables used in query are
32  * present in database, column names uniquely belong to table etc.
33  * Following tests are performed
34  * <br>Table and column semantics are checked</br>
35  * <br>Select list semantics</br>
36  * <br>From clause semantics</br>
37  * <br>Inner query semantics</br>
38  * <br>Sub query semnatics</br>
39  * <br>Aggregate function semnatics</br>
40  * <br>Having clause semantics</br>
41  * <br>Order by semantics</br>
42  * <br>Set operation semantics</br>
43  * <br>View semantics</br>
44  * </br>
45  * <p>Copyright: Copyright (c) 2003</p>
46  * <p>Daffodil software: </p>
47  * @author unascribed
48  * @version 1.0
49  */

50 public class SemanticChecker
51     implements TypeConstants, _SemanticChecker {
52
53   /**
54    * Represents the tables present in the query
55    */

56   private TableDetails[] tableDetails;
57
58   /**
59    * Represents the columns present in the where clause of the query.
60    */

61
62   private ColumnDetails[] whereClauseColumnDetails;
63
64   /**
65    * Represents the columns present in the group by clause of the query.
66    */

67
68   private ColumnDetails[] groupByClauseColumnDetails;
69
70   /**
71    * Represents the columns present in the having clause of the query.
72    */

73
74   private ColumnDetails[] havingClauseColumnDetails;
75
76   /**
77    * Represents the columns present in the order by clause of the query.
78    */

79
80   private ColumnDetails[] orderByClauseColumnDetails;
81
82   /**
83    * Represents the columns present in the select list of the query.
84    */

85   private ColumnDetails[] selectListColumnDetails;
86
87   /**
88    * Represents the columns present in the select list of the query. It is
89    * different from selectListColumnDetails in the way it represents one column
90    * per selectsublist where as selectListColumnDetails represents all the
91    * columns present in select list and it may be greater than number of
92    * select sublist.
93    */

94   private ColumnDetails[] userDefinedColumnDetails;
95
96   /**
97    * Represents the clone of userDefinedColumnDetails
98    */

99
100   private ColumnDetails[] clonedUserDefinedColumnDetails;
101
102   /**
103    * Represents the columns present in 'from clause' of the query.
104    */

105
106   private ColumnDetails[] fromClauseColumnDetails;
107
108   /**
109    * Represents the columns present in the order by clause of the query. It is
110    * different from orderByClauseColumnDetails in the way it represents one
111    * column per sortspecification where as orderByClauseColumnDetails
112    * represents all the columns present in order by clause and it may be
113    * greater than number of sortspecifications.
114    */

115
116   private ColumnDetails[] orderByClauseKeyColumnColumnDetails; // for aviod checking of order by A,B,A+B
117

118   /**
119    * Represents a connection object.
120    */

121
122   private _ServerSession serverSession;
123
124   /**
125    * Represents the selectlist of Select Query.
126    */

127   private selectlist selectList;
128
129   /**
130    * Represents those columns whose values are to be provided by user.
131    */

132
133   private _Reference[] unKnownReferences;
134
135   /**
136    * Represents all the columns present in the query.
137    */

138   private ColumnDetails[] queryColumns;
139
140   /**
141    * Represents all aggregate columns present in the query.
142    */

143
144   private ColumnDetails[] aggregateColumnsPresentInQuery;
145
146   /**
147    * Represents whether 'Distinct' is present with select list.
148    */

149
150   private boolean isDistinct;
151
152   /**
153    * Represents whether 'Contains' clause is present in select query or not.
154    */

155
156   public boolean containsClauseFlag;
157
158   /**
159    * Object of Privilege Table to check the privileges
160    */

161
162   private _PrivilegeTable privileges;
163
164   /* To check for questionmarks in expression*/
165   private int count = 0;
166
167   public SemanticChecker(_ServerSession severSession0,
168                          ColumnDetails[] whereClauseColumnDetails0,
169                          ColumnDetails[] groupByClauseColumnDetails0,
170                          ColumnDetails[] havingClauseColumnDetails0,
171                          ColumnDetails[] orderByClauseColumnDetails0,
172                          ColumnDetails[] selectListColumnDetails0,
173                          ColumnDetails[] fromClauseColumnDetails0,
174                          selectlist selectList0,
175                          ColumnDetails[] orderByClauseKeyColumnColumnDetails0,
176                          boolean isDistinct0) {
177     serverSession = severSession0;
178     whereClauseColumnDetails = whereClauseColumnDetails0;
179     groupByClauseColumnDetails = groupByClauseColumnDetails0;
180     havingClauseColumnDetails = havingClauseColumnDetails0;
181     orderByClauseColumnDetails = orderByClauseColumnDetails0;
182     selectListColumnDetails = selectListColumnDetails0;
183     selectList = selectList0;
184     fromClauseColumnDetails = fromClauseColumnDetails0;
185     orderByClauseKeyColumnColumnDetails = orderByClauseKeyColumnColumnDetails0;
186     isDistinct = isDistinct0;
187     initializeContainFlag(whereClauseColumnDetails);
188   }
189
190   public SemanticChecker(TableDetails[] tableDetails0, ColumnDetails[] whereCD) {
191     tableDetails = tableDetails0;
192     whereClauseColumnDetails = whereCD;
193   }
194
195   /**
196    * This method is used to initialize a flag whether 'Contains' clause is
197    * present in 'where' clause of select query.
198    * @param whereCD represents columns of 'where clause'.
199    */

200   private void initializeContainFlag(ColumnDetails[] whereCD) {
201     if (whereCD != null)
202       for (int i = 0; i < whereCD.length; i++) {
203     if (!containsClauseFlag)
204       containsClauseFlag = whereCD[i].getContainClauseFlag();
205       }
206   }
207
208   /**
209    * Sets the tables.
210    * @param tableDetails0
211    */

212
213   public void setTableDetails(TableDetails[] tableDetails0) {
214     tableDetails = tableDetails0;
215   }
216
217   /**
218    * This method is used to perform semantic checking. It includes following
219    * steps -
220    * <br>Checks Table semantics</br>
221    * <br>Checks Where clause semnatics</br>
222    * <br>Check For Select List Column Semantic</br>
223    * <br>Check For Group By</br>
224    * <br>Check For Having Column Semantic</br>
225    * <br>Check For Where Column Semantic</br>
226    * <br>Check For 'Contains' Semantic</br>
227    * <br>Check For Group Column Semantic</br>
228    * <br>Check For Order Column Semantic</br>
229    * <br>Check For Group And Having Semantic</br>
230    * <br>Check Group by and select and order semantics</br>
231    * <br>Check For Order By And Select Semantic</br>
232    * <br>Initialize Passed UnKnownReferences as Constant</br>
233    *
234    * It also finds out the columns from each constructs of Select, whose values
235    * are to be provided by user of Select.
236    * @return void
237    * @param serverSession
238    * @throws DException
239    */

240
241   public void check(_ServerSession serverSession0) throws DException {
242     serverSession = serverSession0;
243     checkTableSemantic(serverSession0); // table ambiguity checking
244

245     /* Done by kaushik on 28/07/2004 for numbers in Aggregate Columns */
246
247     setDatatypeOfConstantColunmsInSelectList(selectListColumnDetails,
248         serverSession0);
249
250     if (havingClauseColumnDetails != null) {
251       setDatatypeOfConstantColunmsInSelectList(havingClauseColumnDetails,
252           serverSession0);
253     }
254
255     unKnownReferences = whereClauseColumnDetails == null
256                       ? unKnownReferences :
257                         GeneralPurposeStaticClass.getJointReferences(unKnownReferences,
258                         checkWhereColumnSemantic());
259
260
261
262         unKnownReferences = GeneralPurposeStaticClass.getJointReferences(
263         unKnownReferences, checkSelectListColumnSemantic());
264
265     aggregateColumnsPresentInQuery = getAllAggregateColumns();
266
267     unKnownReferences = groupByClauseColumnDetails == null
268                       ? unKnownReferences :
269                         GeneralPurposeStaticClass.getJointReferences(unKnownReferences,
270                         checkGroupColumnSemantic());
271
272     unKnownReferences = havingClauseColumnDetails == null
273                       ? unKnownReferences :
274                         GeneralPurposeStaticClass.getJointReferences(unKnownReferences,
275                         checkHavingColumnSemantic());
276
277
278     _Reference[] orderByUnKnownReferences = orderByClauseColumnDetails == null ? null :
279         checkOrderColumnSemantic();
280
281
282
283     if (containsClauseFlag) {
284       checkSemanticCheckingForContains();
285     }
286     else {
287       if (havingClauseColumnDetails != null)
288         checkHavingSemanticCheckingForContainClause();
289     }
290     if ( (groupByClauseColumnDetails != null || aggregateColumnsPresentInQuery != null) &&
291          havingClauseColumnDetails != null) {
292       unKnownReferences = GeneralPurposeStaticClass.getJointReferences(
293           unKnownReferences,
294           checkGroupByHavingSemantic(havingClauseColumnDetails));
295     }
296     if (groupByClauseColumnDetails != null || aggregateColumnsPresentInQuery != null) {
297       unKnownReferences = GeneralPurposeStaticClass.getJointReferences(
298           unKnownReferences,
299           checkGroupBySelectOrOrderSemantic(userDefinedColumnDetails));
300     }
301     if (orderByClauseColumnDetails != null) {
302       unKnownReferences = GeneralPurposeStaticClass.getJointReferences(
303           unKnownReferences,
304           checkOrderByAndSelectColumnSemantic(orderByUnKnownReferences));
305     }
306     if (unKnownReferences != null)
307       initializingTypeOfUnKnownReferencesAsConstant(unKnownReferences);
308       /* Done by Kaushik on 20/08/2004 for Sequence releted work as told by Mr. Neeraj Khanna*/
309     if (unKnownReferences != null) {
310       for (int i = 0; i < unKnownReferences.length; i++) {
311         if (unKnownReferences[i].getReferenceType() == SimpleConstants.SEQUENCE) {
312           throw new DException("DSE6008", null);
313         }
314       }
315     }
316
317   }
318
319   private void setAliasNameOfFunctionalColumn(ColumnDetails[]
320       selectListColumnDetails) throws
321   DException {
322     for (int i = 0; i < selectListColumnDetails.length; i++) {
323       int type = selectListColumnDetails[i].getType();
324       if ( (selectListColumnDetails[i].getAliasName() == null) &&
325            (type == SCALARFUNCTION || type == CASEEXPRESSION || type == GROUPING ||
326             type == FUNCTIONAL || type == USERFUNCTION )) {
327         selectListColumnDetails[i].setAliasName("Expr" + i);
328       }
329     }
330   }
331
332   /**
333    * This method is used to perform semantic checking of 'Contains' clause.
334    * For 'Contains' clause
335    * 1. Only one table should be present in 'from clause'.
336    * 2. No groupby, having, orderby should be present.
337    * @throws DException
338    */

339
340   private void checkSemanticCheckingForContains() throws DException {
341     checkTableSemanticForContainClause();
342     checkOrderByGroupByHavingSemanticForContainClause();
343     checkForOneBooleanExpressionWhenContainsClauseIsPresent();
344   }
345
346   /**
347    * This method is used to ensure that only one table should be present
348    * in 'from clause' for 'Contains' clause. And it must not be a view.
349    * @throws DException
350    */

351
352   private void checkTableSemanticForContainClause() throws DException {
353     if (tableDetails.length == 1 &&
354         tableDetails[0].getTableType() != TypeConstants.VIEW)
355       return;
356     else
357       throw new DException("DSE0", new Object JavaDoc[] {"Tables Involved in Query not to be greater than one and must be of type TABLE "}); //
358
}
359
360   /**
361    * This method is used to ensure that no groupby, having, orderby are present
362    * in 'from clause' for 'Contains' clause.
363    * @throws DException
364    */

365
366   private void checkOrderByGroupByHavingSemanticForContainClause() throws
367   DException {
368     if (orderByClauseColumnDetails == null && groupByClauseColumnDetails == null &&
369         havingClauseColumnDetails == null)
370       return;
371     else
372       throw new DException("DSE0", new Object JavaDoc[] {"GroupBy,OrderBy and HavingClause Clause Should not be Exist with Contains Clause"}); //
373
}
374
375   /**
376    * This method is used to ensure that 'Contains clause' is not present in
377    * 'having clause'. It needs to be checked for the case when 'Contains clause'
378    * is not present in 'where clause', but it may present in 'having clause'
379    * acc. to grammer rules.
380    * @throws DException
381    */

382
383   private void checkHavingSemanticCheckingForContainClause() throws DException {
384     for (int i = 0; i < havingClauseColumnDetails.length; i++)
385       if (havingClauseColumnDetails[i].getContainClauseFlag())
386         throw new DException("DSE6005", null); // done by kaushik
387
}
388
389   /**
390    * Checks for Table Ambiguity. It ensures that no two table names used in
391    * 'from clause' are same.
392    * <br>e.g. Select * from country , country</br>
393    * @param serverSession
394    * @param tableDetails
395    * @throws com.daffodilwoods.database.resource.DException
396    */

397   private void checkTableSemantic(_ServerSession serverSession) throws com.
398
      daffodilwoods.database.resource.DException {
399     int length = tableDetails.length;
400     for (int index1 = 0; index1 < length - 1; ++index1) {
401       TableDetails tableDetailSource = tableDetails[index1];
402       for (int index2 = index1 + 1; index2 < length; ++index2) {
403         TableDetails tableDetailTarget = tableDetails[index2];
404         if (tableDetailSource.toString().equalsIgnoreCase(tableDetailTarget.
405             toString())) {
406           throw new DException("DSE954",
407                                new Object JavaDoc[] {tableDetailSource.getName(),
408               tableDetailTarget.getName()});
409         }
410       }
411     }
412   }
413
414   /**
415    * This method is used to ensure that if groupby is not present and aggregate
416    * columns are present in select List, then select list can't directly contains
417    * columns of table. It is also true for the case when groupby is not present
418    * and aggregate columns are present either in order by or having clause.
419    * It also initializes the columns of selectlist with appropriate table and
420    * it characteristics.
421    * <br> Examples:</br>
422    * <br> Select productName from Products order by Avg(productid)</br>
423    * <br> Select productName from Products having Avg(productid) > 1</br>
424    * These queries are semantically wrong.
425    * @return _Reference[]
426    * @throws DException
427    */

428
429   private _Reference[] checkSelectListColumnSemantic() throws DException {
430     _Reference[] unKnownReferences = setTableNamesAndDatatypesOfAllColumns(
431         serverSession, selectListColumnDetails, tableDetails);
432
433       initializingTypeOfUnKnownReferencesAsConstant(unKnownReferences);//Done by Sandeep to solve problem in Compeire
434
userDefinedColumnDetails = selectList.getDerivedColumnDetails();
435
436     /* FOR SEMANTIC CHECKING OF SUBQUERY IN SELECTLIST*/
437     checkForScalarSubQueryInSelectList(serverSession);
438
439     /* Debugging purpose */
440
441     clonedUserDefinedColumnDetails = isDistinct ?
442                                      getClonedColumns(userDefinedColumnDetails) : null;
443
444     unKnownReferences = changeReferenceAccToClonedColumns(unKnownReferences,
445         clonedUserDefinedColumnDetails != null ? clonedUserDefinedColumnDetails :
446         userDefinedColumnDetails);
447
448     if (groupByClauseColumnDetails == null)
449       checkingForAggregateAndNonAggregateSemantic(userDefinedColumnDetails, false, false);
450
451     checkOrderByDistinctSemantic(orderByClauseKeyColumnColumnDetails,
452                                  userDefinedColumnDetails);
453
454     return unKnownReferences;
455   }
456
457   /**
458    * This method is used to get the clone of those columns which are not
459    * solvable by select query. These columns are also added in the list. It is
460    * needed when 'Distinct' is present in query.
461    * @param source - columns included in select list.
462    * @param target - clone of columns of select list.
463    * @return
464    * @throws DException
465    */

466
467   private _Reference[] changeReferenceAccToClonedColumns(_Reference[] source,
468       _Reference[] target) throws DException {
469     if (source != null) {
470       ArrayList JavaDoc aList = new ArrayList JavaDoc(Arrays.asList(source));
471       for (int i = 0; i < source.length; i++) {
472         for (int j = 0; j < target.length; j++) {
473           if (source[i].getQualifiedColumnName().trim().equalsIgnoreCase(target[
474               j].getQualifiedColumnName().trim()))
475           aList.add(target[j]);
476         }
477       }
478       return (_Reference[]) aList.toArray(new _Reference[aList.size()]);
479     }
480     return source;
481   }
482
483   /**
484    * This method is used to obtain the clone of passed columns.
485    * @param cd
486    * @return
487    * @throws DException
488    */

489
490   public static ColumnDetails[] getClonedColumns(ColumnDetails[] cd) throws
491   DException {
492     int length = cd.length;
493     ColumnDetails[] result = new ColumnDetails[length];
494     for (int i = 0; i < length; i++) {
495       try {
496         result[i] = (ColumnDetails) cd[i].clone();
497       }
498       catch (CloneNotSupportedException JavaDoc ex) {
499         throw new DException("DSE0", new Object JavaDoc[] {"Clone Not Supported"});
500       }
501     }
502     return result;
503   }
504
505   /**
506    * This method is used to ensure that columns in 'where clause' don't
507    * contains any aggregate column.
508    * It also initializes the columns of 'where clause' with appropriate table
509    * and it characteristics.
510    *<br> e.g. This type of query is invalid</br>
511    * <br>select * from Products where avg(ProductId) >200</br>
512    * <br>An aggregate may not appear in the WHERE clause</br>
513    * <br>called by check</br>
514    * @return _Reference[]
515    * @throws DException
516    */

517   private _Reference[] checkWhereColumnSemantic() throws DException {
518     /* Following 1 LOC is used to resolve column ambiguity on where clause columns.
519      * Manoj Kr. Nov 26,2004
520      * Bug No. 12607 Comopiere Bug..
521      */

522     resolveWhereClauseColumnAmbiguity(tableDetails,whereClauseColumnDetails);
523     _Reference[] unKnownReferences = setTableNamesAndDatatypesOfAllColumns(
524         serverSession, whereClauseColumnDetails, tableDetails);
525     initializingTypeOfUnKnownReferencesAsConstant(unKnownReferences);//Done by Sandeep to solve problem in Compeire
526

527       if (checkForAggregateColumns(whereClauseColumnDetails)) // aggregate columns cannot exist in where clause
528
throw new DException("DSE14", extractStrings(whereClauseColumnDetails));
529
530       return unKnownReferences;
531   }
532
533   /**
534    * This method ensure if column(s) in where clause list exists in multiple
535    * tables specified in from clause then table detail of that column will be
536    * according to following rule...
537    *
538    * IF [Column name is absolute (with table name <tablename>.<columnName> ] THEN
539    * Condition will be resolved on specified table .
540    * ELSE
541    * [Condition will be resolved based on first time column found any table starting from
542    * first table clause table list ]
543    *
544    * @author Manoj Kr.
545    * @date Nov. 26,2004
546    * */

547
548   private void resolveWhereClauseColumnAmbiguity(TableDetails[] tableDetails,
549                                                  ColumnDetails[] whereClauseCDs) throws
550       DException {
551     for (int c = 0; c < whereClauseCDs.length; c++) {
552       if (whereClauseCDs[c].getType() == REFERENCE &&
553           whereClauseCDs[c].getColumnName().length == 1 &&
554           !whereClauseCDs[c].getColumn().trim().equalsIgnoreCase("?") &&
555           ! (serverSession instanceof GlobalSession)) {
556         for (int t = 0; t < tableDetails.length; t++) {
557           String JavaDoc[] columnName = tableDetails[t].getColumnCharacteristics().
558               getColumnNames();
559            if(P.indexOfIgnoreCase(columnName,whereClauseCDs[c].getAppropriateColumn()) != -1){;
560               whereClauseCDs[c].setTableDetails(tableDetails[t]);
561               whereClauseCDs[c].setColumnName(new String JavaDoc[] {tableDetails[t].
562                                               getActualName(),
563                                               whereClauseCDs[c].
564                                               getAppropriateColumn()});
565
566                       break;
567             }
568
569         }
570
571       }
572     }
573   }
574
575   /**
576    * This method is used to obtain the names of passed columns .
577    * @param cds
578    * @return
579    * @throws DException
580    */

581
582   private String JavaDoc[] extractStrings(ColumnDetails[] cds) throws DException {
583     String JavaDoc[] s = new String JavaDoc[cds.length];
584     for (int i = 0; i < cds.length; i++) {
585       s[i] = cds[i].getColumn();
586     }
587     return s;
588   }
589
590   /**
591    * This method is used to initialize the columns of 'group by clause' with
592    * appropriate table and it characteristics.
593    * <br>called by check</br>
594    * @return _Reference[]
595    * @throws DException
596    */

597
598   private _Reference[] checkGroupColumnSemantic() throws DException {
599     checkingForsubqueryInGroupByClause(groupByClauseColumnDetails);
600     _Reference[] unKnownReferences = setTableNamesAndDatatypesOfAllColumns(
601         serverSession, groupByClauseColumnDetails, tableDetails);
602
603   initializingTypeOfUnKnownReferencesAsConstant(unKnownReferences);//Done by Sandeep to solve problem in Compeire
604
checkingForSequence(groupByClauseColumnDetails);
605     if (unKnownReferences != null) {
606       for (int j = 0, length1 = unKnownReferences.length;
607            j < length1; ++j) {
608         for (int i = 0, length = userDefinedColumnDetails.length; i < length;
609              ++i) {
610           String JavaDoc selecListColumnName = userDefinedColumnDetails[i].
611                      getAliasName();
612           if (selecListColumnName != null)
613             if (selecListColumnName.equalsIgnoreCase( ( (ColumnDetails)
614                 unKnownReferences[j]).getAppropriateColumn()))
615               throw new DException("DSE260",
616               extractStrings(groupByClauseColumnDetails));
617
618         }
619         /** If group by column(alias) is not Part of selectList than to show proper
620          * message This is added in to unknown references **/

621         unKnownReferences[j].setReason("DSE256");
622
623       }
624     }
625
626     return unKnownReferences;
627   }
628
629   /**
630    * This method ensures that having can't be present in query without GroupBy
631    * or aggregate columns.
632    * It also initializes the columns of 'having clause' with appropriate table
633    * and it characteristics.
634    * <br>Example</br>
635    * <br> Right</br>
636    * <br>Select Avg(productid) from products having Avg(productid) > 1</br>
637    * <br>Wrong</br>
638    * <br>Select productid from products having 1 > 1</br>
639    * @return _Reference[]
640    * @throws DException
641    */

642   private _Reference[] checkHavingColumnSemantic() throws DException {
643     _Reference[] unKnownReferences = setTableNamesAndDatatypesOfAllColumns(
644         serverSession, havingClauseColumnDetails, tableDetails);
645   initializingTypeOfUnKnownReferencesAsConstant(unKnownReferences);//Done by Sandeep to solve problem in Compeire
646
if (groupByClauseColumnDetails == null && aggregateColumnsPresentInQuery == null)
647       throw new DException("DSE3566", null); // having is permitted only when the serverpp
648
return unKnownReferences;
649   }
650
651   /**
652    * This method is used to perform semantic checking of order by clause. It
653    * includes -
654    * <br>1. Order By Duplicate Column Name Checking</br>
655    * <br>Examples</br>
656    * <br>select stateid from state order by stateid,stateid</br>
657    * <br>2. Order By Duplicate Ordinal Position Checking</br>
658    * <br>Examples</br>
659    * <br>select stateid from state order by 1,1</br>
660    * <br>called by check</br>
661    * It also initializes the columns of 'order by clause' with appropriate table
662    * and it characteristics.
663    * @return _Reference[]
664    * @throws DException
665    */

666   private _Reference[] checkOrderColumnSemantic() throws DException {
667
668     /*Written by Manoj to resolve order by ambiguity ..See complete description in the method documentaion below.*/
669     resolveColumnAmbiguityInOrder(userDefinedColumnDetails,orderByClauseColumnDetails);
670
671     _Reference[] unKnownReferences = setTableNamesAndDatatypesOfAllColumns(
672         serverSession, orderByClauseColumnDetails, tableDetails);
673     checkingForOrder(orderByClauseKeyColumnColumnDetails);
674     /*Done by vibha to , to check that sequence is not allowed in orderColumnSemantic*/
675     checkingForSequence(orderByClauseKeyColumnColumnDetails);
676
677     return unKnownReferences;
678   }
679
680   /**
681    * This method resolve the column ambiguity in order by clause .
682    * i.e.
683    * Threre are two tables , A( ID,NAME,CODE ) and table B(ID,PRIORITY,TASK)
684    * select x.id , y.name from A x , B y order by id
685    * In this case sort specification list contains id that is presend in both tables A
686    * and B . This is ambigous case , to resolve this ambibuity we set the the
687    * column details and columnaname for sort specification list .Table name and columname
688    * of id (in order by clause ) is now same as user definded column details (x.id ).
689    * specification .
690    * @param userDefinedColumnDetails
691    * @param orderByColumnDetails
692    * @throws DException
693    * @author Mnaoj Kr. [Nov. 23,2004 ]
694    * @since Initial compiere support
695    *
696    */

697   private void resolveColumnAmbiguityInOrder(ColumnDetails[] userDefinedCDs,
698                                             ColumnDetails[] orderByCDs) throws
699       DException {
700     for (int i = 0; i < orderByCDs.length; i++) {
701       if (orderByCDs[i].getAppropriateTableName() == null && orderByCDs[i].getType() == REFERENCE) {
702         for (int j = 0; j < userDefinedCDs.length; j++) {
703           if (userDefinedCDs[j].getColumn().equalsIgnoreCase(orderByCDs[i].
704               getColumn()) ) {
705             orderByCDs[i].setTableDetails(userDefinedCDs[j].getTable());
706             orderByCDs[i].setColumnName(new String JavaDoc[] {userDefinedCDs[j].
707                                         getTable().getActualName(),
708                                         userDefinedCDs[j].getAppropriateColumn()});
709             break;
710           }
711         }
712       }
713     }
714   }
715
716   /**
717
718   /**
719    * This method is used to ensure that following things can't be occured in
720    * order by clause.
721    * 1. Duplicate names.
722    * 2. Duplicate ordinal Position.
723    * @param orderKeyColumns represents the columns of 'Order By'
724    * @throws DException
725    */

726
727   public static void checkingForOrder(ColumnDetails[] orderKeyColumns) throws
728   DException {
729     checkForQuestion(orderKeyColumns);
730
731   }
732
733   /**
734    * This method ensures that 'having clause' can include only columns
735    * specified in group by or aggregate columns.
736    *<br> Examples</br>
737    * <br>select countryid from country group by countryid having countryid > 1</br>
738    * <br>Above query is valid one as having condition contains only group by column</br>
739    * <br>select countryid,Avg(population) from country group by countryid having Sum(Population) > 200 </br>
740    * <br> Above query is valid one as having condition contains aggregate Column</br>
741    *
742    * <br>Having can contain only nonAggregate columns present in group By.</br>
743    * <br>Examples</br>
744    * <br>Select Avg(productid) from products having productid > 1</br>
745    *
746    * @param havingClauseColumnDetails
747    * @throws DException
748    */

749   private _Reference[] checkGroupByHavingSemantic(ColumnDetails[]
750       havingClauseColumnDetails) throws
751   DException {
752     ArrayList JavaDoc refs = new ArrayList JavaDoc();
753     for (int i = 0; i < havingClauseColumnDetails.length; i++) {
754       int type = havingClauseColumnDetails[i].getType();
755       if (type != GROUPING && type != CONSTANT) {
756         if (type == SCALARFUNCTION || type == CASEEXPRESSION ||
757             type == FUNCTIONAL) {
758           _Reference[] re=checkGroupByHavingSemantic(havingClauseColumnDetails[i].getExistingColumnDetails());
759           if(re!=null)
760             refs.addAll(Arrays.asList(re));
761           continue;
762         }
763         String JavaDoc havingColumn = havingClauseColumnDetails[i].getStringOfColumn();
764         if (groupByClauseColumnDetails == null)
765           throw new DException("DSE918", new Object JavaDoc[] {havingColumn});
766         int j = 0, length = groupByClauseColumnDetails.length;
767         for (; j < length; j++) {
768           if (groupByClauseColumnDetails[j].getStringOfColumn().
769               equalsIgnoreCase(havingColumn)) {
770             break;
771           }
772         }
773         if (j == length) { //could not find the column in the group by clause
774
refs.add(havingClauseColumnDetails[i]);
775           havingClauseColumnDetails[i].setReason("DSE918");
776
777         }
778       }
779     }
780     return refs.isEmpty() ? null : (_Reference[]) refs.toArray(new _Reference[0]);
781   }
782
783   /**
784    * This method ensures that if group by is present then 'select list' and
785    * 'order by clause' can contains only those columns which are specified in
786    * 'group By clause' or aggregate Columns.
787    * <br>Examples</br>
788    * <br>select countryid from country group by countryid</br>
789    * <br>Above query is valid one as select list contains group by column</br>
790    * <br>select countryid,Avg(population) from country group by countryid</br>
791    * <br>Above query is valid one as select list contains no other column
792    * except group by columns and aggregate Column</br>
793    * @parm1 orderOrSelectListColumns represents columns of orderby or selectlist.
794    * @throws DException
795    */

796   private _Reference[] checkGroupBySelectOrOrderSemantic(ColumnDetails[]
797       orderOrSelectListColumns) throws DException {
798     ArrayList JavaDoc refs = new ArrayList JavaDoc();
799     for (int i = 0, length = orderOrSelectListColumns.length; i < length; ++i) {
800       boolean state = false;
801       int type = orderOrSelectListColumns[i].getType();
802       if (type != GROUPING && type != CONSTANT) {
803         String JavaDoc selecListColumnName = orderOrSelectListColumns[i].
804                                      getStringOfColumn();
805         if (type == HAS_RECORD)
806           throw new DException("DSE3540", null);
807         if (type == SCALARFUNCTION || type == FUNCTIONAL ||
808             type == CASEEXPRESSION || type == USERFUNCTION){
809           boolean directMatch = false;
810           if(groupByClauseColumnDetails !=null){
811             for (int j = 0, length1 = groupByClauseColumnDetails.length;
812                  j < length1; ++j) {
813               if (selecListColumnName.equalsIgnoreCase(
814                   groupByClauseColumnDetails[
815                   j].getStringOfColumn()) && (type != USERFUNCTION)) {
816                 directMatch = true;
817                 break;
818               }
819             }
820           }
821           if (directMatch == false) {
822             state = checkingForAggregateColumn(orderOrSelectListColumns[i].
823                 getExistingColumnDetails());
824           }
825           else
826             state = true; // scalar function is directly present in group by list
827
}
828         else {
829           if (groupByClauseColumnDetails == null)
830             throw new DException("DSE918", new Object JavaDoc[] {selecListColumnName}); // Column Should Either Be Aggregate Column Or Present in Group By Clause
831
for (int j = 0, length1 = groupByClauseColumnDetails.length;
832                j < length1; ++j) {
833             if (selecListColumnName.equalsIgnoreCase(groupByClauseColumnDetails[
834                 j].getStringOfColumn())) {
835             state = true;
836             break;
837           }
838           }
839         }
840        /* to solve bug no 12706 */
841         if( type == SCALARSUBQUERY){
842          state = true;
843        }
844
845         if (!state) {
846           refs.add(orderOrSelectListColumns[i]);
847           orderOrSelectListColumns[i].setReason("DSE918");
848         }
849       }
850     }
851     return refs.isEmpty() ? null : (_Reference[]) refs.toArray(new _Reference[0]);
852   }
853
854   /**
855    * <br>This method is used to perform semantic checking of 'Order By' And
856    * 'Select List'</br>. It includes -
857    * <br>1.If alias name of any column is specified in select list then Order By
858    * can contian Alias name of that Column.</br>
859    * <br>2. Checks the semantic of selctlist with groupby.</br>
860    * <br>3. Checks the semantic of orderby with groupby.</br>
861    * @param unKnownReferences
862    * @return _Reference[]
863    * @throws DException
864    */

865   private _Reference[] checkOrderByAndSelectColumnSemantic(_Reference[]
866       unKnownReferences) throws DException {
867     if (unKnownReferences != null)
868       unKnownReferences = checkOrderByAliasNameSemantic(unKnownReferences,
869           userDefinedColumnDetails);
870     checkOrderByAmbiguousColumnSemantic(orderByClauseColumnDetails,
871                                         userDefinedColumnDetails);
872     checkOrderByOrdinalNoSemantic(userDefinedColumnDetails,
873                                   orderByClauseColumnDetails);
874
875     /*Done by vibha on 13-09-2004 to solve bug no 11822*/
876
877     if (groupByClauseColumnDetails != null || aggregateColumnsPresentInQuery != null)
878       unKnownReferences = GeneralPurposeStaticClass.getJointReferences(
879       unKnownReferences,
880       checkGroupBySelectOrOrderSemantic(orderByClauseColumnDetails));
881     return unKnownReferences;
882
883   }
884
885   /**
886    * This method is used to mark passed columns as 'Constant'. It is required
887    * because the passed columns are those columns whose values are to be
888    * provided by user. So we consider it as Constant.
889    * <br>e.g.</br>
890    * <br>Select productid from products as p where productid > </br>
891    * <br>( select orderid from orders where orderid=p.productid)</br>
892    * <br>inside the innner query the p.productid is of constant type.</br>
893    * <br>So this function sets the type of such unknown references equal to constant</br>
894    * @param unKnownReferences
895    * @throws DException
896    */

897   private void initializingTypeOfUnKnownReferencesAsConstant(_Reference[]
898       unKnownReferences) throws DException {
899     if(unKnownReferences!=null)
900       for (int i = 0, length = unKnownReferences.length; i < length; ++i) {
901         if ( ( (ColumnDetails) unKnownReferences[i]).getType() == REFERENCE) {
902           ( (ColumnDetails) unKnownReferences[i]).setUnderLyingReference(true);
903           ( (ColumnDetails) unKnownReferences[i]).setType(CONSTANT);
904         }
905       }
906   }
907
908   /**
909    * This method ensures that duplicate Column Names are not present in
910    * 'order by clause'.
911    * <br>select countryid from country order by countryID,countryID</br>
912    * <br>comment : incorrect.</br>
913    * @throws DException
914    */

915   private static void checkDuplicateOrderColumnSemantic(ColumnDetails[]
916       orderByClauseKeyColumnColumnDetails) throws DException {
917     for (int i = 0, length = orderByClauseKeyColumnColumnDetails.length;
918          i < length - 1; i++) {
919       String JavaDoc columnName = orderByClauseKeyColumnColumnDetails[i].
920                  getQualifiedColumnName();
921       for (int j = i + 1; j < length; j++) {
922         if (orderByClauseKeyColumnColumnDetails[j].getQualifiedColumnName().
923             equalsIgnoreCase(columnName))
924         throw new DException("DSE3541", null);
925       }
926     }
927   }
928
929   /**
930    * <br> This method ensures that duplicate ordinal positions are not present
931    * in 'order by clause'.</br>
932    * <br>e.g select countryid from country order by 1,1</br>
933    * <br>Above query is incorrect</br>
934    * @throws DException
935    */

936   private static void checkDuplicateOrdinalPositionSemantic(ColumnDetails[]
937       orderByClauseKeyColumnColumnDetails) throws DException {
938     for (int i = 0, length = orderByClauseKeyColumnColumnDetails.length;
939          i < length - 1; i++) {
940       if (orderByClauseKeyColumnColumnDetails[i].getType() == CONSTANT) {
941         Integer JavaDoc obj = getOrdinalNoValue(orderByClauseKeyColumnColumnDetails[i]);
942         if (obj == null)
943           continue;
944         int value = obj.intValue();
945         for (int j = i + 1; j < length; j++) {
946           if (orderByClauseKeyColumnColumnDetails[i].getType() == CONSTANT) {
947             obj = getOrdinalNoValue(orderByClauseKeyColumnColumnDetails[j]);
948             if (obj == null)
949               continue;
950             int value1 = obj.intValue();
951             if (value == value1)
952               throw new DException("DSE3541", null);
953           }
954         }
955       }
956     }
957   }
958
959   /**
960    * Returns Ordinal No Value of Column Passed. It is required in checking of
961    * ordinal position present in columns of order by.
962    * @param orderByColumn
963    * @return int if ordinal are not present then exception occured and ignored
964    * also we return -1 in this case.
965    * @throws DException
966    */

967
968   /* Method rewritten by Kaushik on 17/08/2004 to solve Bug 11690*/
969   private static Integer JavaDoc getOrdinalNoValue(ColumnDetails orderByColumn) throws
970   DException {
971     Integer JavaDoc value = null;
972     try {
973
974       value = new Integer JavaDoc( ( (FieldBase) orderByColumn.getObject()).getObject().
975                            hashCode());
976     }
977     catch (ClassCastException JavaDoc ce) {
978     } //ReviewToDo Not a good style.
979
return value;
980   }
981
982
983 /**
984  * This method is used to ensure that alias name of selected column can
985  * occured in order by clause.
986  * <br>Examples</br>
987  * <br>select countryID as c from country order by c</br>
988  * @param unKnownReferences represents order columns which are not solvable
989  * by this select query.
990  * @param userDefinedColumnDetails represents the columns of select list.
991  * @return _Reference[]
992  * @throws DException
993  */

994   private static _Reference[] checkOrderByAliasNameSemantic(_Reference[]
995       unKnownReferences, ColumnDetails[] userDefinedColumnDetails) throws
996   DException {
997     ArrayList JavaDoc unKnownReferencesList = new ArrayList JavaDoc(Arrays.asList(
998         unKnownReferences));
999     for (int i = 0; i < unKnownReferencesList.size(); ++i) {
1000      ColumnDetails orderColumn = (ColumnDetails) unKnownReferencesList.get(i);
1001      String JavaDoc columnName = orderColumn.getColumn();
1002      if (orderColumn.getType() == CONSTANT)
1003        continue;
1004      TableDetails table = orderColumn.getTable();
1005      boolean matched = false;
1006      for (int j = 0, length1 = userDefinedColumnDetails.length; j < length1;
1007           ++j) {
1008        String JavaDoc columnNameSelectList = userDefinedColumnDetails[j].getAliasName();
1009        if (columnNameSelectList != null &&
1010            columnName.equalsIgnoreCase(columnNameSelectList)) { // making AliasName Same As Original Column
1011
if (matched) //duplicate
1012
throw new DException("DSE3542", null);
1013          unKnownReferencesList.remove(i);
1014          matched = true;
1015          --i;
1016          initializePropertiesOfOrderByColumn(orderColumn,
1017              userDefinedColumnDetails[j]);
1018        }
1019      }
1020    }
1021    return unKnownReferencesList.isEmpty() ? null :
1022        (_Reference[])
1023        unKnownReferencesList.toArray(new _Reference[unKnownReferencesList.size()]);
1024  }
1025
1026  /**
1027   * <br>This method is used to ensure that columns of select list is present
1028   * only once in order by</br>
1029   * <br>select countryID,countryID from country order by countryID</br>
1030   * <br>In this method checking is done with the help of Qualified Column Name, this is done because of
1031   * <br>case specified below:</br>
1032   * <br>Examples</br>
1033   * <br>select State.CountryID,Country.CountryID from country,State order by State.countryID;</br>
1034   * <br>If simple column Name is taken into consideration then ambiguous column exception is there but it</br>
1035   * <br>is not the case in the above query.</br>
1036   * @param orderByClauseColumnDetails
1037   * @param userDefinedColumnDetails
1038   * @throws DException
1039   */

1040  private static void checkOrderByAmbiguousColumnSemantic(ColumnDetails[]
1041      orderByClauseColumnDetails, ColumnDetails[] userDefinedColumnDetails) throws
1042  DException {
1043    for (int i = 0; i < orderByClauseColumnDetails.length; ++i) {
1044      ColumnDetails orderColumn = (ColumnDetails) orderByClauseColumnDetails[i];
1045      String JavaDoc columnName = orderColumn.getStringOfColumn();
1046      if (orderColumn.getType() == CONSTANT)
1047        continue;
1048      boolean matched = false;
1049      for (int j = 0, length1 = userDefinedColumnDetails.length; j < length1;
1050           ++j) {
1051        String JavaDoc columnNameSelectList = userDefinedColumnDetails[j].
1052                   getAppropriateQualifiedName();
1053        if (columnName.equalsIgnoreCase(columnNameSelectList)) { // making AliasName Same As Original Column
1054
if (matched)
1055            throw new DException("DSE3542", null);
1056          matched = true;
1057        }
1058      }
1059    }
1060  }
1061
1062  /**
1063   * Copies the properties of Looser into Gainer ColumnDetail Object
1064   * @param gainer
1065   * @param looser
1066   * @throws DException
1067   */

1068  private static void initializePropertiesOfOrderByColumn(ColumnDetails gainer,
1069      ColumnDetails looser) throws DException {
1070
1071
1072    gainer.setColumnName(looser.getType() == REFERENCE ? looser.getColumnName() :
1073                         new String JavaDoc[] {looser.getColumn()});
1074    gainer.setTableDetails(looser.getTable());
1075    gainer.setType(looser.getType());
1076    gainer.setObject(looser.getObject());
1077    gainer.setDatatype(looser.getDatatype());
1078    gainer.setSize(looser.getSize());
1079    gainer.setQuantifier(looser.getQuantifier());
1080    gainer.setFunctionType(looser.getFunctionType());
1081    gainer.setTableAliasArray(looser.getTableAliasArray());
1082  }
1083
1084  /**
1085   * This method is used to ensure that if group by is not present and
1086   * aggregates are present in select list, then select list can't contain
1087   * columns of tables directly.
1088   * @param selectListColumnDetails
1089   * @param stateForReference
1090   * @param stateForGroup
1091   * @return boolean[]
1092   * @throws DException
1093   */

1094  private boolean[] checkingForAggregateAndNonAggregateSemantic(ColumnDetails[]
1095      selectListColumnDetails, boolean stateForReference, boolean stateForGroup) throws
1096  DException {
1097    if (selectListColumnDetails == null)
1098      return new boolean[] {
1099        stateForReference, stateForGroup};
1100      int length = length = selectListColumnDetails.length;
1101      for (int i = 0; i < length; ++i) {
1102        int type = selectListColumnDetails[i].getType();
1103        if (type == HAS_RECORD) {
1104          checkingForHas_Record(selectListColumnDetails[i]);
1105          continue;
1106        }
1107        if (type != GROUPING && type != CONSTANT) {
1108          boolean[] booleanArray = null;
1109          if (type == SCALARFUNCTION || type == FUNCTIONAL ||
1110              type == CASEEXPRESSION) {
1111            booleanArray = checkingForAggregateAndNonAggregateSemantic(
1112                selectListColumnDetails[i].getExistingColumnDetails(),
1113                stateForReference, stateForGroup);
1114            stateForReference = booleanArray[0];
1115            stateForGroup = booleanArray[1];
1116          }
1117          else if (type == REFERENCE) {
1118            if (stateForGroup)
1119              throw new DException("DSE918",
1120                                   new Object JavaDoc[] {selectListColumnDetails[i].
1121            getColumn()}); // Non Column Should Either Be Aggregate Column Or Present in Group By Clause //mohit
1122
stateForReference = true;
1123          }
1124          continue;
1125        }
1126        if (type != CONSTANT) { // Constant are not considered
1127
if (stateForReference)
1128            throw new DException("DSE918",
1129                                 new Object JavaDoc[] {selectListColumnDetails[i].
1130          getColumn()}); // Non Column Should Either Be Aggregate Column Or Present in Group By Clause
1131
stateForGroup = true;
1132        }
1133      }
1134      return new boolean[] {
1135        stateForReference, stateForGroup};
1136  }
1137
1138  /**
1139   * This method is used to perform the semantic checking or order by columns
1140   * in case of set operators. It ensures -
1141   * 1. dupicate ordinal position is not present in select list.
1142   * 2. Only the columns of select list can participate in 'order by clause'.
1143   * @return
1144   * @throws DException
1145   */

1146  public static void checkSemanticCheckingForOrderInSetOperatorsold(
1147      ColumnDetails[] selectedColumns, ColumnDetails[] orderByColumns) throws
1148  DException {
1149
1150    for (int i = 0; i < orderByColumns.length; i++) {
1151      boolean matched = false;
1152      if (orderByColumns[i].getType() != CONSTANT) {
1153        String JavaDoc[] columnName = orderByColumns[i].getColumnName();
1154        for (int j = 0; j < selectedColumns.length; j++) {
1155          if (check(columnName, selectedColumns[j].getAppColumnName())) {
1156            if (matched)
1157              throw new DException("DSE3542", null);
1158            initializePropertiesOfOrderByColumn(orderByColumns[i],
1159                selectedColumns[j]);
1160            i++;
1161            matched = true;
1162          }
1163        }
1164        for (int k = 0; k < selectedColumns.length; k++) {
1165          matched = false;
1166       if(orderByColumns[i].getAppropriateColumn().equalsIgnoreCase(selectedColumns[k].
1167              getOriginalColumn())) {
1168            if (matched)
1169              throw new DException("DSE3542", null);
1170            initializePropertiesOfOrderByColumn(orderByColumns[i],
1171                selectedColumns[k]);
1172            matched = true;
1173          }
1174        }
1175        if (!matched)
1176          throw new DException("DSE3544",
1177                               new Object JavaDoc[] {orderByColumns[i].getColumn()}); // Invalid Order Columns
1178
i++;
1179      } //fpr end
1180
} //if end
1181

1182    checkOrderByOrdinalNoSemantic(selectedColumns, orderByColumns);
1183
1184  }
1185
1186  public static void checkSemanticCheckingForOrderInSetOperators(ColumnDetails[]
1187      selectedColumns, ColumnDetails[] orderByColumns) throws DException {
1188    ArrayList JavaDoc orderColumns = new ArrayList JavaDoc();
1189    boolean matched = false;
1190    for (int i = 0; i < orderByColumns.length; i++) {
1191      matched = false;
1192      if (orderByColumns[i].getType() != CONSTANT) {
1193        String JavaDoc[] ordercolumn = orderByColumns[i].getColumnName();
1194        for (int j = 0; j < selectedColumns.length; j++) {
1195          if (check(ordercolumn, selectedColumns[j].getAppColumnName())) {
1196            if (matched)
1197              throw new DException("DSE3542", null);
1198            initializePropertiesOfOrderByColumn(orderByColumns[i],
1199                selectedColumns[j]);
1200            matched = true;
1201          }
1202        }
1203        if (!matched)
1204          orderColumns.add(orderByColumns[i]);
1205      }
1206    }
1207    int k = 0;
1208    ColumnDetails[] orderByColumns1 = (ColumnDetails[]) orderColumns.toArray(new
1209        ColumnDetails[orderColumns.size()]);
1210    for (k = 0; k < orderByColumns1.length; k++) {
1211      matched = false;
1212      if (orderByColumns1[k].getType() != CONSTANT) {
1213        for (int l = 0; l < selectedColumns.length; l++) {
1214          if (orderByColumns1[k].getAppropriateColumn().equalsIgnoreCase(selectedColumns[l].
1215              getOriginalColumn())) {
1216          if (matched)
1217            throw new DException("DSE3542", null);
1218          initializePropertiesOfOrderByColumn(orderByColumns[k],
1219              selectedColumns[l]);
1220          matched = true;
1221        }
1222        }
1223        if (!matched) //done by Sandeep to solve 12518
1224
throw new DException("DSE3544",
1225                              new Object JavaDoc[] {orderByColumns1[k].getColumn()}); // Invalid Order Columns
1226

1227      }
1228    }
1229    checkOrderByOrdinalNoSemantic(selectedColumns, orderByColumns);
1230
1231  }
1232
1233  /**
1234   * This method is used to check whether passed arrays are equivalent except
1235   * the last element. It is needed to check the qualified tablenames of two
1236   * columns.
1237   * @param array1
1238   * @param array2
1239   * @return
1240   * @throws DException
1241   */

1242
1243  private static boolean check(String JavaDoc[] array1, String JavaDoc[] array2) throws
1244  DException {
1245    int i = array1.length - 1, j = array2.length - 1;
1246    for (; i >= 0 && j >= 0; i--, j--) {
1247      if (!array1[i].equalsIgnoreCase(array2[j]))
1248        return false;
1249    }
1250    return i < 0;
1251  }
1252
1253  private static boolean checknew(ColumnDetails orderCD, ColumnDetails selectCD) throws
1254  DException {
1255    if (orderCD.getTable().equals(selectCD.getTable())) {
1256      if (orderCD.getAppropriateColumn().equalsIgnoreCase(selectCD.
1257          getAppropriateColumn()))
1258        return true;
1259      else if (orderCD.getOriginalColumn().equalsIgnoreCase(selectCD.
1260          getOriginalColumn()))
1261        return true;
1262      else
1263        return false;
1264    }
1265    return false;
1266
1267  }
1268
1269  /**
1270   * This method is used to check whether passed columns can be solved by this
1271   * select query.
1272   * @param underLyingReferences
1273   * @return _Reference[]
1274   * @throws DException
1275   */

1276  public _Reference[] checkForUnderLyingReferences(ColumnDetails[]
1277      underLyingReferences) throws DException {
1278    ArrayList JavaDoc list = new ArrayList JavaDoc();
1279    if (underLyingReferences == null)
1280      return null;
1281    try {
1282      SetColumnProperties.setTableNamesAndDatatypesOfAllColumns(serverSession,
1283          underLyingReferences, tableDetails, list, new ArrayList JavaDoc());
1284    }
1285    catch (NullPointerException JavaDoc ex) {
1286      throw ex;
1287    }
1288    if (list.size() == 0)
1289      return null;
1290    return (_Reference[]) list.toArray(new _Reference[list.size()]);
1291  }
1292
1293  /**
1294   * This method is used to obtain the map of table and all of its columns
1295   * present in query.
1296   * @return HashMap
1297   * @throws DException
1298   */

1299  public HashMap getMappingOfTableDetailsAndColumnsBelonging() throws
1300  DException {
1301    HashMap listOfTableAndColumns = new HashMap();
1302    if (queryColumns == null)
1303      getAllColumnDetails();
1304    for (int i = 0, length = tableDetails.length; i < length; ++i) {
1305      ArrayList JavaDoc list = new ArrayList JavaDoc();
1306      for (int j = 0, length1 = queryColumns.length; j < length1; ++j) {
1307        if (queryColumns[j].getType() == REFERENCE && queryColumns[j].getTable() != null)
1308          if (queryColumns[j].getTable().equals(tableDetails[i]))
1309            list.add(queryColumns[j]);
1310      }
1311      ColumnDetails[] matchedColumns = list.isEmpty() ? null :
1312                                       (ColumnDetails[]) list.toArray(new ColumnDetails[list.size()]);
1313      listOfTableAndColumns.put(tableDetails[i], matchedColumns);
1314    }
1315    return listOfTableAndColumns;
1316  }
1317
1318  /**
1319   * Returns the selected columns one per select sublist. There may be a column
1320   * which is made up with combination of more than one column. For those
1321   * columns, one column is returned with type functional.
1322   * called by checkSelectListColumnSemantic()
1323   * @return ColumnDetails[]
1324   * @throws DException
1325   */

1326  public ColumnDetails[] getDerivedColumnDetails() throws DException {
1327    return userDefinedColumnDetails;
1328  }
1329
1330  /**
1331   * This method is used to obtain all the columns involved in select query. It
1332   * contains columns of select list one per select sublist.
1333   * @throws DException
1334   */

1335
1336  private void getAllColumnDetails() throws DException {
1337    ArrayList JavaDoc set = new ArrayList JavaDoc();
1338    addColumns(set, userDefinedColumnDetails);
1339    if (clonedUserDefinedColumnDetails != null)
1340      addColumns(set, clonedUserDefinedColumnDetails);
1341    queryColumns = getAddedColumns(set);
1342  }
1343
1344  /**
1345   * This method is used to obtain all the columns involved in select query. It
1346   * contains all the columns present in select list.
1347   * @return
1348   * @throws DException
1349   */

1350
1351  public ColumnDetails[] getAllColumnsInvolvedInQuery() throws DException {
1352    ArrayList JavaDoc set = new ArrayList JavaDoc();
1353    addColumns(set, selectListColumnDetails);
1354    return getAddedColumns(set);
1355  }
1356
1357  /**
1358   * This method is used to add all the columns of select query in passed list
1359   * except the columns involved in select list.
1360   * @param set
1361   * @return
1362   * @throws DException
1363   */

1364
1365  private ColumnDetails[] getAddedColumns(ArrayList JavaDoc set) throws DException {
1366    addColumns(set, fromClauseColumnDetails);
1367    if (whereClauseColumnDetails != null) {
1368      addColumns(set, whereClauseColumnDetails);
1369    }
1370    if (groupByClauseColumnDetails != null)
1371      addColumns(set, groupByClauseColumnDetails);
1372    if (havingClauseColumnDetails != null)
1373      addColumns(set, havingClauseColumnDetails);
1374    if (orderByClauseColumnDetails != null)
1375      addColumns(set, orderByClauseColumnDetails);
1376    return (ColumnDetails[]) set.toArray(new ColumnDetails[set.size()]);
1377  }
1378
1379  /**
1380   * This method is used to check whether any aggregate is present in passed
1381   * columns. It also takes in to the consideration that any functional column
1382   * like - column representing caseexpression or scalarfunction, contains any
1383   * aggregate function or not.
1384   * @param columnDetails
1385   * @return boolean
1386   * @throws DException
1387   */

1388  private boolean checkingForAggregateColumn(ColumnDetails[] columnDetails) throws
1389  DException {
1390    if (columnDetails == null)
1391      return true;
1392    for (int i = 0, length = columnDetails.length; i < length; ++i) {
1393      boolean state = false;
1394      int type = columnDetails[i].getType();
1395      if (type == SCALARFUNCTION || type == CASEEXPRESSION )
1396        state = checkingForAggregateColumn(columnDetails[i].
1397            getExistingColumnDetails());
1398      else if (type == REFERENCE) {
1399        for (int j = 0, length1 = groupByClauseColumnDetails.length;
1400             j < length1; ++j) {
1401          if (columnDetails[i].getStringOfColumn().equalsIgnoreCase(
1402              groupByClauseColumnDetails[j].getStringOfColumn())) {
1403          state = true; // means Present in Group By Clause columns
1404
break;
1405        }
1406        }
1407        if (!state) // means Not Present ThereFore Exception is to be thrown
1408
throw new DException("DSE918",
1409                               new Object JavaDoc[] {columnDetails[i].getColumn()}); // Column Should Either Be Aggregate Column Or Present in Group By Clause
1410
}
1411    }
1412    return true;
1413  }
1414
1415  /**
1416   * This method is used to initialize qualified name of passed table. If
1417   * catalog name or schema name is not given, then their default value is
1418   * obtained from serversession object.
1419   * @param tableDetails
1420   * @param serverSession
1421   * @throws DException
1422   */

1423  public static void initializeCatalogNameAndSchemaNameOfTable(TableDetails
1424      tableDetails, _ServerSession serverSession) throws DException {
1425    String JavaDoc[] userTableSpecified = tableDetails.getTableName();
1426    int length = userTableSpecified.length;
1427    String JavaDoc[] qualifiedTableName = new String JavaDoc[3];
1428    if (length == 1) {
1429      qualifiedTableName[0] = serverSession.getCurrentCatalog();
1430      qualifiedTableName[1] = serverSession.getCurrentSchema();
1431      qualifiedTableName[2] = userTableSpecified[0];
1432    }
1433    else if (length == 2) {
1434      qualifiedTableName[0] = serverSession.getCurrentCatalog();
1435      qualifiedTableName[1] = userTableSpecified[0];
1436      qualifiedTableName[2] = userTableSpecified[1];
1437    }
1438    else
1439      qualifiedTableName = userTableSpecified;
1440    tableDetails.setTableName(qualifiedTableName);
1441  }
1442
1443  /**
1444   * Returns all Aggregate Columns involved in the query.
1445   * Examples
1446   * select floor(sum(population)), avg(population) from country order by count(countryid)
1447   * it will return three aggregate columns like sum(population), avg(population) and count(countryid)
1448   * Aggregate columns are retrieved from -
1449   * selectlist, fromclause, orderbyclause, havingclause.
1450   * @return ColumnDetails[]
1451   * @throws DException
1452   */

1453  public ColumnDetails[] getAllAggregateColumns() throws DException {
1454    if (aggregateColumnsPresentInQuery != null)
1455      return aggregateColumnsPresentInQuery;
1456    ArrayList JavaDoc groupByColumns = new ArrayList JavaDoc(8);
1457    getAggregateColumns(userDefinedColumnDetails, groupByColumns);
1458    getAggregateColumns(fromClauseColumnDetails, groupByColumns);
1459    getAggregateColumns(orderByClauseColumnDetails, groupByColumns);
1460    getAggregateColumns(havingClauseColumnDetails, groupByColumns);
1461    if (groupByColumns.isEmpty())
1462      return null;
1463    aggregateColumnsPresentInQuery = (ColumnDetails[]) groupByColumns.toArray(new
1464        ColumnDetails[groupByColumns.size()]);
1465    return aggregateColumnsPresentInQuery;
1466  }
1467
1468  /**
1469   * This method is used to collect all aggregate columns from passed columns
1470   * in the passed list. It also takes in to the consideration that any
1471   * functional column like - column representing caseexpression or
1472   * scalarfunction, contains any aggregate function or not.
1473   * @param column
1474   * @param list
1475   * @throws DException
1476   */

1477
1478  private void getAggregateColumns(ColumnDetails[] column, ArrayList JavaDoc list) throws
1479  DException {
1480    if (column == null)
1481      return;
1482    for (int i = 0, length = column.length; i < length; i++) {
1483      switch (column[i].getType()) {
1484      case GROUPING:
1485        TableDetails table = column[i].getTableForDisplay();
1486        if (table == null)
1487          list.add(column[i]);
1488        break;
1489      case SCALARFUNCTION:
1490      case FUNCTIONAL:
1491      case CASEEXPRESSION:
1492      case USERFUNCTION :
1493        getAggregateColumns(column[i].getExistingColumnDetails(), list);
1494    }
1495    }
1496  }
1497
1498  /**
1499   * Checks Cardinality and Data type comptability of columns specified in Set
1500   * Operators Queries.
1501   * First Argument is column Details of left Query
1502   * Second Argument is column Details of right Query
1503   * Examples
1504   * select countryid from country union select stateid,stateName from state
1505   * In the above query cardinality of queries does not matches
1506   * Examples
1507   * select countryid from country union select stateName from state
1508   * In the above query Data type of columns specified are not comptabile
1509   * @param columnDetailsLeft
1510   * @param columnDetailsRight
1511   * @throws DException
1512   */

1513
1514  public static void checkCardinalityAndDataTypeComptability(ColumnDetails[]
1515      columnDetailsLeft, ColumnDetails[] columnDetailsRight) throws DException {
1516    if (columnDetailsLeft.length != columnDetailsRight.length)
1517      throw new DException("DSE214", null);
1518    for (int i = 0; i < columnDetailsLeft.length; ++i) {
1519      /*Done by vibha to solve bug no 11893 */
1520      if (columnDetailsLeft[i].getColumnName()[0].equalsIgnoreCase("null")) {
1521        columnDetailsLeft[i].setDatatype(columnDetailsRight[i].getDatatype());
1522        columnDetailsLeft[i].setSize(columnDetailsRight[i].getSize());
1523      }
1524      else {
1525        if (columnDetailsRight[i].getColumnName()[0].equalsIgnoreCase("null")) {
1526          columnDetailsRight[i].setDatatype(columnDetailsLeft[i].getDatatype());
1527          columnDetailsRight[i].setSize(columnDetailsLeft[i].getSize());
1528        }
1529      }
1530      try {
1531        Check.checkForDatatype(columnDetailsLeft[i].getDatatype(),
1532                               columnDetailsRight[i].getDatatype());
1533      }
1534      catch (DException ex) {
1535        throw ex;
1536      }
1537    }
1538  }
1539
1540// */
1541

1542/**
1543 * This method is used to collect the columns of tables from passed columns in
1544 * to passed list. The columns of tables are also collected in the case when
1545 * they are indulged into any aggregates, scalarfunction or caseexpression.
1546 * Examples
1547 * if ColumnDetails passed is of type GroupIng like
1548 * avg(countryID)
1549 * then, list will contain countryid column
1550 * @param set
1551 * @param columnDetails
1552 * @throws DException
1553 */

1554
1555  private void addColumns(ArrayList JavaDoc set, ColumnDetails[] columnDetails1) throws
1556  DException {
1557    if (columnDetails1.length > 0 && columnDetails1[0].getContainClauseFlag()) {
1558      return;
1559    }
1560    for (int i = 0, length = columnDetails1.length; i < length; i++) {
1561      int type = columnDetails1[i].getType();
1562      if (type == FUNCTIONAL || type == GROUPING || type == SCALARFUNCTION ||
1563          type == CASEEXPRESSION || type == USERFUNCTION ) {
1564        addColumns(set, columnDetails1[i].getExistingColumnDetails());
1565      }
1566      else if (columnDetails1[i].getType() != CONSTANT ||
1567               columnDetails1[i].getColumn().equalsIgnoreCase("*")) {
1568        set.add(columnDetails1[i]);
1569      }
1570    }
1571  }
1572
1573  /**
1574   * Utility Method to concatenates the two array of columnDetails passed.
1575   * @param columnDetails1
1576   * @param columnDetails2
1577   * @return ColumnDetais[]
1578   * @throws DException
1579   */

1580  public static ColumnDetails[] addColumnDetails(ColumnDetails[] columnDetails1,
1581      ColumnDetails[] columnDetails2) throws
1582  DException {
1583    int len1 = columnDetails1.length;
1584    int len2 = columnDetails2.length;
1585    int len = len1 + len2;
1586    ColumnDetails[] result = new ColumnDetails[len];
1587    System.arraycopy(columnDetails1, 0, result, 0, len1);
1588    System.arraycopy(columnDetails2, 0, result, len1, len2);
1589    return result;
1590  }
1591
1592  /**
1593   * Checking for Ordinal Range of Order BY no's. The ordinal number specified
1594   * in the order by clause should be less than the number of columns in
1595   * the select list
1596   * Checking For Valid Ordinal No.
1597   * e.g.
1598   * select A,B from table order by 5
1599   * comment - as the number 5 is greater than the number of columns it is invalid
1600   * It also initializes the column representing ordinal no. in Order By with
1601   * the corressponding column of Select List.
1602   * @param userDefinedColumnDetails
1603   * @param orderByClauseColumnDetails
1604   * @throws DException
1605   */

1606  public static void checkOrderByOrdinalNoSemantic(ColumnDetails[]
1607      userDefinedColumnDetails, ColumnDetails[] orderByClauseColumnDetails) throws
1608  DException {
1609    int max = 0;
1610    int lengthOfSelect = userDefinedColumnDetails.length;
1611    for (int i = 0, length = orderByClauseColumnDetails.length; i < length; ++i) {
1612      int type = orderByClauseColumnDetails[i].getType();
1613      if (type == CONSTANT) {
1614        Integer JavaDoc obj = getOrdinalNoValue(orderByClauseColumnDetails[i]);
1615        if (obj == null)
1616          continue;
1617        int value = obj.intValue();
1618        if (value <= 0) {
1619          /*Done by vibha to solve bug no 11827 (append minus)*/
1620          throw new DException("DSE3545",
1621                               new Object JavaDoc[] {"-" +
1622              orderByClauseColumnDetails[i].getColumn()}); // Ordinal position in Order By can't be less than or equal to 0.
1623
}
1624        if (value > lengthOfSelect ) {
1625          throw new DException("DSE3545",
1626                               new Object JavaDoc[] {orderByClauseColumnDetails[i].
1627              getColumn()}); // Ordinal position in Order By can't be less than or equal to 0.
1628
}
1629        else {
1630            /* Done by Kaushik on 17/08/2004 for order by subquery problem
1631             (if subquery in select list and ordinal pos is given in order by) */

1632        Check.checkForAllowedDatatype(userDefinedColumnDetails[ (int) value -
1633                                        1].getDatatype());
1634
1635          checkForQuestion(new ColumnDetails[]{userDefinedColumnDetails[value -1] });// Done by Sandeep
1636
initializePropertiesOfOrderByColumn(orderByClauseColumnDetails[i],userDefinedColumnDetails[ (int)
1637              value - 1]);
1638        }
1639      }
1640    }
1641  }
1642
1643  /**
1644   * This method is used to obtain those columns which are not solved by
1645   * select query for which this object is made.
1646   * @return _Reference[]
1647   * @throws DException
1648   */

1649  public _Reference[] getUnderLyingReferences() throws DException {
1650    return unKnownReferences;
1651  }
1652
1653  /**
1654   * This method is used to obtain those columns of group by which are primary
1655   * keys. It is required to check whether we can perform updation on those
1656   * columns through the resultset of select query.
1657   * @param listOfColumns
1658   * @throws DException
1659   */

1660  public void getGroupByPrimaryColumns(ArrayList JavaDoc listOfColumns) throws
1661  DException {
1662    try {
1663      if (groupByClauseColumnDetails == null)
1664        return;
1665      int length = groupByClauseColumnDetails.length;
1666      TableDetails td = null;
1667      for (int i = 0; i < length; i++) {
1668        if (td == null)
1669          td = groupByClauseColumnDetails[i].getTable();
1670        else if (td != groupByClauseColumnDetails[i].getTable())
1671          return;
1672      }
1673      String JavaDoc[] keyColumns = serverSession.getUniqueInformation(td.
1674          getQualifiedIdentifier());
1675      if (keyColumns == null)
1676        return;
1677      ArrayList JavaDoc aList = new ArrayList JavaDoc(length);
1678      int j = 0, len = keyColumns.length;
1679      for (; j < len; j++) {
1680        for (int i = 0; i < length; i++) {
1681          String JavaDoc name = groupByClauseColumnDetails[i].getOriginalColumn();
1682          if (name.equalsIgnoreCase(keyColumns[j])) {
1683            aList.add(groupByClauseColumnDetails[i].getQualifiedColumnName());
1684            break;
1685          }
1686        }
1687      }
1688      if (j == len)
1689        listOfColumns.addAll(aList);
1690    }
1691    finally {
1692    }
1693
1694  }
1695
1696  /**
1697   * Returns Boolean stating whether duplicate columns are present in the columns passed.
1698   * This is used while doing semantic checking for from subQuery / view
1699   * @param columns
1700   * @returns Boolean
1701   * @throws DException
1702   */

1703
1704  public static void checkForDuplicateColumnsInvolved(ColumnDetails[] columns) throws
1705  DException {
1706    int length = columns.length;
1707    for (int i = 0; i < length - 1; ++i) {
1708      String JavaDoc columnName = columns[i].getAppropriateColumn();
1709      for (int j = i + 1; j < length; ++j) {
1710        if (columnName.equalsIgnoreCase(columns[j].getAppropriateColumn()))
1711          throw new DException("DSE3535", null);
1712      }
1713    }
1714  }
1715
1716  /**
1717   * checks whether Columns passed contains aggregate columns or not. It also
1718   * checks for those columns which inturn contains aggregate columns.
1719   * @param columns
1720   * @return Boolean
1721   * @throws DException
1722   */

1723
1724  public static boolean checkForAggregateColumns(ColumnDetails[] columns) throws
1725  DException {
1726    for (int i = 0, length = columns.length; i < length; i++) {
1727      switch (columns[i].getType()) {
1728      case GROUPING:
1729        return true;
1730      case SCALARFUNCTION:
1731      case FUNCTIONAL:
1732      case CASEEXPRESSION:
1733      case USERFUNCTION :
1734        if (checkForAggregateColumns(columns[i].getExistingColumnDetails()))
1735          return true;
1736        break;
1737    }
1738    }
1739    return false;
1740  }
1741
1742  /**
1743   * This method is used to check whether passed column is hasRecord column or
1744   * not. If it is, then it also sets the corresponding table in it.
1745   * @param columnDetail
1746   * @throws DException
1747   */

1748
1749  public void checkingForHas_Record(ColumnDetails columnDetail) throws
1750  DException {
1751    TableDetails tableDetail = columnDetail.getTable();
1752    String JavaDoc[] tableName = tableDetail.getTableName();
1753    if (tableName.length == 1) {
1754      for (int i = 0; i < tableDetails.length; i++) {
1755        if ( (tableName[0].equalsIgnoreCase(tableDetails[i].getAliasName()) ||
1756              tableName[0].equalsIgnoreCase(tableDetails[i].getActualName()))
1757              && tableDetails[i].getHasRecord()) {
1758        columnDetail.setTableDetails(tableDetails[i]);
1759        return;
1760      }
1761      }
1762    }
1763    else if (tableName.length == 2) {
1764      for (int i = 0; i < tableDetails.length; i++) {
1765        if ( (tableName[0].equalsIgnoreCase(tableDetails[i].getSchemaName()) ||
1766              tableName[1].equalsIgnoreCase(tableDetails[i].getAliasName()) ||
1767              tableName[1].equalsIgnoreCase(tableDetails[i].getActualName()))
1768              && tableDetails[i].getHasRecord()) {
1769        columnDetail.setTableDetails(tableDetails[i]);
1770        return;
1771      }
1772      }
1773    }
1774    else if (tableName.length == 3) {
1775      for (int i = 0; i < tableDetails.length; i++) {
1776        if ( (tableName[0].equalsIgnoreCase(tableDetails[i].getCatalogName()) ||
1777              tableName[1].equalsIgnoreCase(tableDetails[i].getSchemaName()) ||
1778              tableName[2].equalsIgnoreCase(tableDetails[i].getAliasName()) ||
1779              tableName[2].equalsIgnoreCase(tableDetails[i].getActualName()))
1780              && tableDetails[i].getHasRecord()) {
1781        columnDetail.setTableDetails(tableDetails[i]);
1782        return;
1783      }
1784      }
1785    }
1786    throw new DException("DSE3546",
1787                         new Object JavaDoc[] {java.util.Arrays.asList(tableName)});
1788  }
1789
1790  /**
1791   * Returns tables involved in select query.
1792   * @return
1793   * @throws DException
1794   */

1795
1796  public TableDetails[] getTableDetails() throws DException {
1797    return tableDetails;
1798  }
1799
1800  /**
1801   * Performs Various functions Like
1802   * Checks Whether columns passed in the function belongs to tables passed
1803   * If belongs to tables passed
1804   * checks whether column specfiied is ambiguous, that present in two tables
1805   * Examples
1806   * select * from country,state where countryid > 1
1807   * Here countryid column specified in where condition is ambiguous as it is present in both the
1808   * tables.
1809   * Initialises the data type, size , Qualified columnName of column and tableDetails in reference to
1810   * which it belongs.
1811   * else
1812   * returns columns as unKnown reference
1813   * If * is present then setCount method is called to initialise ColumnDetails as columns belonging to
1814   * all tables specified.
1815   * If A.* is present then ColumnDetails are initialised of this particular table A
1816   * Also checks for Chained Columns present, if present then checks the validity of chained column
1817   * Examples
1818   * select S.Cid.CountryNAme from state S
1819   * Here, Cid column must present in State Table and CountryNAme column must present in Country Table
1820   * which Cid is referring.
1821   * @param serverSession
1822   * @param columnDetails
1823   * @param tableDetails
1824   * @param conditionalColumns
1825   * @return _Reference[]
1826   * @throws com.daffodilwoods.database.resource.DException
1827   */

1828
1829  private _Reference[] setTableNamesAndDatatypesOfAllColumns(_ServerSession
1830      serverSession, ColumnDetails[] columnDetails, TableDetails[] tableDetails) throws
1831  com.daffodilwoods.database.resource.DException {
1832    ArrayList JavaDoc unKnownReferences = new ArrayList JavaDoc(5);
1833
1834    for (int indexOfColumnDetails = 0;
1835         indexOfColumnDetails < columnDetails.length; ++indexOfColumnDetails) {
1836      int type = columnDetails[indexOfColumnDetails].getType();
1837
1838      if (type == CONSTANT &&
1839          !columnDetails[indexOfColumnDetails].getUnderLyingReference()) {
1840
1841        if ( ( (String JavaDoc[]) columnDetails[indexOfColumnDetails].getColumnName()).
1842             length == 1) {
1843          if ( ( (String JavaDoc) columnDetails[indexOfColumnDetails].getColumn()).
1844               equals("*")) {
1845            setCount(serverSession, tableDetails,
1846                     columnDetails[indexOfColumnDetails]);
1847          }
1848        }
1849
1850        else {
1851          for (int indexOfTableDetails = 0;
1852               indexOfTableDetails < tableDetails.length;
1853               ++indexOfTableDetails) {
1854
1855            String JavaDoc[] tableName = tableDetails[indexOfTableDetails].
1856              getAppropriateTableName();
1857            String JavaDoc columnName[] = columnDetails[indexOfColumnDetails].
1858                                  getColumnName();
1859            TableDetails tableDetailsn = tableDetails[indexOfTableDetails];
1860            if (check(tableName, columnName, tableDetailsn,
1861                      columnDetails[indexOfColumnDetails], serverSession)) {
1862              String JavaDoc[] keyArray1 = getDetailedColumn(columnName,
1863                  tableDetailsn,
1864                  columnDetails[indexOfColumnDetails], serverSession);
1865              columnDetails[indexOfColumnDetails].setColumn(keyArray1);
1866              columnDetails[indexOfColumnDetails].setTableForDisplay(
1867                  tableDetailsn);
1868              columnDetails[indexOfColumnDetails].setTableDetails(
1869                  tableDetailsn);
1870                    columnDetails[indexOfColumnDetails].setObject(tableDetailsn.
1871                  getColumnPropertiesExcludingCommonColumns());
1872              break;
1873            }
1874          }
1875        }
1876
1877        continue;
1878      }
1879      /* Done by Kaushik on 30/06/2004 for getColumnDetails() work dest*/
1880      if (type == SCALARFUNCTION || type == CASEEXPRESSION || type == GROUPING ||
1881          type == FUNCTIONAL || type == USERFUNCTION ) {
1882        /* dend*/
1883        _Reference[] ref = setTableNamesAndDatatypesOfAllColumns(serverSession,
1884            columnDetails[indexOfColumnDetails].getExistingColumnDetails(),
1885            tableDetails); //recursion
1886
/*Done by Kaushik*/
1887        String JavaDoc oper = null;
1888        try {
1889          oper = (type == GROUPING) ?
1890                 ( (generalsetfunction) columnDetails[indexOfColumnDetails].
1891                 getObject())._setfunctiontype4.run(null).toString() : "Kaushik";
1892        }
1893        catch (ClassCastException JavaDoc ex) {
1894          oper = "Kaushik";
1895        }
1896        if (oper.equalsIgnoreCase("max") || oper.equalsIgnoreCase("min")) {
1897          /* Done by Kaushik on 18/08/2004 to Solve Bug No. 11639 */
1898          if (! ( (generalsetfunction) columnDetails[indexOfColumnDetails].
1899                  getObject()).checkForSubQuery() &&
1900                  !columnDetails[indexOfColumnDetails].getExistingColumnDetails()[0].
1901                  getQuestion())
1902
1903            columnDetails[indexOfColumnDetails].setSize(columnDetails[
1904            indexOfColumnDetails].getExistingColumnDetails()[0].getSize());
1905        }
1906        if (ref != null)
1907          unKnownReferences.addAll(Arrays.asList(ref));
1908        continue;
1909      }
1910      checkForEachTable(serverSession, columnDetails[indexOfColumnDetails],
1911                        tableDetails, unKnownReferences);
1912    }
1913
1914    return unKnownReferences.isEmpty() ? null :
1915        (_Reference[])
1916        unKnownReferences.toArray(new _Reference[unKnownReferences.size()]);
1917  }
1918
1919  /**
1920   * It is required to initialize column representing asterisk in selectlist.
1921   * It is initialized by all the columns of all tables.
1922   * e.g in select * from A,B. column of asterisk(*) is initialized by all the
1923   * columns of table A and table B.
1924   * @param serverSession
1925   * @param tableDetail
1926   * @param columnDetails
1927   * @throws com.daffodilwoods.database.resource.DException
1928   */

1929
1930  private void setCount(_ServerSession serverSession,
1931                        TableDetails[] tableDetail, ColumnDetails columnDetails) throws
1932  com.daffodilwoods.database.resource.DException {
1933    ArrayList JavaDoc aList = new ArrayList JavaDoc(); // in case select *
1934
for (int i = 0; i < tableDetail.length; ++i)
1935      aList.addAll(Arrays.asList(tableDetail[i].
1936                                 getColumnPropertiesExcludingCommonColumns()));
1937    columnDetails.setObject( (ColumnDetails[]) aList.toArray(new ColumnDetails[
1938        aList.size()]));
1939
1940
1941  }
1942
1943  /**
1944   * This method is used to check to which table passed column belongs to. It
1945   * also checks for uniqueness of column. It ensures that passed column
1946   * belongs to one table. It also sets the matched table and its characteristics
1947   * in to column. It also takes into consideration of A.* column and aggregate
1948   * column. If passed column doesn't match to any table or matched to more
1949   * than one table, then it is added into passed list.
1950   * It also ensures that blob and clob type of columns are not allowed in
1951   * predicates except 'like predicate' and 'null predicate'.
1952   * @param serverSession
1953   * @param columnDetail
1954   * @param tableDetails
1955   * @param unKnownReferences
1956   * @param conditionalColumns
1957   * @throws com.daffodilwoods.database.resource.DException
1958   */

1959
1960  private void checkForEachTable(_ServerSession serverSession,
1961                                 ColumnDetails columnDetail,
1962                                 TableDetails[] tableDetails,
1963                                 ArrayList JavaDoc unKnownReferences) throws com.
1964
      daffodilwoods.database.resource.DException {
1965    String JavaDoc[] keyArray;
1966    boolean check = false; // already checked
1967
Object JavaDoc[] result = new Object JavaDoc[4];
1968    for (int indexOfTableDetails = 0; indexOfTableDetails < tableDetails.length;
1969         ++indexOfTableDetails) {
1970      TableDetails tempTableDetails = tableDetails[indexOfTableDetails];
1971      String JavaDoc columnName[] = columnDetail.getColumnName(); // loop invariant shud be outside the loop
1972

1973      if (columnDetail.getType() == GROUPING)
1974        return;
1975      keyArray = getDetailedColumn(columnName, tempTableDetails, columnDetail,
1976                                   serverSession); // returns the tablename concatenated with the column name
1977
if (keyArray == null)
1978        continue; // Means Not From This Table, Check For Next Table.
1979
if (columnDetail.getTableAliasArray() != null) {
1980        columnDetail.setColumn(keyArray);
1981        return;
1982      }
1983
1984
1985
1986      int key = tempTableDetails.checkForColumn(keyArray);
1987      if (key != -1) {
1988        if (check) // Column Found in Duplicate TableDetails
1989
throw new DException("DSE17",
1990                               new Object JavaDoc[] {columnDetail.getNameOfTable()}); // Column Duplicacy
1991
columnDetail.setTableDetails(tempTableDetails); // setting TableDetails in ColumnDetails
1992
columnDetail.setTableForDisplay(tempTableDetails);
1993        check = true;
1994        result[0] = columnDetail;
1995        result[1] = keyArray;
1996        result[2] = new Integer JavaDoc(tempTableDetails.getDatatype(key));
1997        result[3] = new Integer JavaDoc(tempTableDetails.getSize(key));
1998      }
1999      else if (containsClauseFlag) {
2000        if (columnDetail.getContainClauseFlag() && tableDetails.length == 1) {
2001          _FullTextIndexInformation[] fullTextIndexInfo = serverSession.
2002              getIndexTable(tempTableDetails.getQualifiedIdentifier()).
2003              getFullTextIndexInformation();
2004
2005          if (fullTextIndexInfo == null) {
2006            throw new DException("DSE8119",
2007                                 new Object JavaDoc[] {columnDetail.getColumn()});
2008          }
2009
2010          for (int i = 0; i < fullTextIndexInfo.length; i++) {
2011            if (columnDetail.getAppropriateColumn().equalsIgnoreCase(fullTextIndexInfo[i].
2012                getIndexName())) {
2013            columnDetail.setTableDetails(tempTableDetails);
2014            columnDetail.setTableForDisplay(tempTableDetails);
2015            columnDetail.setDatatype(Datatypes.VARCHAR);
2016            return;
2017          }
2018          }
2019          throw new DException("DSE8119", new Object JavaDoc[] {columnDetail.getColumn()});
2020        }
2021      }
2022    }
2023    if (!check) { // Column Not Found in All TableDetails
2024
unKnownReferences.add(columnDetail); // Column Not Found in All Tables Means Either it can be Outer Query Col or InValid Column.
2025
return;
2026    }
2027    /*Work done to check and prevent the BLOB/CLOB/IMAGE type columns in the table expression*/
2028    if (!containsClauseFlag &&
2029        ! ( ( (ColumnDetails) result[0]).ifBelongToSelectList() ||
2030        ( (ColumnDetails) result[0]).ifBelongToAllowedPredicate())) {
2031      Check.checkForAllowedDatatype(result[2].hashCode());
2032    }
2033    ( (ColumnDetails) result[0]).setColumn( (String JavaDoc[]) result[1]);
2034    ( (ColumnDetails) result[0]).setDatatype(result[2].hashCode());
2035    ( (ColumnDetails) result[0]).setSize(result[3].hashCode());
2036  }
2037
2038  /*
2039      private void checkForEachTable(_ServerSession serverSession,ColumnDetails columnDetail,TableDetails[] tableDetails,ArrayList unKnownReferences) throws com.daffodilwoods.database.resource.DException{
2040          String []keyArray;
2041          boolean check = false; // already checked
2042          Object []result = new Object[4];
2043          for(int indexOfTableDetails = 0 ; indexOfTableDetails < tableDetails.length ; ++indexOfTableDetails){
2044       TableDetails tempTableDetails = tableDetails[indexOfTableDetails];
2045              String columnName[] = columnDetail.getColumnName(); // loop invariant shud be outside the loop
2046              if ( columnDetail.getType() == GROUPING)
2047                  return;
2048              keyArray = getDetailedColumn(columnName,tempTableDetails,columnDetail,serverSession);// returns the tablename concatenated with the column name
2049              if(keyArray == null)
2050                  continue; // Means Not From This Table, Check For Next Table.
2051              if ( columnDetail.getTableAliasArray() != null ){
2052       columnDetail.setAppropriateTableName(tempTableDetails.getNameOfTable());
2053                  columnDetail.setColumn(keyArray);
2054                  return;
2055              }
2056              if(keyArray[keyArray.length - 1].equals("*")){ // for A.*
2057                  columnDetail.setColumn(keyArray);
2058                  columnDetail.setTableDetails(tempTableDetails);
2059                  columnDetail.setObject(tempTableDetails.getColumnPropertiesExcludingCommonColumns());
2060                  columnDetail.setTableForDisplay(tempTableDetails);
2061                  return;
2062              }
2063              int key = tempTableDetails.checkForColumn(keyArray);
2064              if ( key != -1 ){
2065                  if ( check ) {// Column Found in Duplicate TableDetails
2066   throw new DException("DSE17",new Object[]{columnDetail.getNameOfTable()});
2067              } // Column Duplicacy
2068       columnDetail.setAppropriateTableName(tempTableDetails.getNameOfTable());
2069                  columnDetail.setTableDetails(tempTableDetails); // setting TableDetails in ColumnDetails
2070                  columnDetail.setTableForDisplay(tempTableDetails);
2071                  check = true;
2072                  result[0] = columnDetail;
2073                  result[1] = keyArray;
2074                  result[2] = new Integer(tempTableDetails.getDatatype(key));
2075                  result[3] = new Integer(tempTableDetails.getSize(key));
2076              }
2077          }
2078          if(! check){ // Column Not Found in All TableDetails
2079              unKnownReferences.add(columnDetail); // Column Not Found in All Tables Means Either it can be Outer Query Col or InValid Column.
2080              return;
2081          }
2082          if(!(((ColumnDetails)result[0]).ifBelongToSelectList() || ((ColumnDetails)result[0]).ifBelongToAllowedPredicate())){
2083              Check.checkForAllowedDatatype(result[2].hashCode());
2084          }
2085          ((ColumnDetails)result[0]).setColumn((String[])result[1]);
2086          ((ColumnDetails)result[0]).setDatatype(result[2].hashCode());
2087          ((ColumnDetails)result[0]).setSize(result[3].hashCode());
2088      }
2089   */

2090
2091   /**
2092    * This method checks passed array of qualified column name matches to
2093    * appropriate table name of passed table. If alias name of table is present
2094    * then qualified name of column is matched to alias name of table otherwise it
2095    * is matched with original name of table. If it is matched then original name
2096    * is appended with the name of column and returned.
2097    * @param columnName
2098    * @param tableDetails
2099    * @param columnDetails
2100    * @param serverSession
2101    * @param conditionalColumns
2102    * @return String[]
2103    * @throws DException
2104    */

2105  private String JavaDoc[] getDetailedColumn(String JavaDoc columnName[],
2106                                     TableDetails tableDetails,
2107                                     ColumnDetails columnDetails,
2108                                     _ServerSession serverSession) throws
2109  DException {
2110    String JavaDoc[] appropriateTableName = tableDetails.getAppropriateTableName(); // alias name is needed for checking purpose
2111
String JavaDoc[] originalTableName = tableDetails.getTableName();
2112    if (check(appropriateTableName, columnName, tableDetails, columnDetails,
2113              serverSession))
2114      return append(originalTableName, columnName);
2115    return null;
2116  }
2117
2118  /**
2119   * Check whether the array of columnname belong to array of tablename.
2120   * Array of columnName can be at the most of length 4(catalog name,schema name,
2121   * table name,column name) and at the least of length one(column name).
2122   * Array of tableName can be at the most of length 3(catalog name,schema name,
2123   * table name) and at the least of length one(table name).
2124   * @param tableName
2125   * @param columnName
2126   * @param tableDetails
2127   * @param columnDetail
2128   * @param serverSession
2129   * @param conditionalColumns
2130   * @return boolean
2131   * @throws DException
2132   */

2133  private boolean check(String JavaDoc[] tableName, String JavaDoc[] columnName,
2134                        TableDetails tableDetails, ColumnDetails columnDetail,
2135                        _ServerSession serverSession) throws DException {
2136    for (int i = columnName.length - 2, j = tableName.length - 1,
2137         length = columnName.length; i >= 0 && j >= 0; i--, j--) {
2138      if (!tableName[j].equalsIgnoreCase(columnName[i])) {
2139        if (length - 2 != 0 && i == length - 2 && j == tableName.length - 1) {
2140          String JavaDoc aliasName = tableDetails.getAliasName();
2141          if (aliasName != null && aliasName.equalsIgnoreCase(columnName[0])) {
2142            checkForeignKeyCC(tableDetails, columnDetail, serverSession,
2143                              columnName);
2144
2145            return true;
2146          }
2147        }
2148
2149        return false;
2150      }
2151    }
2152
2153    return true;
2154  }
2155
2156  /**
2157   * Check for characterstics of Foreign key. Needed in chained column work.
2158   * @param tableDetails
2159   * @param columnDetail
2160   * @param serverSession
2161   * @param columnName
2162   * @param conditionalColumns
2163   * @throws DException
2164   */

2165  private void checkForeignKeyCC(TableDetails tableDetails,
2166                                 ColumnDetails columnDetail,
2167                                 _ServerSession serverSession,
2168                                 String JavaDoc[] columnName) throws DException {
2169    int length = columnName.length;
2170    QualifiedIdentifier identifier = tableDetails.getQualifiedIdentifier();
2171    String JavaDoc[] tableAliasArray = new String JavaDoc[length - 2];
2172    _ColumnCharacteristics columnCharacteristics = serverSession.
2173        getColumnCharacteristics(identifier);
2174    ArrayList JavaDoc listOfFKeyTables = new ArrayList JavaDoc();
2175    TableDetails tempTable = tableDetails;
2176    int serverType = serverSession.getType();
2177
2178    for (int i = 1, j = 0; i < length - 1; i++, j++) {
2179      if (!ifExistsColumnInCC(columnName[i],
2180                              columnCharacteristics.getColumnNames()))
2181      throw new DException("DSE3557", new Object JavaDoc[] {columnName[i], identifier}); // Column Not Present
2182
Object JavaDoc[] object = serverSession.getForeignConstraintCharacteritics(
2183        identifier, columnName[i]);
2184
2185    if (serverType == IteratorConstants.UPDATABLE) {
2186      identifier = (QualifiedIdentifier) object[0];
2187      columnCharacteristics = (_ColumnCharacteristics) object[1];
2188
2189      TableDetails table = new TableDetails();
2190      table.setTableName(identifier.getTableName());
2191      table.cc = columnCharacteristics;
2192      listOfFKeyTables.add(table);
2193
2194      tempTable = table;
2195      String JavaDoc[] referencedColumns = (String JavaDoc[]) object[2];
2196    }
2197    tableAliasArray[j] = columnName[i];
2198    }
2199    columnDetail.setTableAliasArray(tableAliasArray);
2200    tableDetails.setUnderLyingFKeyTables( (TableDetails[]) listOfFKeyTables.
2201        toArray(new TableDetails[
2202        listOfFKeyTables.size()]));
2203    if (columnName[length - 1].equalsIgnoreCase("*"))
2204      initializeAllColumnsOfForeign(columnDetail, columnCharacteristics,
2205                                    tableDetails, tableAliasArray);
2206    else {
2207      if (!ifExistsColumnInCC(columnName[length - 1],
2208                              columnCharacteristics.getColumnNames()))
2209        throw new DException("DSE3557", new Object JavaDoc[] {columnName[length - 1],
2210      identifier}); // Column Not Present
2211
columnDetail.setDatatype(columnCharacteristics.getColumnType(
2212            columnCharacteristics.getColumnIndex(columnName[length - 1])));
2213        columnDetail.setSize(columnCharacteristics.getSize(columnCharacteristics.
2214            getColumnIndex(columnName[length - 1])));
2215        columnDetail.setTableDetails(tableDetails);
2216        columnDetail.setQualifiedIdentifier(new QualifiedIdentifier(
2217            columnCharacteristics.getCatalogName(0),
2218            columnCharacteristics.getSchemaName(0),
2219            columnCharacteristics.getTableName(0)));
2220        columnDetail.setChainedColumnCC(columnCharacteristics);
2221    }
2222  }
2223
2224  /**
2225   * Needed in chained column work.
2226   * @param columnDetail
2227   * @param columnCharacteristics
2228   * @param table
2229   * @param tableAliasArray
2230   * @throws DException
2231   */

2232  private void initializeAllColumnsOfForeign(ColumnDetails columnDetail,
2233      _ColumnCharacteristics
2234      columnCharacteristics,
2235      TableDetails table,
2236      String JavaDoc[] tableAliasArray) throws
2237  DException {
2238    String JavaDoc[] ccColumnNames = columnCharacteristics.getColumnNames();
2239    int length = ccColumnNames.length;
2240    QualifiedIdentifier identifier = new QualifiedIdentifier(
2241        columnCharacteristics.getCatalogName(0),
2242        columnCharacteristics.getSchemaName(0),
2243        columnCharacteristics.getTableName(0));
2244    ColumnDetails[] newColumns = new ColumnDetails[length - 5];
2245    for (int i = 5, j = 0; i < length; i++, j++) {
2246      ColumnDetails columnDetails = new ColumnDetails();
2247      String JavaDoc[] tableName = table.getTableName();
2248      String JavaDoc[] column = new String JavaDoc[4];
2249      System.arraycopy(tableName, 0, column, 0, tableName.length);
2250      column[3] = ccColumnNames[i];
2251      columnDetails.setColumn(column);
2252      columnDetails.setChainedColumnCC(columnCharacteristics);
2253      columnDetails.setDatatype(columnCharacteristics.getColumnType(i));
2254      columnDetails.setSize(columnCharacteristics.getSize(i));
2255      columnDetails.setTableDetails(table);
2256      columnDetails.setTableForDisplay(table);
2257      columnDetails.setType(REFERENCE);
2258
2259      columnDetails.setTableAliasArray(tableAliasArray);
2260      columnDetails.setQualifiedIdentifier(identifier);
2261      newColumns[j] = columnDetails;
2262    }
2263    columnDetail.setObject(newColumns);
2264    columnDetail.setTableDetails(table);
2265  }
2266
2267  /**
2268   * This method is used to check whether passed column belongs to passed array
2269   * of columns.
2270   * @param columnName
2271   * @param columns
2272   * @return boolean
2273   */

2274
2275  private boolean ifExistsColumnInCC(String JavaDoc columnName, String JavaDoc[] columns) {
2276    int length = columns.length;
2277    for (int i = 0; i < length; i++) {
2278      if (columns[i].equalsIgnoreCase(columnName))
2279        return true;
2280    }
2281    return false;
2282  }
2283
2284  /**
2285   * This method is used to append the last element of column name with passed
2286   * table name.
2287   * @param tableName
2288   * @param columnName
2289   * @return
2290   * @throws DException
2291   */

2292  private String JavaDoc[] append(String JavaDoc[] tableName, String JavaDoc[] columnName) throws
2293  DException {
2294    String JavaDoc[] result = new String JavaDoc[tableName.length + 1];
2295    System.arraycopy(tableName, 0, result, 0, tableName.length);
2296    result[result.length - 1] = columnName[columnName.length - 1];
2297    return result;
2298  }
2299
2300  /**
2301   * This method is used to obtain the mapping of hasRecord column and its
2302   * corresponding table.
2303   * @return
2304   * @throws DException
2305   */

2306  public Object JavaDoc[][] getHasRecordMapping() throws DException {
2307    Object JavaDoc[][] hasRecordMapping = null;
2308    for (int i = 0, length = userDefinedColumnDetails.length; i < length; i++) {
2309      ColumnDetails ud = userDefinedColumnDetails[i];
2310      if (userDefinedColumnDetails[i].getType() == HAS_RECORD) {
2311        if (hasRecordMapping == null) {
2312          hasRecordMapping = new Object JavaDoc[1][2];
2313          hasRecordMapping[0][0] = userDefinedColumnDetails[i].getTable();
2314          ArrayList JavaDoc list = new ArrayList JavaDoc();
2315          list.add(ud);
2316          hasRecordMapping[0][1] = list;
2317          continue;
2318        }
2319        int index = searchInMapping(ud.getTable(), hasRecordMapping);
2320        if (index == -1) {
2321          hasRecordMapping = makeAnEntry(ud, hasRecordMapping);
2322          continue;
2323        }
2324        ArrayList JavaDoc columns = (ArrayList JavaDoc) hasRecordMapping[index][1];
2325        columns.add(ud);
2326      }
2327    }
2328    return hasRecordMapping;
2329  }
2330
2331  /**
2332   * This method is used to check whether any hasRecord column is present on
2333   * passed table using hasRecordMapping.
2334   * @param table
2335   * @param hasRecordMapping
2336   * @return int
2337   * @throws DException
2338   */

2339  private int searchInMapping(TableDetails table, Object JavaDoc[][] hasRecordMapping) throws
2340  DException {
2341    for (int i = 0, length = hasRecordMapping.length; i < length; i++) {
2342      if (hasRecordMapping[i][0] == table)
2343        return i;
2344    }
2345    return -1;
2346  }
2347
2348  /**
2349   * This method is used to add one entry of hasRecord column and its table in
2350   * passed hasRecordMapping.
2351   * @param column
2352   * @param hasRecordMapping
2353   * @return Object[][]
2354   * @throws DException
2355   */

2356  private Object JavaDoc[][] makeAnEntry(ColumnDetails column,
2357                                 Object JavaDoc[][] hasRecordMapping) throws DException {
2358    int length = hasRecordMapping.length;
2359    Object JavaDoc[][] newMapping = new Object JavaDoc[length + 1][2];
2360    System.arraycopy(hasRecordMapping, 0, newMapping, 0, length);
2361    newMapping[length][0] = column.getTable();
2362    ArrayList JavaDoc list = new ArrayList JavaDoc();
2363    list.add(column);
2364    newMapping[length][1] = list;
2365    return newMapping;
2366  }
2367
2368  /**
2369   * This method is used to perform semantic checking of 'update' query.
2370   * It does the semantic checking of tables and columns of where clause present
2371   * in the 'update' query.
2372   * @param serverSession
2373   * @param listOfUnderLyingReferences
2374   * @throws DException
2375   */

2376  public void semanticCheckingUpdate(_ServerSession serverSession0,
2377                                     ArrayList JavaDoc listOfUnderLyingReferences) throws
2378  DException {
2379    serverSession = serverSession0;
2380    SetColumnProperties.checkingForAmbuityForTableNamesWithCC(serverSession,
2381        tableDetails); // Table Ambiguity
2382
SetColumnProperties.setTableNamesAndDatatypesOfAllColumns(serverSession,
2383        whereClauseColumnDetails, tableDetails, listOfUnderLyingReferences,
2384        new ArrayList JavaDoc());
2385  }
2386
2387  /**
2388   * In case of Distinct we need cloned columns so as if view is present then
2389   * the order columns will be shifted below view and selected columns will be
2390   * solved above view.
2391   * @return
2392   */

2393
2394  public ColumnDetails[] getAppropriateUserDefinedColumns() {
2395    return clonedUserDefinedColumnDetails == null ? userDefinedColumnDetails :
2396        clonedUserDefinedColumnDetails;
2397  }
2398
2399  /**
2400   * This method is used to mark that 'Distinct' present in select query is
2401   * redundant. 'Distinct' is redundant in following two cases -
2402   * i)- the columns in the select list are also present in the group by clause
2403   * ii)- the columns in the select list form the primary key.
2404   */

2405
2406  public void setDistinctRedundant() {
2407    isDistinct = false;
2408    clonedUserDefinedColumnDetails = null;
2409  }
2410
2411  /* Method Written by Kaushik on 27/07/2004 for some failed test cases in TestAggregateForDataTypes */
2412  public void setDatatypeOfConstantColunmsInSelectList(ColumnDetails[] cd,
2413      _ServerSession session) throws DException {
2414    VariableValues vv = new VariableValues(session);
2415    /*DST by Sandeep to solve bug :12158*/
2416      if(cd==null) return ;
2417      for (int i = 0; i < cd.length; i++) {
2418        int type=cd[i].getType();
2419    if(type==SCALARFUNCTION || type==CASEEXPRESSION || type==FUNCTIONAL || type==USERFUNCTION)
2420      setDatatypeOfConstantColunmsInSelectList(cd[i].getChildColumnDetails(),session);
2421     else if(type==GROUPING){
2422
2423        ColumnDetails[] cdChild = cd[i].getChildColumnDetails();
2424        for (int j = 0; j < cdChild.length; j++) {
2425          if (cdChild[j].getType() == CONSTANT && !cdChild[j].getQuestion() &&
2426              ! (cdChild[j].getTypeForSequence() == SEQUENCETYPE)) {
2427          ( (FieldBase) cdChild[j].run(vv)).setDatatype( -1);
2428        }
2429        }
2430      }
2431    }
2432  }
2433
2434  public void checkOrderByDistinctSemantic(ColumnDetails[] orderCD,
2435      ColumnDetails[] cd2) throws
2436  DException {
2437
2438    if (isDistinct && orderCD != null) {
2439      boolean c = false;
2440      for (int i = 0; i < orderCD.length; i++) {
2441        c = false;
2442        for (int j = 0; j < cd2.length; j++) {
2443          if (orderCD[i].getType() == TypeConstants.CONSTANT ||
2444        ((orderCD[i].getAppropriateColumn().equalsIgnoreCase(cd2[j].
2445    getAppropriateColumn()) ||( orderCD[i].getColumn().equalsIgnoreCase(cd2[j].getColumn())))
2446              &&
2447              (orderCD[i].getTable() == null ||
2448              orderCD[i].getTable() == cd2[j].getTable()))) {
2449          c = true;
2450        }
2451        }
2452        if (!c) {
2453          throw new DException("DSE6006", null);
2454        }
2455      }
2456    }
2457  /*Done by vibha.
2458    This method is commented here and added in execute methods of
2459   QuerySpecificationPlan. Removed from here because datatype of
2460   userDefinedColumnDetails is called but problem in case of outer refernce is
2461   used in inner query . For bug no - 12682 */

2462  }
2463
2464  /* Method written by kaushik on 17/08/2004 for SemanticChecking CLOB,BLOB type cols in Distinct, Bug no. 11487*/
2465  public void checkSelectListDistinctSemantic() throws DException {
2466    if (isDistinct) {
2467      for (int i = 0; i < userDefinedColumnDetails.length; i++) {
2468        if (userDefinedColumnDetails[i].getDatatype() == Datatypes.CLOB ||
2469            userDefinedColumnDetails[i].getDatatype() == Datatypes.BLOB) {
2470              throw new DException("DSE6001",
2471              new Object JavaDoc[] {StaticClass.
2472              getDataTypeName(userDefinedColumnDetails[i].
2473                              getDatatype())});
2474      }
2475      }
2476    }
2477  }
2478
2479  /**public void checkForPrivileges(_ServerSession session,
2480                                     ColumnDetails[] queryColumns) throws
2481          DException {
2482        ArrayList columns = new ArrayList();
2483        boolean foraestrik = false;
2484        if (session.getTypeForPrivilige() == session.serverSession) {
2485          boolean fetchRight = false;
2486          if (tableDetails != null) {
2487            _PrivilegeCharacteristics privChar = session.getUserSession().
2488                getPrivilegeCharacteristics();
2489            for (int i = 0; i < tableDetails.length; i++) {
2490              _ColumnCharacteristics cc = tableDetails[i].
2491                  getColumnCharacteristics();
2492              privileges = privChar.getPrivilegeTable(tableDetails[i].
2493   getQualifiedIdentifier());
2494              for (int j = 0; j < queryColumns.length; j++) {
2495                if (queryColumns[j].getAppropriateColumn().indexOf("*") >0) {
2496                  foraestrik = true;
2497                  break;
2498                }
2499                if (!foraestrik) {
2500   if (queryColumns[j].getTableDetails().getQualifiedIdentifier().
2501                      equals(queryColumns[j].getTableDetails().
2502                             getQualifiedIdentifier())) {
2503                    columns.add(queryColumns[j]);
2504                  }
2505                }
2506                int[] indexes = new int[columns.size()];
2507                ColumnDetails[] cd = (ColumnDetails[]) columns.toArray(new
2508                    ColumnDetails[0]);
2509                for (int k = 0; k < cd.length; k++)
2510                  indexes[k] = cc.getColumnIndex(cd[k].getAppropriateColumn());
2511         fetchRight = privileges.hasColumnPrivileges(_PrivilegeTable.SELECT,
2512                    indexes);
2513                if (!fetchRight) {
2514                  throw new DException("DSE8132", null);
2515                }
2516              }
2517              if (foraestrik) {
2518                int[] indexes = new int[queryColumns.length];
2519                for (int m = 0; m < queryColumns.length; m++) {
2520                  setCount(session, tableDetails, queryColumns[m]);
2521                }
2522                for (int m = 0; m < queryColumns.length; m++) {
2523                  ColumnDetails cd[] = {
2524                      queryColumns[m]};
2525   if (queryColumns[m].getAppropriateColumn().indexOf("*") >= 0) {
2526                    cd = (ColumnDetails[]) queryColumns[m].getObject();
2527                  }
2528                  for (int k = 0; k < cd.length; k++) {
2529   indexes[m] = cc.getColumnIndex(cd[k].getAppropriateColumn());
2530                  }
2531                  fetchRight = privileges.hasColumnPrivileges(_PrivilegeTable.
2532                      SELECT, indexes);
2533                }
2534                if (!fetchRight) {
2535                  throw new DException("DSE8132", null);
2536                }
2537              }
2538            }
2539          }
2540        }
2541      }
2542      **/

2543  /*Done by vibha on 16-09-2004 */
2544  /* questionmark and sequence is not allwed in order by clause*/
2545  private static void checkForQuestion(ColumnDetails[] cd) throws DException {
2546    for (int i = 0; i < cd.length; i++) {
2547      int type = cd[i].getType();
2548      if (cd[i].getQuestion())
2549        throw new DException("DSE3528", null);
2550      if (cd[i].getTypeForSequence() == SEQUENCETYPE)
2551        throw new DException("DSE6013", null);
2552      if ( ( (type == CASEEXPRESSION || type == FUNCTIONAL ||
2553              type == SCALARFUNCTION
2554              || type == GROUPING || type == USERFUNCTION))) {
2555        ColumnDetails[] cd1 = cd[i].getChildColumnDetails();
2556        for (int j = 0; j < cd1.length; j++) {
2557          checkForQuestion(cd1);
2558
2559        }
2560      }
2561    }
2562  }
2563
2564  private static void checkingForSequence(ColumnDetails[] cd) throws DException {
2565    for (int i = 0; i < cd.length; i++) {
2566      int type = cd[i].getType();
2567      if (cd[i].getTypeForSequence() == SEQUENCETYPE)
2568        throw new DException("DSE6013", null);
2569      if ( ( (type == CASEEXPRESSION || type == FUNCTIONAL ||
2570              type == SCALARFUNCTION
2571              || type == GROUPING || type == USERFUNCTION))) {
2572        ColumnDetails[] cd1 = cd[i].getChildColumnDetails();
2573        for (int j = 0; j < cd1.length; j++) {
2574          checkingForSequence(cd1);
2575
2576        }
2577      }
2578    }
2579  }
2580
2581  /*Done by vibha to check for duplicate order
2582     Like::
2583   select col1 from tablename order by col1,1
2584   */

2585  private void checkForDuplicateOrderColumnAndPositionSemantic(
2586      ColumnDetails[] cd) throws DException {
2587    /*Done by Sandeep to Solve bug --11985 And handle NPE in the cases like
2588           Select *,col FROM tbl order by 1 ;
2589           */

2590
2591    for (int i = 0; i < cd.length; i++) {
2592      int value = 0;
2593      if(selectListColumnDetails[i].getType()==CONSTANT && selectListColumnDetails[i].getAppropriateColumn().equalsIgnoreCase("*") )
2594        continue; /*dend */
2595      Integer JavaDoc obj = getOrdinalNoValue(cd[i]);
2596      if (obj == null)
2597        continue;
2598      value = obj.intValue();
2599      int j = value - 1;
2600      for (int k = 0; k < cd.length; k++) {
2601        if (selectListColumnDetails[j].getAppropriateColumn().equals(cd[k].
2602            getAppropriateColumn())) {
2603        throw new DException("DSE3541", null);
2604
2605      }
2606      }
2607    }
2608
2609  }
2610
2611  /* Sequence not allowed in order by caluse.
2612   eg- select seq.nextval from tablename order by 1 is not allowed.
2613   */

2614  private void checkForOrderColumnSemantic(
2615      ColumnDetails[] cd) throws DException {
2616/*DST Done by Sandeep to Solve bug --11985 And handle NPE in the cases like
2617       Select *,col FROM tbl order by 1 ;
2618       */

2619    for (int i = 0; i < cd.length; i++) {
2620      if(selectListColumnDetails[i].getType()==CONSTANT && selectListColumnDetails[i].getAppropriateColumn().equalsIgnoreCase("*"))
2621        continue; /*Dend*/
2622      int value = 0;
2623      Integer JavaDoc obj = getOrdinalNoValue(cd[i]);
2624      if (obj == null)
2625        continue;
2626      value = obj.intValue();
2627      int j = value - 1;
2628      for (int k = 0; k < cd.length; k++) {
2629        checkForQuestion(new ColumnDetails[] {selectListColumnDetails[j]});
2630      }
2631    }
2632  }
2633  /*Done by Sandeep Kadiyan to check like
2634   Select * from tbl where ((contains(FTI,"value")) or col1=3;
2635   */

2636
2637  private void checkForOneBooleanExpressionWhenContainsClauseIsPresent() throws
2638  DException {
2639    if (whereClauseColumnDetails.length > 1)
2640      throw new DException("DSE0", new Object JavaDoc[] {"Boolean expression can't be specified in where clause when Contains clause is present"});
2641  }
2642  private static void checkingForsubqueryInGroupByClause(ColumnDetails[] cd) throws DException {
2643    if(cd.length == 0){
2644      throw new DException("DSE6014",null);
2645    }
2646   for (int i = 0; i < cd.length; i++) {
2647   int type = cd[i].getType();
2648      if ( ( (type == CASEEXPRESSION || type == FUNCTIONAL
2649       || type == GROUPING || type == USERFUNCTION))) {
2650        throw new DException("DSE6015",new Object JavaDoc[]{cd[i].getColumn()});//Done by Sandeep to solve bug--13036
2651
}
2652      ColumnDetails[] cd1 ;
2653      if(type == SCALARFUNCTION){
2654        cd1 = cd[i].getChildColumnDetails();
2655        checkingForsubqueryInGroupByClause(cd1);
2656      }
2657    }
2658  }
2659
2660  private void checkForScalarSubQueryInSelectList(_ServerSession serverSession0) throws
2661      DException {
2662    selectsublist[] selectsublist = selectList._OptRepScomma94843605selectsublist0;
2663    for (int i = 0; i < selectsublist.length; i++) {
2664      if (selectsublist[i].getColumnDetails().length == 0) {
2665        if ( ( (derivedcolumn) selectsublist[i])._valueexpression1.
2666            checkForSubQuery()) {
2667          ( (derivedcolumn) selectsublist[i])._valueexpression1.checkSemantic(
2668              serverSession0);
2669
2670        }
2671      }
2672      ColumnDetails[] cd1 = selectsublist[i].getColumnDetails();
2673      setTemp(cd1,selectsublist[i],serverSession0);
2674      }
2675
2676    }
2677
2678  void setTemp(ColumnDetails[] cd1,selectsublist selectsublist1 ,_ServerSession serverSession0) throws DException {
2679    for (int j = 0; j < cd1.length; j++) {
2680      if (cd1[j].getType() == USERFUNCTION) {
2681        ( (derivedcolumn) selectsublist1)._valueexpression1.checkSemantic(
2682            serverSession0);
2683      }
2684      if (cd1[j].getType() == FUNCTIONAL ) {
2685      ColumnDetails[] cdChild = cd1[j].getChildColumnDetails();
2686     setTemp(cdChild,selectsublist1,serverSession0);
2687    }
2688    }
2689  }
2690
2691}
2692
Popular Tags