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