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 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 "ST_Dump.h"
61 #include "SubSelect.h"
62 #include "Where.h"
63 
64 // STL
65 #include <cassert>
66 
67 void te::da::SQLVisitor::visit(const Expression& /*visited*/)
68 {
69 }
70 
72 {
73  m_sql += visited.getName();
74 
75  if(visited.getAlias().empty() == false)
76  {
77  m_sql += " AS ";
78  m_sql += visited.getAlias();
79  }
80 }
81 
82 void te::da::SQLVisitor::visit(const FromItem& /*visited*/)
83 {
84 }
85 
86 void te::da::SQLVisitor::visit(const Function& visited)
87 {
88  const std::string& fname = visited.getName();
89 
90  const SQLFunctionEncoder* encoder = m_dialect.find(fname);
91 
92  if(encoder == 0)
93  throw Exception(TE_TR("The informed function is not supported by this driver!"));
94 
95  encoder->toSQL(visited, m_sql, *this);
96 }
97 
98 void te::da::SQLVisitor::visit(const Join& visited)
99 {
100  assert(visited.getFirst() && visited.getSecond());
101 
102  m_sql += "(";
103  visited.getFirst()->accept(*this);
104 
105  if(visited.isNatural())
106  m_sql += " NATURAL ";
107 
108  switch(visited.getType())
109  {
110  case JOIN :
111  m_sql += " JOIN ";
112  break;
113 
114  case INNER_JOIN :
115  m_sql += " INNER JOIN ";
116  break;
117 
118  case LEFT_JOIN :
119  m_sql += " LEFT JOIN ";
120  break;
121 
122  case RIGHT_JOIN :
123  m_sql += " RIGHT JOIN ";
124  break;
125 
126  case FULL_OUTER_JOIN :
127  m_sql += " FULL OUTER JOIN ";
128  break;
129 
130  case CROSS_JOIN :
131  m_sql += " CROSS JOIN ";
132  break;
133 
134  case NATURAL_JOIN :
135  m_sql += " NATURAL JOIN ";
136  break;
137  }
138 
139  visited.getSecond()->accept(*this);
140 
141  if(visited.getCondition())
142  {
143  m_sql += " ";
144  visited.getCondition()->accept(*this);
145  }
146 
147  m_sql += ")";
148 }
149 
150 void te::da::SQLVisitor::visit(const JoinCondition& /*visited*/)
151 {
152 }
153 
155 {
156  assert(visited.getCondition());
157  m_sql += "ON (";
158  visited.getCondition()->accept(*this);
159  m_sql += ")";
160 }
161 
163 {
164  m_sql += "USING (";
165 
166  size_t ncols = visited.getNumFields();
167 
168  for(size_t i = 0; i < ncols; ++i)
169  {
170  if(i != 0)
171  m_sql += ", ";
172 
173  assert(visited[i]);
174  visited[i]->accept(*this);
175  }
176 
177  m_sql += ")";
178 }
179 
180 void te::da::SQLVisitor::visit(const Literal& visited)
181 {
182  if(visited.getValue())
183  m_sql += visited.getValue()->toString();
184 }
185 
187 {
188  if(visited.getValue())
189  m_sql += "bool(" + visited.getValue()->toString() + ")";
190 }
191 
193 {
194  if(visited.getValue())
195  m_sql += visited.getValue()->toString();
196 }
197 
199 {
200  if(visited.getValue())
201  m_sql += visited.getValue()->toString();
202 }
203 
205 {
206  if(visited.getValue())
207  m_sql += visited.getValue()->toString();
208 }
209 
211 {
212 }
213 
215 {
216  if(visited.getValue())
217  m_sql += visited.getValue()->toString();
218 }
219 
221 {
222  if(visited.getValue())
223  m_sql += visited.getValue()->toString();
224 }
225 
227 {
228  if(visited.getValue())
229  m_sql += visited.getValue()->toString();
230 }
231 
233 {
234  if(visited.getValue())
235  m_sql += visited.getValue()->toString();
236 }
237 
239 {
240  if(visited.getValue())
241  {
242  m_sql += "'";
243  m_sql += visited.getValue()->toString();
244  m_sql += "'";
245  }
246 }
247 
249 {
250  m_sql += visited.getName();
251 }
252 
253 void te::da::SQLVisitor::visit(const Query& /*visited*/)
254 {
255 }
256 
257 void te::da::SQLVisitor::visit(const Select& visited)
258 {
259  m_sql += "SELECT ";
260 
261  if(visited.getDistinct())
262  {
263  visitDistinct(*(visited.getDistinct()));
264  m_sql += " ";
265  }
266 
267  if(visited.getFields())
268  {
269  visit(*(visited.getFields()));
270  m_sql += " ";
271  }
272 
273  if(visited.getFrom())
274  {
275  visit(*(visited.getFrom()));
276  m_sql += " ";
277  }
278 
279  if(visited.getWhere())
280  {
281  m_sql += "WHERE ";
282  visited.getWhere()->getExp()->accept(*this);
283  m_sql += " ";
284  }
285 
286  if(visited.getGroupBy())
287  {
288  visit(*(visited.getGroupBy()));
289  m_sql += " ";
290  }
291 
292  if(visited.getHaving())
293  {
294  m_sql += "HAVING ";
295  visited.getHaving()->getExp()->accept(*this);
296  m_sql += " ";
297  }
298 
299  if(visited.getOrderBy())
300  visit(*(visited.getOrderBy()));
301 }
302 
304 {
305  assert(visited.getSelect());
306 
307  m_sql += "(";
308  visited.getSelect()->accept(*this);
309  m_sql += ")";
310 
311  if(visited.getAlias().empty() == false)
312  {
313  m_sql += "AS ";
314  m_sql += visited.getAlias();
315  }
316 }
317 
318 void te::da::SQLVisitor::visit(const In& visited)
319 {
320  assert(visited.getPropertyName());
321  visited.getPropertyName()->accept(*this);
322 
323  m_sql += " IN";
324  m_sql += "(";
325 
326  for(size_t i = 0; i < visited.getNumArgs(); ++i)
327  {
328  if(i != 0)
329  m_sql += ", ";
330 
331  assert(visited[i]);
332  visited[i]->accept(*this);
333  }
334 
335  m_sql += ")";
336 }
337 
339 {
340  if(visited.empty())
341  {
342  m_sql += "DISTINCT";
343  }
344  else
345  {
346  m_sql += "DISTINCT ON(";
347 
348  std::size_t ncols = visited.size();
349 
350  for(std::size_t i = 0; i < ncols; ++i)
351  {
352  if(i != 0)
353  m_sql += ", ";
354 
355  visited[i].accept(*this);
356  }
357 
358  m_sql += ")";
359  }
360 }
361 
363 {
364  std::size_t size = visited.size();
365 
366  for(size_t i = 0; i < size; ++i)
367  {
368  if(i != 0)
369  m_sql += ", ";
370 
371  visited[i].getExpression()->accept(*this);
372 
373  if(visited[i].getAlias())
374  m_sql += *(visited[i].getAlias());
375  }
376 }
377 
379 {
380  std::size_t size = visited.size();
381 
382  m_sql += "FROM ";
383 
384  for(std::size_t i = 0; i < size; ++i)
385  {
386  if(i != 0)
387  m_sql += ", ";
388 
389  visited[i].accept(*this);
390  }
391 }
392 
394 {
395  m_sql += "GROUP BY ";
396 
397  std::size_t ncols = visited.size();
398 
399  for(std::size_t i = 0; i < ncols; ++i)
400  {
401  if(i != 0)
402  m_sql += ", ";
403 
404  visited[i].getExpression()->accept(*this);
405  }
406 }
407 
409 {
410  std::size_t size = visited.size();
411 
412  m_sql += "ORDER BY ";
413 
414  for(std::size_t i = 0; i < size; ++i)
415  {
416  if(i != 0)
417  m_sql += ", ";
418 
419  visited[i].getExpression()->accept(*this);
420 
421  if(visited[i].getSortOrder() == te::da::ASC)
422  m_sql += " ASC";
423  else
424  m_sql += " DESC";
425  }
426 }
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:338
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.
Spatial dump 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:347
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:67
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