001package gudusoft.gsqlparser.nodes;
002
003
004import gudusoft.gsqlparser.EDataType;
005import gudusoft.gsqlparser.ESqlClause;
006import gudusoft.gsqlparser.ESqlStatementType;
007import gudusoft.gsqlparser.TCustomSqlStatement;
008import gudusoft.gsqlparser.nodes.TExpression;
009import gudusoft.gsqlparser.nodes.TParseTreeNode;
010import gudusoft.gsqlparser.nodes.TParseTreeVisitor;
011import gudusoft.gsqlparser.sqlenv.TSQLColumn;
012import gudusoft.gsqlparser.stmt.TSelectSqlStatement;
013
014
015public class TUnnestClause  extends TParseTreeNode {
016
017    private TObjectNameList derivedColumnList = null;
018    private TAliasClause withOffsetAlais;
019
020    public TAliasClause getWithOffsetAlais() {
021        return withOffsetAlais;
022    }
023
024    public TDummy getWithOffset() {
025        return withOffset;
026    }
027
028    private TDummy withOffset;
029    private TObjectNameList columns;
030
031    public TObjectNameList getColumns() {
032        return columns;
033    }
034
035    private TExpression arrayExpr;
036
037    public TExpression getArrayExpr() {
038        return arrayExpr;
039    }
040
041    public  void init(Object arg1){
042        if (arg1 instanceof TExpression){
043            //bigquery, athena
044            arrayExpr = (TExpression)arg1;
045        }else if (arg1 instanceof TObjectNameList){
046            //presto,bigquery
047            columns = (TObjectNameList)arg1;
048        }
049
050    }
051
052    public  void init(Object arg1, Object arg2){
053        init(arg1);
054        this.withOffset = (TDummy)arg2;
055        if (this.withOffset != null){
056            if (this.withOffset.int1 == 2){
057                this.withOffsetAlais = (TAliasClause)this.withOffset.node1;
058            }
059        }
060    }
061
062    public TObjectNameList getDerivedColumnList() {
063        return derivedColumnList;
064    }
065
066    public void doParse(TCustomSqlStatement psql, ESqlClause plocation)
067    {
068        if (arrayExpr != null){
069            arrayExpr.doParse(psql,plocation);
070        }else if (columns != null){
071            // link to the first table of the from clause
072            TTable lcFirstTable = null;
073            for(TObjectName pColumn:columns){
074                if (psql.getTables().size() > 0){
075                    lcFirstTable = psql.getTables().getTable(0);
076                    lcFirstTable.getLinkedColumns().addObjectName(pColumn);
077                    pColumn.setSourceTable(lcFirstTable);
078                }else if ((psql.getParentStmt() != null) && (psql.getParentStmt().sqlstatementtype == ESqlStatementType.sstselect)){
079                    // search up level
080                    TSelectSqlStatement selectSqlStatement = (TSelectSqlStatement)psql.getParentStmt();
081                    if (selectSqlStatement.getTables().size()>0){
082                        lcFirstTable = selectSqlStatement.getTables().getTable(0);
083                        lcFirstTable.getLinkedColumns().addObjectName(pColumn);
084                        pColumn.setSourceTable(lcFirstTable);
085                    }
086                }
087
088                // get derived columns from this column if it's type of struct<>
089                // create table absolute-runner-302907.gudu_sqlflow.ADDRESS_NESTED (
090                //      Emp_id INT64,Name STRING
091                //      ,Address ARRAY<STRUCT<State STRING, City STRING, Zipcode INT64>> );
092
093                if ((psql.getSqlEnv() != null)&&(lcFirstTable != null)&&(lcFirstTable.getFullName()!=null)) {
094                   // System.out.println("env\n"+psql.getSqlEnv().toString());
095
096                    TSQLColumn tsqlColumn = psql.getSqlEnv().getColumnInTable(lcFirstTable.getFullName(), pColumn.toString());
097                    if (tsqlColumn != null){
098                        TTypeName columnDataType = tsqlColumn.getColumnDataType();
099                        if (columnDataType != null){
100                          if (columnDataType.getDataType() == EDataType.array_t){
101                              TTypeName subDataType = columnDataType.getTypeOfList();
102                              if (subDataType.getDataType() == EDataType.struct_t){
103                                  if (derivedColumnList == null){
104                                      derivedColumnList = new TObjectNameList();
105                                  }
106                                  //System.out.println("element name in struct: "+subDataType.getDataTypeName());
107                                  for(int i=0;i<subDataType.getColumnDefList().size();i++){
108                                      //System.out.println(subDataType.getColumnDefList().getColumn(i).getColumnName().toString());
109                                      TObjectName attributeName = subDataType.getColumnDefList().getColumn(i).getColumnName();
110                                      attributeName.setParentObjectName(pColumn);
111                                      derivedColumnList.addObjectName(attributeName);
112                                  }
113                              }
114                          }
115                          else if (columnDataType.getDataType() == EDataType.struct_t){
116                              if (derivedColumnList == null){
117                                  derivedColumnList = new TObjectNameList();
118                              }
119                              //System.out.println("element name in struct: "+subDataType.getDataTypeName());
120                              for(int i=0;i<columnDataType.getColumnDefList().size();i++){
121                                  //System.out.println(subDataType.getColumnDefList().getColumn(i).getColumnName().toString());
122                                  TObjectName attributeName = columnDataType.getColumnDefList().getColumn(i).getColumnName();
123                                  attributeName.setParentObjectName(pColumn);
124                                  derivedColumnList.addObjectName(attributeName);
125                              }
126                          }
127                        }
128                        //System.out.println("Find column: "+pColumn.toString()+" in table: "+ lcFirstTable.getFullName().toString()+" with datatype:"+tsqlColumn.getColumnDataType());
129                    }
130                }
131
132            }
133        }
134    }
135
136    public void accept(TParseTreeVisitor v){
137        v.preVisit(this);
138        v.postVisit(this);
139    }
140
141    public void acceptChildren(TParseTreeVisitor v){
142        v.preVisit(this);
143        if (this.getColumns() != null){
144            this.getColumns().acceptChildren(v);
145        }
146        if (this.getArrayExpr() != null){
147            this.getArrayExpr().acceptChildren(v);
148        }
149        v.postVisit(this);
150    }
151}