001package gudusoft.gsqlparser.nodes; 002 003import gudusoft.gsqlparser.*; 004import gudusoft.gsqlparser.stmt.TDeleteSqlStatement; 005import gudusoft.gsqlparser.stmt.TInsertSqlStatement; 006import gudusoft.gsqlparser.stmt.TSelectSqlStatement; 007import gudusoft.gsqlparser.stmt.TUpdateSqlStatement; 008 009import java.util.ArrayList; 010 011/** 012 * A common table expression permits defining a result table with a table-name that can be specified as a table name in any FROM clause of the fullselect that follows. 013 *<p> Multiple common table expressions can be specified following the single WITH keyword. 014 *<p> Each common table expression specified can also be referenced by name in the FROM clause of subsequent common table expressions. 015 *<p> Syntax: 016 * <blockquote><pre> 017 * table-name [column-name [,...n]] AS (fullselect)</pre> 018 * </blockquote> 019*/ 020public class TCTE extends TTable{ 021 022 private boolean recursive = false; 023 024 public void setRecursive(boolean recursive) { 025 this.recursive = recursive; 026 } 027 028 public boolean isRecursive() { 029 return recursive; 030 } 031 032 public void initAttributesFromColumnList(){ 033 if (this.getColumnList() != null){ 034 int i = 0; 035 if ((this.getSubquery() != null)&&(this.getSubquery().getResultColumnList() != null)){ 036 if (this.getSubquery().getResultColumnList().size() != this.getColumnList().size()){ 037 if (TBaseType.DUMP_RESOLVER_LOG_TO_CONSOLE){ 038 TBaseType.log(String.format("CTE: <%s> columns list size is not the same as select list in subQuery ", this.getTableName().toString()) 039 ,TLog.ERROR,this.getTableName()); 040 } 041 } 042 } 043 for(TObjectName column: this.getColumnList()){ 044 if ((this.getSubquery() != null)&&(this.getSubquery().getResultColumnList() != null)){ 045 // 关联 subQuery 中 select list 046 // relationAttributes.add(new TAttributeNode( this.getTableName().toString()+"." + column.toString() ,this,this.getSubquery().getResultColumnList().getResultColumn(i) )); 047 TAttributeNode.addNodeToList(new TAttributeNode( this.getTableName().toString()+"." + column.toString() ,this,this.getSubquery().getResultColumnList().getResultColumn(i) ),relationAttributes); 048 049 }else{ 050 //relationAttributes.add(new TAttributeNode( this.getTableName().toString()+"." + column.toString() ,this)); 051 TAttributeNode.addNodeToList(new TAttributeNode( this.getTableName().toString()+"." + column.toString() ,this),relationAttributes); 052 } 053 i++; 054 } 055 // 056 if ((this.getSubquery() != null)&&(this.getSubquery().isCombinedQuery())&&(this.getSubquery().getLeftStmt().getResultColumnList() != null)){ 057 TSelectSqlStatement left = subquery.getLeftStmt(); 058 059 String prefix = this.getTableName().toString()+"."; 060 addNewAttributeFromSubQuery(left.getResultColumnList(),relationAttributes,prefix,this.getColumnList()); 061 while (left.isCombinedQuery()){ 062 left = left.getLeftStmt(); 063 addNewAttributeFromSubQuery(left.getResultColumnList(),relationAttributes,prefix,this.getColumnList()); 064 } 065 } 066 } 067 068 if (TBaseType.DUMP_RESOLVER_LOG_TO_CONSOLE){ 069 TBaseType.log(String.format("Prepare attributes for CTE: <%s> via column list",this.getTableName().toString()),TLog.DEBUG,this.getTableName()); 070 for(TAttributeNode node:getAttributes()){ 071 TBaseType.log(String.format("\tAttribute: <%s>, Select list column: <%s>",node.getName(),node.getSubLevelResultColumn()!=null?node.getSubLevelResultColumn().toString():"N/A" ),TLog.DEBUG); 072 } 073 } 074 075 } 076 public void initAttributesFromSubQuery(){ 077 if (this.getSubquery() == null) return; 078 super.initAttributesFromSubquery(this.getSubquery(),this.getTableName().toString()+"."); 079 080 if (TBaseType.DUMP_RESOLVER_LOG_TO_CONSOLE){ 081 TBaseType.log(String.format("Prepare attributes (num = %d) for CTE: <%s> via subQuery",getAttributes().size() ,this.getTableName().toString()),TLog.DEBUG,this.getTableName()); 082 } 083 int c = 0; 084 for(TAttributeNode node:getAttributes()){ 085 if (node.getSqlColumn() != null){ 086 if (TBaseType.DUMP_RESOLVER_LOG_TO_CONSOLE){ 087 TBaseType.log(String.format("\tAttribute: <%s>, SQL column: <%s>",node.getName(), node.getSqlColumn()!=null?node.getSqlColumn().toString():"N/A" ),TLog.DEBUG); 088 } 089 }else{ 090 if (TBaseType.DUMP_RESOLVER_LOG_TO_CONSOLE){ 091 TBaseType.log(String.format("\tAttribute: <%s>, Select list column: <%s>",node.getName(), node.getSubLevelResultColumn()!=null?node.getSubLevelResultColumn().toString():"N/A" ),TLog.DEBUG); 092 } 093 } 094 if (node.getAccompaniedAttributeNodes().size() >0 ){ 095 if (TBaseType.DUMP_RESOLVER_LOG_TO_CONSOLE){ 096 TBaseType.log(String.format("\t\tAccompanied nodes: %d",node.getAccompaniedAttributeNodes().size()),TLog.DEBUG); 097 } 098 for(TAttributeNode n:node.getAccompaniedAttributeNodes()){ 099 if (n.getSqlColumn() != null){ 100 if (TBaseType.DUMP_RESOLVER_LOG_TO_CONSOLE){ 101 TBaseType.log(String.format("\t\tAttribute: <%s>, SQL column: <%s>",n.getName(), n.getSqlColumn()!=null?n.getSqlColumn().toString():"N/A" ),TLog.DEBUG); 102 } 103 }else{ 104 if (TBaseType.DUMP_RESOLVER_LOG_TO_CONSOLE){ 105 TBaseType.log(String.format("\t\tAttribute: <%s>, Select list column: <%s>",n.getName(), n.getSubLevelResultColumn()!=null?n.getSubLevelResultColumn().toString():"N/A" ),TLog.DEBUG); 106 } 107 } 108 } 109 } 110 111 c++; 112 if (c > TLog.OUTPUT_ATTRIBUTES_MAX){ 113 if (TBaseType.DUMP_RESOLVER_LOG_TO_CONSOLE){ 114 TBaseType.log(String.format("\t...skipped after output %d attributes",c-1),TLog.DEBUG,this.getTableName().getStartToken()); 115 } 116 117 break; 118 } 119 } 120 } 121 122 public String getRelationName(){ 123 return this.getTableName().toString(); 124 } 125 126// public ArrayList<TAttributeNode> getAttributes(){ 127// return relationAttributes; 128// } 129 130 private TSelectSqlNode selectNode; 131 private TSelectSqlStatement subquery; 132 133 private TInsertSqlNode insertSqlNode; 134 private TInsertSqlStatement insertStmt; 135 136 private TUpdateSqlNode updateSqlNode; 137 private TUpdateSqlStatement updateStmt; 138 139 private TDeleteSqlNode deleteSqlNode; 140 private TDeleteSqlStatement deleteStmt; 141 142 private TCustomSqlStatement preparableStmt; 143 144 public boolean searchColumnInResultSet(TCustomSqlStatement pSql,TTable pTable,TObjectName pColumn,boolean pMustIn){ 145 boolean lcResult = false; 146 if (getColumnList() != null){ 147 for (int i=0;i<getColumnList().size();i++){ 148 lcResult = getColumnList().getObjectName(i).toString().equalsIgnoreCase(pColumn.getColumnNameOnly()); 149 //pColumn.setSourceColumn(getColumnList().getObjectName(i)); 150 if (lcResult) break; 151 } 152 return lcResult; 153 } 154 155 TCustomSqlStatement lcStmt = pSql; 156 while (lcStmt != null){ 157 if (lcStmt == getSubquery()){ 158 pTable.getLinkedColumns().addObjectName(pColumn); 159 pColumn.setSourceTable(pTable); 160 lcResult = true; 161 break; 162 } 163 lcStmt = lcStmt.getParentStmt(); 164 } 165 166 if (lcResult) return true; 167 168 if (getSubquery() == null) return false; 169 lcResult = getSubquery().searchColumnInResultSet(pColumn,pMustIn); 170 171 return lcResult; 172 } 173 174 /** 175 * preparable statement can be: 176 * <p> {@link #getSubquery()} 177 * <p> or{@link #getUpdateStmt()} 178 * <p> or{@link #getInsertStmt()} 179 * <p> or{@link #getDeleteStmt()} 180 * @return 181 */ 182 public TCustomSqlStatement getPreparableStmt() { 183 preparableStmt = null; 184 if (subquery!=null){ 185 preparableStmt = subquery; 186 }else if (updateStmt != null){ 187 preparableStmt = updateStmt; 188 }else if (deleteStmt != null){ 189 preparableStmt = deleteStmt; 190 }else if (insertStmt != null){ 191 preparableStmt = insertStmt; 192 } 193 194 return preparableStmt; 195 } 196 197 public TUpdateSqlStatement getUpdateStmt() { 198 return updateStmt; 199 } 200 201 public TInsertSqlStatement getInsertStmt() { 202 203 return insertStmt; 204 } 205 206 public TDeleteSqlStatement getDeleteStmt() { 207 208 return deleteStmt; 209 } 210 211 /** 212 * @return table name of this common table expression. 213 */ 214 public TObjectName getTableName() { 215 return tableName; 216 } 217 218 private TObjectName tableName; 219 220 public void setColumnList(TObjectNameList columnList) { 221 this.columnList = columnList; 222 } 223 224 /** 225 * fullselect of this common table expression. 226 * @return 227 */ 228 public TSelectSqlStatement getSubquery() { 229 return subquery; 230 } 231 232 /** 233 * @return List of column name of this common table expression. 234 235 */ 236 public TObjectNameList getColumnList() { 237 return columnList; 238 } 239 240 private TObjectNameList columnList = null; 241 242 public void init(Object arg1,Object arg2) 243 { 244 tableName = (TObjectName)arg1; 245 //tableName.parseTablename(); 246 //tableName.setObjectType(TObjectName.ttobjTableCTE); 247 tableName.setDbObjectType(EDbObjectType.cte); 248 249 if (arg2 instanceof TSelectSqlNode){ 250 selectNode = (TSelectSqlNode)arg2; 251 }else if (arg2 instanceof TInsertSqlNode){ 252 insertSqlNode = (TInsertSqlNode)arg2; 253 }else if (arg2 instanceof TUpdateSqlNode){ 254 updateSqlNode = (TUpdateSqlNode)arg2; 255 }else if (arg2 instanceof TDeleteSqlNode){ 256 deleteSqlNode = (TDeleteSqlNode)arg2; 257 } 258 } 259 260 public void incParenthesisCount() { 261 if (selectNode != null){ 262 selectNode.incParenthesisCount(); 263 } 264 } 265 266 public void doParse(TCustomSqlStatement psql, ESqlClause plocation){ 267 268 if (selectNode != null){ 269 //long t = System.currentTimeMillis(); 270 subquery = new TSelectSqlStatement(psql.dbvendor); 271 subquery.rootNode = selectNode; 272 subquery.setQueryOfCTE(true); 273 subquery.setCteIncludeThisStmt(this); 274 subquery.doParseStatement(psql); 275 for(TTable t:subquery.getRelations()){ 276 if (t.isCTEName() && t.getCTE() == this){ 277 // System.out.println("found cte name in the same level:"+ t.getCTE().toString()); 278 t.setCTEName(false); 279 t.setCTE(null); 280 } 281 } 282// if (columnList == null){ 283// columnList = new TObjectNameList(); 284// for(TResultColumn resultColumn:subquery.getResultColumnList()){ 285// columnList.addObjectName(new TObjectName()); 286// 287// } 288// } 289 //System.out.println("Time Escaped: " + (System.currentTimeMillis() - t)+", sql size:"+ this.toString().length() ); 290 }else if (insertSqlNode != null){ 291 insertStmt = new TInsertSqlStatement(psql.dbvendor); 292 insertStmt.rootNode = insertSqlNode; 293 insertStmt.setCteIncludeThisStmt(this); 294 insertStmt.doParseStatement(psql); 295 }else if (deleteSqlNode != null){ 296 deleteStmt = new TDeleteSqlStatement(psql.dbvendor); 297 deleteStmt.rootNode = deleteSqlNode; 298 deleteStmt.setCteIncludeThisStmt(this); 299 deleteStmt.doParseStatement(psql); 300 }else if (updateSqlNode != null){ 301 updateStmt = new TUpdateSqlStatement(psql.dbvendor); 302 updateStmt.rootNode = updateSqlNode; 303 updateStmt.setCteIncludeThisStmt(this); 304 updateStmt.doParseStatement(psql); 305 } 306 } 307 308 public void accept(TParseTreeVisitor v){ 309 v.preVisit(this); 310 v.postVisit(this); 311 } 312 313 public void acceptChildren(TParseTreeVisitor v){ 314 v.preVisit(this); 315 if (subquery != null){ 316 subquery.acceptChildren(v); 317 } 318 v.postVisit(this); 319 } 320 321 public void setSubquery(TSelectSqlStatement subquery) { 322 this.subquery = subquery; 323 } 324 325 public void setInsertStmt(TInsertSqlStatement insertStmt) { 326 this.insertStmt = insertStmt; 327 } 328 329 public void setUpdateStmt(TUpdateSqlStatement updateStmt) { 330 this.updateStmt = updateStmt; 331 } 332 333 public void setDeleteStmt(TDeleteSqlStatement deleteStmt) { 334 this.deleteStmt = deleteStmt; 335 } 336 337 public void setPreparableStmt(TCustomSqlStatement preparableStmt) { 338 this.preparableStmt = preparableStmt; 339 } 340 341 public void setTableName(TObjectName tableName) { 342 this.tableName = tableName; 343 } 344}