All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
SpatialQueryProcessor.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/SpatialQueryProcessor.cpp
22 
23  \brief A basic query processor for spatial restrictions.
24 */
25 
26 // TerraLib
27 #include "../../common/Translator.h"
28 #include "../../geometry/Utils.h"
29 #include "../../srs/Config.h"
30 #include "../dataset/DataSet.h"
31 #include "../dataset/FilteredDataSet.h"
32 #include "../datasource/DataSourceTransactor.h"
33 #include "../datasource/DataSourceCapabilities.h"
34 #include "../utils/Utils.h"
35 #include "../Exception.h"
36 #include "And.h"
38 #include "DataSetName.h"
39 #include "Select.h"
40 #include "Field.h"
41 #include "Fields.h"
42 #include "From.h"
43 #include "FromItem.h"
44 #include "LiteralEnvelope.h"
45 #include "PropertyName.h"
46 #include "Or.h"
47 #include "QueryCapabilities.h"
49 #include "ST_EnvelopeIntersects.h"
50 #include "SpatialQueryProcessor.h"
51 #include "Where.h"
52 
53 // STL
54 #include <cassert>
55 #include <set>
56 #include <vector>
57 
59 {
60 }
61 
63 {
64 }
65 
66 std::auto_ptr<te::da::DataSet> te::da::SpatialQueryProcessor::getDataSet(const DataSourcePtr& ds, const Select& q, te::common::TraverseType travType)
67 {
68  // Gets the datasource query capabilities
69  const QueryCapabilities& capabilities = ds->getCapabilities().getQueryCapabilities();
70 
71  // Gets a data source transactor
72  std::auto_ptr<DataSourceTransactor> t = ds->getTransactor();
73 
74  return getDataSet(t.get(), capabilities, q, travType, false);
75 }
76 
78  const Select& q, te::common::TraverseType travType, bool connected)
79 {
80  assert(t);
81 
82  // Try find the spatial restrictions
84  q.accept(srv);
85 
86  if(!srv.hasSpatialRestrictions())
87  return t->query(q, travType, connected);
88 
89  // Gets the spatial restrictions
90  const std::vector<SpatialRestriction*>& restrictions = srv.getSpatialRestrictions();
91 
92  if(supportsSpatialTopologicOperatos(capabilities, restrictions))
93  return t->query(q, travType, connected);
94 
95  // Generates the oids
96  std::auto_ptr<ObjectIdSet> oids = getOIDSet(t, q);
97  assert(oids.get());
98 
99  if(oids->size() == 0)
100  throw(Exception(TE_TR("The query result is empty.")));
101 
102  // Gets the dataset name
103  std::string datasetName = getDataSetName(q);
104  assert(!datasetName.empty());
105 
106  return t->getDataSet(datasetName, oids.get(), travType, connected);
107 }
108 
109 std::auto_ptr<te::da::ObjectIdSet> te::da::SpatialQueryProcessor::getOIDSet(const DataSourcePtr& ds, const Select& q)
110 {
111  // Gets the datasource query capabilities
112  const QueryCapabilities& capabilities = ds->getCapabilities().getQueryCapabilities();
113 
114  // Gets a data source transactor
115  std::auto_ptr<DataSourceTransactor> t = ds->getTransactor();
116 
117  return getOIDSet(t.get(), capabilities, q);
118 }
119 
121 {
122  assert(t);
123 
124  // Gets the dataset name
125  std::string datasetName = getDataSetName(q);
126  assert(!datasetName.empty());
127 
128  // Gets the dataset type
129  std::auto_ptr<DataSetType> type = t->getDataSetType(datasetName);
130  assert(type.get());
131 
132  // Try find the spatial restrictions
134  q.accept(srv);
135 
136  if(!srv.hasSpatialRestrictions() && supportsSpatialTopologicOperatos(capabilities, srv.getSpatialRestrictions()))
137  {
138  // Gets the dataset
139  std::auto_ptr<DataSet> dataset = t->query(q, te::common::FORWARDONLY);
140  assert(dataset.get());
141 
142  // Generates the oids
143  std::auto_ptr<ObjectIdSet> oids(GenerateOIDSet(dataset.get(), type.get()));
144 
145  return oids;
146  }
147 
148  // Gets the query from
149  const From* from = q.getFrom();
150  assert(from);
151  assert(from->size() == 1);
152  assert(!from->is_null(0));
153 
154  // Gets the query fields
155  const Fields* fields = q.getFields();
156  assert(fields);
157 
158  // The base select
159  Select baseSelect;
160  baseSelect.setFields(fields->clone().release());
161  baseSelect.setFrom(from->clone().release());
162 
163  // Attribute Restrictions
164  te::da::Expression* attrRestrictions = getAttrRestrictions(q);
165 
166  // Gets the spatial restriction
167  const std::vector<SpatialRestriction*>& restrictions = srv.getSpatialRestrictions();
168 
169  // The result
170  ObjectIdSet* oids = 0;
171  GetEmptyOIDSet(type.get(), oids);
172  assert(oids);
173 
174  std::vector<te::gm::Geometry*> geomRestrictions;
175  for(std::size_t i = 0; i < restrictions.size(); ++i)
176  geomRestrictions.push_back(restrictions[i]->m_geometry);
177 
178  for(std::size_t i = 0; i < restrictions.size(); ++i)
179  oids->Union(getOIDSet(t, baseSelect, attrRestrictions, restrictions[i], type.get(), geomRestrictions));
180 
181  return std::auto_ptr<te::da::ObjectIdSet>(oids);
182 }
183 
184 std::auto_ptr<te::da::ObjectIdSet> te::da::SpatialQueryProcessor::getOIDSet(DataSourceTransactor* t, const Select& q)
185 {
186  assert(t);
187 
188  // Gets the dataset name
189  std::string datasetName = getDataSetName(q);
190  assert(!datasetName.empty());
191 
192  // Gets the dataset type
193  std::auto_ptr<DataSetType> type = t->getDataSetType(datasetName);
194  assert(type.get());
195 
196  // Finds the spatial restrictions
198  q.accept(srv);
199 
200  assert(srv.hasSpatialRestrictions());
201 
202  // Gets the query from
203  const From* from = q.getFrom();
204  assert(from);
205  assert(from->size() == 1);
206  assert(!from->is_null(0));
207 
208  // Gets the query fields
209  const Fields* fields = q.getFields();
210  assert(fields);
211 
212  // The base select
213  Select baseSelect;
214  baseSelect.setFields(fields->clone().release());
215  baseSelect.setFrom(from->clone().release());
216 
217  // Attribute Restrictions
218  te::da::Expression* attrRestrictions = getAttrRestrictions(q);
219 
220  // Gets the spatial restriction
221  const std::vector<SpatialRestriction*>& restrictions = srv.getSpatialRestrictions();
222 
223  // The result
224  ObjectIdSet* oids = 0;
225  GetEmptyOIDSet(type.get(), oids);
226  assert(oids);
227 
228  std::vector<te::gm::Geometry*> geomRestrictions;
229  for(std::size_t i = 0; i < restrictions.size(); ++i)
230  geomRestrictions.push_back(restrictions[i]->m_geometry);
231 
232  for(std::size_t i = 0; i < restrictions.size(); ++i)
233  oids->Union(getOIDSet(t, baseSelect, attrRestrictions, restrictions[i], type.get(), geomRestrictions));
234 
235  return std::auto_ptr<te::da::ObjectIdSet>(oids);
236 }
237 
239  SpatialRestriction* restriction, const DataSetType* type,
240  const std::vector<te::gm::Geometry*>& geomRestrictions)
241 {
242  assert(t);
243  assert(restriction);
244  assert(type);
245 
246  // Gets the geometry restriction
247  te::gm::Geometry* geomRestriction = restriction->m_geometry;
248  assert(geomRestriction);
249 
250  // Gets the geometry mbr
251  const te::gm::Envelope* genv = geomRestriction->getMBR();
252  assert(genv);
253 
254  // Creates the ST_Intersects
255  LiteralEnvelope* lenv = new LiteralEnvelope(new te::gm::Envelope(*genv), geomRestriction->getSRID());
256  PropertyName* pname = new PropertyName(restriction->m_pname);
257  ST_EnvelopeIntersects* eIntersects = new ST_EnvelopeIntersects(pname, lenv);
258 
259  // Adds the restriction to the base select
260  if(attrRestrictions == 0)
261  baseSelect.setWhere(new Where(eIntersects)); // only extent restriction
262  else
263  baseSelect.setWhere(new Where(new And(attrRestrictions, eIntersects))); // attribute restrictions AND extent restriction
264 
265  // Retrieves the dataset using the envelope restriction (the candidates)
266  std::auto_ptr<DataSet> dataset(t->query(baseSelect, te::common::FORWARDONLY));
267  assert(dataset.get());
268 
269  // The result
270  ObjectIdSet* oids = 0;
271  GetEmptyOIDSet(type, oids);
272  assert(oids);
273 
274  // The property names that compose the oid set
275  const std::vector<std::string>& pnames = oids->getPropertyNames();
276 
277  std::size_t size = dataset->size();
278 
279  while(dataset->moveNext())
280  {
281  std::auto_ptr<te::gm::Geometry> currentGeom(0);
282  try
283  {
284  currentGeom = dataset->getGeometry(restriction->m_pname);
285  if(currentGeom.get() == 0)
286  continue;
287  }
288  catch(std::exception& /*e*/)
289  {
290  continue;
291  }
292 
293  assert(currentGeom.get());
294 
295  bool equalsToRestriction = false;
296  for(std::size_t i = 0; i < geomRestrictions.size(); ++i)
297  {
298  if(currentGeom->equals(geomRestrictions[i]))
299  {
300  equalsToRestriction = true;
301  break;
302  }
303  }
304 
305  if(equalsToRestriction)
306  continue;
307 
308  if(!te::gm::SatisfySpatialRelation(currentGeom.get(), geomRestriction, restriction->m_type))
309  continue;
310 
311  // Satisfy! Generates the oid to this current dataset element
312  oids->add(GenerateOID(dataset.get(), pnames));
313  }
314 
315  return oids;
316 }
317 
318 te::gm::Envelope* te::da::SpatialQueryProcessor::computeEnvelope(const std::vector<SpatialRestriction*>& restrictions) const
319 {
320  te::gm::Envelope* result = new te::gm::Envelope;
321 
322  for(std::size_t i = 0; i < restrictions.size(); ++i)
323  {
324  SpatialRestriction* sr = restrictions[i];
325 
326  te::gm::Geometry* geom = sr->m_geometry;
327  assert(geom);
328 
329  result->Union(*geom->getMBR());
330  }
331 
332  return result;
333 }
334 
336  const std::vector<SpatialRestriction*>& restrictions) const
337 {
338  const std::set<std::string>& ops = capabilities.getSpatialTopologicOperators();
339 
340  for(std::size_t i = 0; i < restrictions.size(); ++i)
341  {
342  SpatialRestriction* sr = restrictions[i];
343 
344  const std::string& fname = sr->m_function->getName();
345 
346  if(ops.find(fname) == ops.end())
347  return false;
348  }
349 
350  return true;
351 }
352 
354 {
355  // TODO: verify and throw the exceptions!
356 
357  // Gets the query from
358  const From* from = q.getFrom();
359  assert(from);
360  assert(from->size() == 1);
361  assert(!from->is_null(0));
362 
363  // Gets the first from item to extract the dataset name
364  const DataSetName* fromItem = dynamic_cast<const DataSetName*>(&from->at(0));
365 
366  return fromItem->getName();
367 }
368 
370 {
371  // Try find the attribute restrictions
373  q.accept(arv);
374 
375  if(!arv.hasAttributeRestrictions())
376  return 0;
377 
378  const std::vector<AttributeRestriction*> attrRestrictions = arv.getAttributeRestrictions();
379  if(attrRestrictions.size() == 1)
380  return attrRestrictions[0]->m_function->clone();
381 
382  assert(attrRestrictions.size() >= 2);
383 
384  // For while, using the AND operator
385  And* andOp = new And(attrRestrictions[0]->m_function->clone(), attrRestrictions[1]->m_function->clone());
386  Expression* result = andOp;
387  for(std::size_t i = 2; i < attrRestrictions.size(); ++i)
388  {
389  And* nextAndOp = new And(result, attrRestrictions[i]->m_function->clone());
390  result = nextAndOp;
391  }
392 
393  return result;
394 }
A visitor for retrieves spatial restrictions from a Query hierarchy.
virtual ~SpatialQueryProcessor()
Virtual destructor.
te::gm::SpatialRelation m_type
The spatial restriction type.
int getSRID() const
It returns the Spatial Reference System ID associated to this geometric object.
Definition: Geometry.h:189
An abstract class that models a source of data in a query.
A visitor that retrieves spatial restrictions from a Query hierarchy.
TEDATAACCESSEXPORT void GetEmptyOIDSet(const DataSetType *type, ObjectIdSet *&set)
Returns an empty ObjectIdSet, with the definitions of fields that compose it.
Definition: Utils.cpp:283
virtual std::auto_ptr< ObjectIdSet > getOIDSet(const DataSourcePtr &ds, const Select &q)
Expression * getAttrRestrictions(const Select &q) const
TEDATAACCESSEXPORT ObjectId * GenerateOID(DataSet *dataset, const std::vector< std::string > &names)
Definition: Utils.cpp:397
const std::vector< te::da::SpatialRestriction * > & getSpatialRestrictions() const
A class that models the name of a dataset used in a From clause.
Definition: DataSetName.h:43
boost::shared_ptr< DataSource > DataSourcePtr
Definition: DataSource.h:1435
A class that models the name of any property of an object.
A class that models the name of any property of an object.
Definition: PropertyName.h:50
A class that models the description of a dataset.
Definition: DataSetType.h:72
bool supportsSpatialTopologicOperatos(const QueryCapabilities &capabilities, const std::vector< SpatialRestriction * > &restrictions) const
TEGEOMEXPORT bool SatisfySpatialRelation(const Geometry *g1, const Geometry *g2, SpatialRelation relation)
It returns if two geometries satisfy a given spatial relation.
Definition: Utils.cpp:53
A class that models the name of a dataset used in a From clause.
#define TE_TR(message)
It marks a string in order to get translated.
Definition: Translator.h:345
const QueryCapabilities & getQueryCapabilities() const
Boolean logic operator: AND.
Definition: And.h:46
void Union(const Envelope &rhs)
It updates the envelop with coordinates of another envelope.
Definition: Envelope.h:555
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
This operator EnvelopeIntersects considers the intersection among approximations or envelopes of geom...
virtual std::auto_ptr< te::da::DataSetType > getDataSetType(const std::string &name)=0
It gets information about the given dataset.
A class that models a literal for Envelope values.
TraverseType
A dataset can be traversed in two ways:
Definition: Enums.h:53
void setWhere(Where *w)
It sets the filter codition.
Definition: Select.cpp:947
const Function * m_function
The function that represents the spatial restriction.
A class that informs the query support of a given data source.
A basic query processor for spatial restrictions.
An operator that considers the intersection among approximations or envelopes of geometries.
An Envelope defines a 2D rectangular region.
Definition: Envelope.h:51
const std::vector< te::da::AttributeRestriction * > & getAttributeRestrictions() const
This class represents a set of unique ids created in the same context. i.e. from the same data set...
Definition: ObjectIdSet.h:53
te::da::DataSourceCapabilities capabilities
A visitor that retrieves attribute restrictions from a Query hierarchy.
A struct that represents a spatial restriction.
Boolean logic operator: OR - syntatic-suggar.
virtual std::auto_ptr< DataSet > query(const Select &q, te::common::TraverseType travType=te::common::FORWARDONLY, bool connected=false, const te::common::AccessPolicy accessPolicy=te::common::RAccess)=0
It executes a query that may return some data using a generic query. A dataset can be connected or di...
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 can be used to model a filter expression that can be applied to a query.
Definition: Where.h:47
const Fields * getFields() const
It returns the list of output expressions used to form the result set.
Definition: Select.cpp:932
A Select models a query to be used when retrieving data from a data source.
A DataSourceTransactor can be viewed as a connection to the data source for reading/writing things in...
TEDATAACCESSEXPORT ObjectIdSet * GenerateOIDSet(DataSet *dataset, const DataSetType *type)
Definition: Utils.cpp:363
const std::string & getName() const
It returns the function name.
Definition: Function.h:79
std::string m_pname
The property name of the spatial restriction.
Geometry is the root class of the geometries hierarchy, it follows OGC and ISO standards.
Definition: Geometry.h:73
A Select models a query to be used when retrieving data from a DataSource.
Definition: Select.h:65
te::gm::Envelope * computeEnvelope(const std::vector< SpatialRestriction * > &restrictions) const
Boolean logic operator: AND - syntatic-suggar.
const std::set< std::string > & getSpatialTopologicOperators() const
A visitor that retrieves attribute restrictions from a Query hierarchy.
A class that can be used to model a filter expression that can be applied to a query.
boost::ptr_vector< FromItem > From
It models the FROM clause for a query.
Definition: From.h:37
te::gm::Geometry * m_geometry
The geometry of the spatial restriction.
virtual std::auto_ptr< DataSet > getDataSet(const DataSourcePtr &ds, const Select &q, te::common::TraverseType travType=te::common::FORWARDONLY)
virtual ReturnType accept(VisitorType &guest) const =0
It call the visit method from the guest object.
void Union(ObjectIdSet *rhs)
It performs the union operation between this ObjectIdSet and the given ObjectIdSet.
A class that models a literal for Envelope values.
const std::string & getName() const
It returns the dataset name.
Definition: DataSetName.cpp:57
It models the FROM clause for a query.
std::string getDataSetName(const Select &q) const
virtual std::auto_ptr< DataSet > getDataSet(const std::string &name, te::common::TraverseType travType=te::common::FORWARDONLY, bool connected=false, const te::common::AccessPolicy accessPolicy=te::common::RAccess)=0
It gets the dataset identified by the given name. A dataset can be connected or disconnected. A connected dataset, after its creation through the data source transactor, continues to depend on the connection given by its associated data source. Differently, a disconnected dataset, after its creation, no more depends of the connection given by the data source, and it continues to live after the connection has been released to the data source.
The Fields class can be used to model a set of expressions that form the output items of a SELECT...
A class that informs the query support of a given data source.
const Envelope * getMBR() const
It returns the minimum bounding rectangle for the geometry in an internal representation.
Definition: Geometry.cpp:103
void setFields(Fields *f)
It sets the list of output expressions used to form the result set.
Definition: Select.cpp:927
void setFrom(From *f)
It sets the list of source information.
Definition: Select.cpp:937