From f6587fef025d4ec472aa88aa31af2c1fe8cbc70a Mon Sep 17 00:00:00 2001 From: scottmk Date: Mon, 11 May 2009 18:05:52 +0000 Subject: [PATCH] Correct the way that cstore determines whether a class in the SELECT clause is referenced by the FROM clause. Instead of calling jsonObjectFindPath(), which is an imprecise blunt instrument, traverse the join tree recursively, using specific knowledge of how join trees are built to look in all right places, and only in the right places. git-svn-id: svn://svn.open-ils.org/ILS/trunk@13128 dcc99617-32d9-48b4-a31d-7c20da2025e4 --- Open-ILS/src/c-apps/oils_cstore.c | 67 ++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 29 deletions(-) diff --git a/Open-ILS/src/c-apps/oils_cstore.c b/Open-ILS/src/c-apps/oils_cstore.c index c7491fbd3b..4a895bc06f 100644 --- a/Open-ILS/src/c-apps/oils_cstore.c +++ b/Open-ILS/src/c-apps/oils_cstore.c @@ -2666,6 +2666,40 @@ static char* searchWHERE ( const jsonObject* search_hash, osrfHash* meta, int op return buffer_release(sql_buf); } +// Return 1 if the class is in the FROM clause, or 0 if not +static int is_joined( jsonObject* from_clause, const char* class ) { + + if( ! from_clause ) + return 0; + else if( from_clause->type == JSON_STRING ) { + if( strcmp( class, jsonObjectGetString( from_clause ) ) ) + return 0; + else + return 1; + } else if( from_clause->type != JSON_HASH ) { + return 0; + } else { // Look at any subjoins + jsonIterator* class_itr = jsonNewIterator( from_clause ); + jsonObject* curr_class; + int rc = 0; // return code + while ( ( curr_class = jsonIteratorNext( class_itr ) ) ) { + if( ! strcmp( class_itr->key, class ) ) { + rc = 1; + break; + } else { + jsonObject* subjoin = jsonObjectGetKey( curr_class, "join" ); + if( subjoin && is_joined( subjoin, class ) ) { + rc = 1; + break; + } + } + } + jsonIteratorFree( class_itr ); + + return rc; + } +} + char* SELECT ( /* method context */ osrfMethodContext* ctx, @@ -2921,7 +2955,7 @@ char* SELECT ( return NULL; } - // Make sure the target relation is in the join tree. + // Make sure the target relation is in the FROM clause. // At this point join_hash is a step down from the join_hash we // received as a parameter. If the original was a JSON_STRING, @@ -2932,34 +2966,9 @@ char* SELECT ( // that case from_function would be non-NULL, and we wouldn't // be here. - int class_in_from_clause; // boolean - - if ( ! strcmp( core_class, cname )) - // This is the core class -- no problem - class_in_from_clause = 1; - else { - if (!join_hash) - // There's only one class in the FROM clause, and this isn't it - class_in_from_clause = 0; - else if (join_hash->type == JSON_STRING) { - // There's only one class in the FROM clause - const char* str = jsonObjectGetString(join_hash); - if ( strcmp( str, cname ) ) - class_in_from_clause = 0; // This isn't it - else - class_in_from_clause = 1; // This is it - } else { - jsonObject* found = jsonObjectFindPath(join_hash, "//%s", cname); - if ( 0 == found->size ) - class_in_from_clause = 0; // Nowhere in the join tree - else - class_in_from_clause = 1; // Found it - jsonObjectFree( found ); - } - } - - // If the class isn't in the FROM clause, bail out - if( ! class_in_from_clause ) { + // If the current class isn't the core class + // and it isn't in the join tree, bail out + if ( strcmp( core_class, cname ) && ! is_joined( join_hash, cname ) ) { osrfLogError( OSRF_LOG_MARK, "%s: SELECT clause references class not in FROM clause: \"%s\"", -- 2.11.0