From 59cbe4babb543ec3a2e950e50a203b0a65bd75c2 Mon Sep 17 00:00:00 2001 From: Robert Butora <robert.butora@inaf.it> Date: Fri, 17 Jan 2025 16:49:16 +0100 Subject: [PATCH] vlkb-obscore: simplifies syntax of the groups-argument (converts to sql internally) --- .../vlkb-obscore/src/database/database.cpp | 21 +- .../engine/src/vlkb-obscore/src/main.cpp | 284 +++++++++++------- 2 files changed, 185 insertions(+), 120 deletions(-) diff --git a/data-access/engine/src/vlkb-obscore/src/database/database.cpp b/data-access/engine/src/vlkb-obscore/src/database/database.cpp index de5370e..eef2785 100644 --- a/data-access/engine/src/vlkb-obscore/src/database/database.cpp +++ b/data-access/engine/src/vlkb-obscore/src/database/database.cpp @@ -360,11 +360,14 @@ void database::dbModifyGroups(int sid, const string groups, LOG_trace(__func__); DbConn db(db_uri, db_schema); + Survey surv = db.querySurveyAttributes(sid); - vector<string> cmdModGroups{ - "UPDATE obscore SET groups = '{" + groups + "}' WHERE (policy = 'PRIV') AND (obs_publisher_did IN (SELECT CONCAT('" + (obscore_publisher + "?") + "',pubdid) FROM headers WHERE survey_id =" + to_string(sid) + "))"}; + vector<string> cmdModGroups + { + "UPDATE obscore SET groups = ARRAY["+ groups +"]::TEXT[] WHERE (policy = 'PRIV') AND (obs_collection = '"+ surv.getObsCollection() +"') AND (obs_title = '"+ surv.getObsTitle() +"')" + }; - db.dbExecCmds(cmdModGroups); + db.dbExecCmds(cmdModGroups); } @@ -372,17 +375,17 @@ void database::dbModifyGroups(int sid, const string groups, // FIXME hid identifies rows to remove in tables -> no good, should be pubdid as identificator void database::dbRemoveSurvey(int sid, const string db_uri, const string db_schema) { - LOG_trace(__func__); + LOG_trace(__func__); - DbConn db(db_uri, db_schema); + DbConn db(db_uri, db_schema); - Survey surv = db.querySurveyAttributes(sid); + Survey surv = db.querySurveyAttributes(sid); - SqlSchema_DELETE cmdDelete; + SqlSchema_DELETE cmdDelete; - vector<string> deleteRowsAllTables = {cmdDelete.getCommand(sid, surv)}; + vector<string> deleteRowsAllTables = {cmdDelete.getCommand(sid, surv)}; - db.dbExecCmds(deleteRowsAllTables); + db.dbExecCmds(deleteRowsAllTables); } diff --git a/data-access/engine/src/vlkb-obscore/src/main.cpp b/data-access/engine/src/vlkb-obscore/src/main.cpp index 23e8b0c..9e59e05 100644 --- a/data-access/engine/src/vlkb-obscore/src/main.cpp +++ b/data-access/engine/src/vlkb-obscore/src/main.cpp @@ -303,77 +303,139 @@ int cmd_dbAdd(int argc, char * argv[]) return rc; } +// convert argv[] bash arg to sql-TEXT[] string - -int cmd_dbModGroups(int argc, char * argv[]) +// segment fault if str is empty or contains _only_ delimiter(s): "," ",," ",,,,,,,," +std::vector<std::string> split_by_delimiter(std::string_view str, std::string_view delimiter) { - // FIXME groups should be cmd arg and mandatory of policy PRIVATE and empy null if policu PUBLIC - // e.g. exit with error if dbAddSurvey gets sid of PRIVATE but no groups arg supplied - string groups; - int sid_from, sid_to; - int rc; - switch(argc) - { - case 3: - groups = std::string(argv[1]); - sid_from = std::stoi(argv[2]); - sid_to = sid_from; - break; + if (delimiter.empty()) return {std::string(str)}; + // handle empty delimiters explicitly so we can't fall into an infinite loop - case 4: - groups = std::string(argv[1]); - sid_from = std::stoi(argv[2]); - sid_to = std::stoi(argv[3]); - break; - - default: - cout << "Usage: dbmodgroups <groups> <SID-from> [SID-to]" << endl - << "modifies list of groups which can access PRIVATE surveys" << endl; - rc = vlkb::EXIT_WITH_USAGE; - } + std::vector<std::string> tokens; + std::size_t cursor = 0; + std::size_t segment_start = cursor; - try + while ((cursor = str.find(delimiter, cursor)) != std::string_view::npos) { - for(int i=sid_from; i<=sid_to; i++) - database::dbModifyGroups(i, groups, - vlkb::conf.getObsCorePublisher(), vlkb::conf.getDbUri(WITH_PASSWORD), vlkb::conf.getDbSchema()); - rc = 0; + if (segment_start != cursor) tokens.emplace_back(str.substr(segment_start, cursor - segment_start)); + // don't emplace empty tokens in case of leading/trailing/repeated delimiters + cursor += delimiter.size(); + segment_start = cursor; } - catch(exception& e) - { - rc = vlkb::EXIT_WITH_ERROR; - ERROR_STREAM << e.what() << endl; + + if (segment_start != str.size()) tokens.emplace_back(str.substr(segment_start)); + // 'cursor' is now at 'npos', so we compare to the size instead + + return tokens; +} + +inline std::string join_strings(std::vector<std::string> arr, std::string sep, std::string wrap) +{ + std::string out = wrap + arr[0] + wrap; + for(unsigned int i = 1; i < arr.size(); i++) { + out += sep + wrap + arr[i] + wrap; } + return out; +} - return rc; +const string EMPTY_STRING; +string to_sql_text_vec(string arg) +{ + if(!arg.empty()) + { + vector<string> arg_split = split_by_delimiter(arg, string{','} ); + if(!arg_split.empty()) + { + //for (const auto& elem: arg_split) cout << elem << ' '; + //cout << '<' << endl; + + string sql_text_arr{join_strings(arg_split,",","'")}; + OUT_STREAM << "SQL ARRAY[" << sql_text_arr << "]"<< endl; + return sql_text_arr; + } + } + OUT_STREAM << "Cleared all groups for the given datasets." << endl; + return EMPTY_STRING; +} + +int cmd_dbModGroups(int argc, char * argv[]) +{ + string groups; + int sid_from, sid_to; + int rc; + switch(argc) + { + case 3: + groups = std::string(argv[1]); + sid_from = std::stoi(argv[2]); + sid_to = sid_from; + break; + + case 4: + groups = std::string(argv[1]); + sid_from = std::stoi(argv[2]); + sid_to = std::stoi(argv[3]); + break; + + default: + cout << endl + << "Modifies list of groups which are allowed to access proprietary datasets given by SID." << endl + << "SID (survey-id) is in the metadata file in the root of FITS-file store (typically /srv/datasets/<metadata>.csv)." + << "Empty groups (\"\") arg clears the groups list in the database." << endl + << "Usage:" << endl + << " dbmodgroups <groups> <SID-from> [SID-to]" << endl + << endl + << "Examples (groups are comma separated):" << endl + << " vlkb-obscore datasets.conf dbmodgroups \"Group A,Group B\" 3 6" << endl + << " vlkb-obscore datasets.conf dbmodgroups \"\" 3 6" << endl; + rc = vlkb::EXIT_WITH_USAGE; + return rc; + } + + try + { + string sql_groups_vec{to_sql_text_vec(groups)}; + + for(int i=sid_from; i<=sid_to; i++) + database::dbModifyGroups(i, sql_groups_vec, + vlkb::conf.getObsCorePublisher(), vlkb::conf.getDbUri(WITH_PASSWORD), vlkb::conf.getDbSchema()); + rc = 0; + } + catch(exception& e) + { + rc = vlkb::EXIT_WITH_ERROR; + ERROR_STREAM << e.what() << endl; + } + + return rc; } int cmd_dbRemove(int argc, char * argv[]) { - int rc; - switch(argc) - { - case 2: - try - { - database::dbRemoveSurvey(stoi(argv[1]), vlkb::conf.getDbUri(WITH_PASSWORD), vlkb::conf.getDbSchema()); - rc = 0; - } - catch(exception& e) - { - rc = vlkb::EXIT_WITH_ERROR; - ERROR_STREAM << e.what() << endl; - } - break; - - default: - cout << "Usage: dbremove <SID>" << endl - << "removes survey metadata from database" << endl; - rc = vlkb::EXIT_WITH_USAGE; - } - return rc; + int rc; + switch(argc) + { + case 2: + try + { + database::dbRemoveSurvey(stoi(argv[1]), vlkb::conf.getDbUri(WITH_PASSWORD), vlkb::conf.getDbSchema()); + rc = 0; + } + catch(exception& e) + { + rc = vlkb::EXIT_WITH_ERROR; + ERROR_STREAM << e.what() << endl; + } + break; + + default: + cout << "Usage: dbremove <SID>" << endl + << "removes survey metadata from database" << endl; + rc = vlkb::EXIT_WITH_USAGE; + } + return rc; } @@ -383,59 +445,59 @@ int cmd_dbRemove(int argc, char * argv[]) //----------------------------------------------------------- int main (int argc, char * argv[]) { - const std::string progname = base_name(argv[0]); - - if( argc < 3 ) - { - vlkb::usage(progname); - return vlkb::EXIT_WITH_USAGE; - } - - const string conf_filename(argv[1]); - - // recognize command from string - const vlkb::cmd_set cmd(vlkb::to_cmd(argv[2])); - - // sub-command arguments (skips: vlkb <conf-filename>) - int cmd_argc = argc - 2; - char ** cmd_argv = &(argv[2]); - - vlkb::conf.read_config(conf_filename); -/* - cout << "LOG DIR: " << vlkb::conf.getLogDir() << endl; - cout << "FITSDIR: " << vlkb::conf.getFitsDir() << endl; - cout << "DB[" << vlkb::conf.getDbSchema() << "]: " <<vlkb::conf.getDbUri() << endl; - cout << endl; -*/ - LOG_open(vlkb::conf.getLogDir(), vlkb::conf.getLogFileName()); - int rc; - - try - { - switch(cmd) - { - case vlkb::dbinit: rc = cmd_dbInit(cmd_argc,cmd_argv); break; - case vlkb::dbcheck: rc = cmd_dbCheck(); break; - case vlkb::dblist: rc = cmd_dbList(); break; - case vlkb::dbbounds: rc = cmd_dbBounds(cmd_argc,cmd_argv); break; - case vlkb::dbfiles: rc = cmd_dbFiles(cmd_argc,cmd_argv); break; - case vlkb::dbaddsurvey: rc = cmd_dbAdd(cmd_argc,cmd_argv); break; - case vlkb::dbmodgroups: rc = cmd_dbModGroups(cmd_argc,cmd_argv); break; - case vlkb::dbremovesurvey: rc = cmd_dbRemove(cmd_argc,cmd_argv); break; - - default: assert(false); - } - } - catch(const invalid_argument& ex) - { - cout << ex.what() << endl; - } - catch(const exception& ex) - { - cerr << ex.what() << endl; - } - - LOG_close(); - return rc; + const std::string progname = base_name(argv[0]); + + if( argc < 3 ) + { + vlkb::usage(progname); + return vlkb::EXIT_WITH_USAGE; + } + + const string conf_filename(argv[1]); + + // recognize command from string + const vlkb::cmd_set cmd(vlkb::to_cmd(argv[2])); + + // sub-command arguments (skips: vlkb <conf-filename>) + int cmd_argc = argc - 2; + char ** cmd_argv = &(argv[2]); + + vlkb::conf.read_config(conf_filename); + /* + cout << "LOG DIR: " << vlkb::conf.getLogDir() << endl; + cout << "FITSDIR: " << vlkb::conf.getFitsDir() << endl; + cout << "DB[" << vlkb::conf.getDbSchema() << "]: " <<vlkb::conf.getDbUri() << endl; + cout << endl; + */ + LOG_open(vlkb::conf.getLogDir(), vlkb::conf.getLogFileName()); + int rc; + + try + { + switch(cmd) + { + case vlkb::dbinit: rc = cmd_dbInit(cmd_argc,cmd_argv); break; + case vlkb::dbcheck: rc = cmd_dbCheck(); break; + case vlkb::dblist: rc = cmd_dbList(); break; + case vlkb::dbbounds: rc = cmd_dbBounds(cmd_argc,cmd_argv); break; + case vlkb::dbfiles: rc = cmd_dbFiles(cmd_argc,cmd_argv); break; + case vlkb::dbaddsurvey: rc = cmd_dbAdd(cmd_argc,cmd_argv); break; + case vlkb::dbmodgroups: rc = cmd_dbModGroups(cmd_argc,cmd_argv); break; + case vlkb::dbremovesurvey: rc = cmd_dbRemove(cmd_argc,cmd_argv); break; + + default: assert(false); + } + } + catch(const invalid_argument& ex) + { + cout << ex.what() << endl; + } + catch(const exception& ex) + { + cerr << ex.what() << endl; + } + + LOG_close(); + return rc; } -- GitLab