1 17 package org.apache.ws.jaxme.sqls.impl; 18 19 import java.util.ArrayList ; 20 import java.util.Collection ; 21 import java.util.Collections ; 22 import java.util.Iterator ; 23 import java.util.List ; 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 57 public class SQLGeneratorImpl implements SQLGenerator { 58 private String statementTerminator, lineTerminator; 59 60 public String getStatementTerminator() { 61 return statementTerminator; 62 } 63 64 public void setStatementTerminator(String pStatementTerminator) { 65 statementTerminator = pStatementTerminator; 66 } 67 68 public String getLineTerminator() { 69 return lineTerminator; 70 } 71 72 public void setLineTerminator(String pLineTerminator) { 73 lineTerminator = pLineTerminator; 74 } 75 76 protected String newStatement(String pStatement) { 77 String s = getStatementTerminator(); 78 return s == null ? pStatement : pStatement + s; 79 } 80 81 public Collection getCreate(Schema pSchema) { 82 if (pSchema.getName() == null) { 83 return Collections.EMPTY_LIST; 85 } 86 List result = new ArrayList (); 87 result.add(newStatement("CREATE SCHEMA " + pSchema.getName())); 88 return result; 89 } 90 91 public Collection getDrop(Schema pSchema) { 92 if (pSchema.getName() == null) { 93 return Collections.EMPTY_LIST; 95 } 96 List result = new ArrayList (); 97 result.add(newStatement("DROP SCHEMA " + pSchema.getName())); 98 return result; 99 } 100 101 protected String getIndent() { return " "; } 102 103 protected String 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 ("Unknown column type: " + pType); 140 } 141 } 142 143 protected String getCreate(Column pColumn) { 144 StringBuffer sb = new StringBuffer (); 145 sb.append(pColumn.getName()).append(" "); 146 Column.Type type = pColumn.getType(); 147 Long 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 ("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 ("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 180 protected boolean isPrimaryKeyUniqueIndex() { return false; } 181 182 185 protected boolean isPrimaryKeyPartOfCreateTable() { return false; } 186 187 190 protected boolean isUniqueIndexPartOfCreateTable() { return false; } 191 192 195 protected boolean isNonUniqueIndexPartOfCreateTable() { return false; } 196 197 200 protected boolean isForeignKeyPartOfCreateTable() { return false; } 201 202 protected String createPrimaryKeyAsPartOfCreateTable(Table pTable) { 203 Index index = pTable.getPrimaryKey(); 204 if (index == null) { 205 return null; 206 } 207 StringBuffer sb = new StringBuffer (); 208 sb.append("PRIMARY KEY").append(" ("); 209 boolean first = true; 210 for (Iterator 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 createIndexAsPartOfCreateTable(Index pIndex) { 223 StringBuffer sb = new StringBuffer (); 224 sb.append(pIndex.isUnique() ? "UNIQUE" : "KEY").append(" ("); 225 boolean first = true; 226 for (Iterator 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 createForeignKeyAsPartOfCreateTable(ForeignKey pKey) { 239 StringBuffer sb = new StringBuffer (); 240 sb.append("FOREIGN KEY ("); 241 boolean first = true; 242 Iterator iter = pKey.getColumnLinks(); 243 if (!iter.hasNext()) { 244 throw new IllegalStateException ("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 ("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 ("Unknown foreign key mode for ON UPDATE: " + updateMode); 295 } 296 } 297 298 return sb.toString(); 299 } 300 301 protected String getCreateTableHeader(Table pTable) { 302 return "CREATE TABLE " + pTable.getQName(); 303 } 304 305 public Collection getCreate(Table pTable) { 306 String lf = getLineTerminator() == null ? "" : getLineTerminator(); 307 String indent = lf == null ? "" : getIndent(); 308 StringBuffer sb = new StringBuffer (); 309 sb.append(getCreateTableHeader(pTable)).append(" ("); 310 String s = lf + indent; 311 for (Iterator iter = pTable.getColumns(); iter.hasNext(); ) { 312 sb.append(s).append(getCreate((Column) iter.next())); 313 s = "," + lf + indent; 314 } 315 316 for (Iterator iter = pTable.getIndexes(); iter.hasNext(); ) { 317 Index index = (Index) iter.next(); 318 String 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 iter = pTable.getForeignKeys(); iter.hasNext(); ) { 341 ForeignKey key = (ForeignKey) iter.next(); 342 String 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 result = new ArrayList (); 350 result.add(newStatement(sb.toString())); 351 return result; 352 } 353 354 public Collection getDrop(Table pTable) { 355 List result = new ArrayList (); 356 result.add(newStatement("DROP TABLE " + pTable.getQName())); 357 return result; 358 } 359 360 private ColumnReference[] getSetStatementsColumns(SetStatement pStatement) { 361 List result = new ArrayList (); 362 for (Iterator 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 result = new ArrayList (); 375 for (Iterator 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 ("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 pBuffer, 395 StatementMetaData pData, 396 InsertStatement pQuery) { 397 pBuffer.append(" VALUES ("); 398 boolean first = true; 399 for (Iterator 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 o = setValue.getValue(); 407 String s = getBooleanConstraintPart(pData, o); 408 pBuffer.append(s); 409 } 410 pBuffer.append(")"); 411 } 412 413 private void addSubSelectToInsertStatement(StringBuffer pBuffer, StatementMetaData pData, 414 InsertStatement pStatement) { 415 pBuffer.append(" ("); 416 pBuffer.append(getSelectQuery(pStatement.getSubSelect(), pData)); 417 pBuffer.append(")"); 418 } 419 420 public String getInsertQuery(InsertStatement pQuery) { 421 ColumnReference[] columns = getInsertStatementsColumns(pQuery); 422 StatementMetaData smd = newStatementMetaData(pQuery, columns); 423 424 StringBuffer result = new StringBuffer (); 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 ("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 ("Neither values (InsertStatement.addFoo(..)) nor a subselect (InsertStatement.setSubSelect(...)) are set."); 450 } 451 } 452 return newStatement(result.toString()); 453 } 454 455 protected String getValue(Value pValue) { 456 Value.Type type = pValue.getType(); 457 Object o = pValue.getValue(); 458 if (Value.Type.BOOLEAN.equals(type)) { 459 return o == null ? "null" : (((Boolean ) 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 ("Date/time handling not yet implemented."); 471 } else if (Value.Type.DATE.equals(type)) { 472 throw new IllegalStateException ("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 ("Unknown value type: " + type); 481 } 482 } 483 484 protected String getUpdateQuery(UpdateStatement pQuery) { 485 ColumnReference[] columns = getSetStatementsColumns(pQuery); 486 StatementMetaData smd = newStatementMetaData(pQuery, columns); 487 488 StringBuffer sb = new StringBuffer (); 489 sb.append("UPDATE "); 490 sb.append(getTableAlias(smd, pQuery.getTableReference())); 491 sb.append(" SET "); 492 boolean first = true; 493 for (Iterator 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 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 getDeleteQuery(DeleteStatement pQuery) { 512 StatementMetaData smd = newStatementMetaData(pQuery); 513 514 StringBuffer result = new StringBuffer ("DELETE FROM "); 515 result.append(getTableAlias(smd, pQuery.getTableReference())); 516 String 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 num = (Integer ) pData.getColumnNames().get(pColumn.getColumn().getName().toString().toUpperCase()); 529 if (num == null) { 530 throw new IllegalStateException ("Column not in map of column counts: " 531 + pColumn.getColumn().getName()); 532 } 533 return num.intValue() > 1; 534 } 535 536 protected String getFunction(StatementMetaData pData, Function f) { 537 return f.getName() + '(' + getParts(pData, f.getParts()) + ')'; 538 } 539 540 protected String getColumnAlias(StatementMetaData pData, ColumnReference pColumn) { 541 Column col = pColumn.getColumn(); 542 String s = col.getName().toString(); 543 if (col.isVirtual()) { 544 VirtualColumn virtCol = (VirtualColumn) col; 545 Object 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 ) { 551 return ((String ) o) + " AS " + s; 552 } else { 553 throw new IllegalStateException ("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 getColumnAlias(StatementMetaData pData, ColumnReference[] pColumn) { 573 StringBuffer sb = new StringBuffer ("("); 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 getTableAlias(StatementMetaData pData, TableReference pTable) { 585 Table t = pTable.getTable(); 586 String 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 getJoinAlias(StatementMetaData pData, JoinReference pJoinReference) { 606 StringBuffer result = new StringBuffer (); 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 ("Unknown join type"); 613 } 614 result.append(getTableAlias(pData, pJoinReference)); 615 String 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 getEscapedString(String s) { 624 if (s.indexOf('\n') > -1 || s.indexOf('\r') > -1 || s.indexOf('\f') > -1) { 625 throw new IllegalArgumentException ("Don't know how to handle line or page terminators."); 626 } 627 if (s.indexOf('\'') > -1) { 628 throw new IllegalArgumentException ("Don't know how to handle the char ' in strings."); 629 } 630 return "'" + s + "'"; 631 } 632 633 protected String getParts(StatementMetaData pData, Iterator pParts) { 634 StringBuffer sb = new StringBuffer (); 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 getCase(StatementMetaData pData, Case pCase) { 645 StringBuffer sb = new StringBuffer ("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 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 getBooleanConstraintPart(StatementMetaData pData, Object 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 ("Invalid part of a boolean constraint: " + o.getClass().getName()); 683 } 684 } 685 686 protected String getExpression(StatementMetaData pData, Expression pExpr) { 687 int parts = pExpr.getNumParts(); 688 int minParts = pExpr.getMinimumParts(); 689 if (parts < minParts) { 690 throw new IllegalStateException ("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 ("An expression of type " + pExpr.getType() 696 + " must have at least " + maxParts + " parts."); 697 } 698 Iterator iter = pExpr.getParts(); 699 if (parts == 1) { 700 return getBooleanConstraintPart(pData, iter.next()); 701 } else { 702 String 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 ("Invalid type: " + type); 714 } 715 StringBuffer result = new StringBuffer ("("); 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 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 ("Invalid type: " + pType); 744 } 745 } 746 747 protected String getBooleanConstraint(StatementMetaData pData, 748 BooleanConstraint pConstraint) { 749 BooleanConstraint.Type type = pConstraint.getType(); 750 Iterator parts = pConstraint.getParts(); 751 if (!parts.hasNext()) { 752 throw new NullPointerException ("A boolean constraint must have its parts set."); 753 } 754 if (BooleanConstraint.Type.IN.equals(type)) { 755 Object o = parts.next(); 756 return getBooleanConstraintPart(pData, o) + " IN (" + getParts(pData, parts) + ')'; 757 } 758 StringBuffer result = new StringBuffer (); 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 ("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 ("Invalid boolean constraint type: " + type); 796 } 797 } 798 if (expected != 0 && parts.hasNext()) { 799 throw new NullPointerException ("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 getCombinedConstraint(StatementMetaData pData, 807 CombinedConstraint pConstraint) { 808 if (pConstraint.getNumParts() == 0) { 809 return null; 810 } 811 812 List parts = new ArrayList (); 813 for (Iterator iter = pConstraint.getParts(); iter.hasNext(); ) { 814 String s; 815 Object o = iter.next(); 816 if (o == null) { 817 throw new NullPointerException ("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 ("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 ) parts.get(0); 838 } 839 default: 840 StringBuffer sb = new StringBuffer (); 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 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 ("Unknown constraint type: " + 869 pConstraint.getClass().getName()); 870 } 871 } 872 873 protected String getWhereClause(StatementMetaData pData, 874 CombinedConstraint pWhereClause) { 875 return getCombinedConstraint(pData, pWhereClause); 876 } 877 878 protected String getSelectQuery(SelectStatement pQuery) { 879 StatementMetaData selectStatementMetaData = newStatementMetaData(pQuery); 880 return getSelectQuery(pQuery, selectStatementMetaData); 881 } 882 883 884 protected String getSelectQueryResultColumns(SelectStatement pQuery, StatementMetaData pData) { 885 StringBuffer sb = new StringBuffer (); 886 if (pQuery.isDistinct()) { 887 sb.append(" DISTINCT"); 888 } 889 Iterator 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 getSelectQueryFromClause(SelectStatement pQuery, StatementMetaData pData) { 909 SelectTableReference selectTableReference = pQuery.getSelectTableReference(); 910 if (selectTableReference == null) { 911 return null; 912 } 913 StringBuffer sb = new StringBuffer (); 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 getSelectQueryConstraints(SelectStatement pQuery, StatementMetaData pData, 925 StatementMetaData.LocalData pLocalData) { 926 String 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 getSelectQuery(SelectStatement pQuery, StatementMetaData pData) { 934 StringBuffer sb = new StringBuffer ("SELECT"); 935 String 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 getOrderColumn(StatementMetaData pData, SelectStatement.OrderColumn pColumn) { 962 String s = getBooleanConstraintPart(pData, pColumn.getColumn()); 963 if (pColumn.isDescending()) { 964 s += " DESC"; 965 } 966 return s; 967 } 968 969 protected String getSelectQueryOrderClause(StatementMetaData pData, SelectStatement pQuery) { 970 StringBuffer sb = new StringBuffer (); 971 for (Iterator 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 getQuery(Statement pStatement) { 984 String 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 ("The Statement is neither an INSERT, UPDATE, DELETE nor a SELECT statement."); 995 } 996 return newStatement(s); 997 } 998 999 public Collection getCreate(Schema pSchema, boolean pAll) { 1000 if (!pAll) { return getCreate(pSchema); } 1001 List result = new ArrayList (); 1002 result.addAll(getCreate(pSchema)); 1003 for (Iterator 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 getDrop(Schema pSchema, boolean pAll) { 1011 if (!pAll) { return getDrop(pSchema); } 1012 List result = new ArrayList (); 1013 List tables = new ArrayList (); 1014 for (Iterator iter = pSchema.getTables(); iter.hasNext(); ) { 1015 tables.add(iter.next()); 1016 } 1017 Collections.reverse(tables); 1018 for (Iterator 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 getCreate(Table pTable, boolean pAll) { 1027 if (!pAll) { return getCreate(pTable); } 1028 List result = new ArrayList (); 1029 result.addAll(getCreate(pTable)); 1030 for (Iterator 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 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 getDrop(Table pTable, boolean pAll) { 1057 if (!pAll) { return getDrop(pTable); } 1058 List result = new ArrayList (); 1059 for (Iterator iter = pTable.getIndexes(); iter.hasNext(); ) { 1060 Index index = (Index) iter.next(); 1061 result.addAll(getDrop(index)); 1062 } 1063 for (Iterator 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 getCreate(Index pIndex) { 1072 List result = new ArrayList (); 1073 String s = createIndexAsPartOfCreateTable(pIndex); 1074 if (s != null) { 1075 StringBuffer sb = new StringBuffer (); 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 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 getDrop(Index pIndex) { 1100 return Collections.EMPTY_SET; 1101 } 1102 1103 public Collection getCreate(ForeignKey pKey) { 1104 List result = new ArrayList (); 1105 String s = createForeignKeyAsPartOfCreateTable(pKey); 1106 if (s != null) { 1107 result.add(newStatement("CREATE " + s)); 1108 } 1109 return result; 1110 } 1111 1112 public Collection 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 getWhereClause(SelectStatement pQuery) { 1133 StatementMetaData metaData = newStatementMetaData(pQuery); 1134 StringBuffer sb = new StringBuffer (); 1135 1136 StatementMetaData.LocalData localData = new StatementMetaData.LocalData(); 1137 String 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 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 ("Invalid type of Constraint: " + pConstraint); 1171 } 1172 } 1173} 1174 | Popular Tags |