1 /* 2 * Copyright 2015-2018 HuntLabs.cn 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 module hunt.sql.ast.statement.SQLCreateTableStatement; 17 18 19 import hunt.sql.SQLUtils; 20 import hunt.sql.ast; 21 import hunt.sql.ast.expr.SQLIdentifierExpr; 22 import hunt.sql.ast.expr.SQLMethodInvokeExpr; 23 import hunt.sql.ast.expr.SQLPropertyExpr; 24 import hunt.sql.dialect.mysql.ast.MySqlKey; 25 import hunt.sql.dialect.mysql.ast.MySqlUnique; 26 import hunt.sql.dialect.mysql.ast.statement.MySqlTableIndex; 27 // import hunt.sql.dialect.oracle.ast.stmt.OracleCreateSynonymStatement; 28 import hunt.sql.visitor.SQLASTVisitor; 29 import hunt.sql.util.FnvHash; 30 import hunt.sql.util.DBType; 31 import hunt.sql.util.ListDG; 32 import hunt.Functions; 33 import hunt.sql.ast.statement.SQLAlterTableItem; 34 import hunt.sql.ast.statement.SQLColumnDefinition; 35 import hunt.sql.ast.statement.SQLConstraint; 36 import hunt.sql.ast.statement.SQLUniqueConstraint; 37 import hunt.sql.ast.statement.SQLSelectOrderByItem; 38 import hunt.sql.ast.statement.SQLTableElement; 39 import hunt.sql.ast.statement.SQLExprTableSource; 40 41 import hunt.sql.ast.statement.SQLForeignKeyConstraint; 42 import hunt.sql.ast.statement.SQLSelect; 43 import hunt.sql.ast.statement.SQLCreateStatement; 44 import hunt.sql.ast.statement.SQLDDLStatement; 45 import hunt.collection; 46 import hunt.sql.ast.statement.SQLExternalRecordFormat; 47 import hunt.sql.ast.statement.SQLPrimaryKey; 48 import hunt.sql.ast.statement.SQLAlterTableStatement; 49 import hunt.sql.ast.statement.SQLAlterTableRename; 50 import hunt.sql.ast.statement.SQLAlterTableRenameColumn; 51 import hunt.sql.ast.statement.SQLAlterTableDropKey; 52 import hunt.sql.ast.statement.SQLAlterTableDropConstraint; 53 import hunt.sql.ast.statement.SQLAlterTableDropForeignKey; 54 import hunt.sql.ast.statement.SQLAlterTableDropIndex; 55 import hunt.sql.ast.statement.SQLAlterTableDropPrimaryKey; 56 import hunt.sql.ast.statement.SQLAlterTableAddConstraint; 57 import hunt.sql.ast.statement.SQLAlterTableDropColumnItem; 58 import hunt.sql.ast.statement.SQLAlterTableAddIndex; 59 import hunt.sql.ast.statement.SQLAlterTableAddColumn; 60 import hunt.sql.ast.statement.SQLDropIndexStatement; 61 import hunt.sql.ast.statement.SQLCommentStatement; 62 import hunt.String; 63 import std.uni; 64 import hunt.sql.ast.statement.SQLUnique; 65 import hunt.text; 66 67 public class SQLCreateTableStatement : SQLStatementImpl , SQLDDLStatement, SQLCreateStatement { 68 69 protected bool ifNotExiists = false; 70 protected Type type; 71 protected SQLExprTableSource tableSource; 72 73 protected List!SQLTableElement tableElementList; 74 75 // for postgresql 76 protected SQLExprTableSource inherits; 77 78 protected SQLSelect select; 79 80 protected SQLExpr comment; 81 82 protected SQLExprTableSource like; 83 84 protected bool compress; 85 protected bool logging; 86 87 protected SQLName tablespace; 88 protected SQLPartitionBy partitioning; 89 protected SQLName storedAs; 90 91 protected bool onCommitPreserveRows; 92 protected bool onCommitDeleteRows; 93 94 // for hive & odps 95 protected SQLExternalRecordFormat rowFormat; 96 protected List!SQLColumnDefinition partitionColumns; 97 protected List!SQLName clusteredBy; 98 protected List!SQLSelectOrderByItem sortedBy; 99 protected int buckets; 100 101 protected Map!(string, SQLObject) tableOptions; 102 103 public this(){ 104 tableElementList = new ArrayList!SQLTableElement(); 105 partitionColumns = new ArrayList!SQLColumnDefinition(2); 106 clusteredBy = new ArrayList!SQLName(); 107 sortedBy = new ArrayList!SQLSelectOrderByItem(); 108 tableOptions = new LinkedHashMap!(string, SQLObject)(); 109 } 110 111 public this(string dbType){ 112 tableElementList = new ArrayList!SQLTableElement(); 113 partitionColumns = new ArrayList!SQLColumnDefinition(2); 114 clusteredBy = new ArrayList!SQLName(); 115 sortedBy = new ArrayList!SQLSelectOrderByItem(); 116 tableOptions = new LinkedHashMap!(string, SQLObject)(); 117 super(dbType); 118 } 119 120 public SQLExpr getComment() { 121 return comment; 122 } 123 124 public void setComment(SQLExpr comment) { 125 if (comment !is null) { 126 comment.setParent(this); 127 } 128 this.comment = comment; 129 } 130 131 public SQLName getName() { 132 if (tableSource is null) { 133 return null; 134 } 135 136 return cast(SQLName) tableSource.getExpr(); 137 } 138 139 public string getSchema() { 140 SQLName name = getName(); 141 if (name is null) { 142 return null; 143 } 144 145 if (cast(SQLPropertyExpr)(name) !is null ) { 146 return (cast(SQLPropertyExpr) name).getOwnernName(); 147 } 148 149 return null; 150 } 151 152 public void setSchema(string name) { 153 if (this.tableSource is null) { 154 return; 155 } 156 tableSource.setSchema(name); 157 } 158 159 public void setName(SQLName name) { 160 this.setTableSource(new SQLExprTableSource(name)); 161 } 162 163 public void setName(string name) { 164 this.setName(new SQLIdentifierExpr(name)); 165 } 166 167 public SQLExprTableSource getTableSource() { 168 return tableSource; 169 } 170 171 public void setTableSource(SQLExprTableSource tableSource) { 172 if (tableSource !is null) { 173 tableSource.setParent(this); 174 } 175 this.tableSource = tableSource; 176 } 177 178 public Type getType() { 179 return type; 180 } 181 182 public void setType(Type type) { 183 this.type = type; 184 } 185 186 public static enum Type { 187 GLOBAL_TEMPORARY, LOCAL_TEMPORARY 188 } 189 190 public List!SQLTableElement getTableElementList() { 191 return tableElementList; 192 } 193 194 public bool isIfNotExiists() { 195 return ifNotExiists; 196 } 197 198 public void setIfNotExiists(bool ifNotExiists) { 199 this.ifNotExiists = ifNotExiists; 200 } 201 202 public SQLExprTableSource getInherits() { 203 return inherits; 204 } 205 206 public void setInherits(SQLExprTableSource inherits) { 207 if (inherits !is null) { 208 inherits.setParent(this); 209 } 210 this.inherits = inherits; 211 } 212 213 public SQLSelect getSelect() { 214 return select; 215 } 216 217 public void setSelect(SQLSelect select) { 218 if (select !is null) { 219 select.setParent(this); 220 } 221 this.select = select; 222 } 223 224 public SQLExprTableSource getLike() { 225 return like; 226 } 227 228 public void setLike(SQLName like) { 229 this.setLike(new SQLExprTableSource(like)); 230 } 231 232 public void setLike(SQLExprTableSource like) { 233 if (like !is null) { 234 like.setParent(this); 235 } 236 this.like = like; 237 } 238 239 public bool getCompress() { 240 return compress; 241 } 242 243 public void setCompress(bool compress) { 244 this.compress = compress; 245 } 246 247 public bool getLogging() { 248 return logging; 249 } 250 251 public void setLogging(bool logging) { 252 this.logging = logging; 253 } 254 255 public SQLName getTablespace() { 256 return tablespace; 257 } 258 259 public void setTablespace(SQLName tablespace) { 260 if (tablespace !is null) { 261 tablespace.setParent(this); 262 } 263 this.tablespace = tablespace; 264 } 265 266 public SQLPartitionBy getPartitioning() { 267 return partitioning; 268 } 269 270 public void setPartitioning(SQLPartitionBy partitioning) { 271 if (partitioning !is null) { 272 partitioning.setParent(this); 273 } 274 275 this.partitioning = partitioning; 276 } 277 278 public Map!(string, SQLObject) getTableOptions() { 279 return tableOptions; 280 } 281 282 283 override protected void accept0(SQLASTVisitor visitor) { 284 if (visitor.visit(this)) { 285 this.acceptChild(visitor, tableSource); 286 this.acceptChild!SQLTableElement(visitor, tableElementList); 287 this.acceptChild(visitor, inherits); 288 this.acceptChild(visitor, select); 289 } 290 visitor.endVisit(this); 291 } 292 293 override 294 public List!SQLObject getChildren() { 295 List!SQLObject children = new ArrayList!SQLObject(); 296 children.add(tableSource); 297 children.addAll(cast(List!SQLObject)(tableElementList)); 298 if (inherits !is null) { 299 children.add(inherits); 300 } 301 if (select !is null) { 302 children.add(select); 303 } 304 return children; 305 } 306 307 public void addBodyBeforeComment(List!string comments) { 308 if (attributes is null) { 309 attributes = new HashMap!(string, Object)(); 310 } 311 312 List!string attrComments = cast(List!string) attributes.get("format.body_before_comment"); 313 if (attrComments is null) { 314 attributes.put("format.body_before_comment", cast(Object)comments); 315 } else { 316 attrComments.addAll(comments); 317 } 318 } 319 320 public List!string getBodyBeforeCommentsDirect() { 321 if (attributes is null) { 322 return null; 323 } 324 325 return cast(List!string) attributes.get("format.body_before_comment"); 326 } 327 328 public bool hasBodyBeforeComment() { 329 List!string comments = getBodyBeforeCommentsDirect(); 330 if (comments is null) { 331 return false; 332 } 333 334 return !comments.isEmpty(); 335 } 336 337 public string computeName() { 338 if (tableSource is null) { 339 return null; 340 } 341 342 SQLExpr expr = tableSource.getExpr(); 343 if (cast(SQLName)(expr) !is null ) { 344 string name = (cast(SQLName) expr).getSimpleName(); 345 return SQLUtils.normalize(name); 346 } 347 348 return null; 349 } 350 351 public SQLColumnDefinition findColumn(string columName) { 352 if (columName is null) { 353 return null; 354 } 355 356 long hash = FnvHash.hashCode64(columName); 357 return findColumn(hash); 358 } 359 360 public SQLColumnDefinition findColumn(long columName_hash) { 361 foreach (SQLTableElement element ; tableElementList) { 362 if (cast(SQLColumnDefinition)(element) !is null ) { 363 SQLColumnDefinition column = cast(SQLColumnDefinition) element; 364 SQLName columnName = column.getName(); 365 if (columnName !is null && columnName.nameHashCode64() == columName_hash) { 366 return column; 367 } 368 } 369 } 370 371 return null; 372 } 373 374 public bool isPrimaryColumn(string columnName) { 375 SQLPrimaryKey pk = this.findPrimaryKey(); 376 if (pk is null) { 377 return false; 378 } 379 380 return pk.containsColumn(columnName); 381 } 382 383 /** 384 * only for show columns 385 */ 386 public bool isMUL(string columnName) { 387 foreach (SQLTableElement element ; this.tableElementList) { 388 if (cast(MySqlUnique)(element) !is null ) { 389 MySqlUnique unique = cast(MySqlUnique) element; 390 391 SQLExpr column = unique.getColumns().get(0).getExpr(); 392 if ( (cast(SQLIdentifierExpr)column !is null) 393 && SQLUtils.nameEquals(columnName, (cast(SQLIdentifierExpr) column).getName())) { 394 return unique.columns.size() > 1; 395 } else if ( (cast(SQLMethodInvokeExpr)column !is null) 396 && SQLUtils.nameEquals((cast(SQLMethodInvokeExpr) column).getMethodName(), columnName)) { 397 return true; 398 } 399 } else if (cast(MySqlKey)(element) !is null ) { 400 MySqlKey unique = cast(MySqlKey) element; 401 402 SQLExpr column = unique.getColumns().get(0).getExpr(); 403 if ( (cast(SQLIdentifierExpr)column !is null) 404 && SQLUtils.nameEquals(columnName, (cast(SQLIdentifierExpr) column).getName())) { 405 return true; 406 } else if ( (cast(SQLMethodInvokeExpr)column !is null) 407 && SQLUtils.nameEquals((cast(SQLMethodInvokeExpr) column).getMethodName(), columnName)) { 408 return true; 409 } 410 } 411 } 412 return false; 413 } 414 415 /** 416 * only for show columns 417 */ 418 public bool isUNI(string columnName) { 419 foreach (SQLTableElement element ; this.tableElementList) { 420 if (cast(MySqlUnique)(element) !is null ) { 421 MySqlUnique unique = cast(MySqlUnique) element; 422 423 if (unique.getColumns().size() == 0) { 424 continue; 425 } 426 427 SQLExpr column = unique.getColumns().get(0).getExpr(); 428 if ( (cast(SQLIdentifierExpr)column !is null) 429 && SQLUtils.nameEquals(columnName, (cast(SQLIdentifierExpr) column).getName())) { 430 return unique.columns.size() == 1; 431 } else if ( (cast(SQLMethodInvokeExpr)column !is null) 432 && SQLUtils.nameEquals((cast(SQLMethodInvokeExpr) column).getMethodName(), columnName)) { 433 return true; 434 } 435 } 436 } 437 return false; 438 } 439 440 public MySqlUnique findUnique(string columnName) { 441 foreach (SQLTableElement element ; this.tableElementList) { 442 if (cast(MySqlUnique)(element) !is null ) { 443 MySqlUnique unique = cast(MySqlUnique) element; 444 445 if (unique.containsColumn(columnName)) { 446 return unique; 447 } 448 } 449 } 450 451 return null; 452 } 453 454 public SQLTableElement findIndex(string columnName) { 455 foreach (SQLTableElement element ; tableElementList) { 456 if (cast(SQLUniqueConstraint)(element) !is null ) { 457 SQLUniqueConstraint unique = cast(SQLUniqueConstraint) element; 458 foreach (SQLSelectOrderByItem item ; unique.getColumns()) { 459 SQLExpr columnExpr = item.getExpr(); 460 if (cast(SQLIdentifierExpr)(columnExpr) !is null ) { 461 string keyColumName = (cast(SQLIdentifierExpr) columnExpr).getName(); 462 keyColumName = SQLUtils.normalize(keyColumName); 463 if (equalsIgnoreCase(keyColumName, columnName)) { 464 return element; 465 } 466 } 467 } 468 469 } else if (cast(MySqlTableIndex)(element) !is null ) { 470 List!SQLSelectOrderByItem indexColumns = (cast(MySqlTableIndex) element).getColumns(); 471 foreach (SQLSelectOrderByItem orderByItem ; indexColumns) { 472 SQLExpr columnExpr = orderByItem.getExpr(); 473 if (cast(SQLIdentifierExpr)(columnExpr) !is null ) { 474 string keyColumName = (cast(SQLIdentifierExpr) columnExpr).getName(); 475 keyColumName = SQLUtils.normalize(keyColumName); 476 if (equalsIgnoreCase(keyColumName, columnName)) { 477 return element; 478 } 479 } 480 } 481 } 482 483 } 484 485 return null; 486 } 487 488 public void forEachColumn(Consumer!SQLColumnDefinition columnConsumer) { 489 if (columnConsumer is null) { 490 return; 491 } 492 493 foreach (SQLTableElement element ; this.tableElementList) { 494 if (cast(SQLColumnDefinition)(element) !is null ) { 495 columnConsumer(cast(SQLColumnDefinition) element); 496 } 497 } 498 } 499 500 public SQLPrimaryKey findPrimaryKey() { 501 foreach (SQLTableElement element ; this.tableElementList) { 502 if (cast(SQLPrimaryKey)(element) !is null ) { 503 return cast(SQLPrimaryKey) element; 504 } 505 } 506 507 return null; 508 } 509 510 public List!SQLForeignKeyConstraint findForeignKey() { 511 List!SQLForeignKeyConstraint fkList = new ArrayList!SQLForeignKeyConstraint(); 512 foreach (SQLTableElement element ; this.tableElementList) { 513 if (cast(SQLForeignKeyConstraint)(element) !is null ) { 514 fkList.add(cast(SQLForeignKeyConstraint) element); 515 } 516 } 517 return fkList; 518 } 519 520 public bool hashForeignKey() { 521 foreach (SQLTableElement element ; this.tableElementList) { 522 if (cast(SQLForeignKeyConstraint)(element) !is null ) { 523 return true; 524 } 525 } 526 return false; 527 } 528 529 public bool isReferenced(SQLName tableName) { 530 if (tableName is null) { 531 return false; 532 } 533 534 return isReferenced(tableName.getSimpleName()); 535 } 536 537 public bool isReferenced(string tableName) { 538 if (tableName is null) { 539 return false; 540 } 541 542 tableName = SQLUtils.normalize(tableName); 543 544 foreach (SQLTableElement element ; this.tableElementList) { 545 if (cast(SQLForeignKeyConstraint)(element) !is null ) { 546 SQLForeignKeyConstraint fk = cast(SQLForeignKeyConstraint) element; 547 string refTableName = fk.getReferencedTableName().getSimpleName(); 548 549 if (SQLUtils.nameEquals(tableName, refTableName)) { 550 return true; 551 } 552 } 553 } 554 555 return false; 556 } 557 558 public SQLAlterTableStatement foreignKeyToAlterTable() { 559 SQLAlterTableStatement stmt = new SQLAlterTableStatement(); 560 for (int i = this.tableElementList.size() - 1; i >= 0; --i) { 561 SQLTableElement element = this.tableElementList.get(i); 562 if (cast(SQLForeignKeyConstraint)(element) !is null ) { 563 SQLForeignKeyConstraint fk = cast(SQLForeignKeyConstraint) element; 564 this.tableElementList.removeAt(i); 565 stmt.addItem(new SQLAlterTableAddConstraint(fk)); 566 } 567 } 568 569 if (stmt.getItems().size() == 0) { 570 return null; 571 } 572 573 stmt.setDbType(getDbType()); 574 stmt.setTableSource(this.tableSource.clone()); 575 576 // Collections.reverse(stmt.getItems()); @gxc 577 578 return stmt; 579 } 580 581 public static void sort(List!SQLStatement stmtList) { 582 Map!(string, SQLCreateTableStatement) tables = new HashMap!(string, SQLCreateTableStatement)(); 583 Map!(string, List!SQLCreateTableStatement) referencedTables = new HashMap!(string, List!SQLCreateTableStatement)(); 584 585 foreach (SQLStatement stmt ; stmtList) { 586 if (cast(SQLCreateTableStatement)(stmt) !is null ) { 587 SQLCreateTableStatement createTableStmt = cast(SQLCreateTableStatement) stmt; 588 string tableName = createTableStmt.getName().getSimpleName(); 589 tableName = toLower(SQLUtils.normalize(tableName)); 590 tables.put(tableName, createTableStmt); 591 } 592 } 593 594 List!(ListDG.Edge) edges = new ArrayList!(ListDG.Edge)(); 595 596 foreach (SQLCreateTableStatement stmt ; tables.values()) { 597 foreach (SQLTableElement element ; stmt.getTableElementList()) { 598 if (cast(SQLForeignKeyConstraint)(element) !is null ) { 599 SQLForeignKeyConstraint fk = cast(SQLForeignKeyConstraint) element; 600 string refTableName = fk.getReferencedTableName().getSimpleName(); 601 refTableName = toLower(SQLUtils.normalize(refTableName)); 602 603 SQLCreateTableStatement refTable = tables.get(refTableName); 604 if (refTable !is null) { 605 edges.add(new ListDG.Edge(stmt, refTable)); 606 } 607 608 List!SQLCreateTableStatement referencedList = referencedTables.get(refTableName); 609 if (referencedList is null) { 610 referencedList = new ArrayList!SQLCreateTableStatement(); 611 referencedTables.put(refTableName, referencedList); 612 } 613 referencedList.add(stmt); 614 } 615 } 616 } 617 618 // foreach (SQLStatement stmt ; stmtList) { 619 // if (cast(OracleCreateSynonymStatement)(stmt) !is null ) { 620 // OracleCreateSynonymStatement createSynonym = cast(OracleCreateSynonymStatement) stmt; 621 // SQLName object = createSynonym.getObject(); 622 // string refTableName = object.getSimpleName(); 623 // SQLCreateTableStatement refTable = tables.get(refTableName); 624 // if (refTable !is null) { 625 // edges.add(new ListDG.Edge(stmt, refTable)); 626 // } 627 // } 628 // } 629 630 ListDG dg = new ListDG(cast(List!Object)stmtList, edges); 631 632 SQLStatement[] tops = new SQLStatement[stmtList.size()]; 633 if (dg.topologicalSort(cast(Object[])tops)) { 634 for (int i = 0, size = stmtList.size(); i < size; ++i) { 635 stmtList.set(i, tops[size - i - 1]); 636 } 637 return; 638 } 639 640 List!SQLAlterTableStatement alterList = new ArrayList!SQLAlterTableStatement(); 641 642 for (int i = edges.size() - 1; i >= 0; --i) { 643 ListDG.Edge edge = edges.get(i); 644 SQLCreateTableStatement from = cast(SQLCreateTableStatement) edge.from; 645 string fromTableName = from.getName().getSimpleName(); 646 fromTableName = toLower(SQLUtils.normalize(fromTableName)); 647 if (referencedTables.containsKey(fromTableName)) { 648 edges.removeAt(i); 649 650 //Arrays.fill(tops, null);@gxc 651 tops = new SQLStatement[stmtList.size()]; 652 653 dg = new ListDG(cast(List!Object)stmtList, edges); 654 if (dg.topologicalSort(cast(Object[])tops)) { 655 for (int j = 0, size = stmtList.size(); j < size; ++j) { 656 SQLStatement stmt = tops[size - j - 1]; 657 stmtList.set(j, stmt); 658 } 659 660 SQLAlterTableStatement alter = from.foreignKeyToAlterTable(); 661 alterList.add(alter); 662 663 stmtList.add(alter); 664 return; 665 } 666 edges.add(i, edge); 667 } 668 } 669 670 for (int i = edges.size() - 1; i >= 0; --i) { 671 ListDG.Edge edge = edges.get(i); 672 SQLCreateTableStatement from = cast(SQLCreateTableStatement) edge.from; 673 string fromTableName = from.getName().getSimpleName(); 674 fromTableName = toLower(SQLUtils.normalize(fromTableName)); 675 if (referencedTables.containsKey(fromTableName)) { 676 SQLAlterTableStatement alter = from.foreignKeyToAlterTable(); 677 678 edges.removeAt(i); 679 if (alter !is null) { 680 alterList.add(alter); 681 } 682 683 // Arrays.fill(tops, null);@gxc 684 tops = new SQLStatement[stmtList.size()]; 685 686 dg = new ListDG(cast(List!Object)stmtList, edges); 687 if (dg.topologicalSort(cast(Object[])tops)) { 688 for (int j = 0, size = stmtList.size(); j < size; ++j) { 689 SQLStatement stmt = tops[size - j - 1]; 690 stmtList.set(j, stmt); 691 } 692 693 stmtList.addAll(cast(List!SQLStatement)alterList); 694 return; 695 } 696 } 697 } 698 } 699 700 public void simplify() { 701 SQLName name = getName(); 702 if (cast(SQLPropertyExpr)(name) !is null ) { 703 string tableName = (cast(SQLPropertyExpr) name).getName(); 704 tableName = SQLUtils.normalize(tableName); 705 706 string normalized = SQLUtils.normalize(tableName, dbType); 707 if (tableName != normalized) { 708 this.setName(normalized); 709 name = getName(); 710 } 711 } 712 713 if (cast(SQLIdentifierExpr)(name) !is null ) { 714 SQLIdentifierExpr identExpr = cast(SQLIdentifierExpr) name; 715 string tableName = identExpr.getName(); 716 string normalized = SQLUtils.normalize(tableName, dbType); 717 if (normalized != tableName) { 718 setName(normalized); 719 } 720 } 721 722 foreach (SQLTableElement element ; this.tableElementList) { 723 if (cast(SQLColumnDefinition)(element) !is null ) { 724 SQLColumnDefinition column = cast(SQLColumnDefinition) element; 725 column.simplify(); 726 } else if (cast(SQLConstraint)(element) !is null ) { 727 (cast(SQLConstraint) element).simplify(); 728 } 729 } 730 } 731 732 public bool apply(SQLDropIndexStatement x) { 733 long indexNameHashCode64 = x.getIndexName().nameHashCode64(); 734 735 for (int i = tableElementList.size() - 1; i >= 0; i--) { 736 SQLTableElement e = tableElementList.get(i); 737 if (cast(SQLUniqueConstraint)(e) !is null ) { 738 SQLUniqueConstraint unique = cast(SQLUniqueConstraint) e; 739 if (unique.getName().nameHashCode64() == indexNameHashCode64) { 740 tableElementList.removeAt(i); 741 return true; 742 } 743 744 } else if (cast(MySqlTableIndex)(e) !is null ) { 745 MySqlTableIndex tableIndex = cast(MySqlTableIndex) e; 746 if (SQLUtils.nameEquals(tableIndex.getName(), x.getIndexName())) { 747 tableElementList.removeAt(i); 748 return true; 749 } 750 } 751 } 752 return false; 753 } 754 755 public bool apply(SQLCommentStatement x) { 756 SQLName on = x.getOn().getName(); 757 SQLExpr comment = x.getComment(); 758 if (comment is null) { 759 return false; 760 } 761 762 SQLCommentStatement.Type type = x.getType(); 763 if (type == SQLCommentStatement.Type.TABLE) { 764 if (!SQLUtils.nameEquals(getName(), on)) { 765 return false; 766 } 767 768 setComment(comment.clone()); 769 770 return true; 771 } else if (type == SQLCommentStatement.Type.COLUMN) { 772 SQLPropertyExpr propertyExpr = cast(SQLPropertyExpr) on; 773 if (!SQLUtils.nameEquals(getName(), cast(SQLName) propertyExpr.getOwner())) { 774 return false; 775 } 776 777 SQLColumnDefinition column 778 = this.findColumn( 779 propertyExpr.nameHashCode64()); 780 781 if (column !is null) { 782 column.setComment(comment.clone()); 783 } 784 return true; 785 } 786 787 return false; 788 } 789 790 public bool apply(SQLAlterTableStatement alter) { 791 if (!SQLUtils.nameEquals(alter.getName(), this.getName())) { 792 return false; 793 } 794 795 int applyCount = 0; 796 foreach (SQLAlterTableItem item ; alter.getItems()) { 797 if (alterApply(item)) { 798 applyCount++; 799 } 800 } 801 802 return applyCount > 0; 803 } 804 805 protected bool alterApply(SQLAlterTableItem item) { 806 if (cast(SQLAlterTableDropColumnItem)(item) !is null ) { 807 return apply(cast(SQLAlterTableDropColumnItem) item); 808 809 } else if (cast(SQLAlterTableAddColumn)(item) !is null ) { 810 return apply(cast(SQLAlterTableAddColumn) item); 811 812 } else if (cast(SQLAlterTableAddConstraint)(item) !is null ) { 813 return apply(cast(SQLAlterTableAddConstraint) item); 814 815 } else if (cast(SQLAlterTableDropPrimaryKey)(item) !is null ) { 816 return apply(cast(SQLAlterTableDropPrimaryKey) item); 817 818 } else if (cast(SQLAlterTableDropIndex)(item) !is null ) { 819 return apply(cast(SQLAlterTableDropIndex) item); 820 821 } else if (cast(SQLAlterTableDropConstraint)(item) !is null ) { 822 return apply(cast(SQLAlterTableDropConstraint) item); 823 824 } else if (cast(SQLAlterTableDropKey)(item) !is null ) { 825 return apply(cast(SQLAlterTableDropKey) item); 826 827 } else if (cast(SQLAlterTableDropForeignKey)(item) !is null ) { 828 return apply(cast(SQLAlterTableDropForeignKey) item); 829 830 } else if (cast(SQLAlterTableRename)(item) !is null ) { 831 return apply(cast(SQLAlterTableRename) item); 832 833 } else if (cast(SQLAlterTableRenameColumn)(item) !is null ) { 834 return apply(cast(SQLAlterTableRenameColumn) item); 835 836 } else if (cast(SQLAlterTableAddIndex)(item) !is null ) { 837 return apply(cast(SQLAlterTableAddIndex) item); 838 } 839 840 return false; 841 } 842 843 // SQLAlterTableRenameColumn 844 845 private bool apply(SQLAlterTableRenameColumn item) { 846 int columnIndex = columnIndexOf(item.getColumn()); 847 if (columnIndex == -1) { 848 return false; 849 } 850 851 SQLColumnDefinition column = cast(SQLColumnDefinition) tableElementList.get(columnIndex); 852 column.setName(item.getTo().clone()); 853 854 return true; 855 } 856 857 public bool renameColumn(string colummName, string newColumnName) { 858 if (colummName is null || newColumnName is null || newColumnName.length == 0) { 859 return false; 860 } 861 862 int columnIndex = columnIndexOf(new SQLIdentifierExpr(colummName)); 863 if (columnIndex == -1) { 864 return false; 865 } 866 867 SQLColumnDefinition column = cast(SQLColumnDefinition) tableElementList.get(columnIndex); 868 column.setName(new SQLIdentifierExpr(newColumnName)); 869 870 return true; 871 } 872 873 private bool apply(SQLAlterTableRename item) { 874 SQLName name = item.getToName(); 875 if (name is null) { 876 return false; 877 } 878 879 this.setName(name.clone()); 880 881 return true; 882 } 883 884 private bool apply(SQLAlterTableDropForeignKey item) { 885 for (int i = tableElementList.size() - 1; i >= 0; i--) { 886 SQLTableElement e = tableElementList.get(i); 887 if (cast(SQLUniqueConstraint)(e) !is null ) { 888 SQLForeignKeyConstraint fk = cast(SQLForeignKeyConstraint) e; 889 if (SQLUtils.nameEquals(fk.getName(), item.getIndexName())) { 890 tableElementList.removeAt(i); 891 return true; 892 } 893 } 894 } 895 return false; 896 } 897 898 private bool apply(SQLAlterTableDropKey item) { 899 for (int i = tableElementList.size() - 1; i >= 0; i--) { 900 SQLTableElement e = tableElementList.get(i); 901 if (cast(SQLUniqueConstraint)(e) !is null ) { 902 SQLUniqueConstraint unique = cast(SQLUniqueConstraint) e; 903 if (SQLUtils.nameEquals(unique.getName(), item.getKeyName())) { 904 tableElementList.removeAt(i); 905 return true; 906 } 907 } 908 } 909 return false; 910 } 911 912 private bool apply(SQLAlterTableDropConstraint item) { 913 for (int i = tableElementList.size() - 1; i >= 0; i--) { 914 SQLTableElement e = tableElementList.get(i); 915 if (cast(SQLConstraint)(e) !is null ) { 916 SQLConstraint constraint = cast(SQLConstraint) e; 917 if (SQLUtils.nameEquals(constraint.getName(), item.getConstraintName())) { 918 tableElementList.removeAt(i); 919 return true; 920 } 921 } 922 } 923 return false; 924 } 925 926 private bool apply(SQLAlterTableDropIndex item) { 927 for (int i = tableElementList.size() - 1; i >= 0; i--) { 928 SQLTableElement e = tableElementList.get(i); 929 if (cast(SQLUniqueConstraint)(e) !is null ) { 930 SQLUniqueConstraint unique = cast(SQLUniqueConstraint) e; 931 if (SQLUtils.nameEquals(unique.getName(), item.getIndexName())) { 932 tableElementList.removeAt(i); 933 return true; 934 } 935 936 } else if (cast(MySqlTableIndex)(e) !is null ) { 937 MySqlTableIndex tableIndex = cast(MySqlTableIndex) e; 938 if (SQLUtils.nameEquals(tableIndex.getName(), item.getIndexName())) { 939 tableElementList.removeAt(i); 940 return true; 941 } 942 } 943 } 944 return false; 945 } 946 947 private bool apply(SQLAlterTableDropPrimaryKey item) { 948 for (int i = tableElementList.size() - 1; i >= 0; i--) { 949 SQLTableElement e = tableElementList.get(i); 950 if (cast(SQLPrimaryKey)(e) !is null ) { 951 tableElementList.removeAt(i); 952 return true; 953 } 954 } 955 return false; 956 } 957 958 private bool apply(SQLAlterTableAddConstraint item) { 959 tableElementList.add(cast(SQLTableElement) item.getConstraint()); 960 return true; 961 } 962 963 private bool apply(SQLAlterTableDropColumnItem item) { 964 foreach (SQLName column ; item.getColumns()) { 965 string columnName = column.getSimpleName(); 966 for (int i = tableElementList.size() - 1; i >= 0; --i) { 967 SQLTableElement e = tableElementList.get(i); 968 if (cast(SQLColumnDefinition)(e) !is null ) { 969 if (SQLUtils.nameEquals(columnName, (cast(SQLColumnDefinition) e).getName().getSimpleName())) { 970 tableElementList.removeAt(i); 971 } 972 } 973 } 974 975 for (int i = tableElementList.size() - 1; i >= 0; --i) { 976 SQLTableElement e = tableElementList.get(i); 977 if (cast(SQLUnique)(e) !is null ) { 978 SQLUnique unique = cast(SQLUnique) e; 979 unique.applyDropColumn(column); 980 if (unique.getColumns().size() == 0) { 981 tableElementList.removeAt(i); 982 } 983 } else if (cast(MySqlTableIndex)(e) !is null ) { 984 MySqlTableIndex index = cast(MySqlTableIndex) e; 985 index.applyDropColumn(column); 986 if (index.getColumns().size() == 0) { 987 tableElementList.removeAt(i); 988 } 989 } 990 } 991 } 992 993 994 995 return true; 996 } 997 998 protected bool apply(SQLAlterTableAddIndex item) { 999 return false; 1000 } 1001 1002 private bool apply(SQLAlterTableAddColumn item) { 1003 int startIndex = tableElementList.size(); 1004 if (item.isFirst()) { 1005 startIndex = 0; 1006 } 1007 1008 int afterIndex = columnIndexOf(item.getAfterColumn()); 1009 if (afterIndex != -1) { 1010 startIndex = afterIndex + 1; 1011 } 1012 1013 int beforeIndex = columnIndexOf(item.getFirstColumn()); 1014 if (beforeIndex != -1) { 1015 startIndex = beforeIndex; 1016 } 1017 1018 for (int i = 0; i < item.getColumns().size(); i++) { 1019 SQLColumnDefinition column = item.getColumns().get(i); 1020 tableElementList.add(i + startIndex, column); 1021 column.setParent(this); 1022 } 1023 1024 return true; 1025 } 1026 1027 protected int columnIndexOf(SQLName column) { 1028 if (column is null) { 1029 return -1; 1030 } 1031 1032 string columnName = column.getSimpleName(); 1033 for (int i = tableElementList.size() - 1; i >= 0; --i) { 1034 SQLTableElement e = tableElementList.get(i); 1035 if (cast(SQLColumnDefinition)(e) !is null ) { 1036 if (SQLUtils.nameEquals(columnName, (cast(SQLColumnDefinition) e).getName().getSimpleName())) { 1037 return i; 1038 } 1039 } 1040 } 1041 1042 return -1; 1043 } 1044 1045 public void cloneTo(SQLCreateTableStatement x) { 1046 x.ifNotExiists = ifNotExiists; 1047 x.type = type; 1048 if (tableSource !is null) { 1049 x.setTableSource(tableSource.clone()); 1050 } 1051 foreach (SQLTableElement e ; tableElementList) { 1052 SQLTableElement e2 = e.clone(); 1053 e2.setParent(x); 1054 x.tableElementList.add(e2); 1055 } 1056 if (inherits !is null) { 1057 x.setInherits(inherits.clone()); 1058 } 1059 if (select !is null) { 1060 x.setSelect(select.clone()); 1061 } 1062 if (comment !is null) { 1063 x.setComment(comment.clone()); 1064 } 1065 1066 x.onCommitPreserveRows = onCommitPreserveRows; 1067 x.onCommitDeleteRows = onCommitDeleteRows; 1068 1069 if (tableOptions !is null) { 1070 foreach (string k, SQLObject v; tableOptions) { 1071 SQLObject entryVal = v.clone(); 1072 x.tableOptions.put(k, entryVal); 1073 } 1074 } 1075 } 1076 1077 public SQLName getStoredAs() { 1078 return storedAs; 1079 } 1080 1081 public void setStoredAs(SQLName x) { 1082 if (x !is null) { 1083 x.setParent(this); 1084 } 1085 this.storedAs = x; 1086 } 1087 1088 override public SQLCreateTableStatement clone() { 1089 SQLCreateTableStatement x = new SQLCreateTableStatement(dbType); 1090 cloneTo(x); 1091 return x; 1092 } 1093 1094 override public string toString() { 1095 return SQLUtils.toSQLString(this, dbType); 1096 } 1097 1098 public bool isOnCommitPreserveRows() { 1099 return onCommitPreserveRows; 1100 } 1101 1102 public void setOnCommitPreserveRows(bool onCommitPreserveRows) { 1103 this.onCommitPreserveRows = onCommitPreserveRows; 1104 } 1105 1106 public List!SQLName getClusteredBy() { 1107 return clusteredBy; 1108 } 1109 1110 public List!SQLSelectOrderByItem getSortedBy() { 1111 return sortedBy; 1112 } 1113 1114 public void addSortedByItem(SQLSelectOrderByItem item) { 1115 item.setParent(this); 1116 this.sortedBy.add(item); 1117 } 1118 1119 public int getBuckets() { 1120 return buckets; 1121 } 1122 1123 public void setBuckets(int buckets) { 1124 this.buckets = buckets; 1125 } 1126 1127 public List!SQLColumnDefinition getPartitionColumns() { 1128 return partitionColumns; 1129 } 1130 1131 public void addPartitionColumn(SQLColumnDefinition column) { 1132 if (column !is null) { 1133 column.setParent(this); 1134 } 1135 this.partitionColumns.add(column); 1136 } 1137 1138 public SQLExternalRecordFormat getRowFormat() { 1139 return rowFormat; 1140 } 1141 1142 public void setRowFormat(SQLExternalRecordFormat x) { 1143 if (x !is null) { 1144 x.setParent(this); 1145 } 1146 this.rowFormat = x; 1147 } 1148 1149 public bool isPrimaryColumn(long columnNameHash) { 1150 SQLPrimaryKey pk = this.findPrimaryKey(); 1151 if (pk is null) { 1152 return false; 1153 } 1154 1155 return pk.containsColumn(columnNameHash); 1156 } 1157 }