Skip to content

Commit

Permalink
squash. code review
Browse files Browse the repository at this point in the history
  • Loading branch information
korydraughn committed Mar 28, 2024
1 parent 846c383 commit b210f5b
Show file tree
Hide file tree
Showing 15 changed files with 260 additions and 67 deletions.
7 changes: 4 additions & 3 deletions .github/workflows/build-irods-centos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@ jobs:
yum -y install gcc g++ libstdc++-static make rpm-build bzip2-devel curl-devel fakeroot openssl-devel pam-devel python-devel unixODBC unixODBC-devel zlib-devel python36-distro
- name: Install Flex and Bison
run: |
yum -y install centos-release-scl-rh
#yum -y install centos-release-scl-rh
rpm --import https://www.cert.org/forensics/repository/forensics-expires-2022-04-03.asc
wget https://forensics.cert.org/cert-forensics-tools-release-el7.rpm
rpm -i ./cert-forensics-tools-release-el7.rpm
#wget https://forensics.cert.org/cert-forensics-tools-release-el7.rpm
#rpm -i ./cert-forensics-tools-release-el7.rpm
yum -y install https://forensics.cert.org/cert-forensics-tools-release-el7.rpm
yum -y install flex bison
- name: Install iRODS Externals
run: |
Expand Down
81 changes: 77 additions & 4 deletions lib/api/include/irods/genquery2.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,30 @@ struct RcComm;

/// The input data type used to invoke #rc_genquery2.
///
/// \note This data structure is part of an experimental API endpoint and may change in the future.
///
/// \since 4.3.2
typedef struct GenQuery2Input // NOLINT(modernize-use-using)
{
/// TODO
/// The GenQuery2 query string to execute.
///
/// This member variable MUST be non-empty.
///
/// \since 4.3.2
char* query_string;

/// TODO
/// The zone to execute the query string against.
///
/// This member variable is allowed to be set to NULL.
///
/// \since 4.3.2
char* zone;

/// TODO
/// Controls whether the SQL derived from the query string is
/// executed or returned to the caller.
///
/// When set to 0, the generated SQL will be executed.
/// When set to 1, the generated SQL will be returned to the caller. The SQL will not be executed.
///
/// \since 4.3.2
int sql_only;
Expand All @@ -33,7 +43,70 @@ typedef struct GenQuery2Input // NOLINT(modernize-use-using)
extern "C" {
#endif

/// TODO
/// Query the catalog using the GenQuery2 parser.
///
/// \note This is an experimental API endpoint and may change in the future.
///
/// The GenQuery2 parser supports the following:
/// - Enforces the iRODS permission model
/// - Logical AND, OR, and NOT
/// - Grouping via parentheses
/// - SQL CAST
/// - SQL GROUP BY
/// - SQL aggregate functions (e.g. count, sum, avg, etc)
/// - Per-column sorting via ORDER BY [ASC|DESC]
/// - SQL FETCH FIRST <i>N</i> ROWS ONLY (LIMIT offered as an alias)
/// - Metadata queries involving different iRODS entities (i.e. data objects, collections, users, and resources)
/// - Operators: =, !=, <, <=, >, >=, LIKE, BETWEEN, IS [NOT] NULL
/// - SQL keywords are case-insensitive
/// - Federation
/// - Escaping of single quotes
/// - Bytes encoded as hexadecimal (e.g. \x21)
///
/// Limitations:
/// - Groups are not yet fully supported
/// - Cannot resolve tickets to data objects and collections using a single query
/// - Integer values must be treated as strings, except when used for OFFSET, LIMIT, FETCH FIRST <i>N</i> ROWS ONLY
///
/// \param[in] _comm A pointer to a RcComm.
/// \param[in] _input A pointer to a GenQuery2Input.
/// \param[in,out] _output \parblock A pointer that will hold the results of the operation.
/// On success, the pointer will either hold a JSON string or a string representing the SQL derived from
/// the GenQuery2 query string. See GenQuery2Input::sql_only for details.
///
/// The string is always heap-allocated and must be free'd by the caller using free().
///
/// On failure, the pointer will be NULL.
/// \endparblock
///
/// \return An integer.
/// \retval 0 On success.
/// \retval <0 On failure.
///
/// \b Example
/// \code{.cpp}
/// RcComm* comm = // Our iRODS connection.
///
/// // Configure the input object for the API call.
/// struct GenQuery2Input input;
/// memset(&input, 0, sizeof(struct GenQuery2Input));
///
/// // This is the query that will be executed (i.e. input.sql_only is set to 0).
/// input.query_string = strdup("select COLL_NAME, DATA_NAME where RESC_ID = '10016'");
///
/// char* output = NULL;
/// const int ec = rc_genquery2(comm, &input, &output);
///
/// // Handle error.
/// if (ec < 0) {
/// free(input.query_string);
/// return;
/// }
///
/// // At this point, "output" should represent a JSON string.
/// // Parse the string as JSON and inspect the results.
/// // If "input.sql_only" was set to 1, "output" would hold the SQL derived from the GenQuery2 syntax.
/// \endcode
///
/// \since 4.3.2
int rc_genquery2(struct RcComm* _comm, struct GenQuery2Input* _input, char** _output);
Expand Down
1 change: 1 addition & 0 deletions lib/core/include/irods/irods_configuration_keywords.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ namespace irods
extern const char* const KW_CFG_LOG_LEVEL_CATEGORY_AGENT_FACTORY;
extern const char* const KW_CFG_LOG_LEVEL_CATEGORY_AGENT;
extern const char* const KW_CFG_LOG_LEVEL_CATEGORY_DELAY_SERVER;
extern const char* const KW_CFG_LOG_LEVEL_CATEGORY_GENQUERY2;
extern const char* const KW_CFG_LOG_LEVEL_CATEGORY_RESOURCE;
extern const char* const KW_CFG_LOG_LEVEL_CATEGORY_DATABASE;
extern const char* const KW_CFG_LOG_LEVEL_CATEGORY_AUTHENTICATION;
Expand Down
11 changes: 11 additions & 0 deletions lib/core/include/irods/irods_logger.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ namespace irods::experimental::log
struct agent_factory {};
struct agent {};
struct delay_server {};
struct genquery2 {};
struct resource {};
struct database {};
struct authentication {};
Expand Down Expand Up @@ -141,6 +142,7 @@ namespace irods::experimental::log
using agent_factory = logger<category::agent_factory>;
using agent = logger<category::agent>;
using delay_server = logger<category::delay_server>;
using genquery2 = logger<category::genquery2>;
using resource = logger<category::resource>;
using database = logger<category::database>;
using authentication = logger<category::authentication>;
Expand Down Expand Up @@ -834,6 +836,15 @@ namespace irods::experimental::log
friend class logger<category::delay_server>;
}; // class logger_config<category::delay_server>

template <>
class logger_config<category::genquery2>
{
static constexpr const char* const name = "genquery2";
inline static level level = level::info; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)

friend class logger<category::genquery2>;
}; // class logger_config<category::genquery2>

