diff --git a/lib/core/include/irods/irods_query.hpp b/lib/core/include/irods/irods_query.hpp index c9c2f6cc04..79224f88c7 100644 --- a/lib/core/include/irods/irods_query.hpp +++ b/lib/core/include/irods/irods_query.hpp @@ -20,8 +20,6 @@ #include #include -char *getCondFromString( char * t ); - namespace irods { template @@ -167,9 +165,7 @@ namespace irods addKeyVal(&gen_input_.condInput, ZONE_KW, _zone_hint.c_str()); } - const int fill_err = fillGenQueryInpFromStrCond( - const_cast(_query_string.c_str()), - &gen_input_); + const int fill_err = parse_genquery1_string(_query_string.c_str(), &gen_input_); if(fill_err < 0) { THROW(fill_err, fmt::format("query fill failed for [{}]", _query_string)); } diff --git a/lib/core/include/irods/rcMisc.h b/lib/core/include/irods/rcMisc.h index 43dcbaa47b..dc7678cd2c 100644 --- a/lib/core/include/irods/rcMisc.h +++ b/lib/core/include/irods/rcMisc.h @@ -279,8 +279,6 @@ int getNextRepeatTime(char* currTime, char* delayStr, char* nextTime); int printError(rcComm_t* Conn, int status, char* routineName); -int fillGenQueryInpFromStrCond(char* str, genQueryInp_t* genQueryInp); - int parse_genquery1_string(const char* _s, genQueryInp_t* _out); int printGenQueryOut(FILE* fd, char* format, char* hint, genQueryOut_t* genQueryOut); @@ -293,8 +291,6 @@ int getAttrIdFromAttrName(char* cname); int showAttrNames(); -int separateSelFuncFromAttr(char* t, char** aggOp, char** colNm); - int getSelVal(char* c); int parseCachedStructFileStr(char* collInfo2, specColl_t* specColl); diff --git a/lib/core/src/rcMisc.cpp b/lib/core/src/rcMisc.cpp index acd4d86385..633ef1bdd4 100644 --- a/lib/core/src/rcMisc.cpp +++ b/lib/core/src/rcMisc.cpp @@ -3060,8 +3060,6 @@ setStateForRestart( rodsRestart_t * rodsRestart, rodsPath_t * targPath, return 0; } - - int getAttrIdFromAttrName( char * cname ) { @@ -3083,26 +3081,6 @@ showAttrNames() { return 0; } -int -separateSelFuncFromAttr( char * t, char **aggOp, char **colNm ) { - char *s; - - if ( ( s = strchr( t, '(' ) ) == NULL ) { - *colNm = t; - *aggOp = NULL; - return 0; - } - *aggOp = t; - *s = '\0'; - s++; - *colNm = s; - if ( ( s = strchr( *colNm, ')' ) ) == NULL ) { - return NO_COLUMN_NAME_FOUND; - } - *s = '\0'; - return 0; -} - int getSelVal( char * c ) { if ( c == NULL ) { @@ -3136,7 +3114,6 @@ getSelVal( char * c ) { return 1; } - char * getAttrNameFromAttrId( int cid ) { @@ -3149,168 +3126,6 @@ getAttrNameFromAttrId( int cid ) { return NULL; } -int -goodStrExpr( char * expr ) { - int qcnt = 0; - int qqcnt = 0; - int bcnt = 0; - int i = 0; - int inq = 0; - int inqq = 0; - while ( expr[i] != '\0' ) { - if ( inq ) { - if ( expr[i] == '\'' ) { - inq--; - qcnt++; - } - } - else if ( inqq ) { - if ( expr[i] == '"' ) { - inqq--; - qqcnt++; - } - } - else if ( expr[i] == '\'' ) { - inq++; - qcnt++; - } - else if ( expr[i] == '"' ) { - inqq++; - qqcnt++; - } - else if ( expr[i] == '(' ) { - bcnt++; - } - else if ( expr[i] == ')' ) - if ( bcnt > 0 ) { - bcnt--; - } - i++; - } - if ( bcnt != 0 || qcnt % 2 != 0 || qqcnt % 2 != 0 ) { - return -1; - } - return 0; - -} - - -char *getCondFromString( char * t ) { - char *u; - char *u1, *u2; - char *s; - - s = t; - for ( ;; ) { - /* Search for an 'and' string, either case, and use the one - that appears first. */ - u1 = strstr( s, " and " ); - u2 = strstr( s, " AND " ); - u = u1; - if ( u1 == NULL ) { - u = u2; - } - if ( u1 != NULL && u2 != NULL ) { - if ( strlen( u2 ) > strlen( u1 ) ) { - u = u2; /* both are present, use the first */ - } - } - - if ( u != NULL ) { - *u = '\0'; - if ( goodStrExpr( t ) == 0 ) { - *u = ' '; - return u; - } - *u = ' '; - s = u + 1; - } - else { - break; - } - } - return NULL; -} - -int fillGenQueryInpFromStrCond( char * str, genQueryInp_t * genQueryInp ) -{ - int n, m; - char *p, *t, *f, *u, *a, *c; - char *s; - s = strdup( str ); - if ( ( t = strstr( s, "select" ) ) != NULL || - ( t = strstr( s, "SELECT" ) ) != NULL ) { - - if ( ( f = strstr( t, "where" ) ) != NULL || - ( f = strstr( t, "WHERE" ) ) != NULL ) { - /* Where Condition Found*/ - *f = '\0'; - } - t = t + 7; - while ( ( u = strchr( t, ',' ) ) != NULL ) { - *u = '\0'; - trimWS( t ); - separateSelFuncFromAttr( t, &a, &c ); - m = getSelVal( a ); - n = getAttrIdFromAttrName( c ); - if ( n < 0 ) { - free( s ); - return n; - } - addInxIval( &genQueryInp->selectInp, n, m ); - t = u + 1; - } - trimWS( t ); - separateSelFuncFromAttr( t, &a, &c ); - m = getSelVal( a ); - n = getAttrIdFromAttrName( c ); - if ( n < 0 ) { - free( s ); - return n; - } - addInxIval( &genQueryInp->selectInp, n, m ); - if ( f == NULL ) { - free( s ); - return 0; - } - } - else { - free( s ); - return INPUT_ARG_NOT_WELL_FORMED_ERR; - } - t = f + 6; - while ( ( u = getCondFromString( t ) ) != NULL ) { - *u = '\0'; - trimWS( t ); - if ( ( p = strchr( t, ' ' ) ) == NULL ) { - free( s ); - return INPUT_ARG_NOT_WELL_FORMED_ERR; - } - *p = '\0'; - n = getAttrIdFromAttrName( t ); - if ( n < 0 ) { - free( s ); - return n; - } - addInxVal( &genQueryInp->sqlCondInp, n, p + 1 ); - t = u + 5; - } - trimWS( t ); - if ( ( p = strchr( t, ' ' ) ) == NULL ) { - free( s ); - return INPUT_ARG_NOT_WELL_FORMED_ERR; - } - *p = '\0'; - n = getAttrIdFromAttrName( t ); - if ( n < 0 ) { - free( s ); - return n; - } - addInxVal( &genQueryInp->sqlCondInp, n, p + 1 ); - free( s ); - return 0; -} // fillGenQueryInpFromStrCond - int parse_genquery1_string(const char* _s, genQueryInp_t* _out) { try { diff --git a/server/re/src/genQueryMS.cpp b/server/re/src/genQueryMS.cpp index 9c0a2e08d6..0304a58473 100644 --- a/server/re/src/genQueryMS.cpp +++ b/server/re/src/genQueryMS.cpp @@ -52,7 +52,7 @@ int msiExecStrCondQuery( msParam_t* queryParam, msParam_t* genQueryOutParam, rul strcpy( query, ( const char* )queryParam->inOutStruct ); memset( &genQueryInp, 0, sizeof( genQueryInp_t ) ); - i = fillGenQueryInpFromStrCond( query, &genQueryInp ); + i = parse_genquery1_string( query, &genQueryInp ); free( query ); if ( i < 0 ) { return i; @@ -533,9 +533,9 @@ msiMakeGenQuery( msParam_t* selectListStr, msParam_t* condStr, msParam_t* genQue /* set up GenQueryInp */ genQueryInp->maxRows = MAX_SQL_ROWS; genQueryInp->continueInx = 0; - rei->status = fillGenQueryInpFromStrCond( query, genQueryInp ); + rei->status = parse_genquery1_string( query, genQueryInp ); if ( rei->status < 0 ) { - rodsLog( LOG_ERROR, "msiMakeGenQuery: fillGenQueryInpFromStrCond failed." ); + rodsLog( LOG_ERROR, "msiMakeGenQuery: parse_genquery1_string failed." ); freeGenQueryInp( &genQueryInp ); free( rawQuery ); // cppcheck - Memory leak: rawQuery free( query ); diff --git a/unit_tests/src/test_genquery1_flex_bison_parser.cpp b/unit_tests/src/test_genquery1_flex_bison_parser.cpp index 7e6f420e47..dc3265099a 100644 --- a/unit_tests/src/test_genquery1_flex_bison_parser.cpp +++ b/unit_tests/src/test_genquery1_flex_bison_parser.cpp @@ -8,11 +8,22 @@ #include #include +#include #include #include #include // For std::getline #include +// The original GenQuery1 string-based parser. +// This function is maintained as part of this unit test for backward compatibility reasons. +auto fillGenQueryInpFromStrCond(char* str, genQueryInp_t* genQueryInp) -> int; + +// The following functions are only used by the original GenQuery1 parser. +// Therefore, they have been pulled out of the public iRODS interface to keep users from using them. +auto getCondFromString(char* t) -> char*; +auto goodStrExpr(char* expr) -> int; +auto separateSelFuncFromAttr(char* t, char** aggOp, char** colNm) -> int; + // NOLINTNEXTLINE(readability-function-cognitive-complexity) TEST_CASE("GenQuery1 flex bison parser maintains backward compatibility with original GenQuery1 parser") { @@ -82,3 +93,184 @@ TEST_CASE("GenQuery1 flex bison parser maintains backward compatibility with ori } } } + +auto fillGenQueryInpFromStrCond(char* str, genQueryInp_t* genQueryInp) -> int +{ + int n, m; + char *p, *t, *f, *u, *a, *c; + char *s; + s = strdup( str ); + if ( ( t = strstr( s, "select" ) ) != NULL || + ( t = strstr( s, "SELECT" ) ) != NULL ) { + + if ( ( f = strstr( t, "where" ) ) != NULL || + ( f = strstr( t, "WHERE" ) ) != NULL ) { + /* Where Condition Found*/ + *f = '\0'; + } + t = t + 7; + while ( ( u = strchr( t, ',' ) ) != NULL ) { + *u = '\0'; + trimWS( t ); + separateSelFuncFromAttr( t, &a, &c ); + m = getSelVal( a ); + n = getAttrIdFromAttrName( c ); + if ( n < 0 ) { + free( s ); + return n; + } + addInxIval( &genQueryInp->selectInp, n, m ); + t = u + 1; + } + trimWS( t ); + separateSelFuncFromAttr( t, &a, &c ); + m = getSelVal( a ); + n = getAttrIdFromAttrName( c ); + if ( n < 0 ) { + free( s ); + return n; + } + addInxIval( &genQueryInp->selectInp, n, m ); + if ( f == NULL ) { + free( s ); + return 0; + } + } + else { + free( s ); + return INPUT_ARG_NOT_WELL_FORMED_ERR; + } + t = f + 6; + while ( ( u = getCondFromString( t ) ) != NULL ) { + *u = '\0'; + trimWS( t ); + if ( ( p = strchr( t, ' ' ) ) == NULL ) { + free( s ); + return INPUT_ARG_NOT_WELL_FORMED_ERR; + } + *p = '\0'; + n = getAttrIdFromAttrName( t ); + if ( n < 0 ) { + free( s ); + return n; + } + addInxVal( &genQueryInp->sqlCondInp, n, p + 1 ); + t = u + 5; + } + trimWS( t ); + if ( ( p = strchr( t, ' ' ) ) == NULL ) { + free( s ); + return INPUT_ARG_NOT_WELL_FORMED_ERR; + } + *p = '\0'; + n = getAttrIdFromAttrName( t ); + if ( n < 0 ) { + free( s ); + return n; + } + addInxVal( &genQueryInp->sqlCondInp, n, p + 1 ); + free( s ); + return 0; +} // fillGenQueryInpFromStrCond + +auto getCondFromString(char* t) -> char* +{ + char *u; + char *u1, *u2; + char *s; + + s = t; + for ( ;; ) { + /* Search for an 'and' string, either case, and use the one + that appears first. */ + u1 = strstr( s, " and " ); + u2 = strstr( s, " AND " ); + u = u1; + if ( u1 == NULL ) { + u = u2; + } + if ( u1 != NULL && u2 != NULL ) { + if ( strlen( u2 ) > strlen( u1 ) ) { + u = u2; /* both are present, use the first */ + } + } + + if ( u != NULL ) { + *u = '\0'; + if ( goodStrExpr( t ) == 0 ) { + *u = ' '; + return u; + } + *u = ' '; + s = u + 1; + } + else { + break; + } + } + return NULL; +} // getCondFromString + +auto goodStrExpr(char* expr) -> int +{ + int qcnt = 0; + int qqcnt = 0; + int bcnt = 0; + int i = 0; + int inq = 0; + int inqq = 0; + while ( expr[i] != '\0' ) { + if ( inq ) { + if ( expr[i] == '\'' ) { + inq--; + qcnt++; + } + } + else if ( inqq ) { + if ( expr[i] == '"' ) { + inqq--; + qqcnt++; + } + } + else if ( expr[i] == '\'' ) { + inq++; + qcnt++; + } + else if ( expr[i] == '"' ) { + inqq++; + qqcnt++; + } + else if ( expr[i] == '(' ) { + bcnt++; + } + else if ( expr[i] == ')' ) + if ( bcnt > 0 ) { + bcnt--; + } + i++; + } + if ( bcnt != 0 || qcnt % 2 != 0 || qqcnt % 2 != 0 ) { + return -1; + } + return 0; +} // goodStrExpr + +auto separateSelFuncFromAttr(char* t, char** aggOp, char** colNm) -> int +{ + char *s; + + if ( ( s = strchr( t, '(' ) ) == NULL ) { + *colNm = t; + *aggOp = NULL; + return 0; + } + *aggOp = t; + *s = '\0'; + s++; + *colNm = s; + if ( ( s = strchr( *colNm, ')' ) ) == NULL ) { + return NO_COLUMN_NAME_FOUND; + } + *s = '\0'; + return 0; +}