src/terralib/dataaccess/query/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 "../../core/translator/Translator.h"
29 #include "../../datatype/AbstractData.h"
30 #include "../../datatype/SimpleData.h"
31 #include "../../datatype/Enums.h"
32 #include "../Exception.h"
33 #include "Cast.h"
34 #include "DataSetName.h"
35 #include "Distinct.h"
36 #include "Expression.h"
37 #include "Field.h"
38 #include "Function.h"
39 #include "GroupBy.h"
40 #include "GroupByItem.h"
41 #include "Having.h"
42 #include "In.h"
43 #include "Insert.h"
44 #include "Join.h"
45 #include "JoinCondition.h"
46 #include "JoinConditionOn.h"
47 #include "JoinConditionUsing.h"
48 #include "Literal.h"
49 #include "LiteralBool.h"
50 #include "LiteralByteArray.h"
51 #include "LiteralDateTime.h"
52 #include "LiteralDouble.h"
53 #include "LiteralGeom.h"
54 #include "LiteralInt16.h"
55 #include "LiteralInt32.h"
56 #include "LiteralInt64.h"
57 #include "LiteralString.h"
58 #include "OrderByItem.h"
59 #include "PropertyName.h"
60 #include "Select.h"
61 #include "SelectExpression.h"
62 #include "SQLDialect.h"
63 #include "SQLFunctionEncoder.h"
64 #include "SQLVisitor.h"
65 #include "ST_Dump.h"
66 #include "SubSelect.h"
67 #include "Where.h"
68 
69 // STL
70 #include <cassert>
71 
72 // Boost
73 #include <boost/lexical_cast.hpp>
74 
75 void te::da::SQLVisitor::visit(const Expression& /*visited*/)
76 {
77 }
78 
80 {
81  m_sql += visited.getName();
82 
83  if(visited.getAlias().empty() == false)
84  {
85  m_sql += " AS ";
86  m_sql += visited.getAlias();
87  }
88 }
89 
90 void te::da::SQLVisitor::visit(const FromItem& /*visited*/)
91 {
92 }
93 
94 void te::da::SQLVisitor::visit(const Function& visited)
95 {
96  const std::string& fname = visited.getName();
97 
98  const SQLFunctionEncoder* encoder = m_dialect.find(fname);
99 
100  if(encoder == nullptr)
101  throw Exception(TE_TR("The informed function is not supported by this driver!"));
102 
103  encoder->toSQL(visited, m_sql, *this);
104 }
105 
106 void te::da::SQLVisitor::visit(const Insert& visited)
107 {
108  m_sql += "INSERT INTO ";
109 
110  if (visited.getDataSetName())
111  {
112  visit(*(visited.getDataSetName()));
113  m_sql += " ";
114  }
115 
116  if (visited.getFields())
117  {
118  m_sql += "( ";
119  visit(*(visited.getFields()));
120  m_sql += " ) ";
121  }
122 
123  if (visited.getSelect())
124  {
125  visit(*(visited.getSelect()));
126  m_sql += " ";
127  }
128 }
129 
130 void te::da::SQLVisitor::visit(const Join& visited)
131 {
132  assert(visited.getFirst() && visited.getSecond());
133 
134  m_sql += "(";
135  visited.getFirst()->accept(*this);
136 
137  if(visited.isNatural())
138  m_sql += " NATURAL ";
139 
140  switch(visited.getType())
141  {
142  case JOIN :
143  m_sql += " JOIN ";
144  break;
145 
146  case INNER_JOIN :
147  m_sql += " INNER JOIN ";
148  break;
149 
150  case LEFT_JOIN :
151  m_sql += " LEFT JOIN ";
152  break;
153 
154  case RIGHT_JOIN :
155  m_sql += " RIGHT JOIN ";
156  break;
157 
158  case FULL_OUTER_JOIN :
159  m_sql += " FULL OUTER JOIN ";
160  break;
161 
162  case CROSS_JOIN :
163  m_sql += " CROSS JOIN ";
164  break;
165 
166  case NATURAL_JOIN :
167  m_sql += " NATURAL JOIN ";
168  break;
169  }
170 
171  visited.getSecond()->accept(*this);
172 
173  if(visited.getCondition())
174  {
175  m_sql += " ";
176  visited.getCondition()->accept(*this);
177  }
178 
179  m_sql += ")";
180 }
181 
182 void te::da::SQLVisitor::visit(const JoinCondition& /*visited*/)
183 {
184 }
185 
187 {
188  assert(visited.getCondition());
189  m_sql += "ON (";
190  visited.getCondition()->accept(*this);
191  m_sql += ")";
192 }
193 
195 {
196  m_sql += "USING (";
197 
198  size_t ncols = visited.getNumFields();
199 
200  for(size_t i = 0; i < ncols; ++i)
201  {
202  if(i != 0)
203  m_sql += ", ";
204 
205  assert(visited[i]);
206  visited[i]->accept(*this);
207  }
208 
209  m_sql += ")";
210 }
211 
212 void te::da::SQLVisitor::visit(const Literal& visited)
213 {
214  if(visited.getValue())
215  m_sql += visited.getValue()->toString();
216 }
217 
219 {
220  if(visited.getValue())
221  m_sql += "bool(" + visited.getValue()->toString() + ")";
222 }
223 
225 {
226  if(visited.getValue())
227  m_sql += visited.getValue()->toString();
228 }
229 
231 {
232  if(visited.getValue())
233  m_sql += visited.getValue()->toString();
234 }
235 
237 {
238  if(visited.getValue())
239  m_sql += visited.getValue()->toString();
240 }
241 
243 {
244 }
245 
247 {
248  if(visited.getValue())
249  m_sql += visited.getValue()->toString();
250 }
251 
253 {
254  if(visited.getValue())
255  m_sql += visited.getValue()->toString();
256 }
257 
259 {
260  if(visited.getValue())
261  m_sql += visited.getValue()->toString();
262 }
263 
265 {
266  if(visited.getValue())
267  m_sql += visited.getValue()->toString();
268 }
269 
271 {
272  if(visited.getValue())
273  {
274  m_sql += "'";
275  m_sql += visited.getValue()->toString();
276  m_sql += "'";
277  }
278 }
279 
281 {
282  m_sql += visited.getName();
283 }
284 
285 void te::da::SQLVisitor::visit(const Query& /*visited*/)
286 {
287 }
288 
289 void te::da::SQLVisitor::visit(const Select& visited)
290 {
291  m_sql += "SELECT ";
292 
293  if(visited.getDistinct())
294  {
295  visitDistinct(*(visited.getDistinct()));
296  m_sql += " ";
297  }
298 
299  if(visited.getFields())
300  {
301  visit(*(visited.getFields()));
302  m_sql += " ";
303  }
304 
305  if(visited.getFrom())
306  {
307  visit(*(visited.getFrom()));
308  m_sql += " ";
309  }
310 
311  if(visited.getWhere())
312  {
313  m_sql += "WHERE ";
314  visited.getWhere()->getExp()->accept(*this);
315  m_sql += " ";
316  }
317 
318  if(visited.getGroupBy())
319  {
320  visit(*(visited.getGroupBy()));
321  m_sql += " ";
322  }
323 
324  if(visited.getHaving())
325  {
326  m_sql += "HAVING ";
327  visited.getHaving()->getExp()->accept(*this);
328  m_sql += " ";
329  }
330 
331  if(visited.getOrderBy())
332  visit(*(visited.getOrderBy()));
333 }
334 
336 {
337  assert(visited.getSelect());
338 
339  m_sql += "(";
340  visited.getSelect()->accept(*this);
341  m_sql += ")";
342 }
343 
345 {
346  assert(visited.getSelect());
347 
348  m_sql += "(";
349  visited.getSelect()->accept(*this);
350  m_sql += ")";
351 
352  if(visited.getAlias().empty() == false)
353  {
354  m_sql += "AS ";
355  m_sql += visited.getAlias();
356  }
357 }
358 
359 void te::da::SQLVisitor::visit(const In& visited)
360 {
361  assert(visited.getPropertyName());
362  visited.getPropertyName()->accept(*this);
363 
364  m_sql += " IN";
365  m_sql += "(";
366 
367  for(size_t i = 0; i < visited.getNumArgs(); ++i)
368  {
369  if(i != 0)
370  m_sql += ", ";
371 
372  assert(visited[i]);
373  visited[i]->accept(*this);
374  }
375 
376  m_sql += ")";
377 }
378 
379 void te::da::SQLVisitor::visit(const Cast& visited)
380 {
381  for (std::size_t i = 0; i < visited.getNumArgs(); ++i)
382  assert(visited[i]);
383 
384  int type = 0;
385 
386  te::da::LiteralInt32* literalInt = dynamic_cast<te::da::LiteralInt32*>(visited[1]);
387  if (literalInt)
388  {
390 
391  if (sdIntType)
392  type = sdIntType->getValue();
393  }
394 
395  std::string s_type;
396 
397  switch (type)
398  {
399  case te::dt::INT32_TYPE:
400  s_type += "INTEGER";
401  break;
402 
403  case te::dt::STRING_TYPE:
404  s_type += "VARCHAR";
405  break;
406 
408  s_type += "DATE";
409  break;
410 
411  case te::dt::DOUBLE_TYPE:
412  s_type += "DOUBLE";
413  break;
414 
415  default:
416  s_type = "";
417  break;
418  }
419 
420  if (!s_type.empty())
421  {
422  m_sql += "CAST( ";
423  visited[0]->accept(*this);
424  m_sql += " AS " + s_type + " )";
425  }
426  else
427  {
428  visited[0]->accept(*this);
429  }
430 }
431 
433 {
434  if(visited.empty())
435  {
436  m_sql += "DISTINCT";
437  }
438  else
439  {
440  m_sql += "DISTINCT ON(";
441 
442  std::size_t ncols = visited.size();
443 
444  for(std::size_t i = 0; i < ncols; ++i)
445  {
446  if(i != 0)
447  m_sql += ", ";
448 
449  visited[i].accept(*this);
450  }
451 
452  m_sql += ")";
453  }
454 }
455 
457 {
458  std::size_t size = visited.size();
459 
460  for(size_t i = 0; i < size; ++i)
461  {
462  if(i != 0)
463  m_sql += ", ";
464 
465  visited[i].getExpression()->accept(*this);
466 
467  if (visited[i].getAlias())
468  {
469  m_sql += " AS ";
470  m_sql += *(visited[i].getAlias());
471  }
472  }
473 }
474 
476 {
477  std::size_t size = visited.size();
478 
479  m_sql += "FROM ";
480 
481  for(std::size_t i = 0; i < size; ++i)
482  {
483  if(i != 0)
484  m_sql += ", ";
485 
486  visited[i].accept(*this);
487  }
488 }
489 
491 {
492  m_sql += "GROUP BY ";
493 
494  std::size_t ncols = visited.size();
495 
496  for(std::size_t i = 0; i < ncols; ++i)
497  {
498  if(i != 0)
499  m_sql += ", ";
500 
501  visited[i].getExpression()->accept(*this);
502  }
503 }
504 
506 {
507  std::size_t size = visited.size();
508 
509  m_sql += "ORDER BY ";
510 
511  for(std::size_t i = 0; i < size; ++i)
512  {
513  if(i != 0)
514  m_sql += ", ";
515 
516  visited[i].getExpression()->accept(*this);
517 
518  if(visited[i].getSortOrder() == te::da::ASC)
519  m_sql += " ASC";
520  else
521  m_sql += " DESC";
522  }
523 }
const Distinct * getDistinct() const
It returns the Distinct modifier.
Definition: Select.cpp:844
const std::string & getName() const
It returns the property name.
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:834
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:66
virtual void visitDistinct(const Distinct &visited)
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:814
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.
Base exception class for plugin module.
A class that represents the IN operator.
const SQLFunctionEncoder * find(const std::string &funcName) const
It searches for an encoder for the given function.
Definition: SQLDialect.cpp:46
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
T getValue() const
It returns the associated value.
Definition: SimpleData.h:139
JoinType getType() const
It returns the join type.
Definition: Join.cpp:106
virtual ReturnType accept(VisitorType &guest) const =0
It call the visit method from the guest object.
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:242
The Insert object can add the return of a select object.
Definition: Insert.h:50
const From * getFrom() const
It returns the list of source information to be used by the query.
Definition: Select.cpp:794
This is an abstract class that models a query expression.
A Join clause combines two FromItems.
A class that models a literal for Date and Time values.
virtual std::string toString() const =0
It returns the data value in a string notation.
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:77
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.
virtual void visit(const Expression &visited)
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
Fields * getFields() const
It returns the associated fields.
Definition: Insert.cpp:93
std::string & m_sql
The buffer string where the query will be outputed.
boost::ptr_vector< Field > Fields
Fields is just a boost::ptr_vector of Field pointers.
Definition: Fields.h:37
A visitor for building an SQL statement from a given Query hierarchy.
A class that models a Literal for a integer value.
A Insert can be used to add information in a table.
DataSetName * getDataSetName() const
It returns the associated DataSetName.
Definition: Insert.cpp:83
This is an abstract class that models a query expression.
Expression * getExp() const
Definition: Where.cpp:58
A class that models a Function expression.
const Fields * getFields() const
It returns the list of output expressions used to form the result set.
Definition: Select.cpp:784
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:58
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.
Cast a expression function.
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
Select * getSelect() const
It returns the associated select expression.
FromItem * getSecond() const
It returns the second item involved in the join.
Definition: Join.cpp:96
Where * getWhere() const
It returns the filter condition.
Definition: Select.cpp:804
A class that models a literal for double values.
A Select can be used as a source of information in another query.
JoinCondition * getCondition() const
It returns the join condition.
Definition: Join.cpp:116
JoinConditionUsing class can be used to model a USING clause in a Join.
const Having * getHaving() const
It returns the list of expressions used to eliminate group row that doesn&#39;t satisfy the condition...
Definition: Select.cpp:824
A class that models a literal for Envelope values.
Cast a expression function.
Definition: Cast.h:46
The Field class can be used to model an expression that takes part of the output items of a SELECT...
const std::string & getName() const
It returns the dataset name.
Definition: DataSetName.cpp:55
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 template for atomic data types (integers, floats, strings and others).
Definition: SimpleData.h:59
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.
Select * getSelect() const
It returns the associated select.
Definition: Insert.cpp:103
virtual void toSQL(const Function &f, std::string &buff, SQLVisitor &v) const =0
It encodes the function to a SQL notation.
te::dt::AbstractData * getValue() const
It returns the value associated to the literal.
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.
A Select can be used as a source of information in another query.
FromItem * getFirst() const
It returns the first from item involved in the join.
Definition: Join.cpp:86
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
const SQLDialect & m_dialect
The function catalog to use when translating the query.