001package gudusoft.gsqlparser.stmt; 002 003 004import gudusoft.gsqlparser.*; 005import gudusoft.gsqlparser.nodes.*; 006import gudusoft.gsqlparser.nodes.mssql.TMssqlStmtStubSqlNode; 007 008public class TCreateSchemaSqlStatement extends TBlockSqlStatement { 009 010 public enum EFromSource {dataCatalog,hiveMetestore,postgres,mysql,kinesis,redshift,NA}; 011 012 private EFromSource fromSource = EFromSource.NA; 013 014 private TObjectName sourceDatabase; 015 private TObjectName sourceSchema; 016 017 public TObjectName getSourceDatabase() { 018 return sourceDatabase; 019 } 020 021 public TObjectName getSourceSchema() { 022 return sourceSchema; 023 } 024 025 public EFromSource getFromSource() { 026 return fromSource; 027 } 028 029 public TCreateSchemaSqlStatement(EDbVendor dbvendor) { 030 super(dbvendor); 031 sqlstatementtype = ESqlStatementType.sstcreateschema; 032 } 033 034 void buildsql() { 035 } 036 037 void clear() { 038 } 039 040 String getasprettytext() { 041 return ""; 042 } 043 044 void iterate(TVisitorAbs pvisitor) { 045 } 046 047 private boolean externalSchema; 048 049 public boolean isExternalSchema() { 050 return externalSchema; 051 } 052 053 private TObjectName schemaName = null; 054 private TObjectName ownerName; 055 private TObjectName cloneSourceSchema = null; 056 057 public TObjectName getCloneSourceSchema() { 058 return cloneSourceSchema; 059 } 060 061 public TObjectName getOwnerName() { 062 return ownerName; 063 } 064 065 public TObjectName getSchemaName() { 066 return schemaName; 067 } 068 069 /** 070 * For Vertica, skip grammar-based syntax checking since there's no grammar rule. 071 * We do token-based parsing instead. 072 */ 073 @Override 074 protected int dochecksyntax(TCustomSqlStatement psql) { 075 if (dbvendor == EDbVendor.dbvvertica) { 076 isparsed = true; 077 return 0; 078 } 079 return super.dochecksyntax(psql); 080 } 081 082 public int doParseStatement(TCustomSqlStatement psql) { 083 // For Vertica, parse from tokens when rootNode is null (grammar not available) 084 if (rootNode == null && dbvendor == EDbVendor.dbvvertica) { 085 return doParseVerticaFromTokens(psql); 086 } 087 if (rootNode == null) return -1; 088 super.doParseStatement(psql); 089 TDummy node; 090 TCreateSchemaSqlNode schemaNode; 091 switch (dbvendor){ 092 case dbvmssql: 093 case dbvpostgresql: 094 schemaNode = (TCreateSchemaSqlNode) rootNode; 095 schemaName = schemaNode.getSchemaName(); 096 ownerName = schemaNode.getOwnerName(); 097 098 if (schemaNode.getStatementListSqlNode() != null){ 099 schemaNode.getStatementListSqlNode().doParse(this,ESqlClause.unknown); 100 101 for(int i=0;i<schemaNode.getStatementListSqlNode().size();i++){ 102 this.getBodyStatements().add(schemaNode.getStatementListSqlNode().getStatementSqlNode(i).getStmt()); 103 } 104 } 105 break; 106 case dbvredshift: 107 schemaNode = (TCreateSchemaSqlNode) rootNode; 108 schemaName = schemaNode.getSchemaName(); 109 ownerName = schemaNode.getOwnerName(); 110 externalSchema = schemaNode.isExternalSchema(); 111 fromSource = schemaNode.getFromSource(); 112 sourceDatabase = schemaNode.getSourceDatabase(); 113 sourceSchema = schemaNode.getSourceSchema(); 114 break; 115 case dbvsnowflake: 116 node = (TDummy)rootNode; 117 schemaName = (TObjectName)node.node1; 118 cloneSourceSchema = (TObjectName)node.node2; 119 break; 120 case dbvhana: 121 node = (TDummy)rootNode; 122 schemaName = (TObjectName)node.node1; 123 break; 124 } 125 126 if((getSqlEnv().getDefaultCatalogName() != null)&&(schemaName != null)){ 127 if (schemaName.getDatabaseToken() == null){ 128 schemaName.setDatabaseToken(new TSourceToken(getSqlEnv().getDefaultCatalogName())); 129 } 130 } 131 132 return 0; 133 } 134 135 /** 136 * Parse Vertica CREATE SCHEMA from token stream when grammar is not available. 137 * <p> 138 * Vertica CREATE SCHEMA syntax: 139 * CREATE SCHEMA [ IF NOT EXISTS ] [{ database | namespace }.]schema 140 * [ AUTHORIZATION username] 141 * [ DEFAULT { INCLUDE | EXCLUDE } [ SCHEMA ] PRIVILEGES ] 142 * [ DISK_QUOTA quota ] 143 */ 144 private int doParseVerticaFromTokens(TCustomSqlStatement psql) { 145 if (sourcetokenlist == null || sourcetokenlist.size() == 0) { 146 return -1; 147 } 148 super.doParseStatement(psql); 149 150 // Find SCHEMA keyword position 151 int schemaKeywordIndex = -1; 152 for (int i = 0; i < sourcetokenlist.size(); i++) { 153 TSourceToken token = sourcetokenlist.get(i); 154 if (token.toString().equalsIgnoreCase("SCHEMA") && schemaKeywordIndex == -1) { 155 schemaKeywordIndex = i; 156 break; 157 } 158 } 159 160 if (schemaKeywordIndex < 0) { 161 return -1; 162 } 163 164 // Find the next solid token after SCHEMA keyword 165 TSourceToken nextToken = sourcetokenlist.nextsolidtoken(schemaKeywordIndex, 1, false); 166 if (nextToken == null) { 167 return -1; 168 } 169 170 // Handle IF NOT EXISTS 171 if (nextToken.toString().equalsIgnoreCase("IF")) { 172 // Skip IF NOT EXISTS 173 TSourceToken notToken = sourcetokenlist.nextsolidtoken(nextToken.posinlist, 1, false); 174 if (notToken != null && notToken.toString().equalsIgnoreCase("NOT")) { 175 TSourceToken existsToken = sourcetokenlist.nextsolidtoken(notToken.posinlist, 1, false); 176 if (existsToken != null && existsToken.toString().equalsIgnoreCase("EXISTS")) { 177 nextToken = sourcetokenlist.nextsolidtoken(existsToken.posinlist, 1, false); 178 } 179 } 180 } 181 182 if (nextToken == null) { 183 return -1; 184 } 185 186 // Now nextToken should be the schema name (or database.schema) 187 // Skip AUTHORIZATION keyword if present before schema name 188 if (nextToken.toString().equalsIgnoreCase("AUTHORIZATION")) { 189 // AUTHORIZATION username format (no schema name before AUTHORIZATION) 190 TSourceToken ownerToken = sourcetokenlist.nextsolidtoken(nextToken.posinlist, 1, false); 191 if (ownerToken != null && ownerToken.tokentype == ETokenType.ttidentifier) { 192 ownerName = new TObjectName(); 193 ownerName.setObjectToken(ownerToken); 194 } 195 return 0; 196 } 197 198 // Parse schema name - could be schema or database.schema 199 if (nextToken.tokentype == ETokenType.ttidentifier || nextToken.tokentype == ETokenType.ttkeyword) { 200 TSourceToken afterName = sourcetokenlist.nextsolidtoken(nextToken.posinlist, 1, false); 201 if (afterName != null && afterName.toString().equals(".")) { 202 // database.schema format 203 TSourceToken schemaToken = sourcetokenlist.nextsolidtoken(afterName.posinlist, 1, false); 204 if (schemaToken != null) { 205 schemaName = new TObjectName(); 206 schemaName.setSchemaToken(nextToken); 207 schemaName.setObjectToken(schemaToken); 208 209 // Check for AUTHORIZATION after schema name 210 TSourceToken afterSchemaName = sourcetokenlist.nextsolidtoken(schemaToken.posinlist, 1, false); 211 if (afterSchemaName != null && afterSchemaName.toString().equalsIgnoreCase("AUTHORIZATION")) { 212 TSourceToken ownerToken = sourcetokenlist.nextsolidtoken(afterSchemaName.posinlist, 1, false); 213 if (ownerToken != null && ownerToken.tokentype == ETokenType.ttidentifier) { 214 ownerName = new TObjectName(); 215 ownerName.setObjectToken(ownerToken); 216 } 217 } 218 } 219 } else { 220 // Simple schema name 221 schemaName = new TObjectName(); 222 schemaName.setObjectToken(nextToken); 223 224 // Check for AUTHORIZATION after schema name 225 if (afterName != null && afterName.toString().equalsIgnoreCase("AUTHORIZATION")) { 226 TSourceToken ownerToken = sourcetokenlist.nextsolidtoken(afterName.posinlist, 1, false); 227 if (ownerToken != null && ownerToken.tokentype == ETokenType.ttidentifier) { 228 ownerName = new TObjectName(); 229 ownerName.setObjectToken(ownerToken); 230 } 231 } 232 } 233 } 234 235 if((getSqlEnv().getDefaultCatalogName() != null)&&(schemaName != null)){ 236 if (schemaName.getDatabaseToken() == null){ 237 schemaName.setDatabaseToken(new TSourceToken(getSqlEnv().getDefaultCatalogName())); 238 } 239 } 240 241 return 0; 242 } 243 244 public void accept(TParseTreeVisitor v) { 245 v.preVisit(this); 246 v.postVisit(this); 247 } 248 249 250 public void acceptChildren(TParseTreeVisitor v) { 251 v.preVisit(this); 252 v.postVisit(this); 253 } 254 255 public void setSchemaName(TObjectName schemaName) { 256 this.schemaName = schemaName; 257 } 258}