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)  

rsGenQuery.cpp
Go to the documentation of this file.
1 
4 /* See genQuery.h for a description of this API call.*/
5 
6 #include "rcMisc.h"
7 #include "genQuery.h"
9 #include "miscUtil.h"
10 #include "rsGenQuery.hpp"
11 #include "rsGlobalExtern.hpp"
12 #include "miscServerFunct.hpp"
15 #include "irods_lexical_cast.hpp"
16 #include "rodsGenQueryNames.h"
17 
18 #include "boost/format.hpp"
19 #include <boost/regex.hpp>
20 #include <boost/tokenizer.hpp>
21 #include <string>
22 
23 
24 
25 namespace {
26  std::string
27  get_column_name(int j) {
28  const int n = sizeof(columnNames)/sizeof(columnNames[0]);
29  for (int i=0; i<n; ++i) {
30  if (columnNames[i].columnId == j) {
31  return std::string(columnNames[i].columnName);
32  }
33  }
34 
35  std::stringstream ss;
36  ss << j;
37  return std::string("COLUMN_NAME_NOT_FOUND_") + ss.str();
38  }
39 
40  struct option_element{
41  int key;
42  const char* cpp_macro;
43  const char* token;
44  };
45 
46  option_element queryWideOptionsMap[] = {
47  {RETURN_TOTAL_ROW_COUNT, "RETURN_TOTAL_ROW_COUNT", "return_total_row_count"},
48  {NO_DISTINCT, "NO_DISTINCT", "no_distinct"},
49  {QUOTA_QUERY, "QUOTA_QUERY", "quota_query"},
50  {AUTO_CLOSE, "AUTO_CLOSE", "auto_close"},
51  {UPPER_CASE_WHERE, "UPPER_CASE_WHERE", "upper_case_where"}
52  };
53 
54  option_element selectInpOptionsMap[] = {
55  {ORDER_BY, "ORDER_BY", "order"},
56  {ORDER_BY_DESC, "ORDER_BY_DESC", "order_desc"}
57  };
58 
59  option_element selectInpFunctionMap[] = {
60  {SELECT_MIN, "SELECT_MIN", "min"},
61  {SELECT_MAX, "SELECT_MAX", "max"},
62  {SELECT_SUM, "SELECT_SUM", "sum"},
63  {SELECT_AVG, "SELECT_AVG", "avg"},
64  {SELECT_COUNT, "SELECT_COUNT", "count"}
65  };
66 
67  std::string
68  format_selected_column(int columnIndex, int columnOption) {
69  std::string ret = get_column_name(columnIndex);
70  if (columnOption == 0 || columnOption == 1) {
71  return ret;
72  }
73 
74  for (size_t i=0; i<sizeof(selectInpOptionsMap)/sizeof(selectInpOptionsMap[0]); ++i) {
75  if (columnOption == selectInpOptionsMap[i].key) {
76  ret = std::string(selectInpOptionsMap[i].token) + "(" + ret + ")";
77  return ret;
78  }
79  }
80  for (size_t i=0; i<sizeof(selectInpFunctionMap)/sizeof(selectInpFunctionMap[0]); ++i) {
81  if (columnOption == selectInpFunctionMap[i].key) {
82  ret = std::string(selectInpFunctionMap[i].token) + "(" + ret + ")";
83  return ret;
84  }
85  }
86 
87  std::stringstream ss;
88  ss << columnOption;
89  ret = std::string("combo_func_") + ss.str() + "(" + ret + ")";
90  return ret;
91  }
92 
93  template <typename OutStream>
94  void
95  insert_genquery_inp_into_stream(const genQueryInp_t *genQueryInp, OutStream& f) {
96  f << "maxRows: " << genQueryInp->maxRows << " continueInx: " << genQueryInp->continueInx << " rowOffset: " << genQueryInp->rowOffset << '\n';
97  f << "options: " << genQueryInp->options;
98  for (size_t i=0; i<sizeof(queryWideOptionsMap)/sizeof(queryWideOptionsMap[0]); ++i) {
99  if (genQueryInp->options & queryWideOptionsMap[i].key) {
100  f << " " << queryWideOptionsMap[i].cpp_macro;
101  }
102  }
103  f << '\n';
104 
105  f << "selectInp.len: " << genQueryInp->selectInp.len << '\n';
106  for (int i=0; i<genQueryInp->selectInp.len; ++i) {
107  f << " column: " << genQueryInp->selectInp.inx[i] << " " << get_column_name(genQueryInp->selectInp.inx[i]) << '\n';
108  f << " options: " << genQueryInp->selectInp.value[i];
109  for (size_t j=0; j<sizeof(selectInpOptionsMap)/sizeof(selectInpOptionsMap[0]); ++j) {
110  if (genQueryInp->selectInp.value[i] & selectInpOptionsMap[j].key) {
111  f << " " << selectInpOptionsMap[j].cpp_macro;
112  }
113  }
114  for (size_t j=0; j<sizeof(selectInpFunctionMap)/sizeof(selectInpFunctionMap[0]); ++j) {
115  if ((genQueryInp->selectInp.value[i] & 0x7) == selectInpFunctionMap[j].key) {
116  f << " " << selectInpFunctionMap[j].cpp_macro;
117  }
118  }
119  f << '\n';
120  }
121 
122  f << "sqlCondInp.len: " << genQueryInp->sqlCondInp.len << '\n';
123  for (int i=0; i<genQueryInp->sqlCondInp.len; ++i) {
124  f << " column: " << genQueryInp->sqlCondInp.inx[i] << " " << get_column_name(genQueryInp->sqlCondInp.inx[i]) << '\n';
125  f << " condition: " << genQueryInp->sqlCondInp.value[i] << '\n';
126  }
127  f << '\n';
128  }
129 
130 }
131 
132 std::string
134  std::stringstream ss;
135  insert_genquery_inp_into_stream(q, ss);
136  return ss.str();
137 }
138 
139 std::string
141  // TODO: handle queryWideOptionsMap
142  std::stringstream ss;
143  ss << "select ";
144  {
145  const int n = q->selectInp.len;
146  if (n<=0) {
147  ss << "ERROR: 0 columns selected, printing query contents instead of iquest string\n";
148  insert_genquery_inp_into_stream(q, ss);
149  return ss.str();
150  }
151 
152  ss << format_selected_column(q->selectInp.inx[0], q->selectInp.value[0]);
153  for (int i=1; i<n; ++i) {
154  ss << ", ";
155  ss << format_selected_column(q->selectInp.inx[i], q->selectInp.value[i]);
156  }
157  }
158 
159  {
160  const int n = q->sqlCondInp.len;
161  if (n>0) {
162  ss << " where ";
163  ss << get_column_name(q->sqlCondInp.inx[0]) << " " << q->sqlCondInp.value[0];
164  for (int i=1; i<n; ++i) {
165  ss << " and ";
166  ss << get_column_name(q->sqlCondInp.inx[i]) << " " << q->sqlCondInp.value[i];
167  }
168  }
169  }
170  return ss.str();
171 }
172 
174  memset(&genquery_inp_, 0, sizeof(genquery_inp_));
175 }
177  clearGenQueryInp(&genquery_inp_);
178 }
180  return genquery_inp_;
181 }
183  genquery_out_ptr_ = nullptr;
184 }
186  freeGenQueryOut(&genquery_out_ptr_);
187 }
189  return genquery_out_ptr_;
190 }
191 
192 
193 static
195  genQueryInp_t* _inp ) {
196  // =-=-=-=-=-=-=-
197  // cache pointers to the incoming inxIvalPair
198  inxIvalPair_t tmp;
199  tmp.len = _inp->selectInp.len;
200  tmp.inx = _inp->selectInp.inx;
201  tmp.value = _inp->selectInp.value;
202 
203  // =-=-=-=-=-=-=-
204  // zero out the selectInp to copy
205  // fresh community indices and values
206  bzero( &_inp->selectInp, sizeof( _inp->selectInp ) );
207 
208  // =-=-=-=-=-=-=-
209  // iterate over the tmp and only copy community values
210  for ( int i = 0; i < tmp.len; ++i ) {
211  if ( tmp.inx[ i ] == COL_R_RESC_CHILDREN ||
212  tmp.inx[ i ] == COL_R_RESC_CONTEXT ||
213  tmp.inx[ i ] == COL_R_RESC_PARENT ||
214  tmp.inx[ i ] == COL_R_RESC_PARENT_CONTEXT ||
215  tmp.inx[ i ] == COL_D_RESC_HIER ) {
216  continue;
217  }
218  else {
219  addInxIval( &_inp->selectInp, tmp.inx[ i ], tmp.value[ i ] );
220  }
221 
222  } // for i
223 
224  return SUCCESS();
225 
226 } // strip_new_query_terms
227 
228 
229 static
231 
232  const int COL_D_RESC_GROUP_NAME = 408;
233 
234  // sanity check
235  if ( !_inp ) {
237  }
238 
239  // =-=-=-=-=-=-=-
240  // cache pointers to the incoming inxIvalPair
241  inxIvalPair_t tmp;
242  tmp.len = _inp->selectInp.len;
243  tmp.inx = _inp->selectInp.inx;
244  tmp.value = _inp->selectInp.value;
245 
246  // =-=-=-=-=-=-=-
247  // zero out the selectInp to copy
248  // fresh indices and values
249  bzero( &_inp->selectInp, sizeof( _inp->selectInp ) );
250 
251  // =-=-=-=-=-=-=-
252  // iterate over tmp and replace resource group with resource name
253  for ( int i = 0; i < tmp.len; ++i ) {
254  if ( tmp.inx[i] == COL_D_RESC_GROUP_NAME ) {
255  addInxIval( &_inp->selectInp, COL_D_RESC_NAME, tmp.value[i] );
256  _pos = i;
257  }
258  else {
259  addInxIval( &_inp->selectInp, tmp.inx[i], tmp.value[i] );
260  }
261  } // for i
262 
263  // cleanup
264  if ( tmp.inx ) { free( tmp.inx ); }
265  if ( tmp.value ) { free( tmp.value ); }
266 
267  return SUCCESS();
268 
269 } // strip_resc_grp_name_from_query_inp
270 
271 
272 static
274 
275  const int COL_D_RESC_GROUP_NAME = 408;
276 
277  // =-=-=-=-=-=-=-
278  // Sanity checks
279  if ( !_out ) {
281  }
282 
283  if ( _pos < 0 || _pos > MAX_SQL_ATTR - 1 ) {
284  return CODE( SYS_INVALID_INPUT_PARAM );
285  }
286 
287  sqlResult_t *sqlResult = &_out->sqlResult[_pos];
288  if ( !sqlResult || sqlResult->attriInx != COL_D_RESC_NAME ) {
289  return CODE( SYS_INTERNAL_ERR );
290  }
291 
292  // =-=-=-=-=-=-=-
293  // Swap attribute indices back
294  sqlResult->attriInx = COL_D_RESC_GROUP_NAME;
295 
296  return SUCCESS();
297 
298 } // add_resc_grp_name_to_query_out
299 
300 static
302  const char* _cond,
303  std::string& _new_cond ) {
304  const std::string in_cond( _cond );
305  const std::string::size_type p0 = in_cond.find_first_of( "'" );
306  const std::string::size_type p1 = in_cond.find_last_of( "'" );
307  if ( p1 == p0 ) {
308  return ERROR( SYS_INVALID_INPUT_PARAM, _cond );
309  }
310 
311  std::string hier = in_cond.substr( p0 + 1, p1 - p0 - 1);
312 
313  /*
314  * If query condition uses "=", look for exact matches.
315  * Since % is not allowed in resource names, error out if found.
316  */
317  if ( std::string::npos != in_cond.find( "=" ) &&
318  std::string::npos != hier.find( "%" ) ) {
319  return ERROR( SYS_RESC_DOES_NOT_EXIST, hier );
320  }
321 
322  /*
323  * Convert input condition to regex syntax and filter list of
324  * hierarchies. For each matching result, get the leaf ID and
325  * add it to the list of results. Generate 'IN' condition with
326  * the resulting leaf IDs. Return early if none found.
327  */
328  std::string::size_type pos( hier.find_first_of( "%" ) );
329  std::string hierRegex( hier );
330  while ( std::string::npos != pos ) {
331  hierRegex.replace( pos, 1, "(.*)" );
332  pos = hierRegex.find_first_of( "%" );
333  }
334 
335  std::vector<rodsLong_t> leaf_ids;
336  try {
337  const std::vector<std::string> hier_list = resc_mgr.get_all_resc_hierarchies();
338  for ( const auto& hier_ : hier_list ) {
339  if ( boost::regex_match( hier_, boost::regex( hierRegex ) ) ) {
340  rodsLong_t leaf_id{};
341  irods::error ret = resc_mgr.hier_to_leaf_id( hier_, leaf_id );
342  if ( !ret.ok() ) {
343  return PASS( ret );
344  }
345  leaf_ids.push_back( leaf_id );
346  }
347  }
348  }
349  catch ( const irods::exception& e ) {
350  return irods::error( e );
351  }
352 
353  if ( leaf_ids.empty() ) {
354  return ERROR( SYS_RESC_DOES_NOT_EXIST, hier );
355  }
356 
357  _new_cond = "IN (";
358  for ( const auto& leaf_id : leaf_ids ) {
359  std::stringstream current_cond;
360  current_cond << "'" << leaf_id << "'";
361  if( leaf_id != leaf_ids.back() ) {
362  current_cond << ",";
363  }
364  _new_cond += current_cond.str();
365  }
366  _new_cond += ")";
367  return SUCCESS();
368 
369 } // get_resc_id_cond_for_hier_cond
370 
371 static
373  // sanity check
374  if ( !_inp ) {
376  }
377 
378  // =-=-=-=-=-=-=-
379  // cache pointers to the incoming inxIvalPair
380  inxIvalPair_t tmpI;
381  tmpI.len = _inp->selectInp.len;
382  tmpI.inx = _inp->selectInp.inx;
383  tmpI.value = _inp->selectInp.value;
384 
385  // =-=-=-=-=-=-=-
386  // zero out the selectInp to copy
387  // fresh indices and values
388  bzero( &_inp->selectInp, sizeof( _inp->selectInp ) );
389 
390  // =-=-=-=-=-=-=-
391  // iterate over tmp and replace resource group with resource name
392  for ( int i = 0; i < tmpI.len; ++i ) {
393  if ( tmpI.inx[i] == COL_D_RESC_HIER ) {
394  addInxIval( &_inp->selectInp, COL_D_RESC_ID, tmpI.value[i] );
395  _pos = i;
396  }
397  else {
398  addInxIval( &_inp->selectInp, tmpI.inx[i], tmpI.value[i] );
399  }
400  } // for i
401 
402  // cleanup
403  if ( tmpI.inx ) { free( tmpI.inx ); }
404  if ( tmpI.value ) { free( tmpI.value ); }
405 
406 
407  // =-=-=-=-=-=-=-
408  // cache pointers to the incoming inxIvalPair
409  inxValPair_t tmpV;
410  tmpV.len = _inp->sqlCondInp.len;
411  tmpV.inx = _inp->sqlCondInp.inx;
412  tmpV.value = _inp->sqlCondInp.value;
413 
414  // =-=-=-=-=-=-=-
415  // zero out the selectInp to copy
416  // fresh indices and values
417  bzero( &_inp->sqlCondInp, sizeof( _inp->selectInp ) );
418 
419  // =-=-=-=-=-=-=-
420  // iterate over tmp and replace resource group with resource name
421  for ( int i = 0; i < tmpV.len; ++i ) {
422  if ( tmpV.inx[i] == COL_D_RESC_HIER ) {
423  std::string new_cond = "='0'";
425  tmpV.value[i],
426  new_cond);
427  if(!ret.ok()) {
428  irods::log(PASS(ret));
429  }
430 
431  addInxVal( &_inp->sqlCondInp, COL_D_RESC_ID, new_cond.c_str() );
432  }
433  else {
434  addInxVal( &_inp->sqlCondInp, tmpV.inx[i], tmpV.value[i] );
435  }
436  } // for i
437 
438  // cleanup
439  clearInxVal(&tmpV);
440 
441  return SUCCESS();
442 
443 } // strip_resc_hier_name_from_query_inp
444 
445 
446 static
448  // =-=-=-=-=-=-=-
449  // Sanity checks
450  if ( !_out ) {
452  }
453 
454  if ( _pos < 0 || _pos > MAX_SQL_ATTR - 1 ) {
455  return CODE( SYS_INVALID_INPUT_PARAM );
456  }
457 
458  sqlResult_t *sqlResult = &_out->sqlResult[_pos];
459  if ( !sqlResult || sqlResult->attriInx != COL_D_RESC_ID ) {
460  return CODE( SYS_INTERNAL_ERR );
461  }
462 
463  // =-=-=-=-=-=-=-
464  // Swap attribute indices back
465  sqlResult->attriInx = COL_D_RESC_HIER;
466 
467  // =-=-=-=-=-=-=-
468  // cache hier strings for leaf id
469  size_t max_len = 0;
470  std::vector<std::string> resc_hiers(_out->rowCnt);
471  for ( int i = 0; i < _out->rowCnt; ++i ) {
472  char* leaf_id_str = &sqlResult->value[i*sqlResult->len];
473 
474  rodsLong_t leaf_id = 0;
475  irods::error ret = irods::lexical_cast<rodsLong_t>(
476  leaf_id_str,
477  leaf_id);
478  if(!ret.ok()) {
479  irods::log(PASS(ret));
480  continue;
481  }
482 
483  std::string hier;
484  ret = resc_mgr.leaf_id_to_hier( leaf_id, resc_hiers[i] );
485  if(!ret.ok()) {
486  irods::log(PASS(ret));
487  continue;
488  }
489 
490  if(resc_hiers[i].size() > max_len ) {
491  max_len = resc_hiers[i].size();
492  }
493 
494  } // for i
495 
496  free( sqlResult->value );
497 
498  // =-=-=-=-=-=-=-
499  // craft new result string with the hiers
500  sqlResult->len = max_len+1;
501  sqlResult->value = (char*)malloc(sqlResult->len*_out->rowCnt);
502  for( std::size_t i = 0; i < resc_hiers.size(); ++i ) {
503  snprintf(
504  &sqlResult->value[i*sqlResult->len],
505  sqlResult->len,
506  "%s",
507  resc_hiers[i].c_str() );
508  }
509 
510  return SUCCESS();
511 
512 } // add_resc_hier_name_to_query_out
513 
514 
515 static
517  const std::string& _zone_hint,
518  genQueryInp_t* _inp ){
519  std::string zone_name;
520  zoneInfo_t* tmp_zone = ZoneInfoHead;
521 
522  // =-=-=-=-=-=-=-
523  // extract zone name from zone hint
524  boost::char_separator<char> sep("/");
525  boost::tokenizer<boost::char_separator<char> > tokens(_zone_hint, sep);
526  if (tokens.begin() != tokens.end()) {
527  zone_name = *tokens.begin();
528  } else {
529  return ERROR(SYS_INVALID_ZONE_NAME, "No zone name parsed from zone hint");
530  }
531 
532  // =-=-=-=-=-=-=-
533  // grind through the zones and find the match to the kw
534  while (tmp_zone) {
535  if ( zone_name == tmp_zone->zoneName &&
536  tmp_zone->masterServerHost->conn &&
537  tmp_zone->masterServerHost->conn->svrVersion &&
538  tmp_zone->masterServerHost->conn->svrVersion->cookie < 301 ) {
539  return strip_new_query_terms( _inp );
540 
541  }
542  else {
543  tmp_zone = tmp_zone->next;
544 
545  }
546  }
547 
548  return SUCCESS();
549 
550 } // proc_query_terms_for_community_server
551 
552 #if 0 // debug code
553 int
554 print_gen_query_input(
555  genQueryInp_t *genQueryInp ) {
556  if(!genQueryInp) return 0;
557 
558  int i = 0, len = 0;
559  int *ip1 = 0, *ip2 = 0;
560  char *cp = 0;
561  char **cpp = 0;
562 
563  printf( "maxRows=%d\n", genQueryInp->maxRows );
564 
565  len = genQueryInp->selectInp.len;
566  printf( "sel len=%d\n", len );
567 
568  ip1 = genQueryInp->selectInp.inx;
569  ip2 = genQueryInp->selectInp.value;
570  if( ip1 && ip2 ) {
571  for ( i = 0; i < len; i++ ) {
572  printf( "sel inx [%d]=%d\n", i, *ip1 );
573  printf( "sel val [%d]=%d\n", i, *ip2 );
574  ip1++;
575  ip2++;
576  }
577  }
578 
579  len = genQueryInp->sqlCondInp.len;
580  printf( "sqlCond len=%d\n", len );
581  ip1 = genQueryInp->sqlCondInp.inx;
582  cpp = genQueryInp->sqlCondInp.value;
583  if(cpp) {
584  cp = *cpp;
585  }
586  if( ip1 && cp ) {
587  for ( i = 0; i < len; i++ ) {
588  printf( "sel inx [%d]=%d\n", i, *ip1 );
589  printf( "sel val [%d]=:%s:\n", i, cp );
590  ip1++;
591  cpp++;
592  cp = *cpp;
593  }
594  }
595 
596  return 0;
597 }
598 #endif
599 
600 /* can be used for debug: */
601 /* extern int printGenQI( genQueryInp_t *genQueryInp); */
602 
603 int
604 rsGenQuery( rsComm_t *rsComm, genQueryInp_t *genQueryInp,
605  genQueryOut_t **genQueryOut ) {
606 
608  int status;
609  char *zoneHint;
610  zoneHint = getZoneHintForGenQuery( genQueryInp );
611 
612  std::string zone_hint_str;
613  if ( zoneHint ) {
614  zone_hint_str = zoneHint;
615 
616  // clean up path separator(s) and trailing '
617  if('/' == zone_hint_str[0]) {
618  zone_hint_str = zone_hint_str.substr(1);
619 
620  std::string::size_type pos = zone_hint_str.find_first_of("/");
621  if(std::string::npos != pos ) {
622  zone_hint_str = zone_hint_str.substr(0,pos);
623  }
624  }
625  if('\'' == zone_hint_str[zone_hint_str.size()-1]) {
626  zone_hint_str = zone_hint_str.substr(0,zone_hint_str.size()-1);
627  }
628 
629  }
630 
632  rsComm,
633  SLAVE_RCAT,
634  zone_hint_str.c_str(),
635  &rodsServerHost );
636 
637  if ( status < 0 ) {
638  return status;
639  }
640 
641  // =-=-=-=-=-=-=-
642  // handle connections with community iRODS
643  if ( !zone_hint_str.empty() ) {
644  irods::error ret = proc_query_terms_for_community_server( zone_hint_str, genQueryInp );
645  if ( !ret.ok() ) {
646  irods::log( PASS( ret ) );
647  }
648  }
649 
650  if ( rodsServerHost->localFlag == LOCAL_HOST ) {
651  std::string svc_role;
652  irods::error ret = get_catalog_service_role(svc_role);
653  if(!ret.ok()) {
654  irods::log(PASS(ret));
655  return ret.code();
656  }
657 
658  if( irods::CFG_SERVICE_ROLE_PROVIDER == svc_role ) {
659  status = _rsGenQuery( rsComm, genQueryInp, genQueryOut );
660  } else if( irods::CFG_SERVICE_ROLE_CONSUMER == svc_role ) {
662  "rsGenQuery error. RCAT is not configured on this host" );
663  return SYS_NO_RCAT_SERVER_ERR;
664  } else {
665  rodsLog(
666  LOG_ERROR,
667  "role not supported [%s]",
668  svc_role.c_str() );
670  }
671  }
672  else {
673  // =-=-=-=-=-=-=-
674  // strip disable strict acl flag if the agent conn flag is missing
675  char* dis_kw = getValByKey( &genQueryInp->condInput, DISABLE_STRICT_ACL_KW );
676  if ( dis_kw ) {
677  try {
678  irods::get_server_property<const std::string>(irods::AGENT_CONN_KW);
679  } catch ( const irods::exception& ) {
680  rmKeyVal( &genQueryInp->condInput, DISABLE_STRICT_ACL_KW );
681 
682  }
683 
684  } // if dis_kw
685 
687  genQueryInp, genQueryOut );
688  }
689  if ( status < 0 && status != CAT_NO_ROWS_FOUND ) {
690  std::string prefix = ( rodsServerHost->localFlag == LOCAL_HOST ) ? "_rs" : "rc";
692  "rsGenQuery: %sGenQuery failed, status = %d", prefix.c_str(), status );
693  }
694  return status;
695 }
696 
697 int
698 _rsGenQuery( rsComm_t *rsComm, genQueryInp_t *genQueryInp,
699  genQueryOut_t **genQueryOut ) {
700  int status;
701  int resc_grp_attr_pos = -1;
702  int resc_hier_attr_pos = -1;
703 
704  static int ruleExecuted = 0;
705  ruleExecInfo_t rei;
706 
707 
708  static int PrePostProcForGenQueryFlag = -2;
709  int i, argc;
710  ruleExecInfo_t rei2;
711  const char *args[MAX_NUM_OF_ARGS_IN_ACTION];
712 
713  // =-=-=-=-=-=-=-
714  // handle queries from older clients
715  std::string client_rel_version = rsComm->cliVersion.relVersion;
716  std::string local_rel_version = RODS_REL_VERSION;
717  if ( client_rel_version != local_rel_version ) { // skip if version strings match
718  irods::error err = strip_resc_grp_name_from_query_inp( genQueryInp, resc_grp_attr_pos );
719  if ( !err.ok() ) {
720  irods::log( PASS( err ) );
721  }
722  }
723 
724  irods::error err = strip_resc_hier_name_from_query_inp( genQueryInp, resc_hier_attr_pos );
725  if ( !err.ok() ) {
726  irods::log( PASS( err ) );
727  }
728 
729  if ( PrePostProcForGenQueryFlag < 0 ) {
730  if ( getenv( "PREPOSTPROCFORGENQUERYFLAG" ) != NULL ) {
731  PrePostProcForGenQueryFlag = 1;
732  }
733  else {
734  PrePostProcForGenQueryFlag = 0;
735  }
736  }
737 
738  memset( ( char* )&rei2, 0, sizeof( ruleExecInfo_t ) );
739  rei2.rsComm = rsComm;
740 
741  /* printGenQI(genQueryInp); for debug */
742 
743  *genQueryOut = ( genQueryOut_t* )malloc( sizeof( genQueryOut_t ) );
744  memset( ( char * )*genQueryOut, 0, sizeof( genQueryOut_t ) );
745 
746  if ( ruleExecuted == 0 ) {
747  memset( ( char* )&rei, 0, sizeof( rei ) );
748  /* Include the user info for possible use by the rule. Note
749  that when this is called (as the agent is initializing),
750  this user info is not confirmed yet. For password
751  authentication though, the agent will soon exit if this
752  is not valid. But for GSI, the user information may not
753  be present and/or may be changed when the authentication
754  completes, so it may not be safe to use this in a GSI
755  enabled environment. This addition of user information
756  was requested by ARCS/IVEC (Sean Fleming) to avoid a
757  local patch.
758  */
759  rei.uoic = &rsComm->clientUser;
760  rei.uoip = &rsComm->proxyUser;
761 
762  status = applyRule( "acAclPolicy", NULL, &rei, NO_SAVE_REI );
763  if ( status == 0 ) {
764 
765  ruleExecuted = 1; /* No need to retry next time since it
766  succeeded. Since this is called at
767  startup, the Rule Engine may not be
768  initialized yet, in which case the
769  default setting is fine and we should
770  retry next time. */
771  }
772  }
773 
774  // =-=-=-=-=-=-=-
775  // verify that we are running a query for another agent connection
776  bool agent_conn_flag = true;
777  try {
778  irods::get_server_property<const std::string>(irods::AGENT_CONN_KW);
779  } catch ( const irods::exception& ) {
780  agent_conn_flag = false;
781  }
782 
783  // =-=-=-=-=-=-=-
784  // detect if a request for disable of strict acls is made
785  int acl_val = -1;
786  char* dis_kw = getValByKey( &genQueryInp->condInput, DISABLE_STRICT_ACL_KW );
787  if ( agent_conn_flag && dis_kw ) {
788  acl_val = 0;
789  }
790 
791  // =-=-=-=-=-=-=-
792  // cache the old acl value for reuse later if necessary
793  int old_acl_val = chlGenQueryAccessControlSetup(
794  rsComm->clientUser.userName,
795  rsComm->clientUser.rodsZone,
796  rsComm->clientAddr,
797  rsComm->clientUser.authInfo.authFlag,
798  acl_val );
799 
800  if ( PrePostProcForGenQueryFlag == 1 ) {
801  std::string arg = str( boost::format( "%ld" ) % ( ( long )genQueryInp ) );
802  args[0] = arg.c_str();
803  argc = 1;
804  i = applyRuleArg( "acPreProcForGenQuery", args, argc, &rei2, NO_SAVE_REI );
805  if ( i < 0 ) {
807  "rsGenQuery:acPreProcForGenQuery error,stat=%d", i );
808  if ( i != NO_MICROSERVICE_FOUND_ERR ) {
809  return i;
810  }
811  }
812  }
815  status = chlGenQuery( *genQueryInp, *genQueryOut );
816 
817  // =-=-=-=-=-=-=-
818  // if a disable was requested, repave with old value immediately
819  if ( agent_conn_flag && dis_kw ) {
821  rsComm->clientUser.userName,
822  rsComm->clientUser.rodsZone,
823  rsComm->clientAddr,
824  rsComm->clientUser.authInfo.authFlag,
825  old_acl_val );
826  }
827 
829  if ( PrePostProcForGenQueryFlag == 1 ) {
830  std::string in_string = str( boost::format( "%ld" ) % ( ( long )genQueryInp ) );
831  std::string out_string = str( boost::format( "%ld" ) % ( ( long )genQueryOut ) );
832  std::string status_string = str( boost::format( "%d" ) % ( ( long )status ) );
833  args[0] = in_string.c_str();
834  args[1] = out_string.c_str();
835  args[2] = status_string.c_str();
836  argc = 3;
837  i = applyRuleArg( "acPostProcForGenQuery", args, argc, &rei2, NO_SAVE_REI );
838  if ( i < 0 ) {
840  "rsGenQuery:acPostProcForGenQuery error,stat=%d", i );
841  if ( i != NO_MICROSERVICE_FOUND_ERR ) {
842  return i;
843  }
844  }
845  }
848  // =-=-=-=-=-=-=-
849  // handle queries from older clients
850  if ( status >= 0 && resc_grp_attr_pos >= 0 ) {
851  irods::error err = add_resc_grp_name_to_query_out( *genQueryOut, resc_grp_attr_pos );
852  if ( !err.ok() ) {
853  irods::log( PASS( err ) );
854  }
855  }
856 
857  if ( status >= 0 && resc_hier_attr_pos >= 0 ) {
858  // restore COL_D_RESC_HIER in select index
859  genQueryInp->selectInp.inx[resc_hier_attr_pos] = COL_D_RESC_HIER;
860 
861  // replace resc ids with resc hier strings in output
862  irods::error err = add_resc_hier_name_to_query_out( *genQueryOut, resc_hier_attr_pos );
863  if ( !err.ok() ) {
864  irods::log( PASS( err ) );
865  }
866  }
867 
868  if ( status < 0 ) {
869  if ( status != CAT_NO_ROWS_FOUND ) {
871  "_rsGenQuery: genQuery status = %d", status );
872  }
873  return status;
874  }
875  return status;
876 }
rodsLog
void rodsLog(int level, const char *formatStr,...)
Definition: rodsLog.cpp:86
getValByKey
char * getValByKey(const keyValPair_t *condInput, const char *keyWord)
Definition: rcMisc.cpp:675
NULL
#define NULL
Definition: rodsDef.h:70
zoneInfo::masterServerHost
rodsServerHost_t * masterServerHost
Definition: rodsConnect.h:77
COL_R_RESC_CHILDREN
#define COL_R_RESC_CHILDREN
Definition: rodsGenQuery.h:157
rsComm_t
Definition: rcConnect.h:145
irods::CFG_SERVICE_ROLE_CONSUMER
const std::string CFG_SERVICE_ROLE_CONSUMER("consumer")
SYS_INTERNAL_NULL_INPUT_ERR
@ SYS_INTERNAL_NULL_INPUT_ERR
Definition: rodsErrorTable.h:92
rodsServerHost::localFlag
int localFlag
Definition: rodsConnect.h:68
irods.pyparsing.columnName
def columnName
Definition: pyparsing.py:3815
GenQueryInp::continueInx
int continueInx
Definition: rodsGenQuery.h:28
SYS_SERVICE_ROLE_NOT_SUPPORTED
@ SYS_SERVICE_ROLE_NOT_SUPPORTED
Definition: rodsErrorTable.h:217
NO_MICROSERVICE_FOUND_ERR
@ NO_MICROSERVICE_FOUND_ERR
Definition: rodsErrorTable.h:676
SELECT_COUNT
#define SELECT_COUNT
Definition: rodsGenQuery.h:106
irods_server_properties.hpp
COL_R_RESC_CONTEXT
#define COL_R_RESC_CONTEXT
Definition: rodsGenQuery.h:158
COL_D_RESC_HIER
#define COL_D_RESC_HIER
Definition: rodsGenQuery.h:184
rodsServerHost::conn
rcComm_t * conn
Definition: rodsConnect.h:64
SqlResult::attriInx
int attriInx
Definition: rodsGenQuery.h:62
userInfo_t::userName
char userName[64]
Definition: rodsUser.h:66
rodsGenQueryNames.h
PASS
#define PASS(prev_error_)
Definition: irods_error.hpp:118
resc_mgr
irods::resource_manager resc_mgr
Definition: irods_resource_manager.cpp:31
irods::AGENT_CONN_KW
const std::string AGENT_CONN_KW("agent_conn")
NO_SAVE_REI
#define NO_SAVE_REI
Definition: rodsDef.h:103
rsGenQuery
int rsGenQuery(rsComm_t *rsComm, genQueryInp_t *genQueryInp, genQueryOut_t **genQueryOut)
Definition: rsGenQuery.cpp:604
chlGenQueryAccessControlSetup
int chlGenQueryAccessControlSetup(const char *user, const char *zone, const char *host, int priv, int controlFlag)
Definition: icatHighLevelRoutines.cpp:4511
genquery_inp_to_iquest_string
std::string genquery_inp_to_iquest_string(const genQueryInp_t *q)
Definition: rsGenQuery.cpp:140
get_resc_id_cond_for_hier_cond
static irods::error get_resc_id_cond_for_hier_cond(const char *_cond, std::string &_new_cond)
Definition: rsGenQuery.cpp:301
GenQueryInp
Definition: rodsGenQuery.h:24
SELECT_MAX
#define SELECT_MAX
Definition: rodsGenQuery.h:103
AUTO_CLOSE
#define AUTO_CLOSE
Definition: rodsGenQuery.h:89
rcMisc.h
SELECT_AVG
#define SELECT_AVG
Definition: rodsGenQuery.h:105
LOCAL_HOST
#define LOCAL_HOST
Definition: rodsConnect.h:44
zoneInfo::zoneName
char zoneName[64]
Definition: rodsConnect.h:75
InxIvalPair::len
int len
Definition: objInfo.h:206
irods::GenQueryInpWrapper::get
genQueryInp_t & get(void)
Definition: rsGenQuery.cpp:179
manual_cleanup.zone_name
zone_name
Definition: manual_cleanup.py:16
InxValPair::inx
int * inx
Definition: objInfo.h:215
irods::GenQueryOutPtrWrapper::~GenQueryOutPtrWrapper
~GenQueryOutPtrWrapper(void)
Definition: rsGenQuery.cpp:185
token
Definition: restructs.hpp:293
addInxVal
int addInxVal(inxValPair_t *inxValPair, int inx, const char *value)
Definition: rcMisc.cpp:921
LOG_ERROR
#define LOG_ERROR
Definition: rodsLog.h:43
irods::GenQueryInpWrapper::~GenQueryInpWrapper
~GenQueryInpWrapper(void)
Definition: rsGenQuery.cpp:176
ZoneInfoHead
zoneInfo_t * ZoneInfoHead
Definition: irods_server_globals.cpp:23
SYS_INVALID_INPUT_PARAM
@ SYS_INVALID_INPUT_PARAM
Definition: rodsErrorTable.h:195
UPPER_CASE_WHERE
#define UPPER_CASE_WHERE
Definition: rodsGenQuery.h:90
SELECT_MIN
#define SELECT_MIN
Definition: rodsGenQuery.h:102
irods::GenQueryInpWrapper::genquery_inp_
genQueryInp_t genquery_inp_
Definition: rsGenQuery.hpp:10
GenQueryInp::selectInp
inxIvalPair_t selectInp
Definition: rodsGenQuery.h:53
GenQueryInp::maxRows
int maxRows
Definition: rodsGenQuery.h:25
GenQueryOut::sqlResult
sqlResult_t sqlResult[50]
Definition: rodsGenQuery.h:72
InxValPair::value
char ** value
Definition: objInfo.h:216
SYS_INTERNAL_ERR
@ SYS_INTERNAL_ERR
Definition: rodsErrorTable.h:211
SUCCESS
#define SUCCESS()
Definition: irods_error.hpp:121
rsGlobalExtern.hpp
getZoneHintForGenQuery
char * getZoneHintForGenQuery(genQueryInp_t *genQueryInp)
Definition: miscUtil.cpp:1835
irods::error::code
long long code() const
Definition: irods_error.cpp:194
SYS_INVALID_ZONE_NAME
@ SYS_INVALID_ZONE_NAME
Definition: rodsErrorTable.h:94
_rsGenQuery
int _rsGenQuery(rsComm_t *rsComm, genQueryInp_t *genQueryInp, genQueryOut_t **genQueryOut)
Definition: rsGenQuery.cpp:698
strip_new_query_terms
static irods::error strip_new_query_terms(genQueryInp_t *_inp)
Definition: rsGenQuery.cpp:194
COL_D_RESC_NAME
#define COL_D_RESC_NAME
Definition: rodsGenQuery.h:171
rsComm_t::proxyUser
userInfo_t proxyUser
Definition: rcConnect.h:152
GenQueryInp::condInput
keyValPair_t condInput
Definition: rodsGenQuery.h:52
rcGenQuery
int rcGenQuery(rcComm_t *conn, genQueryInp_t *genQueryInp, genQueryOut_t **genQueryOut)
Definition: rcGenQuery.cpp:89
irods::GenQueryOutPtrWrapper::GenQueryOutPtrWrapper
GenQueryOutPtrWrapper(void)
Definition: rsGenQuery.cpp:182
irods::CFG_SERVICE_ROLE_PROVIDER
const std::string CFG_SERVICE_ROLE_PROVIDER("provider")
InxIvalPair::inx
int * inx
Definition: objInfo.h:207
applyRuleArg
int applyRuleArg(const char *action, const char *args[20], int argc, ruleExecInfo_t *rei, int reiSaveFlag)
Definition: irods_re_structs.cpp:95
GenQueryInp::sqlCondInp
inxValPair_t sqlCondInp
Definition: rodsGenQuery.h:56
genQuery.h
SYS_RESC_DOES_NOT_EXIST
@ SYS_RESC_DOES_NOT_EXIST
Definition: rodsErrorTable.h:145
terminate_irods_processes.e
e
Definition: terminate_irods_processes.py:19
irods::resource_manager::get_all_resc_hierarchies
std::vector< std::string > get_all_resc_hierarchies(void)
Definition: irods_resource_manager.cpp:1056
MAX_NUM_OF_ARGS_IN_ACTION
#define MAX_NUM_OF_ARGS_IN_ACTION
Definition: irods_re_structs.hpp:13
zoneInfo::next
struct zoneInfo * next
Definition: rodsConnect.h:79
addInxIval
int addInxIval(inxIvalPair_t *inxIvalPair, int inx, int value)
Definition: rcMisc.cpp:883
SYS_NO_RCAT_SERVER_ERR
@ SYS_NO_RCAT_SERVER_ERR
Definition: rodsErrorTable.h:110
MAX_SQL_ATTR
#define MAX_SQL_ATTR
Definition: rodsGenQuery.h:15
rmKeyVal
int rmKeyVal(keyValPair_t *condInput, const char *keyWord)
Definition: rcMisc.cpp:710
GenQueryInp::rowOffset
int rowOffset
Definition: rodsGenQuery.h:32
GenQueryOut
Definition: rodsGenQuery.h:67
version_t::cookie
int cookie
Definition: rodsDef.h:292
irods.pypyodbc.status
status
Definition: pypyodbc.py:467
userInfo_t::rodsZone
char rodsZone[64]
Definition: rodsUser.h:67
zoneHint
char zoneHint[(1024+64)]
Definition: lsUtil.cpp:13
GenQueryOut::rowCnt
int rowCnt
Definition: rodsGenQuery.h:68
irods::log
void log(const error &)
Definition: irods_log.cpp:13
LOG_NOTICE
#define LOG_NOTICE
Definition: rodsLog.h:33
rsComm_t::clientUser
userInfo_t clientUser
Definition: rcConnect.h:153
ERROR
#define ERROR(code_, message_)
Definition: irods_error.hpp:117
COL_R_RESC_PARENT_CONTEXT
#define COL_R_RESC_PARENT_CONTEXT
Definition: rodsGenQuery.h:160
InxIvalPair::value
int * value
Definition: objInfo.h:208
irods::error
Definition: irods_error.hpp:23
InxValPair::len
int len
Definition: objInfo.h:214
miscServerFunct.hpp
irods::GenQueryInpWrapper::GenQueryInpWrapper
GenQueryInpWrapper(void)
Definition: rsGenQuery.cpp:173
add_resc_grp_name_to_query_out
static irods::error add_resc_grp_name_to_query_out(genQueryOut_t *_out, int &_pos)
Definition: rsGenQuery.cpp:273
irods_lexical_cast.hpp
irods::resource_manager::leaf_id_to_hier
error leaf_id_to_hier(const rodsLong_t &, std::string &)
Definition: irods_resource_manager.cpp:1119
getAndConnRcatHost
int getAndConnRcatHost(rsComm_t *rsComm, int rcatType, const char *rcatZoneHint, rodsServerHost_t **rodsServerHost)
Definition: rodsConnect.cpp:26
irods::GenQueryOutPtrWrapper::get
genQueryOut_t *& get(void)
Definition: rsGenQuery.cpp:188
SqlResult::value
char * value
Definition: rodsGenQuery.h:64
version_t::relVersion
char relVersion[64]
Definition: rodsDef.h:288
irods::resource_manager::hier_to_leaf_id
error hier_to_leaf_id(const std::string &, rodsLong_t &)
Definition: irods_resource_manager.cpp:1082
genquery_inp_to_diagnostic_string
std::string genquery_inp_to_diagnostic_string(const genQueryInp_t *q)
Definition: rsGenQuery.cpp:133
RETURN_TOTAL_ROW_COUNT
#define RETURN_TOTAL_ROW_COUNT
Definition: rodsGenQuery.h:86
get_catalog_service_role
irods::error get_catalog_service_role(std::string &_role)
Definition: miscServerFunct.cpp:3153
columnNames
columnName_t columnNames[]
Definition: rodsGenQueryNames.h:18
rodsServerHost
Definition: rodsConnect.h:62
CAT_NO_ROWS_FOUND
@ CAT_NO_ROWS_FOUND
Definition: rodsErrorTable.h:423
SqlResult
Definition: rodsGenQuery.h:61
ORDER_BY_DESC
#define ORDER_BY_DESC
Definition: rodsGenQuery.h:82
error
int error
Definition: filesystem.cpp:101
strip_resc_grp_name_from_query_inp
static irods::error strip_resc_grp_name_from_query_inp(genQueryInp_t *_inp, int &_pos)
Definition: rsGenQuery.cpp:230
RuleExecInfo
Definition: irods_re_structs.hpp:18
strip_resc_hier_name_from_query_inp
static irods::error strip_resc_hier_name_from_query_inp(genQueryInp_t *_inp, int &_pos)
Definition: rsGenQuery.cpp:372
irods_resource_manager.hpp
clearInxVal
int clearInxVal(inxValPair_t *inxValPair)
Definition: rcMisc.cpp:1082
rcComm_t::svrVersion
version_t * svrVersion
Definition: rcConnect.h:105
InxIvalPair
Definition: objInfo.h:205
applyRule
int applyRule(char *inAction, msParamArray_t *inMsParamArray, ruleExecInfo_t *rei, int reiSaveFlag)
Definition: irods_re_structs.cpp:65
irods::exception
Definition: irods_exception.hpp:15
SqlResult::len
int len
Definition: rodsGenQuery.h:63
QUOTA_QUERY
#define QUOTA_QUERY
Definition: rodsGenQuery.h:88
COL_R_RESC_PARENT
#define COL_R_RESC_PARENT
Definition: rodsGenQuery.h:159
icatHighLevelRoutines.hpp
ORDER_BY
#define ORDER_BY
Definition: rodsGenQuery.h:81
SLAVE_RCAT
#define SLAVE_RCAT
Definition: rodsDef.h:86
SELECT_SUM
#define SELECT_SUM
Definition: rodsGenQuery.h:104
add_resc_hier_name_to_query_out
static irods::error add_resc_hier_name_to_query_out(genQueryOut_t *_out, int &_pos)
Definition: rsGenQuery.cpp:447
chlGenQuery
int chlGenQuery(genQueryInp_t genQueryInp, genQueryOut_t *result)
Definition: icatHighLevelRoutines.cpp:4462
NO_DISTINCT
#define NO_DISTINCT
Definition: rodsGenQuery.h:87
size
long long size
Definition: filesystem.cpp:102
rsGenQuery.hpp
userInfo_t::authInfo
authInfo_t authInfo
Definition: rodsUser.h:70
miscUtil.h
rsComm_t::clientAddr
char clientAddr[64]
Definition: rcConnect.h:151
rsComm_t::cliVersion
version_t cliVersion
Definition: rcConnect.h:155
zoneInfo
Definition: rodsConnect.h:74
freeGenQueryOut
int freeGenQueryOut(genQueryOut_t **genQueryOut)
Definition: rcMisc.cpp:1133
authInfo_t::authFlag
int authFlag
Definition: rodsUser.h:42
CODE
#define CODE(code_)
Definition: irods_error.hpp:120
irods::error::ok
bool ok()
Definition: irods_error.cpp:258
DISABLE_STRICT_ACL_KW
#define DISABLE_STRICT_ACL_KW
Definition: rodsKeyWdDef.h:285
proc_query_terms_for_community_server
static irods::error proc_query_terms_for_community_server(const std::string &_zone_hint, genQueryInp_t *_inp)
Definition: rsGenQuery.cpp:516
clearGenQueryInp
void clearGenQueryInp(void *voidInp)
Definition: rcMisc.cpp:1118
InxValPair
Definition: objInfo.h:213
GenQueryInp::options
int options
Definition: rodsGenQuery.h:34
rodsLong_t
long long rodsLong_t
Definition: rodsType.h:32
COL_D_RESC_ID
#define COL_D_RESC_ID
Definition: rodsGenQuery.h:185