KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > ws > jaxme > sqls > impl > SQLGeneratorImpl


1 /*
2  * Copyright 2003, 2004 The Apache Software Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15
16  */

17 package org.apache.ws.jaxme.sqls.impl;
18
19 import java.util.ArrayList JavaDoc;
20 import java.util.Collection JavaDoc;
21 import java.util.Collections JavaDoc;
22 import java.util.Iterator JavaDoc;
23 import java.util.List JavaDoc;
24
25 import org.apache.ws.jaxme.sqls.BinaryColumn;
26 import org.apache.ws.jaxme.sqls.BooleanConstraint;
27 import org.apache.ws.jaxme.sqls.Case;
28 import org.apache.ws.jaxme.sqls.Column;
29 import org.apache.ws.jaxme.sqls.ColumnReference;
30 import org.apache.ws.jaxme.sqls.CombinedConstraint;
31 import org.apache.ws.jaxme.sqls.Constraint;
32 import org.apache.ws.jaxme.sqls.DeleteStatement;
33 import org.apache.ws.jaxme.sqls.Expression;
34 import org.apache.ws.jaxme.sqls.ForeignKey;
35 import org.apache.ws.jaxme.sqls.Function;
36 import org.apache.ws.jaxme.sqls.Index;
37 import org.apache.ws.jaxme.sqls.RawSQLCode;
38 import org.apache.ws.jaxme.sqls.SQLGenerator;
39 import org.apache.ws.jaxme.sqls.InsertStatement;
40 import org.apache.ws.jaxme.sqls.JoinReference;
41 import org.apache.ws.jaxme.sqls.Schema;
42 import org.apache.ws.jaxme.sqls.SelectStatement;
43 import org.apache.ws.jaxme.sqls.SelectTableReference;
44 import org.apache.ws.jaxme.sqls.SetStatement;
45 import org.apache.ws.jaxme.sqls.Statement;
46 import org.apache.ws.jaxme.sqls.StringColumn;
47 import org.apache.ws.jaxme.sqls.Table;
48 import org.apache.ws.jaxme.sqls.TableReference;
49 import org.apache.ws.jaxme.sqls.UpdateStatement;
50 import org.apache.ws.jaxme.sqls.Value;
51
52
53 /** <p>Default implementation of an SQL generator.</p>
54  *
55  * @author <a HREF="mailto:joe@ispsoft.de">Jochen Wiedmann</a>
56  */

