| 1 | /** |
| 2 | * Copyright (C) 2006 NetMind Consulting Bt. |
| 3 | * |
| 4 | * This library is free software; you can redistribute it and/or |
| 5 | * modify it under the terms of the GNU Lesser General Public |
| 6 | * License as published by the Free Software Foundation; either |
| 7 | * version 3 of the License, or (at your option) any later version. |
| 8 | * |
| 9 | * This library is distributed in the hope that it will be useful, |
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 12 | * Lesser General Public License for more details. |
| 13 | * |
| 14 | * You should have received a copy of the GNU Lesser General Public |
| 15 | * License along with this library; if not, write to the Free Software |
| 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 17 | */ |
| 18 | |
| 19 | package hu.netmind.beankeeper.parser; |
| 20 | |
| 21 | import java.util.Iterator; |
| 22 | import java.util.List; |
| 23 | import java.util.ArrayList; |
| 24 | import java.util.Date; |
| 25 | import java.util.Set; |
| 26 | import java.util.HashSet; |
| 27 | import org.apache.log4j.Logger; |
| 28 | |
| 29 | /** |
| 30 | * This class represents a query statement. A query statement |
| 31 | * has four parts: A table name to select from, additional tables to |
| 32 | * left join, a query expression, and order by parts. |
| 33 | * @author Brautigam Robert |
| 34 | * @version Revision: $Revision$ |
| 35 | */ |
| 36 | public class QueryStatement |
| 37 | { |
| 38 | private static Logger logger = Logger.getLogger(QueryStatement.class); |
| 39 | |
| 40 | public static final int MODE_FIND = 1; |
| 41 | public static final int MODE_VIEW = 2; |
| 42 | |
| 43 | private int mode = MODE_FIND; |
| 44 | private List selectTerms = new ArrayList(); |
| 45 | private Set specifiedTerms = new HashSet(); |
| 46 | private Expression queryExpression; |
| 47 | private List orderByList = new ArrayList(); |
| 48 | private List groupByList = new ArrayList(); |
| 49 | private Expression havingExpression; |
| 50 | private TimeControl timeControl; |
| 51 | private String originalStatement; |
| 52 | private String staticRepresentation; |
| 53 | |
| 54 | public QueryStatement(QueryStatement stmt) |
| 55 | { |
| 56 | setSelectTerms(stmt.getSelectTerms()); |
| 57 | setSpecifiedTerms(stmt.getSpecifiedTerms()); |
| 58 | setMode(stmt.getMode()); |
| 59 | setTimeControl(stmt.getTimeControl()); |
| 60 | setQueryExpression(stmt.getQueryExpression()); |
| 61 | setOrderByList(stmt.getOrderByList()); |
| 62 | setGroupByList(stmt.getGroupByList()); |
| 63 | setHavingExpression(stmt.getHavingExpression()); |
| 64 | setOriginalStatement(stmt.getOriginalStatement()); |
| 65 | setStaticRepresentation(stmt.getStaticRepresentation()); |
| 66 | } |
| 67 | |
| 68 | public QueryStatement deepCopy() |
| 69 | { |
| 70 | QueryStatement result = new QueryStatement(this); |
| 71 | if ( getSelectTerms() != null ) |
| 72 | result.setSelectTerms(new ArrayList(getSelectTerms())); |
| 73 | if ( getQueryExpression() != null ) |
| 74 | result.setQueryExpression(getQueryExpression().deepCopy()); |
| 75 | if ( getHavingExpression() != null ) |
| 76 | result.setHavingExpression(getHavingExpression().deepCopy()); |
| 77 | if ( getOrderByList() != null ) |
| 78 | result.setOrderByList(new ArrayList(getOrderByList())); |
| 79 | if ( getGroupByList() != null ) |
| 80 | result.setGroupByList(new ArrayList(getGroupByList())); |
| 81 | result.setSpecifiedTerms(new HashSet()); |
| 82 | Iterator specifiedTermsIterator = specifiedTerms.iterator(); |
| 83 | while ( specifiedTermsIterator.hasNext() ) |
| 84 | result.getSpecifiedTerms().add(((SpecifiedTableTerm) |
| 85 | specifiedTermsIterator.next()).deepCopy()); |
| 86 | return result; |
| 87 | } |
| 88 | |
| 89 | public QueryStatement(List selectTerms, Expression queryExpression, List orderByList, List groupByList, |
| 90 | Expression havingExpression) |
| 91 | { |
| 92 | setSelectTerms(selectTerms); |
| 93 | Set specifiedTerms = new HashSet(); |
| 94 | for ( int i=0; i<selectTerms.size(); i++ ) |
| 95 | { |
| 96 | TableTerm term = (TableTerm) selectTerms.get(i); |
| 97 | if ( term instanceof SpecifiedTableTerm ) |
| 98 | specifiedTerms.add(term); |
| 99 | else |
| 100 | specifiedTerms.add(new SpecifiedTableTerm(term)); |
| 101 | } |
| 102 | setSpecifiedTerms(specifiedTerms); |
| 103 | setQueryExpression(queryExpression); |
| 104 | setOrderByList(orderByList); |
| 105 | setGroupByList(groupByList); |
| 106 | setHavingExpression(havingExpression); |
| 107 | } |
| 108 | |
| 109 | public QueryStatement(TableTerm tableTerm, Expression queryExpression, List orderByList) |
| 110 | { |
| 111 | ArrayList selectTerms = new ArrayList(); |
| 112 | selectTerms.add(tableTerm); |
| 113 | setSelectTerms(selectTerms); |
| 114 | Set specifiedTerms = new HashSet(); |
| 115 | if ( tableTerm instanceof SpecifiedTableTerm ) |
| 116 | specifiedTerms.add(tableTerm); |
| 117 | else |
| 118 | specifiedTerms.add(new SpecifiedTableTerm(tableTerm)); |
| 119 | setSpecifiedTerms(specifiedTerms); |
| 120 | setQueryExpression(queryExpression); |
| 121 | setOrderByList(orderByList); |
| 122 | } |
| 123 | |
| 124 | public QueryStatement(String tableName, Expression queryExpression, List orderByList) |
| 125 | { |
| 126 | this(new TableTerm(tableName,null),queryExpression,orderByList); |
| 127 | } |
| 128 | |
| 129 | /** |
| 130 | * Compute all tables in this statement. |
| 131 | */ |
| 132 | public Set computeTables() |
| 133 | { |
| 134 | Set tables = new HashSet(); |
| 135 | Iterator specifiedTermsIterator = specifiedTerms.iterator(); |
| 136 | while ( specifiedTermsIterator.hasNext() ) |
| 137 | { |
| 138 | SpecifiedTableTerm term = (SpecifiedTableTerm) specifiedTermsIterator.next(); |
| 139 | tables.add(term.getTableName()); |
| 140 | for ( int i=0; i<term.getRelatedLeftTerms().size(); i++ ) |
| 141 | tables.add(((SpecifiedTableTerm.LeftjoinEntry) |
| 142 | term.getRelatedLeftTerms().get(i)).term.getTableName()); |
| 143 | for ( int i=0; i<term.getReferencedLeftTerms().size(); i++ ) |
| 144 | tables.add(((SpecifiedTableTerm.LeftjoinEntry) |
| 145 | term.getReferencedLeftTerms().get(i)).term.getTableName()); |
| 146 | } |
| 147 | return tables; |
| 148 | } |
| 149 | |
| 150 | /** |
| 151 | * Get the specified term for a given term. |
| 152 | * @return The specified term for the given term, or an empty |
| 153 | * specified term, if the given term is not found in the specifiedTerms |
| 154 | * list. |
| 155 | */ |
| 156 | public SpecifiedTableTerm getSpecifiedTerm(TableTerm source) |
| 157 | { |
| 158 | Iterator specifiedTermsIterator = specifiedTerms.iterator(); |
| 159 | while ( specifiedTermsIterator.hasNext() ) |
| 160 | { |
| 161 | SpecifiedTableTerm term = (SpecifiedTableTerm) specifiedTermsIterator.next(); |
| 162 | if ( term.equals(source) ) |
| 163 | return term; |
| 164 | } |
| 165 | return new SpecifiedTableTerm(source); |
| 166 | } |
| 167 | |
| 168 | /** |
| 169 | * Replace all occurences of the given term with the new term. |
| 170 | */ |
| 171 | public void replace(TableTerm oldTerm, TableTerm newTerm) |
| 172 | { |
| 173 | replace(oldTerm,new SpecifiedTableTerm(newTerm),null); |
| 174 | } |
| 175 | |
| 176 | /** |
| 177 | * Replace all occurences of the given term with the new term. |
| 178 | * If the term is inserted into a reference term, then substitute |
| 179 | * the column name too. |
| 180 | */ |
| 181 | public void replace(TableTerm oldTerm, SpecifiedTableTerm newTerm, String newColumnName) |
| 182 | { |
| 183 | // First, replace in selected terms |
| 184 | for ( int i=0; i<selectTerms.size(); i++ ) |
| 185 | { |
| 186 | TableTerm term = (TableTerm) selectTerms.get(i); |
| 187 | TableTerm replaceTerm = newTerm; |
| 188 | if ( term.equals(oldTerm) ) |
| 189 | { |
| 190 | if ( term instanceof ReferenceTerm ) |
| 191 | { |
| 192 | replaceTerm = new ReferenceTerm(newTerm, |
| 193 | (newColumnName!=null)?newColumnName:(((ReferenceTerm) term).getColumnName()), |
| 194 | ((ReferenceTerm) term).getColumnAlias()); |
| 195 | ((ReferenceTerm)replaceTerm).setFunction(((ReferenceTerm)term).getFunction()); |
| 196 | } |
| 197 | selectTerms.set(i,replaceTerm); |
| 198 | logger.debug("replaced: "+term+" with "+newTerm+"("+newColumnName+")"); |
| 199 | } |
| 200 | } |
| 201 | // Replace in specified terms |
| 202 | Iterator specifiedTermsIterator = new HashSet(specifiedTerms).iterator(); |
| 203 | while ( specifiedTermsIterator.hasNext() ) |
| 204 | { |
| 205 | SpecifiedTableTerm term = (SpecifiedTableTerm) specifiedTermsIterator.next(); |
| 206 | if ( term.equals(oldTerm) ) |
| 207 | { |
| 208 | specifiedTerms.remove(oldTerm); |
| 209 | specifiedTerms.add(newTerm); |
| 210 | } |
| 211 | } |
| 212 | // Replace in expressions |
| 213 | if ( getQueryExpression() != null ) |
| 214 | getQueryExpression().replace(oldTerm,newTerm,newColumnName); |
| 215 | if ( getHavingExpression() != null ) |
| 216 | getHavingExpression().replace(oldTerm,newTerm,newColumnName); |
| 217 | // Replace in group by terms |
| 218 | if ( getGroupByList() != null ) |
| 219 | { |
| 220 | for ( int i=0; i<getGroupByList().size(); i++ ) |
| 221 | { |
| 222 | TableTerm term = (TableTerm) getGroupByList().get(i); |
| 223 | TableTerm replaceTerm = newTerm; |
| 224 | if ( term.equals(oldTerm) ) |
| 225 | { |
| 226 | if ( term instanceof ReferenceTerm ) |
| 227 | { |
| 228 | replaceTerm = new ReferenceTerm(newTerm, |
| 229 | (newColumnName!=null)?newColumnName:(((ReferenceTerm) term).getColumnName()), |
| 230 | ((ReferenceTerm) term).getColumnAlias()); |
| 231 | ((ReferenceTerm)replaceTerm).setFunction(((ReferenceTerm)term).getFunction()); |
| 232 | } |
| 233 | getGroupByList().set(i,replaceTerm); |
| 234 | if ( logger.isDebugEnabled() ) |
| 235 | logger.debug("replaced in group by: "+term+" with "+newTerm+"("+newColumnName+")"); |
| 236 | } |
| 237 | } |
| 238 | } |
| 239 | // Replace in order bys |
| 240 | for ( int i=0; (getOrderByList()!=null) && (i<getOrderByList().size()); i++ ) |
| 241 | { |
| 242 | OrderBy orderBy = (OrderBy) getOrderByList().get(i); |
| 243 | if ( orderBy.getReferenceTerm().equals(oldTerm) ) |
| 244 | { |
| 245 | ReferenceTerm replaceTerm = new ReferenceTerm(orderBy.getReferenceTerm()); |
| 246 | replaceTerm.setTableName(newTerm.getTableName()); |
| 247 | replaceTerm.setAlias(newTerm.getAlias()); |
| 248 | if ( newColumnName != null ) |
| 249 | replaceTerm.setColumnName(newColumnName); |
| 250 | if ( logger.isDebugEnabled() ) |
| 251 | logger.debug("replacing order by term: "+orderBy.getReferenceTerm()+" with "+replaceTerm); |
| 252 | getOrderByList().set(i,new OrderBy(replaceTerm,orderBy.getDirection())); |
| 253 | } |
| 254 | } |
| 255 | } |
| 256 | |
| 257 | public Expression getQueryExpression() |
| 258 | { |
| 259 | return queryExpression; |
| 260 | } |
| 261 | public void setQueryExpression(Expression queryExpression) |
| 262 | { |
| 263 | this.queryExpression=queryExpression; |
| 264 | } |
| 265 | |
| 266 | public List getOrderByList() |
| 267 | { |
| 268 | return orderByList; |
| 269 | } |
| 270 | public void setOrderByList(List orderByList) |
| 271 | { |
| 272 | this.orderByList=orderByList; |
| 273 | } |
| 274 | |
| 275 | public TimeControl getTimeControl() |
| 276 | { |
| 277 | return timeControl; |
| 278 | } |
| 279 | public void setTimeControl(TimeControl timeControl) |
| 280 | { |
| 281 | this.timeControl=timeControl; |
| 282 | } |
| 283 | |
| 284 | public List getSelectTerms() |
| 285 | { |
| 286 | return selectTerms; |
| 287 | } |
| 288 | public void setSelectTerms(List selectTerms) |
| 289 | { |
| 290 | this.selectTerms=selectTerms; |
| 291 | } |
| 292 | |
| 293 | public int getMode() |
| 294 | { |
| 295 | return mode; |
| 296 | } |
| 297 | public void setMode(int mode) |
| 298 | { |
| 299 | this.mode=mode; |
| 300 | } |
| 301 | |
| 302 | public Set getSpecifiedTerms() |
| 303 | { |
| 304 | return specifiedTerms; |
| 305 | } |
| 306 | public void setSpecifiedTerms(Set specifiedTerms) |
| 307 | { |
| 308 | this.specifiedTerms=specifiedTerms; |
| 309 | } |
| 310 | |
| 311 | public String getStaticRepresentation() |
| 312 | { |
| 313 | return staticRepresentation; |
| 314 | } |
| 315 | public void setStaticRepresentation(String staticRepresentation) |
| 316 | { |
| 317 | this.staticRepresentation=staticRepresentation; |
| 318 | } |
| 319 | |
| 320 | public String getOriginalStatement() |
| 321 | { |
| 322 | return originalStatement; |
| 323 | } |
| 324 | public void setOriginalStatement(String originalStatement) |
| 325 | { |
| 326 | this.originalStatement=originalStatement; |
| 327 | } |
| 328 | |
| 329 | public List getGroupByList() |
| 330 | { |
| 331 | return groupByList; |
| 332 | } |
| 333 | public void setGroupByList(List groupByList) |
| 334 | { |
| 335 | this.groupByList=groupByList; |
| 336 | } |
| 337 | |
| 338 | public Expression getHavingExpression() |
| 339 | { |
| 340 | return havingExpression; |
| 341 | } |
| 342 | public void setHavingExpression(Expression havingExpression) |
| 343 | { |
| 344 | this.havingExpression=havingExpression; |
| 345 | } |
| 346 | } |
| 347 | |
| 348 | |