001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019package lucee.runtime.sql;
020
021import java.util.ArrayList;
022import java.util.Iterator;
023import java.util.List;
024
025import lucee.runtime.exp.DatabaseException;
026import lucee.runtime.sql.exp.Column;
027import lucee.runtime.sql.exp.Expression;
028import lucee.runtime.sql.exp.op.Operation;
029import lucee.runtime.sql.exp.value.ValueNumber;
030
031public class Selects {
032
033        private List<Column> orderbys=new ArrayList<Column>();
034        private List<Select> selects=new ArrayList<Select>();
035        
036
037
038        public void addOrderByExpression(Column exp) {
039                this.orderbys.add(exp);
040        }
041
042        /**
043         * @return the orderbys
044         */
045        public Column[] getOrderbys() {
046                if(orderbys==null) return new Column[0];
047                return orderbys.toArray(new Column[orderbys.size()]);
048        }
049
050        public void addSelect(Select select) {
051                selects.add(select);
052        }
053        
054        public Select[] getSelects() {
055                if(selects==null) return new Select[0];
056                return selects.toArray(new Select[selects.size()]);
057        }
058        
059
060        @Override
061
062        public String toString() {
063                return _toString(this);
064        }
065        public static String _toString(Selects __selects) {
066                Select[] _selects = __selects.getSelects();
067                Select s;
068                StringBuffer sb=new StringBuffer();
069                
070                for(int y=0;y<_selects.length;y++) {
071                        s = _selects[y];
072                        
073                        if(y>0) {
074                                if(s.isUnionDistinct())sb.append("union distinct\n\n");
075                                else sb.append("union\n\n");
076                        }
077                        
078                        sb.append("select\n\t");
079
080                        if(s.isDistinct()) sb.append("distinct\n\t");
081                        ValueNumber top = s.getTop();
082                        if(top!=null) sb.append("top "+top.getString()+"\n\t");
083                        // select
084                        Expression[] sels = s.getSelects();
085                        Expression exp;
086                        boolean first=true;
087                        for(int i=0;i<sels.length;i++) {
088                                if(!first)sb.append("\t,");
089                                exp=sels[i];
090                                sb.append(exp.toString(false)+"\n");
091                                first=false;
092                        }
093        
094                        // from
095                        sb.append("from\n\t");
096                        Column[] forms = s.getFroms();
097                        first=true;
098                        for(int i=0;i<forms.length;i++) {
099                                if(!first)sb.append("\t,");
100                                exp=forms[i];
101                                sb.append(exp.toString(false)+"\n");
102                                first=false;
103                        }
104        
105                        // where
106                        if(s.getWhere()!=null){
107                                sb.append("where \n\t");
108                                sb.append(s.getWhere().toString(true));
109                                sb.append("\n");
110                        }
111        
112                        // group by
113                        Column[] gbs = s.getGroupbys();
114                        if(gbs.length>0) {
115                                sb.append("group by\n\t");
116                                first=true;
117                                for(int i=0;i<gbs.length;i++) {
118                                        if(!first)sb.append("\t,");
119                                        exp=gbs[i];
120                                        sb.append(exp.toString(false)+"\n");
121                                        first=false;
122                                }
123                        }
124        
125                        
126                        // having
127                        Operation having = s.getHaving();
128                        if(having!=null){
129                                sb.append("having \n\t");
130                                sb.append(having.toString(true));
131                                sb.append("\n");
132                        }
133                        
134                }
135
136                // order by
137                if(__selects.orderbys!=null && __selects.orderbys.size()>0) {
138                        sb.append("order by\n\t");
139                        Iterator<Column> it = __selects.orderbys.iterator();
140                        Expression exp;
141                        boolean first = true;
142                        while(it.hasNext()) {
143                                if(!first)sb.append("\t,");
144                                exp=it.next();
145                                sb.append(exp.toString(false)+" "+(exp.isDirectionBackward()?"DESC":"ASC")+"\n");
146                                first=false;
147                        }
148                }
149                return sb.toString();
150        }
151
152        public Column[] getTables() {
153                Iterator<Select> it = selects.iterator();
154                Select s;
155                ArrayList<Column> rtn=new ArrayList<Column>();
156                Column[] froms;
157                while(it.hasNext()) {
158                        s=it.next();
159                        froms = s.getFroms();
160                        for(int i=0;i<froms.length;i++) {
161                                rtn.add(froms[i]);
162                        }
163                }
164                return rtn.toArray(new Column[rtn.size()]);
165        }
166
167        public boolean isDistinct() {
168                Select s;
169                int len=selects.size();
170                if(len==1) {
171                        s=selects.get(0);
172                        return s.isDistinct();
173                }
174                for(int i=1;i<len;i++) {
175                        s=selects.get(i);
176                        if(!s.isUnionDistinct()) return false;
177                }
178                return true;
179        }
180        public Column[] getDistincts() throws DatabaseException {
181                List<Column> columns=new ArrayList<Column>();
182                Select s;
183                int len=selects.size();
184                if(len==1) {
185                        s=selects.get(0);
186                        Expression[] _selects = s.getSelects();
187                        for(int i=0;i<_selects.length;i++){
188                                if(_selects[i] instanceof Column) {
189                                        columns.add((Column) _selects[i]);
190                                }       
191                        }
192                        return columns.toArray(new Column[columns.size()]);
193                }
194                throw new DatabaseException("not supported for Union distinct",null,null,null);
195        }
196}