57 public class SQLGeneratorImpl implements SQLGenerator {
58     private String JavaDoc statementTerminator, lineTerminator;
59     
60     public String JavaDoc getStatementTerminator() {
61         return statementTerminator;
62     }
63     
64     public void setStatementTerminator(String JavaDoc pStatementTerminator) {
65         statementTerminator = pStatementTerminator;
66     }
67     
68     public String JavaDoc getLineTerminator() {
69         return lineTerminator;
70     }
71     
72     public void setLineTerminator(String JavaDoc pLineTerminator) {
73         lineTerminator = pLineTerminator;
74     }
75     
76     protected String JavaDoc newStatement(String JavaDoc pStatement) {
77         String JavaDoc s = getStatementTerminator();
78         return s == null ? pStatement : pStatement + s;
79     }
80     
81     public Collection JavaDoc getCreate(Schema pSchema) {
82         if (pSchema.getName() == null) {
83             // Default schema cannot be created
84
return Collections.EMPTY_LIST;
85         }
86         List JavaDoc result = new ArrayList JavaDoc();
87         result.add(newStatement("CREATE SCHEMA " + pSchema.getName()));
88         return result;
89     }
90     
91     public Collection JavaDoc getDrop(Schema pSchema) {
92         if (pSchema.getName() == null) {
93             // Default schema cannot be dropped
94
return Collections.EMPTY_LIST;
95         }
96         List JavaDoc result = new ArrayList JavaDoc();
97         result.add(newStatement("DROP SCHEMA " + pSchema.getName()));
98         return result;
99     }
100     
101     protected String JavaDoc getIndent() { return " "; }
102     
103     protected String JavaDoc getTypeName(Column.Type pType) {
104         if (pType.equals(Column.Type.BIGINT)) {
105             return "BIGINT";
106         } else if (pType.equals(Column.Type.BINARY)) {
107             return "BINARY";
108         } else if (pType.equals(Column.Type.BIT)) {
109             return "BIT";
110         } else if (pType.equals(Column.Type.CHAR)) {
111             return "CHAR";
112         } else if (pType.equals(Column.Type.DATE)) {
113             return "DATE";
114         } else if (pType.equals(Column.Type.DOUBLE)) {
115             return "DOUBLE";
116         } else if (pType.equals(Column.Type.FLOAT)) {
117             return "FLOAT";
118         } else if (pType.equals(Column.Type.INTEGER)) {
119             return "INT";
120         } else if (pType.equals(Column.Type.SMALLINT)) {
121             return "SMALLINT";
122         } else if (pType.equals(Column.Type.TIME)) {
123             return "TIME";
124         } else if (pType.equals(Column.Type.TIMESTAMP)) {
125             return "TIMESTAMP";
126         } else if (pType.equals(Column.Type.TINYINT)) {
127             return "TINYINT";
128         } else if (pType.equals(Column.Type.VARBINARY)) {
129             return "VARBINARY";
130         } else if (pType.equals(Column.Type.VARCHAR)) {
131             return "VARCHAR";
132         } else if (pType.equals(Column.Type.CLOB)) {
133             return "CLOB";
134         } else if (pType.equals(Column.Type.BLOB)) {
135             return "BLOB";
136         } else if (pType.equals(Column.Type.OTHER)) {
137             return "BLOB";
138         } else {
139             throw new IllegalStateException JavaDoc("Unknown column type: " + pType);
140         }
141     }
142     
143     protected String JavaDoc getCreate(Column pColumn) {
144         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
145         sb.append(pColumn.getName()).append(" ");
146         Column.Type type = pColumn.getType();
147         Long JavaDoc length = null;
148         if (type.equals(Column.Type.BINARY)
149                 || type.equals(Column.Type.VARBINARY)
150                 || type.equals(Column.Type.BLOB)
151                 || type.equals(Column.Type.OTHER)) {
152             length = ((BinaryColumn) pColumn).getLength();
153             if (length == null) {
154                 throw new IllegalStateException JavaDoc("The length of column " + pColumn.getQName() + " is not set.");
155             }
156         } else if (type.equals(Column.Type.CHAR)
157                 || type.equals(Column.Type.VARCHAR)
158                 || type.equals(Column.Type.CLOB)) {
159             length = ((StringColumn) pColumn).getLength();
160             if (length == null) {
161                 throw new IllegalStateException JavaDoc("The length of column " + pColumn.getQName() + " is not set.");
162             }
163         }
164         sb.append(getTypeName(type));
165         if (length != null) {
166             sb.append("(").append(length).append(")");
167         }
168         if (!pColumn.isNullable()) {
169             sb.append(" NOT NULL");
170         }
171         return sb.toString();
172     }
173     
174     /** <p>Returns whether the primary key requires special handling
175      * (in which case {@link #isPrimaryKeyPartOfCreateTable()} and
176      * {@link #createPrimaryKeyAsPartOfCreateTable(Table)} are used)
177      * or nor (in which case {@link #isUniqueIndexPartOfCreateTable()}
178      * and {@link #createIndexAsPartOfCreateTable(Index)} apply).</p>
179      */

180     protected boolean isPrimaryKeyUniqueIndex() { return false; }
181     
182     /** <p>Returns whether a <code>CREATE TABLE</code> statement may contain
183      * a <code>PRIMARY KEY</code> clause.</p>
184      */

185     protected boolean isPrimaryKeyPartOfCreateTable() { return false; }
186     
187     /** <p>Returns whether a <code>CREATE TABLE</code> statement may contain
188      * a <code>UNIQUE</code> clause.</p>
189      */

190     protected boolean isUniqueIndexPartOfCreateTable() { return false; }
191     
192     /** <p>Returns whether a <code>CREATE TABLE</code> statement may contain
193      * an <code>INDEX</code> clause.</p>
194      */

195     protected boolean isNonUniqueIndexPartOfCreateTable() { return false; }
196     
197     /** <p>Returns whether a <code>CREATE TABLE</code> statement may contain
198      * a <code>FOREIGN KEY</code> clause.</p>
199      */

200     protected boolean isForeignKeyPartOfCreateTable() { return false; }
201     
202     protected String JavaDoc createPrimaryKeyAsPartOfCreateTable(Table pTable) {
203         Index index = pTable.getPrimaryKey();
204         if (index == null) {
205             return null;
206         }
207         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
208         sb.append("PRIMARY KEY").append(" (");
209         boolean first = true;
210         for (Iterator JavaDoc iter = index.getColumns(); iter.hasNext(); ) {
211             if (first) {
212                 first = false;
213             } else {
214                 sb.append(", ");
215             }
216             sb.append(((Column) iter.next()).getName().getName());
217         }
218         sb.append(")");
219         return sb.toString();
220     }
221     
222     protected String JavaDoc createIndexAsPartOfCreateTable(Index pIndex) {
223         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
224         sb.append(pIndex.isUnique() ? "UNIQUE" : "KEY").append(" (");
225         boolean first = true;
226         for (Iterator JavaDoc iter = pIndex.getColumns(); iter.hasNext(); ) {
227             if (first) {
228                 first = false;
229             } else {
230                 sb.append(", ");
231             }
232             sb.append(((Column) iter.next()).getName().getName());
233         }
234         sb.append(")");
235         return sb.toString();
236     }
237     
238     protected String JavaDoc createForeignKeyAsPartOfCreateTable(ForeignKey pKey) {
239         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
240         sb.append("FOREIGN KEY (");
241         boolean first = true;
242         Iterator JavaDoc iter = pKey.getColumnLinks();
243         if (!iter.hasNext()) {
244             throw new IllegalStateException JavaDoc("Foreign key on " +
245                     pKey.getTable().getQName() +
246                     " referencing " +
247                     pKey.getReferencedTable().getQName() +
248             " doesn't have any columns.");
249         }
250         while (iter.hasNext()) {
251             ForeignKey.ColumnLink link = (ForeignKey.ColumnLink) iter.next();
252             if (first) {
253                 first = false;
254             } else {
255                 sb.append(", ");
256             }
257             sb.append(link.getLocalColumn().getName().getName());
258         }
259         sb.append(") REFERENCES ");
260         sb.append(pKey.getReferencedTable().getQName());
261         sb.append(" (");
262         first = true;
263         iter = pKey.getColumnLinks();
264         while (iter.hasNext()) {
265             ForeignKey.ColumnLink link = (ForeignKey.ColumnLink) iter.next();
266             if (first) {
267                 first = false;
268             } else {
269                 sb.append(", ");
270             }
271             sb.append(link.getReferencedColumn().getName().getName());
272         }
273         sb.append(")");
274         
275         ForeignKey.Mode deleteMode = pKey.getOnDelete();
276         if (deleteMode != null) {
277             if (ForeignKey.Mode.CASCADE.equals(deleteMode)) {
278                 sb.append(" ON DELETE CASCADE");
279             } else if (ForeignKey.Mode.REJECT.equals(deleteMode)) {
280                 sb.append(" ON DELETE RESTRICT");
281             } else if (ForeignKey.Mode.SETNULL.equals(deleteMode)) {
282                 sb.append(" ON DELETE SET NULL");
283             } else {
284                 throw new IllegalStateException JavaDoc("Unknown foreign key mode for ON DELETE: " + deleteMode);
285             }
286         }
287         ForeignKey.Mode updateMode = pKey.getOnUpdate();
288         if (updateMode != null) {
289             if (ForeignKey.Mode.CASCADE.equals(updateMode)) {
290                 sb.append(" ON UPDATE CASCADE");
291             } else if (ForeignKey.Mode.REJECT.equals(updateMode)) {
292                 sb.append(" ON UPDATE RESTRICT");
293             } else {
294                 throw new IllegalStateException JavaDoc("Unknown foreign key mode for ON UPDATE: " + updateMode);
295             }
296         }
297         
298         return sb.toString();
299     }
300     
301     protected String JavaDoc getCreateTableHeader(Table pTable) {
302         return "CREATE TABLE " + pTable.getQName();
303     }
304     
305     public Collection JavaDoc getCreate(Table pTable) {
306         String JavaDoc lf = getLineTerminator() == null ? "" : getLineTerminator();
307         String JavaDoc indent = lf == null ? "" : getIndent();
308         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
309         sb.append(getCreateTableHeader(pTable)).append(" (");
310         String JavaDoc s = lf + indent;
311         for (Iterator JavaDoc iter = pTable.getColumns(); iter.hasNext(); ) {
312             sb.append(s).append(getCreate((Column) iter.next()));
313             s = "," + lf + indent;
314         }
315         
316         for (Iterator JavaDoc iter = pTable.getIndexes(); iter.hasNext(); ) {
317             Index index = (Index) iter.next();
318             String JavaDoc st;
319             if (index.isPrimaryKey() && !isPrimaryKeyUniqueIndex()) {
320                 if (!isPrimaryKeyPartOfCreateTable()) {
321                     continue;
322                 }
323                 st = createPrimaryKeyAsPartOfCreateTable(pTable);
324             } else if (index.isUnique()) {
325                 if (!isUniqueIndexPartOfCreateTable()) {
326                     continue;
327                 }
328                 st = createIndexAsPartOfCreateTable(index);
329             } else {
330                 if (!isNonUniqueIndexPartOfCreateTable()) {
331                     continue;
332                 }
333                 st = createIndexAsPartOfCreateTable(index);
334             }
335             if (st != null) {
336                 sb.append(s).append(st);
337             }
338         }
339         if (isForeignKeyPartOfCreateTable()) {
340             for (Iterator JavaDoc iter = pTable.getForeignKeys(); iter.hasNext(); ) {
341                 ForeignKey key = (ForeignKey) iter.next();
342                 String JavaDoc st = createForeignKeyAsPartOfCreateTable(key);
343                 if (st != null) {
344                     sb.append(s).append(st);
345                 }
346             }
347         }
348         sb.append(lf).append(")").append(lf);
349         List JavaDoc result = new ArrayList JavaDoc();
350         result.add(newStatement(sb.toString()));
351         return result;
352     }
353     
354     public Collection JavaDoc getDrop(Table pTable) {
355         List JavaDoc result = new ArrayList JavaDoc();
356         result.add(newStatement("DROP TABLE " + pTable.getQName()));
357         return result;
358     }
359
360     private ColumnReference[] getSetStatementsColumns(SetStatement pStatement) {
361         List JavaDoc result = new ArrayList JavaDoc();
362         for (Iterator JavaDoc iter = pStatement.getSetValues(); iter.hasNext(); ) {
363             SetStatement.SetValue setValue = (SetStatement.SetValue) iter.next();
364             result.add(setValue.getColumnReference());
365         }
366         return (ColumnReference[]) result.toArray(new ColumnReference[result.size()]);
367     }
368
369     private ColumnReference[] getInsertStatementsColumns(InsertStatement pStatement) {
370         SelectStatement subSelect = pStatement.getSubSelect();
371         if (subSelect == null) {
372             return getSetStatementsColumns(pStatement);
373         } else {
374             List JavaDoc result = new ArrayList JavaDoc();
375             for (Iterator JavaDoc iter = subSelect.getResultColumns(); iter.hasNext(); ) {
376                 ColumnReference cRef = (ColumnReference) iter.next();
377                 Column.Name name;
378                 if (cRef.getAlias() == null) {
379                     name = cRef.getColumn().getName();
380                 } else {
381                     name = cRef.getAlias();
382                 }
383                 Column col = pStatement.getTableReference().getTable().getColumn(name);
384                 if (col == null) {
385                     throw new IllegalStateException JavaDoc("A result column " + name
386                             + " is used in the subselect, which is not present in the insert statements table.");
387                 }
388                 result.add(pStatement.getTableReference().newColumnReference(col));
389             }
390             return (ColumnReference[]) result.toArray(new ColumnReference[result.size()]);
391         }
392     }
393
394     private void addSetValuesToInsertStatement(StringBuffer JavaDoc pBuffer,
395                                                StatementMetaData pData,
396                                                InsertStatement pQuery) {
397         pBuffer.append(" VALUES (");
398         boolean first = true;
399         for (Iterator JavaDoc iter = pQuery.getSetValues(); iter.hasNext(); ) {
400             if (first) {
401                 first = false;
402             } else {
403                 pBuffer.append(", ");
404             }
405             SetStatement.SetValue setValue = (SetStatement.SetValue) iter.next();
406             Object JavaDoc o = setValue.getValue();
407             String JavaDoc s = getBooleanConstraintPart(pData, o);
408             pBuffer.append(s);
409         }
410         pBuffer.append(")");
411     }
412
413     private void addSubSelectToInsertStatement(StringBuffer JavaDoc pBuffer, StatementMetaData pData,
414                                                InsertStatement pStatement) {
415         pBuffer.append(" (");
416         pBuffer.append(getSelectQuery(pStatement.getSubSelect(), pData));
417         pBuffer.append(")");
418     }
419
420     public String JavaDoc getInsertQuery(InsertStatement pQuery) {
421         ColumnReference[] columns = getInsertStatementsColumns(pQuery);
422         StatementMetaData smd = newStatementMetaData(pQuery, columns);
423         
424         StringBuffer JavaDoc result = new StringBuffer JavaDoc();
425         result.append("INSERT INTO ");
426         result.append(getTableAlias(smd, pQuery.getTableReference()));
427         if (columns.length > 0) {
428             result.append(" (");
429             for (int i = 0; i < columns.length; i++) {
430                 if (i > 0) {
431                     result.append(", ");
432                 }
433                 result.append(getColumnAlias(smd, columns[i]));
434             }
435             result.append(")");
436         }
437         boolean hasSetValues = pQuery.getSetValues().hasNext();
438         boolean hasSubselect = pQuery.getSubSelect() != null;
439         if (hasSetValues) {
440             if (hasSubselect) {
441                 throw new IllegalStateException JavaDoc("Using values (InsertStatement.addFoo(..)) and subselects (InsertStatement.setSubSelect(...)) is mutually exclusive.");
442             } else {
443                 addSetValuesToInsertStatement(result, smd, pQuery);
444             }
445         } else {
446             if (hasSubselect) {
447                 addSubSelectToInsertStatement(result, smd, pQuery);
448             } else {
449                 throw new IllegalStateException JavaDoc("Neither values (InsertStatement.addFoo(..)) nor a subselect (InsertStatement.setSubSelect(...)) are set.");
450             }
451         }
452         return newStatement(result.toString());
453     }
454     
455     protected String JavaDoc getValue(Value pValue) {
456         Value.Type type = pValue.getType();
457         Object JavaDoc o = pValue.getValue();
458         if (Value.Type.BOOLEAN.equals(type)) {
459             return o == null ? "null" : (((Boolean JavaDoc) o).booleanValue() ? "TRUE" : "FALSE");
460         } else if (Value.Type.BYTE.equals(type) ||
461                 Value.Type.SHORT.equals(type) ||
462                 Value.Type.INT.equals(type) ||
463                 Value.Type.LONG.equals(type) ||
464                 Value.Type.FLOAT.equals(type) ||
465                 Value.Type.DOUBLE.equals(type)) {
466             return o == null ? "null" : o.toString();
467         } else if (Value.Type.DATE.equals(type) ||
468                 Value.Type.DATETIME.equals(type) ||
469                 Value.Type.TIME.equals(type)) {
470             throw new IllegalStateException JavaDoc("Date/time handling not yet implemented.");
471         } else if (Value.Type.DATE.equals(type)) {
472             throw new IllegalStateException JavaDoc("Date handling not yet implemented.");
473         } else if (Value.Type.PLACEHOLDER.equals(type)) {
474             return "?";
475         } else if (Value.Type.STRING.equals(type)) {
476             return o == null ? "null" : getEscapedString(o.toString());
477         } else if (Value.Type.NULL.equals(type)) {
478             return "null";
479         } else {
480             throw new IllegalStateException JavaDoc("Unknown value type: " + type);
481         }
482     }
483     
484     protected String JavaDoc getUpdateQuery(UpdateStatement pQuery) {
485         ColumnReference[] columns = getSetStatementsColumns(pQuery);
486         StatementMetaData smd = newStatementMetaData(pQuery, columns);
487
488         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
489         sb.append("UPDATE ");
490         sb.append(getTableAlias(smd, pQuery.getTableReference()));
491         sb.append(" SET ");
492         boolean first = true;
493         for (Iterator JavaDoc iter = pQuery.getSetValues(); iter.hasNext(); ) {
494             UpdateStatement.SetValue setValue = (UpdateStatement.SetValue) iter.next();
495             if (first) {
496                 first = false;
497             } else {
498                 sb.append(", ");
499             }
500             sb.append(getColumnAlias(smd, setValue.getColumnReference()));
501             sb.append("=");
502             sb.append(getBooleanConstraintPart(smd, setValue.getValue()));
503         }
504         String JavaDoc s = getWhereClause(smd, pQuery.getWhere());
505         if (s != null) {
506             sb.append(" WHERE ").append(s);
507         }
508         return newStatement(sb.toString());
509     }
510     
511     protected String JavaDoc getDeleteQuery(DeleteStatement pQuery) {
512         StatementMetaData smd = newStatementMetaData(pQuery);
513         
514         StringBuffer JavaDoc result = new StringBuffer JavaDoc("DELETE FROM ");
515         result.append(getTableAlias(smd, pQuery.getTableReference()));
516         String JavaDoc s = getWhereClause(smd, pQuery.getWhere());
517         if (s != null) {
518             result.append(" WHERE ");
519             result.append(s);
520         }
521         return result.toString();
522     }
523     
524     protected boolean isQualifiedColumn(StatementMetaData pData, ColumnReference pColumn) {
525         if (pData == null) {
526             return false;
527         }
528         Integer JavaDoc num = (Integer JavaDoc) pData.getColumnNames().get(pColumn.getColumn().getName().toString().toUpperCase());
529         if (num == null) {
530             throw new IllegalStateException JavaDoc("Column not in map of column counts: "
531                     + pColumn.getColumn().getName());
532         }
533         return num.intValue() > 1;
534     }
535     
536     protected String JavaDoc getFunction(StatementMetaData pData, Function f) {
537         return f.getName() + '(' + getParts(pData, f.getParts()) + ')';
538     }
539     
540     protected String JavaDoc getColumnAlias(StatementMetaData pData, ColumnReference pColumn) {
541         Column col = pColumn.getColumn();
542         String JavaDoc s = col.getName().toString();
543         if (col.isVirtual()) {
544             VirtualColumn virtCol = (VirtualColumn) col;
545             Object JavaDoc o = virtCol.getValue();
546             if (o instanceof SelectStatement) {
547                 return "(" + getSelectQuery((SelectStatement) o, pData) + ") AS " + s;
548             } else if (o instanceof Function) {
549                 return getFunction(pData, (Function) o) + " AS " + s;
550             } else if (o instanceof String JavaDoc) {
551                 return ((String JavaDoc) o) + " AS " + s;
552             } else {
553                 throw new IllegalStateException JavaDoc("Invalid type of VirtualColumn: " + o);
554             }
555         } else {
556             if (isQualifiedColumn(pData, pColumn)) {
557                 TableReference tableReference = pColumn.getTableReference();
558                 if (tableReference.getAlias() != null) {
559                     s = tableReference.getAlias().getName() + "." + s;
560                 } else {
561                     s = tableReference.getTable().getName() + "." + s;
562                 }
563             }
564             
565             if (pColumn.getAlias() != null) {
566                 s = s + " AS " + pColumn.getAlias().getName();
567             }
568         }
569         return s;
570     }
571     
572     protected String JavaDoc getColumnAlias(StatementMetaData pData, ColumnReference[] pColumn) {
573         StringBuffer JavaDoc sb = new StringBuffer JavaDoc("(");
574         for (int i = 0; i < pColumn.length; i++) {
575             if (i > 0) sb.append(", ");
576             sb.append(getColumnAlias(pData, pColumn[i]));
577         }
578         sb.append(")");
579         return sb.toString();
580     }
581     
582     protected boolean isTableAliasUsingAs() { return true; }
583     
584     protected String JavaDoc getTableAlias(StatementMetaData pData, TableReference pTable) {
585         Table t = pTable.getTable();
586         String JavaDoc tableName;
587         Table.Name alias = pTable.getAlias();
588         if (t instanceof ViewImpl) {
589             ViewImpl v = (ViewImpl) t;
590             tableName = "(" + getSelectQuery(v.getViewStatement(), pData) + ")";
591         } else {
592             tableName = pTable.getTable().getQName();
593         }
594         if (alias == null) {
595             return tableName;
596         } else {
597             if (isTableAliasUsingAs()) {
598                 return tableName + " AS " + alias.getName();
599             } else {
600                 return tableName + " " + alias.getName();
601             }
602         }
603     }
604     
605     protected String JavaDoc getJoinAlias(StatementMetaData pData, JoinReference pJoinReference) {
606         StringBuffer JavaDoc result = new StringBuffer JavaDoc();
607         if (pJoinReference.isLeftOuterJoin()) {
608             result.append(" LEFT OUTER JOIN ");
609         } else if (pJoinReference.isJoin()) {
610             result.append(" JOIN ");
611         } else {
612             throw new IllegalStateException JavaDoc("Unknown join type");
613         }
614         result.append(getTableAlias(pData, pJoinReference));
615         String JavaDoc s = getWhereClause(pData, pJoinReference.getOn());
616         if (s != null) {
617             result.append(" ON ");
618             result.append(s);
619         }
620         return result.toString();
621     }
622     
623     protected String JavaDoc getEscapedString(String JavaDoc s) {
624         if (s.indexOf('\n') > -1 || s.indexOf('\r') > -1 || s.indexOf('\f') > -1) {
625             throw new IllegalArgumentException JavaDoc("Don't know how to handle line or page terminators.");
626         }
627         if (s.indexOf('\'') > -1) {
628             throw new IllegalArgumentException JavaDoc("Don't know how to handle the char ' in strings.");
629         }
630         return "'" + s + "'";
631     }
632     
633     protected String JavaDoc getParts(StatementMetaData pData, Iterator JavaDoc pParts) {
634         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
635         while (pParts.hasNext()) {
636             if (sb.length() > 0) {
637                 sb.append(", ");
638             }
639             sb.append(getBooleanConstraintPart(pData, pParts.next()));
640         }
641         return sb.toString();
642     }
643
644     protected String JavaDoc getCase(StatementMetaData pData, Case pCase) {
645         StringBuffer JavaDoc sb = new StringBuffer JavaDoc("CASE ");
646         sb.append(getBooleanConstraintPart(pData, pCase.getCheckedValue()));
647         Case.When[] whens = pCase.getWhens();
648         for (int i = 0; i < whens.length; i++) {
649             Case.When when = whens[i];
650             sb.append(" WHEN ");
651             sb.append(getBooleanConstraintPart(pData, when.getCondition()));
652             sb.append(" THEN ");
653             sb.append(getBooleanConstraintPart(pData, when.getValue()));
654         }
655         Object JavaDoc o = pCase.getElseValue();
656         if (o != null) {
657             sb.append(" ELSE ");
658             sb.append(getBooleanConstraintPart(pData, o));
659         }
660         sb.append(" END");
661         return sb.toString();
662     }
663
664     protected String JavaDoc getBooleanConstraintPart(StatementMetaData pData, Object JavaDoc o) {
665         if (o instanceof Value) {
666             return getValue((Value) o);
667         } else if (o instanceof ColumnReference) {
668             return getColumnAlias(pData, (ColumnReference) o);
669         } else if (o instanceof ColumnReference[]) {
670             return getColumnAlias(pData, (ColumnReference[]) o);
671         } else if (o instanceof SelectStatement) {
672             return '(' + getSelectQuery((SelectStatement) o, pData) + ')';
673         } else if (o instanceof RawSQLCode) {
674             return ((RawSQLCode) o).getRawSQL();
675         } else if (o instanceof Function) {
676             return getFunction(pData, (Function) o);
677         } else if (o instanceof Case) {
678             return getCase(pData, (Case) o);
679         } else if (o instanceof Expression) {
680             return getExpression(pData, (Expression) o);
681         } else {
682             throw new IllegalArgumentException JavaDoc("Invalid part of a boolean constraint: " + o.getClass().getName());
683         }
684     }
685
686     protected String JavaDoc getExpression(StatementMetaData pData, Expression pExpr) {
687         int parts = pExpr.getNumParts();
688         int minParts = pExpr.getMinimumParts();
689         if (parts < minParts) {
690             throw new IllegalStateException JavaDoc("An expression of type " + pExpr.getType()
691                                             + " must have at least " + minParts + " parts.");
692         }
693         int maxParts = pExpr.getMaximumParts();
694         if (maxParts > 0 && parts > maxParts) {
695             throw new IllegalStateException JavaDoc("An expression of type " + pExpr.getType()
696                                             + " must have at least " + maxParts + " parts.");
697         }
698         Iterator JavaDoc iter = pExpr.getParts();
699         if (parts == 1) {
700             return getBooleanConstraintPart(pData, iter.next());
701         } else {
702             String JavaDoc sep;
703             Expression.Type type = pExpr.getType();
704             if (Expression.SUM.equals(type)) {
705                 sep = "+";
706             } else if (Expression.PRODUCT.equals(type)) {
707                 sep = "*";
708             } else if (Expression.DIFFERENCE.equals(type)) {
709                 sep = "-";
710             } else if (Expression.QUOTIENT.equals(type)) {
711                 sep = "/";
712             } else {
713                 throw new IllegalStateException JavaDoc("Invalid type: " + type);
714             }
715             StringBuffer JavaDoc result = new StringBuffer JavaDoc("(");
716             for (int i = 0; i < parts; i++) {
717                 if (i > 0) {
718                     result.append(sep);
719                 }
720                 result.append(getBooleanConstraintPart(pData, iter.next()));
721             }
722             result.append(")");
723             return result.toString();
724         }
725     }
726
727     protected String JavaDoc getBooleanConstraintType(BooleanConstraint.Type pType) {
728         if (BooleanConstraint.Type.EQ.equals(pType)) {
729             return "=";
730         } else if (BooleanConstraint.Type.NE.equals(pType)) {
731             return "<>";
732         } else if (BooleanConstraint.Type.GT.equals(pType)) {
733             return ">";
734         } else if (BooleanConstraint.Type.LT.equals(pType)) {
735             return "<";
736         } else if (BooleanConstraint.Type.GE.equals(pType)) {
737             return ">=";
738         } else if (BooleanConstraint.Type.LE.equals(pType)) {
739             return "<=";
740         } else if (BooleanConstraint.Type.LIKE.equals(pType)) {
741             return " LIKE ";
742         } else {
743             throw new IllegalArgumentException JavaDoc("Invalid type: " + pType);
744         }
745     }
746     
747     protected String JavaDoc getBooleanConstraint(StatementMetaData pData,
748                                           BooleanConstraint pConstraint) {
749         BooleanConstraint.Type type = pConstraint.getType();
750         Iterator JavaDoc parts = pConstraint.getParts();
751         if (!parts.hasNext()) {
752             throw new NullPointerException JavaDoc("A boolean constraint must have its parts set.");
753         }
754         if (BooleanConstraint.Type.IN.equals(type)) {
755             Object JavaDoc o = parts.next();
756             return getBooleanConstraintPart(pData, o) + " IN (" + getParts(pData, parts) + ')';
757         }
758         StringBuffer JavaDoc result = new StringBuffer JavaDoc();
759         int expected;
760         if (BooleanConstraint.Type.EXISTS.equals(type)) {
761             SelectStatement selectStatement = (SelectStatement) parts.next();
762             result.append("EXISTS(");
763             result.append(getSelectQuery(selectStatement, pData));
764             result.append(")");
765             expected = 1;
766         } else if (BooleanConstraint.Type.BETWEEN.equals(type)) {
767             expected = 3;
768             if (pConstraint.getNumParts() >= 3) {
769                 result.append(getBooleanConstraintPart(pData, parts.next()));
770                 result.append(" BETWEEN ");
771                 result.append(getBooleanConstraintPart(pData, parts.next()));
772                 result.append(" AND ");
773                 result.append(getBooleanConstraintPart(pData, parts.next()));
774             }
775         } else {
776             result.append(getBooleanConstraintPart(pData, parts.next()));
777             if (BooleanConstraint.Type.EQ.equals(type) ||
778                     BooleanConstraint.Type.NE.equals(type) ||
779                     BooleanConstraint.Type.GT.equals(type) ||
780                     BooleanConstraint.Type.LT.equals(type) ||
781                     BooleanConstraint.Type.GE.equals(type) ||
782                     BooleanConstraint.Type.LE.equals(type) ||
783                     BooleanConstraint.Type.LIKE.equals(type)) {
784                 expected = 2;
785                 if (!parts.hasNext()) {
786                     throw new NullPointerException JavaDoc("The boolean constraint " + type +
787                                                    " must have exactly two parts set.");
788                 }
789                 result.append(getBooleanConstraintType(type));
790                 result.append(getBooleanConstraintPart(pData, parts.next()));
791             } else if (BooleanConstraint.Type.ISNULL.equals(type)) {
792                 expected = 1;
793                 result.append(" IS NULL");
794             } else {
795                 throw new IllegalArgumentException JavaDoc("Invalid boolean constraint type: " + type);
796             }
797         }
798         if (expected != 0 && parts.hasNext()) {
799             throw new NullPointerException JavaDoc("The boolean constraint " + type +
800                                            " must have exactly " + expected +
801                                            " parts set, but has " + pConstraint.getNumParts());
802         }
803         return result.toString();
804     }
805     
806     protected String JavaDoc getCombinedConstraint(StatementMetaData pData,
807             CombinedConstraint pConstraint) {
808         if (pConstraint.getNumParts() == 0) {
809             return null;
810         }
811         
812         List JavaDoc parts = new ArrayList JavaDoc();
813         for (Iterator JavaDoc iter = pConstraint.getParts(); iter.hasNext(); ) {
814             String JavaDoc s;
815             Object JavaDoc o = iter.next();
816             if (o == null) {
817                 throw new NullPointerException JavaDoc("A CombinedConstraints part must not be null");
818             }
819             if (o instanceof CombinedConstraint) {
820                 s = getCombinedConstraint(pData, (CombinedConstraint) o);
821             } else if (o instanceof BooleanConstraint) {
822                 s = getBooleanConstraint(pData, (BooleanConstraint) o);
823             } else {
824                 throw new IllegalArgumentException JavaDoc("Invalid part: " + o.getClass().getName());
825             }
826             if (s != null) {
827                 parts.add(s);
828             }
829         }
830
831         switch (parts.size()) {
832             case 0: return null;
833             case 1:
834                 if (pConstraint.isNOT()) {
835                     return "NOT (" + parts.get(0) + ")";
836                 } else {
837                     return (String JavaDoc) parts.get(0);
838                 }
839             default:
840                 StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
841                 if (pConstraint.isNOT()) {
842                     sb.append("(NOT ");
843                 }
844                 for (int i = 0; i < parts.size(); i++) {
845                     if (i == 0) {
846                         sb.append("(");
847                     } else {
848                         sb.append(" ");
849                         sb.append(pConstraint.getType());
850                         sb.append(" ");
851                     }
852                     sb.append(parts.get(i));
853                 }
854                 sb.append(")");
855                 if (pConstraint.isNOT()) {
856                     sb.append(")");
857                 }
858                 return sb.toString();
859         }
860     }
861     
862     public String JavaDoc getConstraint(StatementMetaData pData, Constraint pConstraint) {
863         if (pConstraint instanceof CombinedConstraint) {
864             return getWhereClause(pData, (CombinedConstraint) pConstraint);
865         } else if (pConstraint instanceof BooleanConstraint) {
866             return getBooleanConstraint(pData, (BooleanConstraint) pConstraint);
867         } else {
868             throw new IllegalArgumentException JavaDoc("Unknown constraint type: " +
869                     pConstraint.getClass().getName());
870         }
871     }
872     
873     protected String JavaDoc getWhereClause(StatementMetaData pData,
874             CombinedConstraint pWhereClause) {
875         return getCombinedConstraint(pData, pWhereClause);
876     }
877     
878     protected String JavaDoc getSelectQuery(SelectStatement pQuery) {
879         StatementMetaData selectStatementMetaData = newStatementMetaData(pQuery);
880         return getSelectQuery(pQuery, selectStatementMetaData);
881     }
882     
883
884     protected String JavaDoc getSelectQueryResultColumns(SelectStatement pQuery, StatementMetaData pData) {
885         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
886         if (pQuery.isDistinct()) {
887             sb.append(" DISTINCT");
888         }
889         Iterator JavaDoc columnIter = pQuery.getResultColumns();
890         if (!columnIter.hasNext()) {
891             sb.append(" *");
892         } else {
893             boolean first = true;
894             do {
895                 ColumnReference column = (ColumnReference) columnIter.next();
896                 if (first) {
897                     sb.append(" ");
898                     first = false;
899                 } else {
900                     sb.append(", ");
901                 }
902                 sb.append(getColumnAlias(pData, column));
903             } while (columnIter.hasNext());
904         }
905         return sb.toString();
906     }
907
908     protected String JavaDoc getSelectQueryFromClause(SelectStatement pQuery, StatementMetaData pData) {
909         SelectTableReference selectTableReference = pQuery.getSelectTableReference();
910         if (selectTableReference == null) {
911             return null;
912         }
913         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
914         sb.append(" FROM ");
915         sb.append(getTableAlias(pData, selectTableReference));
916         for (JoinReference joinReference = selectTableReference.getRightJoinedTableReference();
917         joinReference != null;
918         joinReference = joinReference.getRightJoinedTableReference()) {
919             sb.append(getJoinAlias(pData, joinReference));
920         }
921         return sb.toString();
922     }
923
924     protected String JavaDoc getSelectQueryConstraints(SelectStatement pQuery, StatementMetaData pData,
925                                                StatementMetaData.LocalData pLocalData) {
926         String JavaDoc s = getWhereClause(pData, pQuery.getWhere());
927         if (pLocalData != null && s != null && s.length() > 0) {
928             pLocalData.setWhereClause(true);
929         }
930         return s;
931     }
932
933     protected String JavaDoc getSelectQuery(SelectStatement pQuery, StatementMetaData pData) {
934         StringBuffer JavaDoc sb = new StringBuffer JavaDoc("SELECT");
935         String JavaDoc s = getSelectQueryResultColumns(pQuery, pData);
936         if (s != null) {
937             sb.append(s);
938         }
939
940         s = getSelectQueryFromClause(pQuery, pData);
941         if (s != null) {
942             sb.append(s);
943         }
944
945         StatementMetaData.LocalData localData = new StatementMetaData.LocalData();
946         s = getSelectQueryConstraints(pQuery, pData, localData);
947         if (s != null && s.length() > 0) {
948             if (localData.hasWhereClause()) {
949                 sb.append(" WHERE ");
950             }
951             sb.append(s);
952         }
953         
954         s = getSelectQueryOrderClause(pData, pQuery);
955         if (s != null) {
956             sb.append(s);
957         }
958         return sb.toString();
959     }
960
961     protected String JavaDoc getOrderColumn(StatementMetaData pData, SelectStatement.OrderColumn pColumn) {
962         String JavaDoc s = getBooleanConstraintPart(pData, pColumn.getColumn());
963         if (pColumn.isDescending()) {
964             s += " DESC";
965         }
966         return s;
967     }
968
969     protected String JavaDoc getSelectQueryOrderClause(StatementMetaData pData, SelectStatement pQuery) {
970         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
971         for (Iterator JavaDoc iter = pQuery.getOrderColumns(); iter.hasNext(); ) {
972             SelectStatement.OrderColumn col = (SelectStatement.OrderColumn) iter.next();
973             if (sb.length() == 0) {
974                 sb.append(" ORDER BY ");
975             } else {
976                 sb.append(", ");
977             }
978             sb.append(getOrderColumn(pData, col));
979         }
980         return sb.toString();
981     }
982     
983     public String JavaDoc getQuery(Statement pStatement) {
984         String JavaDoc s;
985         if (pStatement instanceof InsertStatement) {
986             s = getInsertQuery((InsertStatement) pStatement);
987         } else if (pStatement instanceof UpdateStatement) {
988             s = getUpdateQuery((UpdateStatement) pStatement);
989         } else if (pStatement instanceof DeleteStatement) {
990             s = getDeleteQuery((DeleteStatement) pStatement);
991         } else if (pStatement instanceof SelectStatement) {
992             s = getSelectQuery((SelectStatement) pStatement);
993         } else {
994             throw new IllegalArgumentException JavaDoc("The Statement is neither an INSERT, UPDATE, DELETE nor a SELECT statement.");
995         }
996         return newStatement(s);
997     }
998     
999     public Collection JavaDoc getCreate(Schema pSchema, boolean pAll) {
1000        if (!pAll) { return getCreate(pSchema); }
1001        List JavaDoc result = new ArrayList JavaDoc();
1002        result.addAll(getCreate(pSchema));
1003        for (Iterator JavaDoc iter = pSchema.getTables(); iter.hasNext(); ) {
1004            Table table = (Table) iter.next();
1005            result.addAll(getCreate(table, true));
1006        }
1007        return result;
1008    }
1009    
1010    public Collection JavaDoc getDrop(Schema pSchema, boolean pAll) {
1011        if (!pAll) { return getDrop(pSchema); }
1012        List JavaDoc result = new ArrayList JavaDoc();
1013        List JavaDoc tables = new ArrayList JavaDoc();
1014        for (Iterator JavaDoc iter = pSchema.getTables(); iter.hasNext(); ) {
1015            tables.add(iter.next());
1016        }
1017        Collections.reverse(tables);
1018        for (Iterator JavaDoc iter = tables.iterator(); iter.hasNext(); ) {
1019            Table table = (Table) iter.next();
1020            result.addAll(getDrop(table, true));
1021        }
1022        result.addAll(getDrop(pSchema));
1023        return result;
1024    }
1025    
1026    public Collection JavaDoc getCreate(Table pTable, boolean pAll) {
1027        if (!pAll) { return getCreate(pTable); }
1028        List JavaDoc result = new ArrayList JavaDoc();
1029        result.addAll(getCreate(pTable));
1030        for (Iterator JavaDoc iter = pTable.getIndexes(); iter.hasNext(); ) {
1031            Index index = (Index) iter.next();
1032            if (index.isPrimaryKey() && !isPrimaryKeyUniqueIndex()) {
1033                if (isPrimaryKeyPartOfCreateTable()) {
1034                    continue;
1035                }
1036            } else if (index.isUnique()) {
1037                if (isUniqueIndexPartOfCreateTable()) {
1038                    continue;
1039                }
1040            } else {
1041                if (isNonUniqueIndexPartOfCreateTable()) {
1042                    continue;
1043                }
1044            }
1045            result.addAll(getCreate(index));
1046        }
1047        if (!isForeignKeyPartOfCreateTable()) {
1048            for (Iterator JavaDoc iter = pTable.getForeignKeys(); iter.hasNext(); ) {
1049                ForeignKey key = (ForeignKey) iter.next();
1050                result.addAll(getCreate(key));
1051            }
1052        }
1053        return result;
1054    }
1055    
1056    public Collection JavaDoc getDrop(Table pTable, boolean pAll) {
1057        if (!pAll) { return getDrop(pTable); }
1058        List JavaDoc result = new ArrayList JavaDoc();
1059        for (Iterator JavaDoc iter = pTable.getIndexes(); iter.hasNext(); ) {
1060            Index index = (Index) iter.next();
1061            result.addAll(getDrop(index));
1062        }
1063        for (Iterator JavaDoc iter = pTable.getForeignKeys(); iter.hasNext(); ) {
1064            ForeignKey key = (ForeignKey) iter.next();
1065            result.addAll(getDrop(key));
1066        }
1067        result.addAll(getDrop(pTable));
1068        return result;
1069    }
1070    
1071    public Collection JavaDoc getCreate(Index pIndex) {
1072        List JavaDoc result = new ArrayList JavaDoc();
1073        String JavaDoc s = createIndexAsPartOfCreateTable(pIndex);
1074        if (s != null) {
1075            StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
1076            sb.append("CREATE");
1077            if (pIndex.isUnique()) {
1078                sb.append(" UNIQUE");
1079            }
1080            sb.append(" INDEX");
1081            sb.append(" ");
1082            sb.append(pIndex.getName());
1083            sb.append(" ON ").append(pIndex.getTable().getQName()).append(" (");
1084            boolean first = true;
1085            for (Iterator JavaDoc iter = pIndex.getColumns(); iter.hasNext(); ) {
1086                if (first) {
1087                    first = false;
1088                } else {
1089                    sb.append(", ");
1090                }
1091                sb.append(((Column) iter.next()).getName().getName());
1092            }
1093            sb.append(")");
1094            result.add(newStatement(sb.toString()));
1095        }
1096        return result;
1097    }
1098    
1099    public Collection JavaDoc getDrop(Index pIndex) {
1100        return Collections.EMPTY_SET;
1101    }
1102    
1103    public Collection JavaDoc getCreate(ForeignKey pKey) {
1104        List JavaDoc result = new ArrayList JavaDoc();
1105        String JavaDoc s = createForeignKeyAsPartOfCreateTable(pKey);
1106        if (s != null) {
1107            result.add(newStatement("CREATE " + s));
1108        }
1109        return result;
1110    }
1111    
1112    public Collection JavaDoc getDrop(ForeignKey pKey) {
1113        return Collections.EMPTY_SET;
1114    }
1115    
1116    protected StatementMetaData newStatementMetaData(SelectStatement pQuery) {
1117        return new StatementMetaData(pQuery);
1118    }
1119
1120    protected StatementMetaData newStatementMetaData(DeleteStatement pQuery) {
1121        return new StatementMetaData(pQuery);
1122    }
1123
1124    protected StatementMetaData newStatementMetaData(UpdateStatement pQuery, ColumnReference[] pColumns) {
1125        return new StatementMetaData(pQuery, pColumns);
1126    }
1127
1128    protected StatementMetaData newStatementMetaData(InsertStatement pQuery, ColumnReference[] pColumns) {
1129        return new StatementMetaData(pQuery, pColumns);
1130    }
1131
1132    public String JavaDoc getWhereClause(SelectStatement pQuery) {
1133        StatementMetaData metaData = newStatementMetaData(pQuery);
1134        StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
1135
1136        StatementMetaData.LocalData localData = new StatementMetaData.LocalData();
1137        String JavaDoc s = getSelectQueryConstraints(pQuery, metaData, localData);
1138        if (s != null) {
1139            sb.append(s);
1140        }
1141        
1142        s = getSelectQueryOrderClause(metaData, pQuery);
1143        if (s != null) {
1144            sb.append(s);
1145        }
1146
1147        return sb.toString();
1148    }
1149
1150    public String JavaDoc getConstraint(Constraint pConstraint) {
1151        if (pConstraint instanceof CombinedConstraint) {
1152            CombinedConstraint cc = (CombinedConstraint) pConstraint;
1153            Statement st = cc.getConstrainedStatement();
1154            if (st instanceof SelectStatement) {
1155                StatementMetaData selectStatementMetaData = newStatementMetaData((SelectStatement) st);
1156                return getCombinedConstraint(selectStatementMetaData, cc);
1157            } else {
1158                return getCombinedConstraint(null, cc);
1159            }
1160        } else if (pConstraint instanceof BooleanConstraint) {
1161            BooleanConstraint bc = (BooleanConstraint) pConstraint;
1162            Statement st = bc.getConstrainedStatement();
1163            if (st instanceof SelectStatement) {
1164                StatementMetaData selectStatementMetaData = newStatementMetaData((SelectStatement) st);
1165                return getBooleanConstraint(selectStatementMetaData, bc);
1166            } else {
1167                return getBooleanConstraint(null, bc);
1168            }
1169        } else {
1170            throw new IllegalStateException JavaDoc("Invalid type of Constraint: " + pConstraint);
1171        }
1172    }
1173}
1174
Popular Tags