template <>
class logger_config<category::resource>
{
Expand Down
1 change: 1 addition & 0 deletions lib/core/src/irods_configuration_keywords.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ namespace irods
const char* const KW_CFG_LOG_LEVEL_CATEGORY_AGENT_FACTORY{"agent_factory"};
const char* const KW_CFG_LOG_LEVEL_CATEGORY_AGENT{"agent"};
const char* const KW_CFG_LOG_LEVEL_CATEGORY_DELAY_SERVER{"delay_server"};
const char* const KW_CFG_LOG_LEVEL_CATEGORY_GENQUERY2{"genquery2"};
const char* const KW_CFG_LOG_LEVEL_CATEGORY_RESOURCE{"resource"};
const char* const KW_CFG_LOG_LEVEL_CATEGORY_DATABASE{"database"};
const char* const KW_CFG_LOG_LEVEL_CATEGORY_AUTHENTICATION{"authentication"};
Expand Down
1 change: 1 addition & 0 deletions scripts/core_tests_list.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
"test_ipwd",
"test_iqmod",
"test_iqstat",
"test_iquery",
"test_iquest.Test_Iquest",
"test_iquest.test_iquest_logical_or_operator_with_data_resc_hier",
"test_iquest.test_iquest_with_data_resc_hier",
Expand Down
3 changes: 0 additions & 3 deletions scripts/irods/test/test_genquery2_microservices.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import os
import sys
import textwrap
import unittest

from . import session
from .. import lib
from ..configuration import IrodsConfig

rodsadmins = [('otherrods', 'rods')]
Expand Down
24 changes: 24 additions & 0 deletions scripts/irods/test/test_iquery.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import json
import unittest

from . import session
from .. import lib

rodsadmins = [('otherrods', 'rods')]
rodsusers = [('alice', 'apass')]

class Test_IQuery(session.make_sessions_mixin(rodsadmins, rodsusers), unittest.TestCase):

def setUp(self):
super(Test_IQuery, self).setUp()

self.admin = self.admin_sessions[0]
self.user = self.user_sessions[0]

def tearDown(self):
super(Test_IQuery, self).tearDown()

def test_iquery_can_run_a_query__issue_7570(self):
json_string = json.dumps([[self.user.session_collection]])
self.user.assert_icommand(
['iquery', f"select COLL_NAME where COLL_NAME = '{self.user.session_collection}'"], 'STDOUT', [json_string])
65 changes: 64 additions & 1 deletion server/api/include/irods/rs_genquery2.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,70 @@

struct RsComm;

/// TODO
/// Query the catalog using the GenQuery2 parser.
///
/// \note This is an experimental API endpoint and may change in the future.
///
/// The GenQuery2 parser supports the following:
/// - Enforces the iRODS permission model
/// - Logical AND, OR, and NOT
/// - Grouping via parentheses
/// - SQL CAST
/// - SQL GROUP BY
/// - SQL aggregate functions (e.g. count, sum, avg, etc)
/// - Per-column sorting via ORDER BY [ASC|DESC]
/// - SQL FETCH FIRST <i>N</i> ROWS ONLY (LIMIT offered as an alias)
/// - Metadata queries involving different iRODS entities (i.e. data objects, collections, users, and resources)
/// - Operators: =, !=, <, <=, >, >=, LIKE, BETWEEN, IS [NOT] NULL
/// - SQL keywords are case-insensitive
/// - Federation
/// - Escaping of single quotes
/// - Bytes encoded as hexadecimal (e.g. \x21)
///
/// Limitations:
/// - Groups are not yet fully supported
/// - Cannot resolve tickets to data objects and collections using a single query
/// - Integer values must be treated as strings, except when used for OFFSET, LIMIT, FETCH FIRST <i>N</i> ROWS ONLY
///
/// \param[in] _comm A pointer to a RsComm.
/// \param[in] _input A pointer to a GenQuery2Input.
/// \param[in,out] _output \parblock A pointer that will hold the results of the operation.
/// On success, the pointer will either hold a JSON string or a string representing the SQL derived from
/// the GenQuery2 query string. See GenQuery2Input::sql_only for details.
///
/// The string is always heap-allocated and must be free'd by the caller using free().
///
/// On failure, the pointer will be NULL.
/// \endparblock
///
/// \return An integer.
/// \retval 0 On success.
/// \retval <0 On failure.
///
/// \b Example
/// \code{.cpp}
/// RsComm* comm = // Our iRODS connection.
///
/// // Configure the input object for the API call.
/// struct GenQuery2Input input;
/// memset(&input, 0, sizeof(struct GenQuery2Input));
///
/// // This is the query that will be executed (i.e. input.sql_only is set to 0).
/// input.query_string = strdup("select COLL_NAME, DATA_NAME where RESC_ID = '10016'");
///
/// char* output = NULL;
/// const int ec = rc_genquery2(comm, &input, &output);
///
/// // Handle error.
/// if (ec < 0) {
/// free(input.query_string);
/// return;
/// }
///
/// // At this point, "output" should represent a JSON string.
/// // Parse the string as JSON and inspect the results.
/// // If "input.sql_only" was set to 1, "output" would hold the SQL derived from the GenQuery2 syntax.
/// \endcode
///
/// \since 4.3.2
int rs_genquery2(RsComm* _comm, GenQuery2Input* _input, char** _output);
Expand Down
7 changes: 2 additions & 5 deletions server/api/src/rs_genquery2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,17 @@
#include "irods/genquery2_sql.hpp"

#include "irods/apiHandler.hpp"
//#include "irods/catalog.hpp" // Requires linking against libnanodbc.so
#include "irods/irods_logger.hpp"
#include "irods/irods_rs_comm_query.hpp"
#include "irods/irods_server_properties.hpp"
#include "irods/irods_version.h"
//#include "irods/procApiRequest.h"
#include "irods/rodsConnect.h"
#include "irods/rodsDef.h"
#include "irods/rodsErrorTable.h"
#include "irods/icatHighLevelRoutines.hpp"

//#include <fmt/format.h>
//#include <nanodbc/nanodbc.h>
#include <nlohmann/json.hpp>

//#include <cstdlib> // For std::malloc.
#include <cstring> // For strdup.
#include <string_view>
#include <vector>
Expand Down Expand Up @@ -52,6 +47,8 @@ auto rs_genquery2(RsComm* _comm, GenQuery2Input* _input, char** _output) -> int
log_api::trace("{}: Received: query_string=[{}], zone=[nullptr]", __func__, _input->query_string);
}

