irods  4.2.8
About: iRODS (the integrated Rule Oriented Data System) is a distributed data-management system for creating data grids, digital libraries, persistent archives, and real-time data systems.
  Fossies Dox: irods-4.2.8.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

irods_query.hpp
Go to the documentation of this file.
1 #ifndef IRODS_QUERY_HPP
2 #define IRODS_QUERY_HPP
3 
4 #ifdef RODS_SERVER
5  #include "rsGenQuery.hpp"
6  #include "specificQuery.h"
7  #include "rsSpecificQuery.hpp"
8 #else
9  #include "genQuery.h"
10  #include "specificQuery.h"
11 #endif
12 
13 #include "irods_log.hpp"
14 #include "rcMisc.h"
15 
16 #include <algorithm>
17 #include <string>
18 #include <vector>
19 
20 char *getCondFromString( char * t );
21 
22 namespace irods {
23 
24  template <typename connection_type>
25  class query {
26  public:
27  typedef std::vector<std::string> value_type;
28 
29  enum query_type {
30  GENERAL = 0,
31  SPECIFIC = 1
32  };
33 
35  const std::string& _str) {
36  // default option
37  if(_str.empty()) {
38  return GENERAL;
39  }
40 
41  const std::string GEN_STR{"general"};
42  const std::string SPEC_STR{"specific"};
43 
44  std::string lowered{_str};
46  lowered.begin(),
47  lowered.end(),
48  lowered.begin(),
49  ::tolower);
50 
51  if(GEN_STR == lowered) {
52  return GENERAL;
53  }
54  else if(SPEC_STR == lowered) {
55  return SPECIFIC;
56  }
57  else {
58  THROW(
60  _str + " - is not a query type");
61  }
62  } // convert_string_to_query_type
63 
65  {
66  public:
67  size_t size() {
68  if(!gen_output_) {
69  return 0;
70  }
71  return gen_output_->rowCnt;
72  }
73 
74  int cont_idx() {
75  return gen_output_->continueInx;
76  }
77 
78  int row_cnt() {
79  return gen_output_->rowCnt;
80  }
81 
82  std::string query_string() {
83  return query_string_;
84  }
85 
86  bool query_limit_exceeded(const uint32_t _count) {
87  return query_limit_ && _count >= query_limit_;
88  }
89 
90  bool page_in_flight(const int row_idx_) {
91  return (row_idx_ < row_cnt());
92  }
93 
94  bool query_complete() {
95  // finished page, and out of pages
96  return cont_idx() <= 0;
97  }
98 
99  value_type capture_results(int _row_idx) {
100  value_type res;
101  for(int attr_idx = 0; attr_idx < gen_output_->attriCnt; ++attr_idx) {
102  uint32_t offset = gen_output_->sqlResult[attr_idx].len * _row_idx;
103  std::string str{&gen_output_->sqlResult[attr_idx].value[offset]};
104  res.push_back(str);
105  }
106  return res;
107  }
108 
109  bool results_valid() {
110  if(gen_output_) {
111  return (gen_output_->rowCnt > 0);
112  }
113  else {
114  return false;
115  }
116  }
117 
118  virtual int fetch_page() = 0;
119  virtual void reset_for_page_boundary() = 0;
120  virtual ~query_impl_base() {
121  }
122 
123  query_impl_base(connection_type* _comm,
124  const uint32_t _query_limit,
125  const uint32_t _row_offset,
126  const std::string& _query_string)
127  : comm_{_comm}
128  , query_limit_{_query_limit}
129  , row_offset_{_row_offset}
130  , query_string_{_query_string}
131  , gen_output_{}
132  {
133  }
134 
135  protected:
136  connection_type* comm_;
137  const uint32_t query_limit_;
138  const uint32_t row_offset_;
139  const std::string query_string_;
141  }; // class query_impl_base
142 
144  {
145  public:
146  virtual ~gen_query_impl() {
147  if(this->gen_output_ && this->gen_output_->continueInx) {
148  // Close statements for this query
151  gen_input_.maxRows = 0;
152  auto err = gen_query_fcn(
153  this->comm_,
154  &gen_input_,
155  &this->gen_output_);
156  if (CAT_NO_ROWS_FOUND != err && err < 0) {
157  irods::log(ERROR(err, (boost::format(
158  "[%s] - Failed to close statement with continueInx [%d]") %
159  __FUNCTION__ % gen_input_.continueInx).str()));
160  }
161  }
164  }
165 
166  void reset_for_page_boundary() override {
167  if(this->gen_output_) {
170  }
171  }
172 
173  int fetch_page() override {
174  return gen_query_fcn(
175  this->comm_,
176  &gen_input_,
177  &this->gen_output_);
178  } // fetch_page
179 
180  gen_query_impl(connection_type* _comm,
181  int _query_limit,
182  int _row_offset,
183  const std::string& _query_string,
184  const std::string& _zone_hint)
185  : query_impl_base(_comm, _query_limit, _row_offset, _query_string)
186  {
187  memset(&gen_input_, 0, sizeof(gen_input_));
189  gen_input_.rowOffset = _row_offset;
190 
191  if (!_zone_hint.empty()) {
192  addKeyVal(&gen_input_.condInput, ZONE_KW, _zone_hint.c_str());
193  }
194 
195  const int fill_err = fillGenQueryInpFromStrCond(
196  const_cast<char*>(_query_string.c_str()),
197  &gen_input_);
198  if(fill_err < 0) {
199  THROW(
200  fill_err,
201  boost::format("query fill failed for [%s]") %
202  _query_string);
203  }
204  } // ctor
205 
206  private:
208 #ifdef RODS_SERVER
209  const std::function<
210  int(connection_type*,
211  genQueryInp_t*,
212  genQueryOut_t**)>
214 #else
215  const std::function<
216  int(connection_type*,
217  genQueryInp_t*,
218  genQueryOut_t**)>
220 #endif
221  }; // class gen_query_impl
222 
224  public:
225  virtual ~spec_query_impl() {
226  if(this->gen_output_ && this->gen_output_->continueInx) {
227  // Close statement for this query
230  spec_input_.maxRows = 0;
231  auto err = spec_query_fcn(
232  this->comm_,
233  &spec_input_,
234  &this->gen_output_);
235  if (CAT_NO_ROWS_FOUND != err && err < 0) {
237  err, (boost::format(
238  "[%s] - Failed to close statement with continueInx [%d]") %
239  __FUNCTION__ % spec_input_.continueInx).str()));
240  }
241  }
243  }
244 
245  void reset_for_page_boundary() override {
246  if(this->gen_output_) {
249  }
250  }
251 
252  int fetch_page() override {
253  return spec_query_fcn(
254  this->comm_,
255  &spec_input_,
256  &this->gen_output_);
257  } // fetch_page
258 
259  spec_query_impl(connection_type* _comm,
260  int _query_limit,
261  int _row_offset,
262  const std::string& _query_string,
263  const std::string& _zone_hint,
264  const std::vector<std::string>* _args)
265  : query_impl_base(_comm, _query_limit, _row_offset, _query_string)
266  {
267  memset(&spec_input_, 0, sizeof(spec_input_));
269  spec_input_.sql = const_cast<char*>(_query_string.c_str());
270 
271  if (!_zone_hint.empty()) {
272  addKeyVal(&spec_input_.condInput, ZONE_KW, _zone_hint.c_str());
273  }
274 
275  if (_args) {
276  for (decltype(_args->size()) i = 0; i < _args->size(); ++i) {
277  spec_input_.args[i] = const_cast<char*>((*_args)[i].data());
278  }
279  }
280 
281  int spec_err = spec_query_fcn(
282  _comm,
283  &spec_input_,
284  &this->gen_output_);
285  if (spec_err < 0) {
286  if (CAT_NO_ROWS_FOUND != spec_err) {
287  THROW(spec_err, boost::format("query fill failed for [%s]") % _query_string);
288  }
289  }
290  } // ctor
291 
292  private:
293 
295  #ifdef RODS_SERVER
296  const std::function<
297  int(connection_type*,
299  genQueryOut_t**)>
301  #else
302  const std::function<
303  int(connection_type*,
305  genQueryOut_t**)>
307  #endif
308  }; // class spec_query_impl
309 
310  class iterator {
311  const std::string query_string_;
312  uint32_t row_idx_;
316 
317  std::shared_ptr<query_impl_base> query_impl_;
318 
319  public:
321  using pointer = const value_type*;
324  using iterator_category = std::forward_iterator_tag;
325 
326  explicit iterator() :
327  query_string_{},
328  row_idx_{},
330  gen_input_{},
331  end_iteration_state_{true},
332  query_impl_{} {
333  }
334 
335  explicit iterator(std::shared_ptr<query_impl_base> _qimp) :
336  query_string_{},
337  row_idx_{},
339  gen_input_{},
340  end_iteration_state_{false},
341  query_impl_(_qimp) {
342  }
343 
344  explicit iterator(
345  const std::string& _query_string,
346  genQueryInp_t* _gen_input) :
347  query_string_{_query_string},
348  row_idx_{},
350  gen_input_{_gen_input},
351  end_iteration_state_{false},
352  query_impl_{} {
353  } // ctor
354 
356  advance_query();
357  return *this;
358  }
359 
361  iterator ret = *this;
362  ++(*this);
363  return ret;
364  }
365 
366  bool operator==(const iterator& _rhs) const {
368  return true;
369  }
370 
371  return (query_impl_->query_string() == _rhs.query_string_);
372  }
373 
374  bool operator!=(const iterator& _rhs) const {
375  return !(*this == _rhs);
376  }
377 
379  return capture_results();
380  }
381 
383  row_idx_ = 0;
384  query_impl_->reset_for_page_boundary();
385  }
386 
387  void advance_query() {
389  if(query_impl_->query_limit_exceeded(total_rows_processed_)) {
390  end_iteration_state_ = true;
391  return;
392  }
393 
394  row_idx_++;
395  if(query_impl_->page_in_flight(row_idx_)) {
396  return;
397  }
398 
399  if(query_impl_->query_complete()) {
400  end_iteration_state_ = true;
401  return;
402  }
403 
405  const int query_err = query_impl_->fetch_page();
406  if(query_err < 0) {
407  if(CAT_NO_ROWS_FOUND != query_err) {
408  THROW(
409  query_err,
410  boost::format("gen query failed for [%s] on idx %d") %
411  query_string_ %
413  }
414 
415  end_iteration_state_ = true;
416 
417  } // if
418 
419  } // advance_query
420 
422  return query_impl_->capture_results(row_idx_);
423  }
424  }; // class iterator
425 
426  query(connection_type* _comm,
427  const std::string& _query_string,
428  const std::vector<std::string>* _specific_query_args,
429  const std::string& _zone_hint,
430  uintmax_t _query_limit,
431  uintmax_t _row_offset,
432  query_type _query_type)
433  : iter_{}
434  , query_impl_{}
435  {
436  if(_query_type == GENERAL) {
437  query_impl_ = std::make_shared<gen_query_impl>(
438  _comm,
439  _query_limit,
440  _row_offset,
441  _query_string,
442  _zone_hint);
443  }
444  else if(_query_type == SPECIFIC) {
445  query_impl_ = std::make_shared<spec_query_impl>(
446  _comm,
447  _query_limit,
448  _row_offset,
449  _query_string,
450  _zone_hint,
451  _specific_query_args);
452  }
453 
454  const int fetch_err = query_impl_->fetch_page();
455  if(fetch_err < 0) {
456  if(CAT_NO_ROWS_FOUND == fetch_err) {
457  iter_ = std::make_unique<iterator>();
458  }
459  else {
460  THROW(
461  fetch_err,
462  boost::format("query failed for [%s] type [%d]") %
463  _query_string %
464  _query_type);
465  }
466  }
467 
468  if(query_impl_->results_valid()) {
469  iter_ = std::make_unique<iterator>(query_impl_);
470  }
471  else {
472  iter_ = std::make_unique<iterator>();
473  }
474  } // ctor
475 
476  query(connection_type* _comm,
477  const std::string& _query_string,
478  uintmax_t _query_limit = 0,
479  uintmax_t _row_offset = 0,
480  query_type _query_type = GENERAL)
481  : query{_comm, _query_string, nullptr, {}, _query_limit, _row_offset, _query_type}
482  {
483  } // ctor
484 
485  query(query&&) = default;
486  query& operator=(query&&) = default;
487 
488  ~query() {
489  }
490 
491  iterator begin() {
492  return *iter_;
493  }
494 
495  iterator end() {
496  return iterator();
497  }
498 
500  return (*(*iter_));
501  }
502 
503  size_t size() {
504  return query_impl_->size();
505  }
506 
507  private:
508  std::unique_ptr<iterator> iter_;
509  std::shared_ptr<query_impl_base> query_impl_;
510  }; // class query
511 } // namespace irods
512 
513 #endif // IRODS_QUERY_HPP
514 
specificQueryInp_t::maxRows
int maxRows
Definition: specificQuery.h:13
irods::query< ConnectionType >::query_type
query_type
Definition: irods_query.hpp:29
MAX_SQL_ROWS
#define MAX_SQL_ROWS
Definition: rodsGenQuery.h:16
irods::query::iterator::operator++
iterator operator++()
Definition: irods_query.hpp:355
irods::query::query_impl_base::query_impl_base
query_impl_base(connection_type *_comm, const uint32_t _query_limit, const uint32_t _row_offset, const std::string &_query_string)
Definition: irods_query.hpp:123
irods::query::spec_query_impl::reset_for_page_boundary
void reset_for_page_boundary() override
Definition: irods_query.hpp:245
addKeyVal
int addKeyVal(keyValPair_t *condInput, const char *keyWord, const char *value)
Definition: rcMisc.cpp:789
irods::query::iterator::reference
value_type reference
Definition: irods_query.hpp:322
GenQueryInp::continueInx
int continueInx
Definition: rodsGenQuery.h:28
irods::query::iterator::query_string_
const std::string query_string_
Definition: irods_query.hpp:311
irods::query::iterator::difference_type
value_type difference_type
Definition: irods_query.hpp:323
THROW
#define THROW(_code, _msg)
Definition: irods_exception.hpp:68
irods::query::iterator::iterator
iterator(const std::string &_query_string, genQueryInp_t *_gen_input)
Definition: irods_query.hpp:344
irods::transform
void transform(const InputC &ic, OutputC &oc, UnaryOperation func)
Definition: irods_re_plugin.hpp:822
irods::query::query_impl_base
Definition: irods_query.hpp:65
irods::query::spec_query_impl::spec_query_fcn
const std::function< int(connection_type *, specificQueryInp_t *, genQueryOut_t **)> spec_query_fcn
Definition: irods_query.hpp:306
getCondFromString
char * getCondFromString(char *t)
Definition: rcMisc.cpp:2883
irods::query::query_impl_base::row_offset_
const uint32_t row_offset_
Definition: irods_query.hpp:138
irods::query::iterator::operator==
bool operator==(const iterator &_rhs) const
Definition: irods_query.hpp:366
specificQueryInp_t::continueInx
int continueInx
Definition: specificQuery.h:14
irods::query::query_impl_base::row_cnt
int row_cnt()
Definition: irods_query.hpp:78
irods::query::query_impl_base::size
size_t size()
Definition: irods_query.hpp:67
irods::query::query_impl_base::query_string
std::string query_string()
Definition: irods_query.hpp:82
irods::query::iterator::end_iteration_state_
bool end_iteration_state_
Definition: irods_query.hpp:315
GenQueryInp
Definition: rodsGenQuery.h:24
irods::query::iterator::row_idx_
uint32_t row_idx_
Definition: irods_query.hpp:312
rcMisc.h
irods::query::gen_query_impl::gen_query_fcn
const std::function< int(connection_type *, genQueryInp_t *, genQueryOut_t **)> gen_query_fcn
Definition: irods_query.hpp:219
specificQueryInp_t::args
char * args[10]
Definition: specificQuery.h:10
irods::query::front
value_type front()
Definition: irods_query.hpp:499
irods::query::query_impl_base::cont_idx
int cont_idx()
Definition: irods_query.hpp:74
irods::query::iterator::total_rows_processed_
uint32_t total_rows_processed_
Definition: irods_query.hpp:313
pointer
Definition: parser.hpp:34
SYS_INVALID_INPUT_PARAM
@ SYS_INVALID_INPUT_PARAM
Definition: rodsErrorTable.h:195
irods::query::iterator::iterator_category
std::forward_iterator_tag iterator_category
Definition: irods_query.hpp:324
GenQueryInp::maxRows
int maxRows
Definition: rodsGenQuery.h:25
GenQueryOut::sqlResult
sqlResult_t sqlResult[50]
Definition: rodsGenQuery.h:72
specificQueryInp_t::condInput
keyValPair_t condInput
Definition: specificQuery.h:17
specificQueryInp_t
Definition: specificQuery.h:8
rsSpecificQuery
int rsSpecificQuery(rsComm_t *rsComm, specificQueryInp_t *specificQueryInp, genQueryOut_t **genQueryOut)
Definition: rsSpecificQuery.cpp:16
irods::query::query
query(query &&)=default
irods::query::query_impl_base::query_complete
bool query_complete()
Definition: irods_query.hpp:94
irods::query::iterator::reset_for_page_boundary
void reset_for_page_boundary()
Definition: irods_query.hpp:382
irods::query::begin
iterator begin()
Definition: irods_query.hpp:491
rsSpecificQuery.hpp
irods::query::SPECIFIC
@ SPECIFIC
Definition: irods_query.hpp:31
irods::query::iterator::capture_results
value_type capture_results()
Definition: irods_query.hpp:421
GenQueryOut::continueInx
int continueInx
Definition: rodsGenQuery.h:70
irods::query::query_impl_base::~query_impl_base
virtual ~query_impl_base()
Definition: irods_query.hpp:120
specificQueryInp_t::sql
char * sql
Definition: specificQuery.h:9
GenQueryInp::condInput
keyValPair_t condInput
Definition: rodsGenQuery.h:52
irods
Definition: apiHandler.hpp:35
irods::query::iterator::value_type
value_type value_type
Definition: irods_query.hpp:320
rcGenQuery
int rcGenQuery(rcComm_t *conn, genQueryInp_t *genQueryInp, genQueryOut_t **genQueryOut)
Definition: rcGenQuery.cpp:89
irods::query::iterator::query_impl_
std::shared_ptr< query_impl_base > query_impl_
Definition: irods_query.hpp:317
irods::query::gen_query_impl::reset_for_page_boundary
void reset_for_page_boundary() override
Definition: irods_query.hpp:166
irods::query::spec_query_impl::spec_input_
specificQueryInp_t spec_input_
Definition: irods_query.hpp:294
irods::query::GENERAL
@ GENERAL
Definition: irods_query.hpp:30
genQuery.h
irods::query::iterator::iterator
iterator(std::shared_ptr< query_impl_base > _qimp)
Definition: irods_query.hpp:335
irods::query::end
iterator end()
Definition: irods_query.hpp:495
GenQueryInp::rowOffset
int rowOffset
Definition: rodsGenQuery.h:32
GenQueryOut
Definition: rodsGenQuery.h:67
irods::query::query_impl_base::query_limit_exceeded
bool query_limit_exceeded(const uint32_t _count)
Definition: irods_query.hpp:86
GenQueryOut::attriCnt
int attriCnt
Definition: rodsGenQuery.h:69
irods::query::spec_query_impl::spec_query_impl
spec_query_impl(connection_type *_comm, int _query_limit, int _row_offset, const std::string &_query_string, const std::string &_zone_hint, const std::vector< std::string > *_args)
Definition: irods_query.hpp:259
GenQueryOut::rowCnt
int rowCnt
Definition: rodsGenQuery.h:68
irods::log
void log(const error &)
Definition: irods_log.cpp:13
irods::query::query_impl_
std::shared_ptr< query_impl_base > query_impl_
Definition: irods_query.hpp:509
irods::query::iterator::operator++
iterator operator++(int)
Definition: irods_query.hpp:360
irods::query::gen_query_impl
Definition: irods_query.hpp:144
irods::query::spec_query_impl::~spec_query_impl
virtual ~spec_query_impl()
Definition: irods_query.hpp:225
irods::query::iter_
std::unique_ptr< iterator > iter_
Definition: irods_query.hpp:508
irods::query::iterator::operator*
value_type operator*()
Definition: irods_query.hpp:378
ERROR
#define ERROR(code_, message_)
Definition: irods_error.hpp:117
int
typedef int((*funcPtr)())
irods::query::convert_string_to_query_type
static query_type convert_string_to_query_type(const std::string &_str)
Definition: irods_query.hpp:34
irods::query::query_impl_base::reset_for_page_boundary
virtual void reset_for_page_boundary()=0
irods::query::~query
~query()
Definition: irods_query.hpp:488
SqlResult::value
char * value
Definition: rodsGenQuery.h:64
specificQuery.h
irods::query::query_impl_base::fetch_page
virtual int fetch_page()=0
irods::query::iterator::iterator
iterator()
Definition: irods_query.hpp:326
irods::query::iterator::operator!=
bool operator!=(const iterator &_rhs) const
Definition: irods_query.hpp:374
irods::query::query_impl_base::page_in_flight
bool page_in_flight(const int row_idx_)
Definition: irods_query.hpp:90
irods::query::query_impl_base::capture_results
value_type capture_results(int _row_idx)
Definition: irods_query.hpp:99
CAT_NO_ROWS_FOUND
@ CAT_NO_ROWS_FOUND
Definition: rodsErrorTable.h:423
irods::query::iterator
Definition: irods_query.hpp:310
irods::query::iterator::advance_query
void advance_query()
Definition: irods_query.hpp:387
irods::query::gen_query_impl::~gen_query_impl
virtual ~gen_query_impl()
Definition: irods_query.hpp:146
irods::query::spec_query_impl
Definition: irods_query.hpp:223
irods::query::query_impl_base::query_string_
const std::string query_string_
Definition: irods_query.hpp:139
irods::query::query_impl_base::query_limit_
const uint32_t query_limit_
Definition: irods_query.hpp:137
irods::query::query_impl_base::results_valid
bool results_valid()
Definition: irods_query.hpp:109
SqlResult::len
int len
Definition: rodsGenQuery.h:63
irods::query::gen_query_impl::fetch_page
int fetch_page() override
Definition: irods_query.hpp:173
irods::query::iterator::gen_input_
genQueryInp_t * gen_input_
Definition: irods_query.hpp:314
ZONE_KW
#define ZONE_KW
Definition: rodsKeyWdDef.h:80
rsGenQuery.hpp
irods::query
Definition: irods_query.hpp:25
irods::query::query
query(connection_type *_comm, const std::string &_query_string, const std::vector< std::string > *_specific_query_args, const std::string &_zone_hint, uintmax_t _query_limit, uintmax_t _row_offset, query_type _query_type)
Definition: irods_query.hpp:426
irods::query::query
query(connection_type *_comm, const std::string &_query_string, uintmax_t _query_limit=0, uintmax_t _row_offset=0, query_type _query_type=GENERAL)
Definition: irods_query.hpp:476
irods::query::spec_query_impl::fetch_page
int fetch_page() override
Definition: irods_query.hpp:252
freeGenQueryOut
int freeGenQueryOut(genQueryOut_t **genQueryOut)
Definition: rcMisc.cpp:1133
rcSpecificQuery
int rcSpecificQuery(rcComm_t *conn, specificQueryInp_t *specificQueryInp, genQueryOut_t **genQueryOut)
Definition: rcSpecificQuery.cpp:49
irods::query::operator=
query & operator=(query &&)=default
irods::query::value_type
std::vector< std::string > value_type
Definition: irods_query.hpp:27
irods::query::size
size_t size()
Definition: irods_query.hpp:503
clearGenQueryInp
void clearGenQueryInp(void *voidInp)
Definition: rcMisc.cpp:1118
rsGenQuery
int rsGenQuery(rsComm_t *rsComm, genQueryInp_t *genQueryInp, genQueryOut_t **genQueryOut)
Definition: rsGenQuery.cpp:604
fillGenQueryInpFromStrCond
int fillGenQueryInpFromStrCond(char *str, genQueryInp_t *genQueryInp)
Definition: rcMisc.cpp:2921
irods_log.hpp
irods::query::query_impl_base::gen_output_
genQueryOut_t * gen_output_
Definition: irods_query.hpp:140
irods::query::query_impl_base::comm_
connection_type * comm_
Definition: irods_query.hpp:136
irods::query::gen_query_impl::gen_query_impl
gen_query_impl(connection_type *_comm, int _query_limit, int _row_offset, const std::string &_query_string, const std::string &_zone_hint)
Definition: irods_query.hpp:180
irods::query::gen_query_impl::gen_input_
genQueryInp_t gen_input_
Definition: irods_query.hpp:207