All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
SQLVisitor.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2008-2013 National Institute For Space Research (INPE) - Brazil.
2 
3  This file is part of the TerraLib - a Framework for building GIS enabled applications.
4 
5  TerraLib is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as published by
7  the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  TerraLib is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public License
16  along with TerraLib. See COPYING. If not, write to
17  TerraLib Team at <terralib-team@terralib.org>.
18  */
19 
20 /*!
21  \file terralib/dataaccess/query/SQLVisitor.cpp
22 
23  \brief A visitor for building an SQL statement from a given Query hierarchy.
24 */
25 
26 // TerraLib
27 #include "../../common/StringUtils.h"
28 #include "../../common/Translator.h"
29 #include "../../datatype/AbstractData.h"
30 #include "../Exception.h"
31 #include "DataSetName.h"
32 #include "Distinct.h"
33 #include "Expression.h"
34 #include "Field.h"
35 #include "Function.h"
36 #include "GroupBy.h"
37 #include "GroupByItem.h"
38 #include "Having.h"
39 #include "In.h"
40 #include "Join.h"
41 #include "JoinCondition.h"
42 #include "JoinConditionOn.h"
43 #include "JoinConditionUsing.h"
44 #include "Literal.h"
45 #include "LiteralBool.h"
46 #include "LiteralByteArray.h"
47 #include "LiteralDateTime.h"
48 #include "LiteralDouble.h"
49 #include "LiteralGeom.h"
50 #include "LiteralInt16.h"
51 #include "LiteralInt32.h"
52 #include "LiteralInt64.h"
53 #include "LiteralString.h"
54 #include "OrderByItem.h"
55 #include "PropertyName.h"
56 #include "Select.h"
57 #include "SQLDialect.h"
58 #include "SQLFunctionEncoder.h"
59 #include "SQLVisitor.h"
60 #include "SubSelect.h"
61 #include "Where.h"
62 
63 // STL
64 #include <cassert>
65 
66 void te::da::SQLVisitor::visit(const Expression& /*visited*/)
67 {
68 }
69 
71 {
72  m_sql += visited.getName();
73 
74  if(visited.getAlias().empty() == false)
75  {
76  m_sql += " AS ";
77  m_sql += visited.getAlias();
78  }
79 }
80 
81 void te::da::SQLVisitor::visit(const FromItem& /*visited*/)
82 {
83 }
84 
85 void te::da::SQLVisitor::visit(const Function& visited)
86 {
87  const std::string& fname = visited.getName();
88 
89  const SQLFunctionEncoder* encoder = m_dialect.find(fname);
90 
91  if(encoder == 0)
92  throw Exception(TE_TR("The informed function is not supported by this driver!"));
93 
94  encoder->toSQL(visited, m_sql, *this);
95 }
96 
97 void te::da::SQLVisitor::visit(const Join& visited)
98 {
99  assert(visited.getFirst() && visited.getSecond());
100 
101  m_sql += "(";
102  visited.getFirst()->accept(*this);
103 
104  if(visited.isNatural())
105  m_sql += " NATURAL ";
106 
107  switch(visited.getType())
108  {
109  case JOIN :
110  m_sql += " JOIN ";
111  break;
112 
113  case INNER_JOIN :
114  m_sql += " INNER JOIN ";
115  break;
116 
117  case LEFT_JOIN :
118  m_sql += " LEFT JOIN ";
119  break;
120 
121  case RIGHT_JOIN :
122  m_sql += " RIGHT JOIN ";
123  break;
124 
125  case FULL_OUTER_JOIN :
126  m_sql += " FULL OUTER JOIN ";
127  break;
128 
129  case CROSS_JOIN :
130  m_sql += " CROSS JOIN ";
131  break;
132 
133  case NATURAL_JOIN :
134  m_sql += " NATURAL JOIN ";
135  break;
136  }
137 
138  visited.getSecond()->accept(*this);
139 
140  if(visited.getCondition())
141  {
142  m_sql += " ";
143  visited.getCondition()->accept(*this);
144  }
145 
146  m_sql += ")";
147 }
148 
149 void te::da::SQLVisitor::visit(const JoinCondition& /*visited*/)
150 {
151 }
152 
154 {
155  assert(visited.getCondition());
156  m_sql += "ON (";
157  visited.getCondition()->accept(*this);
158  m_sql += ")";
159 }
160 
162 {
163  m_sql += "USING (";
164 
165  size_t ncols = visited.getNumFields();
166 
167  for(size_t i = 0; i < ncols; ++i)
168  {
169  if(i != 0)
170  m_sql += ", ";
171 
172  assert(visited[i]);
173  visited[i]->accept(*this);
174  }
175 
176  m_sql += ")";
177 }
178 
179 void te::da::SQLVisitor::visit(const Literal& visited)
180 {
181  if(visited.getValue())
182  m_sql += visited.getValue()->toString();
183 }
184 
186 {
187  if(visited.getValue())
188  m_sql += "bool(" + visited.getValue()->toString() + ")";
189 }
190 
192 {
193  if(visited.getValue())
194  m_sql += visited.getValue()->toString();
195 }
196 
198 {
199  if(visited.getValue())
200  m_sql += visited.getValue()->toString();
201 }
202 
204 {
205  if(visited.getValue())
206  m_sql += visited.getValue()->toString();
207 }
208 
210 {
211 }
212 
214 {
215  if(visited.getValue())
216  m_sql += visited.getValue()->toString();
217 }
218 
220 {
221  if(visited.getValue())
222  m_sql += visited.getValue()->toString();
223 }
224 
226 {
227  if(visited.getValue())
228  m_sql += visited.getValue()->toString();
229 }
230 
232 {
233  if(visited.getValue())
234  m_sql += visited.getValue()->toString();
235 }
236 
238 {
239  if(visited.getValue())
240  {
241  m_sql += "'";
242  m_sql += visited.getValue()->toString();
243  m_sql += "'";
244  }
245 }
246 
248 {
249  m_sql += visited.getName();
250 }
251 
252 void te::da::SQLVisitor::visit(const Query& /*visited*/)
253 {
254 }
255 
256 void te::da::SQLVisitor::visit(const Select& visited)
257 {
258  m_sql += "SELECT ";
259 
260  if(visited.getDistinct())
261  {
262  visitDistinct(*(visited.getDistinct()));
263  m_sql += " ";
264  }
265 
266  if(visited.getFields())
267  {
268  visit(*(visited.getFields()));
269  m_sql += " ";
270  }
271 
272  if(visited.getFrom())
273  {
274  visit(*(visited.getFrom()));
275  m_sql += " ";
276  }
277 
278  if(visited.getWhere())
279  {
280  m_sql += "WHERE ";
281  visited.getWhere()->getExp()->accept(*this);
282  m_sql += " ";
283  }
284 
285  if(visited.getGroupBy())
286  {
287  visit(*(visited.getGroupBy()));
288  m_sql += " ";
289  }
290 
291  if(visited.getHaving())
292  {
293  m_sql += "HAVING ";
294  visited.getHaving()->getExp()->accept(*this);
295  m_sql += " ";
296  }
297 
298  if(visited.getOrderBy())
299  visit(*(visited.getOrderBy()));
300 }
301 
303 {
304  assert(visited.getSelect());
305  visited.getSelect()->accept(*this);
306 
307  if(visited.getAlias().empty() == false)
308  {
309  m_sql += " AS ";
310  m_sql += visited.getAlias();
311  }
312 }
313 
314 void te::da::SQLVisitor::visit(const In& visited)
315 {
316  assert(visited.getPropertyName());
317  visited.getPropertyName()->accept(*this);
318 
319  m_sql += " IN";
320  m_sql += "(";
321 
322  for(size_t i = 0; i < visited.getNumArgs(); ++i)
323  {
324  if(i != 0)
325  m_sql += ", ";
326 
327  assert(visited[i]);
328  visited[i]->accept(*this);
329  }
330 
331  m_sql += ")";
332 }
333 
335 {
336  if(visited.empty())
337  {
338  m_sql += "DISTINCT";
339  }
340  else
341  {
342  m_sql += "DISTINCT ON(";
343 
344  std::size_t ncols = visited.size();
345 
346  for(std::size_t i = 0; i < ncols; ++i)
347  {
348  if(i != 0)
349  m_sql += ", ";
350 
351  visited[i].accept(*this);
352  }
353 
354  m_sql += ")";
355  }
356 }
357 
359 {
360  std::size_t size = visited.size();
361 
362  for(size_t i = 0; i < size; ++i)
363  {
364  if(i != 0)
365  m_sql += ", ";
366 
367  visited[i].getExpression()->accept(*this);
368 
369  if(visited[i].getAlias())
370  m_sql += *(visited[i].getAlias());
371  }
372 }
373 
375 {
376  std::size_t size = visited.size();
377 
378  m_sql += "FROM ";
379 
380  for(std::size_t i = 0; i < size; ++i)
381  {
382  if(i != 0)
383  m_sql += ", ";
384 
385  visited[i].accept(*this);
386  }
387 }
388 
390 {
391  m_sql += "GROUP BY ";
392 
393  std::size_t ncols = visited.size();
394 
395  for(std::size_t i = 0; i < ncols; ++i)
396  {
397  if(i != 0)
398  m_sql += ", ";
399 
400  visited[i].getExpression()->accept(*this);
401  }
402 }
403 
405 {
406  std::size_t size = visited.size();
407 
408  m_sql += "ORDER BY ";
409 
410  for(std::size_t i = 0; i < size; ++i)
411  {
412  if(i != 0)
413  m_sql += ", ";
414 
415  visited[i].getExpression()->accept(*this);
416 
417  if(visited[i].getSortOrder() == te::da::ASC)
418  m_sql += " ASC";
419  else
420  m_sql += " DESC";
421  }
422 }
const Distinct * getDistinct() const
It returns the Distinct modifier.
Definition: Select.cpp:992
const std::string & getName() const
It returns the property name.
Definition: PropertyName.h:80
A class that models a Literal for a integer value.
boost::ptr_vector< GroupByItem > GroupBy
A class that can be used to model a GROUP BY clause.
Definition: GroupBy.h:37
const OrderBy * getOrderBy() const
It returns the list of expressions used to sort the output result.
Definition: Select.cpp:982
An abstract class that models a source of data in a query.
Definition: FromItem.h:50
A class that models a Function expression.
Select * getSelect() const
It returns the associated subselect.
Definition: SubSelect.cpp:69
virtual void visitDistinct(const Distinct &visited)
Definition: SQLVisitor.cpp:334
A class that models the name of a dataset used in a From clause.
Definition: DataSetName.h:43
A class that models the name of any property of an object.
const GroupBy * getGroupBy() const
It returns the list of expressions used to condense the result set.
Definition: Select.cpp:962
boost::ptr_vector< Expression > Distinct
A class that models a Distinct clause on a query.
Definition: Distinct.h:37
A base class for encoders of SQL function expressions.
A class that models the name of any property of an object.
Definition: PropertyName.h:50
A class that represents the IN operator.
A class that models a Literal Bool value.
A class that models the name of a dataset used in a From clause.
A class that models a Distinct clause on a query.
This class models a bool Literal value.
Definition: LiteralBool.h:43
It represents the SQL query dialect accepted by a given data source.
Expression * getCondition() const
It returns a pointer to a join condition.
boost::ptr_vector< OrderByItem > OrderBy
A class that can be used to model an ORDER BY clause.
Definition: OrderBy.h:37
virtual std::string toString() const =0
It returns the data value in a string notation.
JoinType getType() const
It returns the join type.
Definition: Join.cpp:111
A class that models a literal for ByteArray values.
#define TE_TR(message)
It marks a string in order to get translated.
Definition: Translator.h:345
A visitor for building an SQL statement from a given Query hierarchy.
const From * getFrom() const
It returns the list of source information to be used by the query.
Definition: Select.cpp:942
This is an abstract class that models a query expression.
Definition: Expression.h:47
A Join clause combines two FromItems.
A class that models a literal for Date and Time values.
JoinConditionOn is a boolean expression and it specifies which items in a join are considered to matc...
PropertyName * getPropertyName() const
It returns the property name.
Definition: In.cpp:82
bool isNatural() const
It tells if the join is Natural.
Definition: Join.h:141
A Having is a filter expression that can be applied to a query with a group by clause.
A class that models a literal for Date and Time values.
const std::string & getAlias() const
It returns the alias associated to the source item.
Definition: FromItem.cpp:47
This class models a literal value.
Definition: Literal.h:53
virtual void visit(const Expression &visited)
Definition: SQLVisitor.cpp:66
A condition to be used in a Join clause.
A class that models a Literal for a integer value.
A class that models a literal for ByteArray values.
A condition to be used in a Join clause.
Definition: JoinCondition.h:44
The Field class can be used to model an expression that takes part of the output items of a SELECT...
boost::ptr_vector< Field > Fields
Fields is just a boost::ptr_vector of Field pointers.
Definition: Fields.h:37
A class that models a Literal for a integer value.
This is an abstract class that models a query expression.
Expression * getExp() const
Definition: Where.cpp:60
A class that models a Function expression.
Definition: Function.h:47
const Fields * getFields() const
It returns the list of output expressions used to form the result set.
Definition: Select.cpp:932
A class that can be used in a GROUP BY clause.
A Join clause combines two FromItems.
Definition: Join.h:50
Expression * getExp() const
Definition: Having.cpp:60
A class that models a literal for double values.
Definition: LiteralDouble.h:43
A Select models a query to be used when retrieving data from a data source.
std::size_t getNumFields() const
It returns the number of fields in this join condition.
const std::string & getName() const
It returns the function name.
Definition: Function.h:79
A Select models a query to be used when retrieving data from a DataSource.
Definition: Select.h:65
JoinConditionUsing class can be used to model a USING clause in a Join.
A class that can be used to model a GROUP BY clause.
A class that can be used to model a filter expression that can be applied to a query.
A class that models a Literal String value.
boost::ptr_vector< FromItem > From
It models the FROM clause for a query.
Definition: From.h:37
FromItem * getSecond() const
It returns the second item involved in the join.
Definition: Join.cpp:101
Where * getWhere() const
It returns the filter condition.
Definition: Select.cpp:952
A class that models a literal for double values.
JoinCondition * getCondition() const
It returns the join condition.
Definition: Join.cpp:121
JoinConditionUsing class can be used to model a USING clause in a Join.
virtual ReturnType accept(VisitorType &guest) const =0
It call the visit method from the guest object.
const Having * getHaving() const
It returns the list of expressions used to eliminate group row that doesn't satisfy the condition...
Definition: Select.cpp:972
A class that models a literal for Envelope values.
const std::string & getName() const
It returns the dataset name.
Definition: DataSetName.cpp:57
A Select can be used as a source of information in another query.
A class that represents the IN operator.
Definition: In.h:52
JoinConditionOn is a boolean expression and it specifies which items in a join are considered to matc...
A class that can be used in an ORDER BY clause to sort the items of a resulting query.
A Select can be used as a source of information in another query.
Definition: SubSelect.h:49
A class that models a literal for Geometry values.
te::dt::AbstractData * getValue() const
It returns the value associated to the literal.
Definition: Literal.cpp:65
A base class for encoders of SQL function expressions.
A Query is independent from the data source language/dialect.
Definition: Query.h:46
std::size_t getNumArgs() const
It returns the number of arguments informed to the function.
Definition: Function.cpp:62
virtual void toSQL(const Function &f, std::string &buff, SQLVisitor &v) const =0
It encodes the function to a SQL notation.
FromItem * getFirst() const
It returns the first from item involved in the join.
Definition: Join.cpp:91
A class that models a literal for Geometry values.
Definition: LiteralGeom.h:46
This class models a literal value.
This class models a string Literal value.
Definition: LiteralString.h:46