*_output = nullptr;

rodsServerHost* host_info{};

if (const auto ec = getAndConnRcatHost(_comm, PRIMARY_RCAT, _input->zone, &host_info); ec < 0) {
Expand Down
1 change: 0 additions & 1 deletion server/core/src/irods_api_calling_functions.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#include "irods/genquery2.h"
#include "irods/rcConnect.h"
#include "irods/apiHeaderAll.h"
#include "irods/apiHandler.hpp"
Expand Down
1 change: 1 addition & 0 deletions server/core/src/rodsAgent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,7 @@ void set_log_levels_for_all_log_categories()
log_ns::agent::set_level(log_ns::get_level_from_config(irods::KW_CFG_LOG_LEVEL_CATEGORY_AGENT));
log_ns::legacy::set_level(log_ns::get_level_from_config(irods::KW_CFG_LOG_LEVEL_CATEGORY_LEGACY));
log_ns::resource::set_level(log_ns::get_level_from_config(irods::KW_CFG_LOG_LEVEL_CATEGORY_RESOURCE));
log_ns::genquery2::set_level(log_ns::get_level_from_config(irods::KW_CFG_LOG_LEVEL_CATEGORY_GENQUERY2));
log_ns::database::set_level(log_ns::get_level_from_config(irods::KW_CFG_LOG_LEVEL_CATEGORY_DATABASE));
log_ns::authentication::set_level(log_ns::get_level_from_config(irods::KW_CFG_LOG_LEVEL_CATEGORY_AUTHENTICATION));
log_ns::api::set_level(log_ns::get_level_from_config(irods::KW_CFG_LOG_LEVEL_CATEGORY_API));
Expand Down
Loading

0 comments on commit b210f5b

Please sign in to comment.