001    package railo.runtime.db;
002    
003    import java.io.ByteArrayInputStream;
004    import java.util.Enumeration;
005    import java.util.HashSet;
006    import java.util.Set;
007    import java.util.Vector;
008    
009    import railo.runtime.sql.old.ParseException;
010    import railo.runtime.sql.old.ZExp;
011    import railo.runtime.sql.old.ZExpression;
012    import railo.runtime.sql.old.ZFromItem;
013    import railo.runtime.sql.old.ZQuery;
014    import railo.runtime.sql.old.ZStatement;
015    import railo.runtime.sql.old.ZqlParser;
016    
017    
018    /**
019     * utilities for sql statements
020     */
021    public final class HSQLUtil {
022            
023            private ZqlParser parser;
024            private String sql;
025            private boolean isUnion;
026    
027            /**or of the class
028             * construct
029             * @param sql SQl Statement as String
030             */
031            public HSQLUtil(String sql) {
032                    this.sql=SQLPrettyfier.prettyfie(sql,true);//sqlToZQL(sql,true);
033                    parser = new ZqlParser(new ByteArrayInputStream(this.sql.getBytes()));
034            }
035            
036            /* *
037             * transalte SQL syntax to a ZQL combatible form
038             * @param sql sql to transalte
039             * @param changePlaceHolder
040             * @return translated sql
041             * /
042            private static String sqlToZQL(String sql,boolean changePlaceHolder) {
043                    sql=sql.trim();
044                    char c=' ';//,last=' ';
045                    int len=sql.length();
046                    boolean insideString=false;
047                    StringBuffer sb=new StringBuffer(len);
048                    
049                    
050                    
051                    for(int i=0;i<len;i++) {
052                        c=sql.charAt(i);
053                        if(insideString) {
054                            if(c=='\'') {
055                                if(i+1>=len || sql.charAt(i+1)!='\'')insideString=false;
056                            }
057                        }
058                        else {
059                            if(c=='\'')insideString=true;
060                            else if(changePlaceHolder && c=='?') {
061                                sb.append("QUESTION_MARK_SIGN");
062                                        //last=c;
063                                continue;
064                            }
065                            else if(c=='a'|| c=='A') {
066                                if(
067                                        (i!=0 && isWhiteSpace(sql.charAt(i-1)))
068                                        &&
069                                        (i+1<len && (sql.charAt(i+1)=='s' || sql.charAt(i+1)=='S'))
070                                        &&
071                                        (i+2<len && isWhiteSpace(sql.charAt(i+2)))
072                                )   {
073                                    i++;
074                                        //last=c;
075                                    continue;
076                                }
077                            }
078                            else if(c=='*') {
079                                    
080                            }
081                        }
082                        //last=c;
083                        sb.append(c);
084                    }
085                    
086                    if(c!=';')sb.append(';');
087                    
088                    return sb.toString();
089                    
090            }*/
091            
092            /*private static boolean isWhiteSpace(char c) {
093                return (c==' ' || c=='\t' || c=='\b' || c=='\r' || c=='\n');
094            }*/
095    
096            /**
097             * @return return the sql state inside
098             */
099            public String getSQL() {
100                    return sql;
101            }
102            
103            /**
104             * return all invoked tables by a sql statement
105             * @return invoked tables in a ArrayList
106             * @throws ParseException
107             */
108            public Set<String> getInvokedTables() throws ParseException {
109                    
110                    
111                    // Read all SQL statements from input
112                    ZStatement st;
113                    Set<String> tables=new HashSet<String>();
114                    
115                    while((st = parser.readStatement()) != null) {
116                            this.sql=st.toString();
117                            if(st instanceof ZQuery) { // An SQL query: query the DB
118                          getInvokedTables((ZQuery)st,tables);                
119                        }
120                        break;
121                    }
122                    return tables;
123            }
124            
125            private void getInvokedTables(ZQuery query, Set<String> tablesNames) {
126                    //print.out("qry:"+query.getSet());
127                    Vector tables=query.getFrom();
128                    Enumeration e = tables.elements();
129                    
130                    // from
131                            while(e.hasMoreElements()) {
132                                    ZFromItem fromItem=(ZFromItem) e.nextElement();
133                                    tablesNames.add(fromItem.getFullName());
134                            }
135                    // where
136                            ZExp where = query.getWhere();
137                            if(where instanceof ZExpression) {
138                                    parseZExpression((ZExpression) where, tablesNames);
139                            }
140                    // set
141                            ZExpression set = query.getSet();
142                            if(set!=null){
143                                    isUnion=true;
144                                    ZExp op = set.getOperand(0);
145                                    if(op instanceof ZQuery) getInvokedTables((ZQuery)op, tablesNames);
146                            }
147            }
148            
149    
150    
151            public boolean isUnion() {
152                    return isUnion;
153            }
154            
155            private void parseZExpression(ZExpression expression, Set tablesNames) {
156                    Vector operands = expression.getOperands();
157                    Enumeration e = operands.elements();
158                    while(e.hasMoreElements()) {
159                            Object el=e.nextElement();
160                            if(el instanceof ZExpression)parseZExpression((ZExpression)el,tablesNames);
161                            else if(el instanceof ZQuery)getInvokedTables((ZQuery)el,tablesNames);
162                    }
163            }
164    }