SpatialQueryProcessor.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/SpatialQueryProcessor.cpp
22 
23  \brief A basic query processor for spatial restrictions.
24 */
25 
26 // TerraLib
27 #include "../../core/translator/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 
61 
62 std::unique_ptr<te::da::DataSet> te::da::SpatialQueryProcessor::getDataSet(const DataSourcePtr& ds, const Select& q, te::common::TraverseType travType)
63 {
64  // Gets the datasource query capabilities
65  const QueryCapabilities& capabilities = ds->getCapabilities().getQueryCapabilities();
66 
67  // Gets a data source transactor
68  std::unique_ptr<DataSourceTransactor> t = ds->getTransactor();
69 
70  return getDataSet(t.get(), capabilities, q, travType, false);
71 }
72 
74  const Select& q, te::common::TraverseType travType, bool connected)
75 {
76  assert(t);
77 
78  // Try find the spatial restrictions
80  q.accept(srv);
81 
82  if(!srv.hasSpatialRestrictions())
83  return t->query(q, travType, connected);
84 
85  // Gets the spatial restrictions
86  const std::vector<SpatialRestriction*>& restrictions = srv.getSpatialRestrictions();
87 
88  if(supportsSpatialTopologicOperatos(capabilities, restrictions))
89  return t->query(q, travType, connected);
90 
91  // Generates the oids
92  std::unique_ptr<ObjectIdSet> oids = getOIDSet(t, q);
93  assert(oids.get());
94 
95  if(oids->size() == 0)
96  throw(Exception(TE_TR("The query result is empty.")));
97 
98  // Gets the dataset name
99  std::string datasetName = getDataSetName(q);
100  assert(!datasetName.empty());
101 
102  return t->getDataSet(datasetName, oids.get(), travType, connected);
103 }
104 
105 std::unique_ptr<te::da::ObjectIdSet> te::da::SpatialQueryProcessor::getOIDSet(const DataSourcePtr& ds, const Select& q)
106 {
107  // Gets the datasource query capabilities
108  const QueryCapabilities& capabilities = ds->getCapabilities().getQueryCapabilities();
109 
110  // Gets a data source transactor
111  std::unique_ptr<DataSourceTransactor> t = ds->getTransactor();
112 
113  return getOIDSet(t.get(), capabilities, q);
114 }
115 
117 {
118  assert(t);
119 
120  // Gets the dataset name
121  std::string datasetName = getDataSetName(q);
122  assert(!datasetName.empty());
123 
124  // Gets the dataset type
125  std::unique_ptr<DataSetType> type = t->getDataSetType(datasetName);
126  assert(type.get());
127 
128  // Try find the spatial restrictions
130  q.accept(srv);
131 
132  if(!srv.hasSpatialRestrictions() && supportsSpatialTopologicOperatos(capabilities, srv.getSpatialRestrictions()))
133  {
134  // Gets the dataset
135  std::unique_ptr<DataSet> dataset = t->query(q, te::common::FORWARDONLY);
136  assert(dataset.get());
137 
138  // Generates the oids
139  std::unique_ptr<ObjectIdSet> oids(GenerateOIDSet(dataset.get(), type.get()));
140 
141  return oids;
142  }
143 
144  // Gets the query from
145  const From* from = q.getFrom();
146  assert(from);
147  assert(from->size() == 1);
148  assert(!from->is_null(0));
149 
150  // Gets the query fields
151  const Fields* fields = q.getFields();
152  assert(fields);
153 
154  // The base select
155  Select baseSelect;
156  baseSelect.setFields(fields->clone().release());
157  baseSelect.setFrom(from->clone().release());
158 
159  // Attribute Restrictions
160  te::da::Expression* attrRestrictions = getAttrRestrictions(q);
161 
162  // Gets the spatial restriction
163  const std::vector<SpatialRestriction*>& restrictions = srv.getSpatialRestrictions();
164 
165  // The result
166  ObjectIdSet* oids = 0;
167  GetEmptyOIDSet(type.get(), oids);
168  assert(oids);
169 
170  std::vector<te::gm::Geometry*> geomRestrictions;
171  for(std::size_t i = 0; i < restrictions.size(); ++i)
172  geomRestrictions.push_back(restrictions[i]->m_geometry);
173 
174  for(std::size_t i = 0; i < restrictions.size(); ++i)
175  oids->Union(getOIDSet(t, baseSelect, attrRestrictions, restrictions[i], type.get(), geomRestrictions));
176 
177  return std::unique_ptr<te::da::ObjectIdSet>(oids);
178 }
179 
180 std::unique_ptr<te::da::ObjectIdSet> te::da::SpatialQueryProcessor::getOIDSet(DataSourceTransactor* t, const Select& q)
181 {
182  assert(t);
183 
184  // Gets the dataset name
185  std::string datasetName = getDataSetName(q);
186  assert(!datasetName.empty());
187 
188  // Gets the dataset type
189  std::unique_ptr<DataSetType> type = t->getDataSetType(datasetName);
190  assert(type.get());
191 
192  // Finds the spatial restrictions
194  q.accept(srv);
195 
196  assert(srv.hasSpatialRestrictions());
197 
198  // Gets the query from
199  const From* from = q.getFrom();
200  assert(from);
201  assert(from->size() == 1);
202  assert(!from->is_null(0));
203 
204  // Gets the query fields
205  const Fields* fields = q.getFields();
206  assert(fields);
207 
208  // The base select
209  Select baseSelect;
210  baseSelect.setFields(fields->clone().release());
211  baseSelect.setFrom(from->clone().release());
212 
213  // Attribute Restrictions
214  te::da::Expression* attrRestrictions = getAttrRestrictions(q);
215 
216  // Gets the spatial restriction
217  const std::vector<SpatialRestriction*>& restrictions = srv.getSpatialRestrictions();
218 
219  // The result
220  ObjectIdSet* oids = 0;
221  GetEmptyOIDSet(type.get(), oids);
222  assert(oids);
223 
224  std::vector<te::gm::Geometry*> geomRestrictions;
225  for(std::size_t i = 0; i < restrictions.size(); ++i)
226  geomRestrictions.push_back(restrictions[i]->m_geometry);
227 
228  for(std::size_t i = 0; i < restrictions.size(); ++i)
229  oids->Union(getOIDSet(t, baseSelect, attrRestrictions, restrictions[i], type.get(), geomRestrictions));
230 
231  return std::unique_ptr<te::da::ObjectIdSet>(oids);
232 }
233 
235  SpatialRestriction* restriction, const DataSetType* type,
236  const std::vector<te::gm::Geometry*>& geomRestrictions)
237 {
238  assert(t);
239  assert(restriction);
240  assert(type);
241 
242  // Gets the geometry restriction
243  te::gm::Geometry* geomRestriction = restriction->m_geometry;
244  assert(geomRestriction);
245 
246  // Gets the geometry mbr
247  const te::gm::Envelope* genv = geomRestriction->getMBR();
248  assert(genv);
249 
250  // Creates the ST_Intersects
251  LiteralEnvelope* lenv = new LiteralEnvelope(new te::gm::Envelope(*genv), geomRestriction->getSRID());
252  PropertyName* pname = new PropertyName(restriction->m_pname);
253  ST_EnvelopeIntersects* eIntersects = new ST_EnvelopeIntersects(pname, lenv);
254 
255  // Adds the restriction to the base select
256  if(attrRestrictions == 0)
257  baseSelect.setWhere(new Where(eIntersects)); // only extent restriction
258  else
259  baseSelect.setWhere(new Where(new And(attrRestrictions, eIntersects))); // attribute restrictions AND extent restriction
260 
261  // Retrieves the dataset using the envelope restriction (the candidates)
262  std::unique_ptr<DataSet> dataset(t->query(baseSelect, te::common::FORWARDONLY));
263  assert(dataset.get());
264 
265  // The result
266  ObjectIdSet* oids = 0;
267  GetEmptyOIDSet(type, oids);
268  assert(oids);
269 
270  // The property names that compose the oid set
271  const std::vector<std::string>& pnames = oids->getPropertyNames();
272 
273  while(dataset->moveNext())
274  {
275  std::unique_ptr<te::gm::Geometry> currentGeom;
276  try
277  {
278  currentGeom = std::move(dataset->getGeometry(restriction->m_pname));
279  if(currentGeom.get() == 0)
280  continue;
281  }
282  catch(std::exception& /*e*/)
283  {
284  continue;
285  }
286 
287  assert(currentGeom.get());
288 
289  bool equalsToRestriction = false;
290  for(std::size_t i = 0; i < geomRestrictions.size(); ++i)
291  {
292  if(currentGeom->equals(geomRestrictions[i]))
293  {
294  equalsToRestriction = true;
295  break;
296  }
297  }
298 
299  if(equalsToRestriction)
300  continue;
301 
302  if(!te::gm::SatisfySpatialRelation(currentGeom.get(), geomRestriction, restriction->m_type))
303  continue;
304 
305  // Satisfy! Generates the oid to this current dataset element
306  oids->add(GenerateOID(dataset.get(), pnames));
307  }
308 
309  return oids;
310 }
311 
312 te::gm::Envelope* te::da::SpatialQueryProcessor::computeEnvelope(const std::vector<SpatialRestriction*>& restrictions) const
313 {
314  te::gm::Envelope* result = new te::gm::Envelope;
315 
316  for(std::size_t i = 0; i < restrictions.size(); ++i)
317  {
318  SpatialRestriction* sr = restrictions[i];
319 
320  te::gm::Geometry* geom = sr->m_geometry;
321  assert(geom);
322 
323  result->Union(*geom->getMBR());
324  }
325 
326  return result;
327 }
328 
330  const std::vector<SpatialRestriction*>& restrictions) const
331 {
332  const std::set<std::string>& ops = capabilities.getSpatialTopologicOperators();
333 
334  for(std::size_t i = 0; i < restrictions.size(); ++i)
335  {
336  SpatialRestriction* sr = restrictions[i];
337 
338  const std::string& fname = sr->m_function->getName();
339 
340  if(ops.find(fname) == ops.end())
341  return false;
342  }
343 
344  return true;
345 }
346 
348 {
349  // TODO: verify and throw the exceptions!
350 
351  // Gets the query from
352  const From* from = q.getFrom();
353  assert(from);
354  assert(from->size() == 1);
355  assert(!from->is_null(0));
356 
357  // Gets the first from item to extract the dataset name
358  const DataSetName* fromItem = dynamic_cast<const DataSetName*>(&from->at(0));
359 
360  return fromItem->getName();
361 }
362 
364 {
365  // Try find the attribute restrictions
367  q.accept(arv);
368 
369  if(!arv.hasAttributeRestrictions())
370  return 0;
371 
372  const std::vector<AttributeRestriction*> attrRestrictions = arv.getAttributeRestrictions();
373  if(attrRestrictions.size() == 1)
374  return attrRestrictions[0]->m_function->clone();
375 
376  assert(attrRestrictions.size() >= 2);
377 
378  // For while, using the AND operator
379  And* andOp = new And(attrRestrictions[0]->m_function->clone(), attrRestrictions[1]->m_function->clone());
380  Expression* result = andOp;
381  for(std::size_t i = 2; i < attrRestrictions.size(); ++i)
382  {
383  And* nextAndOp = new And(result, attrRestrictions[i]->m_function->clone());
384  result = nextAndOp;
385  }
386 
387  return result;
388 }
A visitor for retrieves spatial restrictions from a Query hierarchy.
virtual ~SpatialQueryProcessor()
Virtual destructor.
te::gm::SpatialRelation m_type
The spatial restriction type.
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.
Expression * getAttrRestrictions(const Select &q) const
TEDATAACCESSEXPORT ObjectId * GenerateOID(DataSet *dataset, const std::vector< std::string > &names)
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
A class that models the name of any property of an object.
A class that models the name of any property of an object.
Base exception class for plugin module.
SpatialQueryProcessor()
Constructor.
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.
A class that models the name of a dataset used in a From clause.
virtual std::unique_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...
virtual ReturnType accept(VisitorType &guest) const =0
It call the visit method from the guest object.
static te::dt::Date ds(2010, 01, 01)
#define TE_TR(message)
It marks a string in order to get translated.
Definition: Translator.h:242
const QueryCapabilities & getQueryCapabilities() const
Boolean logic operator: AND.
void Union(const Envelope &rhs)
It updates the envelop with coordinates of another envelope.
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.
This operator EnvelopeIntersects considers the intersection among approximations or envelopes of geom...
A class that models a literal for Envelope values.
TraverseType
A dataset can be traversed in two ways:
void setWhere(Where *w)
It sets the filter codition.
Definition: Select.cpp:799
int getSRID() const _NOEXCEPT_OP(true)
It returns the Spatial Reference System ID associated to this geometric object.
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.
const Envelope * getMBR() const _NOEXCEPT_OP(true)
It returns the minimum bounding rectangle for the geometry in an internal representation.
An operator that considers the intersection among approximations or envelopes of geometries.
An Envelope defines a 2D rectangular region.
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:55
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::unique_ptr< ObjectIdSet > getOIDSet(const DataSourcePtr &ds, const Select &q)
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
virtual std::unique_ptr< DataSet > getDataSet(const DataSourcePtr &ds, const Select &q, te::common::TraverseType travType=te::common::FORWARDONLY)
const Fields * getFields() const
It returns the list of output expressions used to form the result set.
Definition: Select.cpp:784
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)
const std::string & getName() const
It returns the function name.
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.
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::unique_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.
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.
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
It models the FROM clause for a query.
std::string getDataSetName(const Select &q) const
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.
virtual std::unique_ptr< te::da::DataSetType > getDataSetType(const std::string &name)=0
It gets information about the given dataset.
void setFields(Fields *f)
It sets the list of output expressions used to form the result set.
Definition: Select.cpp:779
void setFrom(From *f)
It sets the list of source information.
Definition: Select.cpp:789