1 /* Copyright (c) 2001-2015, The HSQL Development Group
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * Redistributions of source code must retain the above copyright notice, this
8  * list of conditions and the following disclaimer.
9  *
10  * Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13  *
14  * Neither the name of the HSQL Development Group nor the names of its
15  * contributors may be used to endorse or promote products derived from this
16  * software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
22  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 
32 package org.hsqldb;
33 
34 import org.hsqldb.HsqlNameManager.HsqlName;
35 import org.hsqldb.error.Error;
36 import org.hsqldb.error.ErrorCode;
37 import org.hsqldb.lib.HashMappedList;
38 import org.hsqldb.lib.HashSet;
39 import org.hsqldb.lib.OrderedHashSet;
40 import org.hsqldb.lib.OrderedIntHashSet;
41 import org.hsqldb.result.Result;
42 import org.hsqldb.result.ResultConstants;
43 import org.hsqldb.types.Type;
44 
45 /**
46  * Implementation of Statement for PSM compound statements.
47 
48  * @author Fred Toussi (fredt@users dot sourceforge.net)
49  * @version 2.3.3
50  * @since 1.9.0
51  */
52 public class StatementCompound extends Statement implements RangeGroup {
53 
54     final boolean       isLoop;
55     HsqlName            label;
56     StatementHandler[]  handlers = StatementHandler.emptyExceptionHandlerArray;
57     boolean             hasUndoHandler;
58     StatementQuery      loopCursor;
59     Statement[]         statements;
60     StatementExpression condition;
61     boolean             isAtomic;
62 
63     //
64     ColumnSchema[]    variables      = ColumnSchema.emptyArray;
65     StatementCursor[] cursors        = StatementCursor.emptyArray;
66     HashMappedList    scopeVariables = new HashMappedList();
67     RangeVariable[]   rangeVariables = RangeVariable.emptyArray;
68     Table[]           tables         = Table.emptyArray;
69     HashMappedList    scopeTables;
70 
71     //
72     int variablesOffset;
73 
74     //
75     public static final StatementCompound[] emptyStatementArray =
76         new StatementCompound[]{};
77 
StatementCompound(int type, HsqlName label, StatementCompound parent)78     StatementCompound(int type, HsqlName label, StatementCompound parent) {
79 
80         super(type, StatementTypes.X_SQL_CONTROL);
81 
82         this.label             = label;
83         isTransactionStatement = false;
84 
85         switch (type) {
86 
87             case StatementTypes.FOR :
88             case StatementTypes.LOOP :
89             case StatementTypes.WHILE :
90             case StatementTypes.REPEAT :
91                 isLoop = true;
92                 break;
93 
94             case StatementTypes.BEGIN_END :
95             case StatementTypes.IF :
96                 isLoop = false;
97                 break;
98 
99             default :
100                 throw Error.runtimeError(ErrorCode.U_S0500,
101                                          "StatementCompound");
102         }
103 
104         this.parent = parent;
105     }
106 
getSQL()107     public String getSQL() {
108 
109 /*
110         StringBuffer sb = new StringBuffer();
111 
112         if (label != null) {
113             sb.append(label.getStatementName()).append(':').append(' ');
114         }
115 
116         switch (type) {
117             case StatementTypes.FOR :
118                 // todo
119                 break;
120 
121             case StatementTypes.LOOP :
122                 sb.append(Tokens.T_LOOP).append(' ');
123 
124                 for (int i = 0; i < statements.length; i++) {
125                     sb.append(statements[i].getSQL()).append(';');
126                 }
127 
128                 sb.append(Tokens.T_END).append(' ').append(Tokens.T_LOOP);
129                 break;
130 
131             case StatementTypes.WHILE :
132                 sb.append(Tokens.T_WHILE).append(' ');
133                 sb.append(condition.getSQL()).append(' ').append(Tokens.T_DO);
134                 sb.append(' ');
135 
136                 for (int i = 0; i < statements.length; i++) {
137                     sb.append(statements[i].getSQL()).append(';');
138                 }
139 
140                 sb.append(Tokens.T_END).append(' ').append(Tokens.T_WHILE);
141                 break;
142 
143             case StatementTypes.REPEAT :
144                 sb.append(Tokens.T_REPEAT).append(' ');
145 
146                 for (int i = 0; i < statements.length; i++) {
147                     sb.append(statements[i].getSQL()).append(';');
148                 }
149 
150                 sb.append(Tokens.T_UNTIL).append(' ');
151                 sb.append(condition.getSQL()).append(' ');
152                 sb.append(Tokens.T_END).append(' ').append(Tokens.T_REPEAT);
153                 break;
154 
155             case StatementTypes.BEGIN_END :
156                 sb.append(Tokens.T_BEGIN).append(' ').append(Tokens.T_ATOMIC);
157                 sb.append(' ');
158 
159                 for (int i = 0; i < handlers.length; i++) {
160                     sb.append(handlers[i].getSQL()).append(';');
161                 }
162 
163                 for (int i = 0; i < variables.length; i++) {
164                     sb.append(Tokens.T_DECLARE).append(' ');
165                     sb.append(variables[i].getSQL());
166 
167                     if (variables[i].hasDefault()) {
168                         sb.append(' ').append(Tokens.T_DEFAULT).append(' ');
169                         sb.append(variables[i].getDefaultSQL());
170                     }
171 
172                     sb.append(';');
173                 }
174 
175                 for (int i = 0; i < statements.length; i++) {
176                     sb.append(statements[i].getSQL()).append(';');
177                 }
178 
179                 sb.append(Tokens.T_END);
180                 break;
181 
182             case StatementTypes.IF :
183                 for (int i = 0; i < statements.length; i++) {
184                     if (statements[i].type == StatementTypes.CONDITION) {
185                         if (i != 0) {
186                             sb.append(Tokens.T_ELSE).append(' ');
187                         }
188 
189                         sb.append(Tokens.T_IF).append(' ');
190                         sb.append(statements[i].getSQL()).append(' ');
191                         sb.append(Tokens.T_THEN).append(' ');
192                     } else {
193                         sb.append(statements[i].getSQL()).append(';');
194                     }
195                 }
196 
197                 sb.append(Tokens.T_END).append(' ').append(Tokens.T_IF);
198                 break;
199         }
200 
201         return sb.toString();
202 */
203         return sql;
204     }
205 
describe(Session session, int blanks)206     String describe(Session session, int blanks) {
207 
208         StringBuffer sb = new StringBuffer();
209 
210         sb.append('\n');
211 
212         for (int i = 0; i < blanks; i++) {
213             sb.append(' ');
214         }
215 
216         sb.append(Tokens.T_STATEMENT);
217 
218         return sb.toString();
219     }
220 
isLoop()221     boolean isLoop() {
222         return isLoop;
223     }
224 
setLocalDeclarations(Object[] declarations)225     void setLocalDeclarations(Object[] declarations) {
226 
227         int varCount     = 0;
228         int handlerCount = 0;
229         int cursorCount  = 0;
230         int tableCount   = 0;
231 
232         for (int i = 0; i < declarations.length; i++) {
233             if (declarations[i] instanceof ColumnSchema) {
234                 varCount++;
235             } else if (declarations[i] instanceof StatementHandler) {
236                 handlerCount++;
237             } else if (declarations[i] instanceof Table) {
238                 tableCount++;
239             } else {
240                 cursorCount++;
241             }
242         }
243 
244         if (varCount > 0) {
245             variables = new ColumnSchema[varCount];
246         }
247 
248         if (handlerCount > 0) {
249             handlers = new StatementHandler[handlerCount];
250         }
251 
252         if (tableCount > 0) {
253             tables = new Table[tableCount];
254         }
255 
256         if (cursorCount > 0) {
257             cursors = new StatementCursor[cursorCount];
258         }
259 
260         varCount     = 0;
261         handlerCount = 0;
262         tableCount   = 0;
263         cursorCount  = 0;
264 
265         for (int i = 0; i < declarations.length; i++) {
266             if (declarations[i] instanceof ColumnSchema) {
267                 variables[varCount++] = (ColumnSchema) declarations[i];
268             } else if (declarations[i] instanceof StatementHandler) {
269                 StatementHandler handler = (StatementHandler) declarations[i];
270 
271                 handler.setParent(this);
272 
273                 handlers[handlerCount++] = handler;
274 
275                 if (handler.handlerType == StatementHandler.UNDO) {
276                     hasUndoHandler = true;
277                 }
278             } else if (declarations[i] instanceof Table) {
279                 Table table = (Table) declarations[i];
280 
281                 tables[tableCount++] = table;
282             } else {
283                 StatementCursor cursor = (StatementCursor) declarations[i];
284 
285                 cursors[cursorCount++] = cursor;
286             }
287         }
288 
289         setVariables();
290         setHandlers();
291         setTables();
292         setCursors();
293     }
294 
setLoopStatement(HsqlName name, StatementQuery cursorStatement)295     void setLoopStatement(HsqlName name, StatementQuery cursorStatement) {
296 
297         loopCursor = cursorStatement;
298 
299         HsqlName[] colNames =
300             cursorStatement.queryExpression.getResultColumnNames();
301         Type[] colTypes = cursorStatement.queryExpression.getColumnTypes();
302         ColumnSchema[] columns = new ColumnSchema[colNames.length];
303 
304         for (int i = 0; i < colNames.length; i++) {
305             columns[i] = new ColumnSchema(colNames[i], colTypes[i], false,
306                                           false, null);
307 
308             columns[i].setParameterMode(SchemaObject.ParameterModes.PARAM_IN);
309         }
310 
311         setLocalDeclarations(columns);
312     }
313 
setStatements(Statement[] statements)314     void setStatements(Statement[] statements) {
315 
316         for (int i = 0; i < statements.length; i++) {
317             statements[i].setParent(this);
318         }
319 
320         this.statements = statements;
321     }
322 
setCondition(StatementExpression condition)323     void setCondition(StatementExpression condition) {
324         this.condition = condition;
325     }
326 
execute(Session session)327     public Result execute(Session session) {
328 
329         Result result;
330 
331         switch (type) {
332 
333             case StatementTypes.BEGIN_END : {
334                 initialiseVariables(session);
335 
336                 result = executeBlock(session);
337 
338                 break;
339             }
340             case StatementTypes.FOR :
341                 result = executeForLoop(session);
342                 break;
343 
344             case StatementTypes.LOOP :
345             case StatementTypes.WHILE :
346             case StatementTypes.REPEAT : {
347                 result = executeLoop(session);
348 
349                 break;
350             }
351             case StatementTypes.IF : {
352                 result = executeIf(session);
353 
354                 break;
355             }
356             default :
357                 throw Error.runtimeError(ErrorCode.U_S0500,
358                                          "StatementCompound");
359         }
360 
361         if (result.isError()) {
362             result.getException().setStatementType(group, type);
363         }
364 
365         return result;
366     }
367 
executeBlock(Session session)368     private Result executeBlock(Session session) {
369 
370         Result  result = Result.updateZeroResult;
371         boolean push   = !root.isTrigger();
372 
373         if (push) {
374             session.sessionContext.push();
375 
376             if (hasUndoHandler) {
377                 String name = HsqlNameManager.getAutoSavepointNameString(
378                     session.actionTimestamp, session.sessionContext.depth);
379 
380                 session.savepoint(name);
381             }
382         }
383 
384         for (int i = 0; i < statements.length; i++) {
385             result = executeProtected(session, statements[i]);
386             result = handleCondition(session, result);
387 
388             if (result.isError()) {
389                 break;
390             }
391 
392             if (result.getType() == ResultConstants.VALUE) {
393                 break;
394             }
395 
396             if (result.getType() == ResultConstants.DATA) {
397                 break;
398             }
399         }
400 
401         if (result.getType() == ResultConstants.VALUE) {
402             if (result.getErrorCode() == StatementTypes.LEAVE) {
403                 if (result.getMainString() == null) {
404                     result = Result.updateZeroResult;
405                 } else if (label != null
406                            && label.name.equals(result.getMainString())) {
407                     result = Result.updateZeroResult;
408                 }
409             }
410         }
411 
412         if (push) {
413             session.sessionContext.pop();
414         }
415 
416         return result;
417     }
418 
handleCondition(Session session, Result result)419     private Result handleCondition(Session session, Result result) {
420 
421         String sqlState = null;
422 
423         if (result.isError()) {
424             sqlState = result.getSubString();
425         } else if (session.getLastWarning() != null) {
426             sqlState = session.getLastWarning().getSQLState();
427         } else {
428             return result;
429         }
430 
431         if (sqlState != null) {
432             for (int i = 0; i < handlers.length; i++) {
433                 StatementHandler handler = handlers[i];
434 
435                 session.clearWarnings();
436 
437                 /**
438                  * @todo - if condition is "transaction rollback" promote to
439                  * top call level without any further action
440                  * if condition is system related promote to top level
441                  * schema manipulation conditions are never handled
442                  */
443                 if (handler.handlesCondition(sqlState)) {
444                     String labelString = label == null ? null
445                                                        : label.name;
446 
447                     switch (handler.handlerType) {
448 
449                         case StatementHandler.CONTINUE :
450                             result = Result.updateZeroResult;
451                             break;
452 
453                         case StatementHandler.UNDO :
454                             session.rollbackToSavepoint();
455 
456                             result = Result.newPSMResult(StatementTypes.LEAVE,
457                                                          labelString, null);
458                             break;
459 
460                         case StatementHandler.EXIT :
461                             result = Result.newPSMResult(StatementTypes.LEAVE,
462                                                          labelString, null);
463                             break;
464                     }
465 
466                     Result actionResult = executeProtected(session, handler);
467 
468                     if (actionResult.isError()) {
469                         result = actionResult;
470 
471                         // parent should handle this
472                     } else if (actionResult.getType()
473                                == ResultConstants.VALUE) {
474                         result = actionResult;
475                     }
476                 }
477             }
478 
479             if (result.isError() && parent != null) {
480 
481                 // unhandled exception condition
482                 return parent.handleCondition(session, result);
483             }
484         }
485 
486         return result;
487     }
488 
executeForLoop(Session session)489     private Result executeForLoop(Session session) {
490 
491         Result queryResult = loopCursor.execute(session);
492 
493         if (queryResult.isError()) {
494             return queryResult;
495         }
496 
497         Result result = Result.updateZeroResult;
498 
499         while (queryResult.navigator.hasNext()) {
500             queryResult.navigator.next();
501 
502             Object[] data = queryResult.navigator.getCurrent();
503 
504             initialiseVariables(session, data,
505                                 queryResult.metaData.getColumnCount());
506 
507             for (int i = 0; i < statements.length; i++) {
508                 result = executeProtected(session, statements[i]);
509                 result = handleCondition(session, result);
510 
511                 if (result.isError()) {
512                     break;
513                 }
514 
515                 if (result.getType() == ResultConstants.VALUE) {
516                     break;
517                 }
518 
519                 if (result.getType() == ResultConstants.DATA) {
520                     break;
521                 }
522             }
523 
524             if (result.isError()) {
525                 break;
526             }
527 
528             if (result.getType() == ResultConstants.VALUE) {
529                 if (result.getErrorCode() == StatementTypes.ITERATE) {
530                     if (result.getMainString() == null) {
531                         continue;
532                     }
533 
534                     if (label != null
535                             && label.name.equals(result.getMainString())) {
536                         continue;
537                     }
538 
539                     break;
540                 }
541 
542                 if (result.getErrorCode() == StatementTypes.LEAVE) {
543                     break;
544                 }
545 
546                 // return
547                 break;
548             }
549 
550             if (result.getType() == ResultConstants.DATA) {
551                 break;
552             }
553         }
554 
555         queryResult.navigator.release();
556 
557         return result;
558     }
559 
executeLoop(Session session)560     private Result executeLoop(Session session) {
561 
562         Result result = Result.updateZeroResult;
563 
564         while (true) {
565             if (type == StatementTypes.WHILE) {
566                 result = condition.execute(session);
567 
568                 if (result.isError()) {
569                     break;
570                 }
571 
572                 if (!Boolean.TRUE.equals(result.getValueObject())) {
573                     result = Result.updateZeroResult;
574 
575                     break;
576                 }
577             }
578 
579             for (int i = 0; i < statements.length; i++) {
580                 result = executeProtected(session, statements[i]);
581                 result = handleCondition(session, result);
582 
583                 if (result.getType() == ResultConstants.VALUE) {
584                     break;
585                 }
586 
587                 if (result.getType() == ResultConstants.DATA) {
588                     break;
589                 }
590             }
591 
592             if (result.isError()) {
593                 break;
594             }
595 
596             if (result.getType() == ResultConstants.VALUE) {
597                 if (result.getErrorCode() == StatementTypes.ITERATE) {
598                     if (result.getMainString() == null) {
599                         continue;
600                     }
601 
602                     if (label != null
603                             && label.name.equals(result.getMainString())) {
604                         continue;
605                     }
606 
607                     break;
608                 }
609 
610                 if (result.getErrorCode() == StatementTypes.LEAVE) {
611                     if (result.getMainString() == null) {
612                         result = Result.updateZeroResult;
613                     }
614 
615                     if (label != null
616                             && label.name.equals(result.getMainString())) {
617                         result = Result.updateZeroResult;
618                     }
619 
620                     break;
621                 }
622 
623                 // return
624                 break;
625             }
626 
627             if (result.getType() == ResultConstants.DATA) {
628                 break;
629             }
630 
631             if (type == StatementTypes.REPEAT) {
632                 result = condition.execute(session);
633 
634                 if (result.isError()) {
635                     break;
636                 }
637 
638                 if (Boolean.TRUE.equals(result.getValueObject())) {
639                     result = Result.updateZeroResult;
640 
641                     break;
642                 }
643             }
644         }
645 
646         return result;
647     }
648 
executeIf(Session session)649     private Result executeIf(Session session) {
650 
651         Result  result  = Result.updateZeroResult;
652         boolean execute = false;
653 
654         for (int i = 0; i < statements.length; i++) {
655             if (statements[i].getType() == StatementTypes.CONDITION) {
656                 if (execute) {
657                     break;
658                 }
659 
660                 result = executeProtected(session, statements[i]);
661 
662                 if (result.isError()) {
663                     break;
664                 }
665 
666                 Object value = result.getValueObject();
667 
668                 execute = Boolean.TRUE.equals(value);
669 
670                 i++;
671             }
672 
673             result = Result.updateZeroResult;
674 
675             if (!execute) {
676                 continue;
677             }
678 
679             result = executeProtected(session, statements[i]);
680             result = handleCondition(session, result);
681 
682             if (result.isError()) {
683                 break;
684             }
685 
686             if (result.getType() == ResultConstants.VALUE) {
687                 break;
688             }
689         }
690 
691         return result;
692     }
693 
executeProtected(Session session, Statement statement)694     private Result executeProtected(Session session, Statement statement) {
695 
696         int actionIndex = session.rowActionList.size();
697 
698         session.actionTimestamp =
699             session.database.txManager.getNextGlobalChangeTimestamp();
700 
701         Result result = statement.execute(session);
702 
703         if (result.isError()) {
704             session.rollbackAction(actionIndex, session.actionTimestamp);
705         }
706 
707         return result;
708     }
709 
resolve(Session session)710     public void resolve(Session session) {
711 
712         for (int i = 0; i < statements.length; i++) {
713             if (statements[i].getType() == StatementTypes.LEAVE
714                     || statements[i].getType() == StatementTypes.ITERATE) {
715                 if (!findLabel((StatementSimple) statements[i])) {
716                     throw Error.error(
717                         ErrorCode.X_42508,
718                         ((StatementSimple) statements[i]).label.name);
719                 }
720 
721                 continue;
722             }
723 
724             if (statements[i].getType() == StatementTypes.RETURN) {
725                 if (!root.isFunction()) {
726                     throw Error.error(ErrorCode.X_42602, Tokens.T_RETURN);
727                 }
728             }
729         }
730 
731         for (int i = 0; i < statements.length; i++) {
732             statements[i].resolve(session);
733         }
734 
735         for (int i = 0; i < handlers.length; i++) {
736             handlers[i].resolve(session);
737         }
738 
739         OrderedHashSet writeTableNamesSet = new OrderedHashSet();
740         OrderedHashSet readTableNamesSet  = new OrderedHashSet();
741         OrderedHashSet set                = new OrderedHashSet();
742 
743         for (int i = 0; i < variables.length; i++) {
744             OrderedHashSet refs = variables[i].getReferences();
745 
746             if (refs != null) {
747                 set.addAll(refs);
748             }
749         }
750 
751         if (condition != null) {
752             set.addAll(condition.getReferences());
753             readTableNamesSet.addAll(condition.getTableNamesForRead());
754         }
755 
756         for (int i = 0; i < statements.length; i++) {
757             set.addAll(statements[i].getReferences());
758             readTableNamesSet.addAll(statements[i].getTableNamesForRead());
759             writeTableNamesSet.addAll(statements[i].getTableNamesForWrite());
760         }
761 
762         for (int i = 0; i < handlers.length; i++) {
763             set.addAll(handlers[i].getReferences());
764             readTableNamesSet.addAll(handlers[i].getTableNamesForRead());
765             writeTableNamesSet.addAll(handlers[i].getTableNamesForWrite());
766         }
767 
768         readTableNamesSet.removeAll(writeTableNamesSet);
769 
770         readTableNames = new HsqlName[readTableNamesSet.size()];
771 
772         readTableNamesSet.toArray(readTableNames);
773 
774         writeTableNames = new HsqlName[writeTableNamesSet.size()];
775 
776         writeTableNamesSet.toArray(writeTableNames);
777 
778         references = set;
779     }
780 
setRoot(Routine routine)781     public void setRoot(Routine routine) {
782 
783         root = routine;
784 /*
785         if (condition != null) {
786             condition.setRoot(routine);
787         }
788 
789         for (int i = 0; i < statements.length; i++) {
790             statements[i].setRoot(routine);
791         }
792 */
793     }
794 
describe(Session session)795     public String describe(Session session) {
796         return "";
797     }
798 
getReferences()799     public OrderedHashSet getReferences() {
800         return references;
801     }
802 
setAtomic(boolean atomic)803     public void setAtomic(boolean atomic) {
804         this.isAtomic = atomic;
805     }
806 
807     //
setVariables()808     private void setVariables() {
809 
810         HashMappedList list = new HashMappedList();
811 
812         if (parent != null && parent.scopeVariables != null) {
813             for (int i = 0; i < parent.scopeVariables.size(); i++) {
814                 list.add(parent.scopeVariables.getKey(i),
815                          parent.scopeVariables.get(i));
816             }
817         }
818 
819         variablesOffset = list.size();
820 
821         for (int i = 0; i < variables.length; i++) {
822             String  name  = variables[i].getName().name;
823             boolean added = list.add(name, variables[i]);
824 
825             if (!added) {
826                 throw Error.error(ErrorCode.X_42606, name);
827             }
828 
829             if (root.getParameterIndex(name) != -1) {
830                 throw Error.error(ErrorCode.X_42606, name);
831             }
832         }
833 
834         scopeVariables = list;
835 
836         RangeVariable[] parameterRangeVariables = root.getRangeVariables();
837         RangeVariable range = new RangeVariable(list, null, true,
838             RangeVariable.VARIALBE_RANGE);
839 
840         rangeVariables = new RangeVariable[parameterRangeVariables.length + 1];
841 
842         for (int i = 0; i < parameterRangeVariables.length; i++) {
843             rangeVariables[i] = parameterRangeVariables[i];
844         }
845 
846         rangeVariables[parameterRangeVariables.length] = range;
847         root.variableCount                             = list.size();
848     }
849 
setHandlers()850     private void setHandlers() {
851 
852         if (handlers.length == 0) {
853             return;
854         }
855 
856         HashSet           statesSet = new HashSet();
857         OrderedIntHashSet typesSet  = new OrderedIntHashSet();
858 
859         for (int i = 0; i < handlers.length; i++) {
860             int[] types = handlers[i].getConditionTypes();
861 
862             for (int j = 0; j < types.length; j++) {
863                 if (!typesSet.add(types[j])) {
864                     throw Error.error(ErrorCode.X_42601);
865                 }
866             }
867 
868             String[] states = handlers[i].getConditionStates();
869 
870             for (int j = 0; j < states.length; j++) {
871                 if (!statesSet.add(states[j])) {
872                     throw Error.error(ErrorCode.X_42601);
873                 }
874             }
875         }
876     }
877 
setTables()878     private void setTables() {
879 
880         if (tables.length == 0) {
881             return;
882         }
883 
884         HashMappedList list = new HashMappedList();
885 
886         if (parent != null && parent.scopeTables != null) {
887             for (int i = 0; i < parent.scopeTables.size(); i++) {
888                 list.add(parent.scopeTables.getKey(i),
889                          parent.scopeTables.get(i));
890             }
891         }
892 
893         for (int i = 0; i < tables.length; i++) {
894             String  name  = tables[i].getName().name;
895             boolean added = list.add(name, tables[i]);
896 
897             if (!added) {
898                 throw Error.error(ErrorCode.X_42606, name);
899             }
900         }
901 
902         scopeTables = list;
903     }
904 
setCursors()905     private void setCursors() {
906 
907         if (cursors.length == 0) {
908             return;
909         }
910 
911         HashSet list = new HashSet();
912 
913         for (int i = 0; i < cursors.length; i++) {
914             StatementCursor cursor = cursors[i];
915             boolean         added  = list.add(cursor.getCursorName().name);
916 
917             if (!added) {
918                 throw Error.error(ErrorCode.X_42606,
919                                   cursor.getCursorName().name);
920             }
921         }
922     }
923 
findLabel(StatementSimple statement)924     private boolean findLabel(StatementSimple statement) {
925 
926         if (label != null && statement.label.name.equals(label.name)) {
927             if (!isLoop && statement.getType() == StatementTypes.ITERATE) {
928                 return false;
929             }
930 
931             return true;
932         }
933 
934         if (parent == null) {
935             return false;
936         }
937 
938         return parent.findLabel(statement);
939     }
940 
initialiseVariables(Session session)941     private void initialiseVariables(Session session) {
942 
943         Object[] vars   = session.sessionContext.routineVariables;
944         int      offset = parent == null ? 0
945                                          : parent.scopeVariables.size();
946 
947         for (int i = 0; i < variables.length; i++) {
948             try {
949                 vars[offset + i] = variables[i].getDefaultValue(session);
950             } catch (HsqlException e) {}
951         }
952     }
953 
initialiseVariables(Session session, Object[] data, int count)954     private void initialiseVariables(Session session, Object[] data,
955                                      int count) {
956 
957         Object[] vars = session.sessionContext.routineVariables;
958 
959         for (int i = 0; i < count; i++) {
960             try {
961                 vars[variablesOffset + i] = data[i];
962             } catch (HsqlException e) {}
963         }
964     }
965 
getRangeVariables()966     public RangeVariable[] getRangeVariables() {
967         return rangeVariables;
968     }
969 
setCorrelated()970     public void setCorrelated() {
971 
972         //
973     }
974 
isVariable()975     public boolean isVariable() {
976         return true;
977     }
978 }
979