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.parser.SQLCreateTableParser; 17 18 import hunt.collection; 19 20 import hunt.sql.ast.SQLExpr; 21 import hunt.sql.ast.SQLName; 22 import hunt.sql.ast.statement; 23 import hunt.sql.util.FnvHash; 24 import hunt.sql.util.DBType; 25 import hunt.sql.ast.statement.SQLConstraint; 26 import hunt.sql.ast.statement.SQLTableElement; 27 import hunt.sql.parser.Token; 28 import hunt.sql.parser.ParserException; 29 import hunt.String; 30 import hunt.sql.parser.SQLDDLParser; 31 import hunt.sql.parser.SQLExprParser; 32 import hunt.text; 33 34 public class SQLCreateTableParser : SQLDDLParser { 35 36 public this(string sql) { 37 super(sql); 38 } 39 40 public this(SQLExprParser exprParser) { 41 super(exprParser); 42 } 43 44 override public SQLCreateTableStatement parseCreateTable() { 45 List!(string) comments = null; 46 if (lexer.isKeepComments() && lexer.hasComment()) { 47 comments = lexer.readAndResetComments(); 48 } 49 50 SQLCreateTableStatement stmt = parseCreateTable(true); 51 if (comments !is null) { 52 stmt.addBeforeComment(comments); 53 } 54 55 return stmt; 56 } 57 58 public SQLCreateTableStatement parseCreateTable(bool acceptCreate) { 59 SQLCreateTableStatement createTable = newCreateStatement(); 60 61 if (acceptCreate) { 62 if (lexer.hasComment() && lexer.isKeepComments()) { 63 createTable.addBeforeComment(lexer.readAndResetComments()); 64 } 65 66 accept(Token.CREATE); 67 } 68 69 if (lexer.identifierEquals("GLOBAL")) { 70 lexer.nextToken(); 71 72 if (lexer.identifierEquals("TEMPORARY")) { 73 lexer.nextToken(); 74 createTable.setType(SQLCreateTableStatement.Type.GLOBAL_TEMPORARY); 75 } else { 76 throw new ParserException("syntax error " ~ lexer.info()); 77 } 78 } else if (lexer.token == Token.IDENTIFIER && lexer.stringVal().equalsIgnoreCase("LOCAL")) { 79 lexer.nextToken(); 80 if (lexer.token == Token.IDENTIFIER && lexer.stringVal().equalsIgnoreCase("TEMPORAY")) { 81 lexer.nextToken(); 82 createTable.setType(SQLCreateTableStatement.Type.LOCAL_TEMPORARY); 83 } else { 84 throw new ParserException("syntax error. " ~ lexer.info()); 85 } 86 } 87 88 accept(Token.TABLE); 89 90 if (lexer.token() == Token.IF) { 91 lexer.nextToken(); 92 accept(Token.NOT); 93 accept(Token.EXISTS); 94 95 createTable.setIfNotExiists(true); 96 } 97 98 createTable.setName(this.exprParser.name()); 99 100 if (lexer.token == Token.LPAREN) { 101 lexer.nextToken(); 102 103 for (; ; ) { 104 Token token = lexer.token; 105 if (token == Token.IDENTIFIER 106 && lexer.stringVal().equalsIgnoreCase("SUPPLEMENTAL") 107 && DBType.ORACLE.opEquals(dbType)) { 108 this.parseCreateTableSupplementalLogingProps(createTable); 109 } else if (token == Token.IDENTIFIER // 110 || token == Token.LITERAL_ALIAS) { 111 SQLColumnDefinition column = this.exprParser.parseColumn(); 112 createTable.getTableElementList().add(column); 113 } else if (token == Token.PRIMARY // 114 || token == Token.UNIQUE // 115 || token == Token.CHECK // 116 || token == Token.CONSTRAINT 117 || token == Token.FOREIGN) { 118 SQLConstraint constraint = this.exprParser.parseConstaint(); 119 constraint.setParent(createTable); 120 createTable.getTableElementList().add(cast(SQLTableElement) constraint); 121 } else if (token == Token.TABLESPACE) { 122 throw new ParserException("TODO " ~ lexer.info()); 123 } else { 124 SQLColumnDefinition column = this.exprParser.parseColumn(); 125 createTable.getTableElementList().add(column); 126 } 127 128 if (lexer.token == Token.COMMA) { 129 lexer.nextToken(); 130 131 if (lexer.token == Token.RPAREN) { // compatible for sql server 132 break; 133 } 134 continue; 135 } 136 137 break; 138 } 139 140 accept(Token.RPAREN); 141 142 if (lexer.identifierEquals(FnvHash.Constants.INHERITS)) { 143 lexer.nextToken(); 144 accept(Token.LPAREN); 145 SQLName inherits = this.exprParser.name(); 146 createTable.setInherits(new SQLExprTableSource(inherits)); 147 accept(Token.RPAREN); 148 } 149 } 150 151 if (lexer.token == Token.AS) { 152 lexer.nextToken(); 153 SQLSelect select = this.createSQLSelectParser().select(); 154 createTable.setSelect(select); 155 } 156 157 if (lexer.token == Token.WITH && DBType.POSTGRESQL.opEquals(dbType)) { 158 lexer.nextToken(); 159 accept(Token.LPAREN); 160 161 for (;;) { 162 string name = lexer.stringVal(); 163 lexer.nextToken(); 164 accept(Token.EQ); 165 SQLExpr value = this.exprParser.expr(); 166 value.setParent(createTable); 167 168 createTable.getTableOptions().put(name, value); 169 170 if (lexer.token == Token.COMMA) { 171 lexer.nextToken(); 172 continue; 173 } 174 175 break; 176 } 177 accept(Token.RPAREN); 178 } 179 180 return createTable; 181 } 182 183 protected void parseCreateTableSupplementalLogingProps(SQLCreateTableStatement stmt) { 184 throw new ParserException("TODO " ~ lexer.info()); 185 } 186 187 override protected SQLCreateTableStatement newCreateStatement() { 188 return new SQLCreateTableStatement(getDbType()); 189 } 190 }