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.dialect.mysql.ast.statement.MySqlCreateTableStatement; 17 18 import hunt.collection; 19 20 import hunt.sql.SQLUtils; 21 import hunt.sql.ast; 22 import hunt.sql.ast.statement; 23 import hunt.sql.dialect.mysql.ast.MySqlKey; 24 import hunt.sql.dialect.mysql.ast.MySqlObjectImpl; 25 import hunt.sql.dialect.mysql.ast.MySqlUnique; 26 import hunt.sql.dialect.mysql.visitor.MySqlASTVisitor; 27 import hunt.sql.dialect.mysql.visitor.MySqlOutputVisitor; 28 import hunt.sql.dialect.mysql.visitor.MySqlShowColumnOutpuVisitor; 29 import hunt.sql.visitor.SQLASTVisitor; 30 import hunt.sql.util.DBType; 31 import hunt.sql.dialect.mysql.ast.statement.MySqlStatement; 32 import hunt.sql.dialect.mysql.ast.statement.MySqlAlterTableOption; 33 import hunt.sql.dialect.mysql.ast.statement.MySqlRenameTableStatement; 34 import hunt.sql.dialect.mysql.ast.statement.MySqlAlterTableAlterColumn; 35 import hunt.sql.dialect.mysql.ast.statement.MySqlAlterTableChangeColumn; 36 import hunt.sql.dialect.mysql.ast.statement.MySqlAlterTableModifyColumn; 37 import hunt.sql.dialect.mysql.ast.statement.MySqlTableIndex; 38 39 import hunt.util.Appendable; 40 import hunt.util.Common; 41 import hunt.util.StringBuilder; 42 43 public class MySqlCreateTableStatement : SQLCreateTableStatement , MySqlStatement { 44 45 alias cloneTo = SQLCreateTableStatement.cloneTo; 46 47 private Map!(string, SQLObject) tableOptions = new LinkedHashMap!(string, SQLObject)(); 48 private List!(SQLCommentHint) hints ; 49 private List!(SQLCommentHint) optionHints ; 50 private SQLName tableGroup; 51 52 protected SQLPartitionBy dbPartitionBy; 53 protected SQLPartitionBy tablePartitionBy; 54 protected SQLExpr tbpartitions; 55 56 public this(){ 57 hints = new ArrayList!(SQLCommentHint)(); 58 optionHints = new ArrayList!(SQLCommentHint)(); 59 super (DBType.MYSQL.name); 60 } 61 62 63 64 public List!(SQLCommentHint) getHints() { 65 return hints; 66 } 67 68 public void setHints(List!(SQLCommentHint) hints) { 69 this.hints = hints; 70 } 71 72 public void setTableOptions(Map!(string, SQLObject) tableOptions) { 73 this.tableOptions = tableOptions; 74 } 75 76 //@Deprecated 77 public SQLSelect getQuery() { 78 return select; 79 } 80 81 //@Deprecated 82 public void setQuery(SQLSelect query) { 83 this.select = query; 84 } 85 86 87 override protected void accept0(SQLASTVisitor visitor) { 88 if (cast(MySqlASTVisitor)(visitor) !is null) { 89 accept0(cast(MySqlASTVisitor) visitor); 90 } else { 91 super.accept0(visitor); 92 } 93 } 94 95 public void accept0(MySqlASTVisitor visitor) { 96 if (visitor.visit(this)) { 97 this.acceptChild!SQLCommentHint(visitor, getHints()); 98 this.acceptChild(visitor, getTableSource()); 99 this.acceptChild!SQLTableElement(visitor, getTableElementList()); 100 this.acceptChild(visitor, getLike()); 101 this.acceptChild(visitor, getSelect()); 102 } 103 visitor.endVisit(this); 104 } 105 106 public static class TableSpaceOption : MySqlObjectImpl { 107 108 alias accept0 = MySqlObjectImpl.accept0; 109 110 private SQLName name; 111 private SQLExpr storage; 112 113 public SQLName getName() { 114 return name; 115 } 116 117 public void setName(SQLName name) { 118 if (name !is null) { 119 name.setParent(this); 120 } 121 this.name = name; 122 } 123 124 public SQLExpr getStorage() { 125 return storage; 126 } 127 128 public void setStorage(SQLExpr storage) { 129 if (storage !is null) { 130 storage.setParent(this); 131 } 132 this.storage = storage; 133 } 134 135 override 136 public void accept0(MySqlASTVisitor visitor) { 137 if (visitor.visit(this)) { 138 acceptChild(visitor, getName()); 139 acceptChild(visitor, getStorage()); 140 } 141 visitor.endVisit(this); 142 } 143 144 override public TableSpaceOption clone() { 145 TableSpaceOption x = new TableSpaceOption(); 146 147 if (name !is null) { 148 x.setName(name.clone()); 149 } 150 151 if (storage !is null) { 152 x.setStorage(storage.clone()); 153 } 154 155 return x; 156 } 157 158 } 159 160 public List!(SQLCommentHint) getOptionHints() { 161 return optionHints; 162 } 163 164 public void setOptionHints(List!(SQLCommentHint) optionHints) { 165 this.optionHints = optionHints; 166 } 167 168 169 public SQLName getTableGroup() { 170 return tableGroup; 171 } 172 173 public void setTableGroup(SQLName tableGroup) { 174 this.tableGroup = tableGroup; 175 } 176 177 override 178 public void simplify() { 179 tableOptions.clear(); 180 super.simplify(); 181 } 182 183 public void showCoumns(Appendable out_p) { 184 this.accept(new MySqlShowColumnOutpuVisitor(out_p)); 185 } 186 187 public bool apply(MySqlRenameTableStatement x) { 188 foreach(MySqlRenameTableStatement.Item item ; x.getItems()) { 189 if (apply(item)) { 190 return true; 191 } 192 } 193 194 return false; 195 } 196 197 override protected bool alterApply(SQLAlterTableItem item) { 198 if (cast(MySqlAlterTableAlterColumn)(item) !is null) { 199 return apply(cast(MySqlAlterTableAlterColumn) item); 200 201 } else if (cast(MySqlAlterTableChangeColumn)(item) !is null) { 202 return apply(cast(MySqlAlterTableChangeColumn) item); 203 204 } else if (cast(SQLAlterCharacter)(item) !is null) { 205 return apply(cast(SQLAlterCharacter) item); 206 207 } else if (cast(MySqlAlterTableModifyColumn)(item) !is null) { 208 return apply(cast(MySqlAlterTableModifyColumn) item); 209 210 } else if (cast(MySqlAlterTableOption)(item) !is null) { 211 return apply(cast(MySqlAlterTableOption) item); 212 } 213 214 return super.alterApply(item); 215 } 216 217 override public bool apply(SQLAlterTableAddIndex item) { 218 if (item.isUnique()) { 219 MySqlUnique x = new MySqlUnique(); 220 item.cloneTo(x); 221 x.setParent(this); 222 this.tableElementList.add(x); 223 return true; 224 } 225 226 if (item.isKey()) { 227 MySqlKey x = new MySqlKey(); 228 item.cloneTo(x); 229 x.setParent(this); 230 this.tableElementList.add(x); 231 return true; 232 } 233 234 MySqlTableIndex x = new MySqlTableIndex(); 235 item.cloneTo(x); 236 x.setParent(this); 237 this.tableElementList.add(x); 238 return true; 239 } 240 241 public bool apply(MySqlAlterTableOption item) { 242 this.tableOptions.put(item.getName(), item.getValue()); 243 return true; 244 } 245 246 public bool apply(SQLAlterCharacter item) { 247 SQLExpr charset = item.getCharacterSet(); 248 if (charset !is null) { 249 this.tableOptions.put("CHARACTER SET", charset); 250 } 251 252 SQLExpr collate = item.getCollate(); 253 if (collate !is null) { 254 this.tableOptions.put("COLLATE", collate); 255 } 256 return true; 257 } 258 259 public bool apply(MySqlRenameTableStatement.Item item) { 260 if (!SQLUtils.nameEquals(cast(SQLName) item.getName(), this.getName())) { 261 return false; 262 } 263 this.setName(cast(SQLName) item.getTo().clone()); 264 return true; 265 } 266 267 public bool apply(MySqlAlterTableAlterColumn x) { 268 int columnIndex = columnIndexOf(x.getColumn()); 269 if (columnIndex == -1) { 270 return false; 271 } 272 273 SQLExpr defaultExpr = x.getDefaultExpr(); 274 SQLColumnDefinition column = cast(SQLColumnDefinition) tableElementList.get(columnIndex); 275 276 if (x.isDropDefault()) { 277 column.setDefaultExpr(null); 278 } else if (defaultExpr !is null) { 279 column.setDefaultExpr(defaultExpr); 280 } 281 282 return true; 283 } 284 285 public bool apply(MySqlAlterTableChangeColumn item) { 286 SQLName columnName = item.getColumnName(); 287 int columnIndex = columnIndexOf(columnName); 288 if (columnIndex == -1) { 289 return false; 290 } 291 292 int afterIndex = columnIndexOf(item.getAfterColumn()); 293 int beforeIndex = columnIndexOf(item.getFirstColumn()); 294 295 int insertIndex = -1; 296 if (beforeIndex != -1) { 297 insertIndex = beforeIndex; 298 } else if (afterIndex != -1) { 299 insertIndex = afterIndex + 1; 300 } else if (item.isFirst()) { 301 insertIndex = 0; 302 } 303 304 SQLColumnDefinition column = item.getNewColumnDefinition().clone(); 305 column.setParent(this); 306 if (insertIndex == -1 || insertIndex == columnIndex) { 307 tableElementList.set(columnIndex, column); 308 } else { 309 if (insertIndex > columnIndex) { 310 tableElementList.add(insertIndex, column); 311 tableElementList.removeAt(columnIndex); 312 } else { 313 tableElementList.removeAt(columnIndex); 314 tableElementList.add(insertIndex, column); 315 } 316 } 317 318 for (int i = 0; i < tableElementList.size(); i++) { 319 SQLTableElement e = tableElementList.get(i); 320 if(cast(MySqlTableIndex)(e) !is null) { 321 (cast(MySqlTableIndex) e).applyColumnRename(columnName, column.getName()); 322 } else if (cast(SQLUnique)(e) !is null) { 323 SQLUnique unique = cast(SQLUnique) e; 324 unique.applyColumnRename(columnName, column.getName()); 325 } 326 } 327 328 return true; 329 } 330 331 public bool apply(MySqlAlterTableModifyColumn item) { 332 SQLColumnDefinition column = item.getNewColumnDefinition().clone(); 333 SQLName columnName = column.getName(); 334 335 int columnIndex = columnIndexOf(columnName); 336 if (columnIndex == -1) { 337 return false; 338 } 339 340 int afterIndex = columnIndexOf(item.getAfterColumn()); 341 int beforeIndex = columnIndexOf(item.getFirstColumn()); 342 343 int insertIndex = -1; 344 if (beforeIndex != -1) { 345 insertIndex = beforeIndex; 346 } else if (afterIndex != -1) { 347 insertIndex = afterIndex + 1; 348 } 349 350 column.setParent(this); 351 if (insertIndex == -1 || insertIndex == columnIndex) { 352 tableElementList.set(columnIndex, column); 353 return true; 354 } else { 355 if (insertIndex > columnIndex) { 356 tableElementList.add(insertIndex, column); 357 tableElementList.removeAt(columnIndex); 358 } else { 359 tableElementList.removeAt(columnIndex); 360 tableElementList.add(insertIndex, column); 361 } 362 } 363 364 return true; 365 } 366 367 override public void output(StringBuilder buf) { 368 this.accept(new MySqlOutputVisitor(buf)); 369 } 370 371 public void cloneTo(MySqlCreateTableStatement x) { 372 super.cloneTo(x); 373 foreach(string k, SQLObject v ; tableOptions) { 374 SQLObject obj = v.clone(); 375 obj.setParent(x); 376 x.tableOptions.put(k, obj); 377 } 378 if (partitioning !is null) { 379 x.setPartitioning(partitioning.clone()); 380 } 381 foreach(SQLCommentHint hint ; hints) { 382 SQLCommentHint h2 = hint.clone(); 383 h2.setParent(x); 384 x.hints.add(h2); 385 } 386 foreach(SQLCommentHint hint ; optionHints) { 387 SQLCommentHint h2 = hint.clone(); 388 h2.setParent(x); 389 x.optionHints.add(h2); 390 } 391 if (like !is null) { 392 x.setLike(like.clone()); 393 } 394 if (tableGroup !is null) { 395 x.setTableGroup(tableGroup.clone()); 396 } 397 } 398 399 override public MySqlCreateTableStatement clone() { 400 MySqlCreateTableStatement x = new MySqlCreateTableStatement(); 401 cloneTo(x); 402 return x; 403 } 404 405 public SQLPartitionBy getDbPartitionBy() { 406 return dbPartitionBy; 407 } 408 409 public void setDbPartitionBy(SQLPartitionBy x) { 410 if (x !is null) { 411 x.setParent(this); 412 } 413 this.dbPartitionBy = x; 414 } 415 416 public SQLPartitionBy getTablePartitionBy() { 417 return tablePartitionBy; 418 } 419 420 public void setTablePartitionBy(SQLPartitionBy x) { 421 if (x !is null) { 422 x.setParent(this); 423 } 424 this.tablePartitionBy = x; 425 } 426 427 public SQLExpr getTbpartitions() { 428 return tbpartitions; 429 } 430 431 public void setTbpartitions(SQLExpr x) { 432 if (x !is null) { 433 x.setParent(this); 434 } 435 this.tbpartitions = x; 436 } 437 }