From bf0ee57ba3ddbcc79285b75d81ceb12ed514c42b Mon Sep 17 00:00:00 2001 From: Lebbeous Fogle-Weekley Date: Wed, 26 Oct 2011 14:04:54 -0400 Subject: [PATCH] Trying to affect rs_size indirectly, but: things put into an osrfHash with osrfHashSet aren't immediately available with osrfHashGetFmt !?!? Signed-off-by: Lebbeous Fogle-Weekley --- Open-ILS/src/c-apps/oils_sql.c | 426 ++++++++++++++++++++++------------------- 1 file changed, 227 insertions(+), 199 deletions(-) diff --git a/Open-ILS/src/c-apps/oils_sql.c b/Open-ILS/src/c-apps/oils_sql.c index b002e61022..af3ba0a19e 100644 --- a/Open-ILS/src/c-apps/oils_sql.c +++ b/Open-ILS/src/c-apps/oils_sql.c @@ -119,7 +119,7 @@ static ClassInfo* add_joined_class( const char* alias, const char* classname ); static void clear_query_stack( void ); static const jsonObject* verifyUserPCRUD( osrfMethodContext* ); -static int verifyObjectPCRUD( osrfMethodContext*, osrfHash*, const jsonObject*, const int ); +static int verifyObjectPCRUD( osrfMethodContext*, osrfHash*, const jsonObject*, int ); static const char* org_tree_root( osrfMethodContext* ctx ); static jsonObject* single_hash( const char* key, const char* value ); @@ -1422,7 +1422,7 @@ static const jsonObject* verifyUserPCRUD( osrfMethodContext* ctx ) { The @a obj parameter points to a JSON_HASH of column values, keyed on column name. */ -static int verifyObjectPCRUD ( osrfMethodContext* ctx, osrfHash *class, const jsonObject* obj, const int rs_size ) { +static int verifyObjectPCRUD ( osrfMethodContext* ctx, osrfHash *class, const jsonObject* obj, int rs_size ) { dbhandle = writehandle; @@ -1430,6 +1430,14 @@ static int verifyObjectPCRUD ( osrfMethodContext* ctx, osrfHash *class, const js osrfHash* method_metadata = (osrfHash*) ctx->method->userData; const char* method_type = osrfHashGet( method_metadata, "methodtype" ); + if (!rs_size) { + int *rs_size_from_hash = osrfHashGetFmt( (osrfHash *) ctx->session->userData, "req_%d_rs_size", ctx->request ); + if (rs_size_from_hash) { + rs_size = *rs_size_from_hash; + osrfLogDebug(OSRF_LOG_MARK, "used rs_size from request-scoped hash: %d", rs_size); + } + } + // Set fetch to 1 in all cases except for inserts, meaning that for local or foreign // contexts we will do another lookup of the current row, even if we already have a // previously fetched row image, because the row image in hand may not include the @@ -1558,11 +1566,11 @@ static int verifyObjectPCRUD ( osrfMethodContext* ctx, osrfHash *class, const js if( fetch ) { // Fetch the row so that we can look at the foreign key(s) - osrfHashSet((osrfHash*) ctx->method->userData, "1", "inside_verify"); + osrfHashSet((osrfHash*) ctx->session->userData, "1", "inside_verify"); jsonObject* _tmp_params = single_hash( pkey, pkey_value ); jsonObject* _list = doFieldmapperSearch( ctx, class, _tmp_params, NULL, &err ); jsonObjectFree( _tmp_params ); - osrfHashSet((osrfHash*) ctx->method->userData, "0", "inside_verify"); + osrfHashSet((osrfHash*) ctx->session->userData, "0", "inside_verify"); param = jsonObjectExtractIndex( _list, 0 ); jsonObjectFree( _list ); @@ -1653,10 +1661,10 @@ static int verifyObjectPCRUD ( osrfMethodContext* ctx, osrfHash *class, const js // Look up the row to which the foreign key points jsonObject* _tmp_params = single_hash( foreign_pkey, foreign_pkey_value ); - osrfHashSet((osrfHash*) ctx->method->userData, "1", "inside_verify"); + osrfHashSet((osrfHash*) ctx->session->userData, "1", "inside_verify"); jsonObject* _list = doFieldmapperSearch( ctx, osrfHashGet( oilsIDL(), class_name ), _tmp_params, NULL, &err ); - osrfHashSet((osrfHash*) ctx->method->userData, "0", "inside_verify"); + osrfHashSet((osrfHash*) ctx->session->userData, "0", "inside_verify"); jsonObject* _fparam = NULL; if( _list && JSON_ARRAY == _list->type && _list->size > 0 ) @@ -5541,13 +5549,14 @@ static jsonObject* doFieldmapperSearch( osrfMethodContext* ctx, osrfHash* class_ char* pkey = osrfHashGet( class_meta, "primarykey" ); - char *inside_verify = osrfHashGet( (osrfHash*) ctx->method->userData, "inside_verify" ); + char *inside_verify = osrfHashGet( (osrfHash*) ctx->session->userData, "inside_verify" ); int need_to_verify = 1; if (inside_verify) need_to_verify = !atoi(inside_verify); - const jsonObject* _tmp; + int want_flesh = 0; // we don't know yet + int flesh_depth = 0; // XXX This can be redundant with another instance of the same test that happens // within the functions that call doFieldmapperSearch(), but we have it here to @@ -5598,6 +5607,33 @@ static jsonObject* doFieldmapperSearch( osrfMethodContext* ctx, osrfHash* class_ jsonObject* res_list = jsonNewObjectType( JSON_ARRAY ); jsonObject* row_obj = NULL; + // The following two steps are for verifyObjectPCRUD()'s benefit. + // 1. get the flesh depth + const jsonObject* _tmp = jsonObjectGetKeyConst( query_hash, "flesh" ); + if( _tmp ) { + want_flesh = 1; + flesh_depth = (int) jsonObjectGetNumber( _tmp ); + if( flesh_depth == -1 || flesh_depth > max_flesh_depth ) + flesh_depth = max_flesh_depth; + } + + // 2. figure out one consistent rs_size for verifyObjectPCRUD to use + // over the whole life of this request. This means if we've already set + // up a req_%d_rs_size, do nothing. + int *rs_size = osrfHashGetFmt( (osrfHash *) ctx->session->userData, "req_%d_rs_size", ctx->request ); + if (!rs_size) { // pointer null, so value not set in hash + rs_size = (int *) safe_malloc( sizeof(int) ); + unsigned long long result_count = dbi_result_get_numrows( result ); + *rs_size = (int) result_count * (flesh_depth + 1); // yes, we could lose some bits, but come on + osrfLogDebug( OSRF_LOG_MARK, "about to set rs_size to %d", *rs_size ); + osrfHashSet( (osrfHash *) ctx->session->userData, rs_size, "req_%d_rs_size", ctx->request ); + int *rs_size_test = osrfHashGetFmt( (osrfHash *) ctx->session->userData, "req_%d_rs_size", ctx->request ); + if (rs_size_test) + osrfLogDebug( OSRF_LOG_MARK, "immediately after set, get says rs_size is %d", *rs_size_test ); + else + osrfLogDebug( OSRF_LOG_MARK, "immediately after set, get says rs_size is NULL!" ); + } + if( dbi_result_first_row( result )) { // Convert each row to a JSON_ARRAY of column values, and enclose those objects @@ -5613,7 +5649,7 @@ static jsonObject* doFieldmapperSearch( osrfMethodContext* ctx, osrfHash* class_ free( pkey_val ); } else { if( !enforce_pcrud || !need_to_verify || - verifyObjectPCRUD( ctx, class_meta, row_obj, 1 /* not at all sure about this 1 */ )) { + verifyObjectPCRUD( ctx, class_meta, row_obj, 0 /* means check user data for rs_size */ )) { osrfHashSet( dedup, pkey_val, pkey_val ); jsonObjectPush( res_list, row_obj ); } @@ -5633,243 +5669,235 @@ static jsonObject* doFieldmapperSearch( osrfMethodContext* ctx, osrfHash* class_ // If we're asked to flesh, and there's anything to flesh, then flesh it // (formerly we would skip fleshing if in pcrud mode, but now we support // fleshing even in PCRUD). - if( res_list->size && query_hash ) { - _tmp = jsonObjectGetKeyConst( query_hash, "flesh" ); - if( _tmp ) { - // Get the flesh depth - int flesh_depth = (int) jsonObjectGetNumber( _tmp ); - if( flesh_depth == -1 || flesh_depth > max_flesh_depth ) - flesh_depth = max_flesh_depth; - - // We need a non-zero flesh depth, and a list of fields to flesh - const jsonObject* temp_blob = jsonObjectGetKeyConst( query_hash, "flesh_fields" ); - if( temp_blob && flesh_depth > 0 ) { - - jsonObject* flesh_blob = jsonObjectClone( temp_blob ); - const jsonObject* flesh_fields = jsonObjectGetKeyConst( flesh_blob, core_class ); - - osrfStringArray* link_fields = NULL; - osrfHash* links = osrfHashGet( class_meta, "links" ); - - // Make an osrfStringArray of the names of fields to be fleshed - if( flesh_fields ) { - if( flesh_fields->size == 1 ) { - const char* _t = jsonObjectGetString( - jsonObjectGetIndex( flesh_fields, 0 ) ); - if( !strcmp( _t, "*" )) - link_fields = osrfHashKeys( links ); - } + if( res_list->size && query_hash && want_flesh ) { + // We need a non-zero flesh depth, and a list of fields to flesh + const jsonObject* temp_blob = jsonObjectGetKeyConst( query_hash, "flesh_fields" ); + if( temp_blob && flesh_depth > 0 ) { + + jsonObject* flesh_blob = jsonObjectClone( temp_blob ); + const jsonObject* flesh_fields = jsonObjectGetKeyConst( flesh_blob, core_class ); + + osrfStringArray* link_fields = NULL; + osrfHash* links = osrfHashGet( class_meta, "links" ); + + // Make an osrfStringArray of the names of fields to be fleshed + if( flesh_fields ) { + if( flesh_fields->size == 1 ) { + const char* _t = jsonObjectGetString( + jsonObjectGetIndex( flesh_fields, 0 ) ); + if( !strcmp( _t, "*" )) + link_fields = osrfHashKeys( links ); + } - if( !link_fields ) { - jsonObject* _f; - link_fields = osrfNewStringArray( 1 ); - jsonIterator* _i = jsonNewIterator( flesh_fields ); - while ((_f = jsonIteratorNext( _i ))) { - osrfStringArrayAdd( link_fields, jsonObjectGetString( _f ) ); - } - jsonIteratorFree( _i ); + if( !link_fields ) { + jsonObject* _f; + link_fields = osrfNewStringArray( 1 ); + jsonIterator* _i = jsonNewIterator( flesh_fields ); + while ((_f = jsonIteratorNext( _i ))) { + osrfStringArrayAdd( link_fields, jsonObjectGetString( _f ) ); } + jsonIteratorFree( _i ); } + } - osrfHash* fields = osrfHashGet( class_meta, "fields" ); - - // Iterate over the JSON_ARRAY of rows - jsonObject* cur; - unsigned long res_idx = 0; - while((cur = jsonObjectGetIndex( res_list, res_idx++ ) )) { + osrfHash* fields = osrfHashGet( class_meta, "fields" ); - int i = 0; - const char* link_field; + // Iterate over the JSON_ARRAY of rows + jsonObject* cur; + unsigned long res_idx = 0; + while((cur = jsonObjectGetIndex( res_list, res_idx++ ) )) { - // Iterate over the list of fleshable fields - while( (link_field = osrfStringArrayGetString(link_fields, i++)) ) { + int i = 0; + const char* link_field; - osrfLogDebug( OSRF_LOG_MARK, "Starting to flesh %s", link_field ); + // Iterate over the list of fleshable fields + while( (link_field = osrfStringArrayGetString(link_fields, i++)) ) { - osrfHash* kid_link = osrfHashGet( links, link_field ); - if( !kid_link ) - continue; // Not a link field; skip it + osrfLogDebug( OSRF_LOG_MARK, "Starting to flesh %s", link_field ); - osrfHash* field = osrfHashGet( fields, link_field ); - if( !field ) - continue; // Not a field at all; skip it (IDL is ill-formed) + osrfHash* kid_link = osrfHashGet( links, link_field ); + if( !kid_link ) + continue; // Not a link field; skip it - osrfHash* kid_idl = osrfHashGet( oilsIDL(), - osrfHashGet( kid_link, "class" )); - if( !kid_idl ) - continue; // The class it links to doesn't exist; skip it + osrfHash* field = osrfHashGet( fields, link_field ); + if( !field ) + continue; // Not a field at all; skip it (IDL is ill-formed) - const char* reltype = osrfHashGet( kid_link, "reltype" ); - if( !reltype ) - continue; // No reltype; skip it (IDL is ill-formed) + osrfHash* kid_idl = osrfHashGet( oilsIDL(), + osrfHashGet( kid_link, "class" )); + if( !kid_idl ) + continue; // The class it links to doesn't exist; skip it - osrfHash* value_field = field; + const char* reltype = osrfHashGet( kid_link, "reltype" ); + if( !reltype ) + continue; // No reltype; skip it (IDL is ill-formed) - if( !strcmp( reltype, "has_many" ) - || !strcmp( reltype, "might_have" ) ) { // has_many or might_have - value_field = osrfHashGet( - fields, osrfHashGet( class_meta, "primarykey" ) ); - } + osrfHash* value_field = field; - osrfStringArray* link_map = osrfHashGet( kid_link, "map" ); + if( !strcmp( reltype, "has_many" ) + || !strcmp( reltype, "might_have" ) ) { // has_many or might_have + value_field = osrfHashGet( + fields, osrfHashGet( class_meta, "primarykey" ) ); + } - if( link_map->size > 0 ) { - jsonObject* _kid_key = jsonNewObjectType( JSON_ARRAY ); - jsonObjectPush( - _kid_key, - jsonNewObject( osrfStringArrayGetString( link_map, 0 ) ) - ); + osrfStringArray* link_map = osrfHashGet( kid_link, "map" ); - jsonObjectSetKey( - flesh_blob, - osrfHashGet( kid_link, "class" ), - _kid_key - ); - }; + if( link_map->size > 0 ) { + jsonObject* _kid_key = jsonNewObjectType( JSON_ARRAY ); + jsonObjectPush( + _kid_key, + jsonNewObject( osrfStringArrayGetString( link_map, 0 ) ) + ); - osrfLogDebug( - OSRF_LOG_MARK, - "Link field: %s, remote class: %s, fkey: %s, reltype: %s", - osrfHashGet( kid_link, "field" ), + jsonObjectSetKey( + flesh_blob, osrfHashGet( kid_link, "class" ), - osrfHashGet( kid_link, "key" ), - osrfHashGet( kid_link, "reltype" ) + _kid_key ); + }; - const char* search_key = jsonObjectGetString( - jsonObjectGetIndex( cur, - atoi( osrfHashGet( value_field, "array_position" ) ) - ) - ); + osrfLogDebug( + OSRF_LOG_MARK, + "Link field: %s, remote class: %s, fkey: %s, reltype: %s", + osrfHashGet( kid_link, "field" ), + osrfHashGet( kid_link, "class" ), + osrfHashGet( kid_link, "key" ), + osrfHashGet( kid_link, "reltype" ) + ); - if( !search_key ) { - osrfLogDebug( OSRF_LOG_MARK, "Nothing to search for!" ); - continue; - } + const char* search_key = jsonObjectGetString( + jsonObjectGetIndex( cur, + atoi( osrfHashGet( value_field, "array_position" ) ) + ) + ); - osrfLogDebug( OSRF_LOG_MARK, "Creating param objects..." ); + if( !search_key ) { + osrfLogDebug( OSRF_LOG_MARK, "Nothing to search for!" ); + continue; + } - // construct WHERE clause - jsonObject* where_clause = jsonNewObjectType( JSON_HASH ); - jsonObjectSetKey( - where_clause, - osrfHashGet( kid_link, "key" ), - jsonNewObject( search_key ) - ); + osrfLogDebug( OSRF_LOG_MARK, "Creating param objects..." ); + + // construct WHERE clause + jsonObject* where_clause = jsonNewObjectType( JSON_HASH ); + jsonObjectSetKey( + where_clause, + osrfHashGet( kid_link, "key" ), + jsonNewObject( search_key ) + ); - // construct the rest of the query, mostly - // by copying pieces of the previous level of query - jsonObject* rest_of_query = jsonNewObjectType( JSON_HASH ); - jsonObjectSetKey( rest_of_query, "flesh", - jsonNewNumberObject( flesh_depth - 1 + link_map->size ) + // construct the rest of the query, mostly + // by copying pieces of the previous level of query + jsonObject* rest_of_query = jsonNewObjectType( JSON_HASH ); + jsonObjectSetKey( rest_of_query, "flesh", + jsonNewNumberObject( flesh_depth - 1 + link_map->size ) + ); + + if( flesh_blob ) + jsonObjectSetKey( rest_of_query, "flesh_fields", + jsonObjectClone( flesh_blob )); + + if( jsonObjectGetKeyConst( query_hash, "order_by" )) { + jsonObjectSetKey( rest_of_query, "order_by", + jsonObjectClone( jsonObjectGetKeyConst( query_hash, "order_by" )) ); + } - if( flesh_blob ) - jsonObjectSetKey( rest_of_query, "flesh_fields", - jsonObjectClone( flesh_blob )); + if( jsonObjectGetKeyConst( query_hash, "select" )) { + jsonObjectSetKey( rest_of_query, "select", + jsonObjectClone( jsonObjectGetKeyConst( query_hash, "select" )) + ); + } - if( jsonObjectGetKeyConst( query_hash, "order_by" )) { - jsonObjectSetKey( rest_of_query, "order_by", - jsonObjectClone( jsonObjectGetKeyConst( query_hash, "order_by" )) - ); - } + // do the query, recursively, to expand the fleshable field + jsonObject* kids = doFieldmapperSearch( ctx, kid_idl, + where_clause, rest_of_query, err ); - if( jsonObjectGetKeyConst( query_hash, "select" )) { - jsonObjectSetKey( rest_of_query, "select", - jsonObjectClone( jsonObjectGetKeyConst( query_hash, "select" )) - ); - } + jsonObjectFree( where_clause ); + jsonObjectFree( rest_of_query ); - // do the query, recursively, to expand the fleshable field - jsonObject* kids = doFieldmapperSearch( ctx, kid_idl, - where_clause, rest_of_query, err ); + if( *err ) { + osrfStringArrayFree( link_fields ); + jsonObjectFree( res_list ); + jsonObjectFree( flesh_blob ); + return NULL; + } - jsonObjectFree( where_clause ); - jsonObjectFree( rest_of_query ); + osrfLogDebug( OSRF_LOG_MARK, "Search for %s return %d linked objects", + osrfHashGet( kid_link, "class" ), kids->size ); - if( *err ) { - osrfStringArrayFree( link_fields ); - jsonObjectFree( res_list ); - jsonObjectFree( flesh_blob ); - return NULL; - } + // Traverse the result set + jsonObject* X = NULL; + if( link_map->size > 0 && kids->size > 0 ) { + X = kids; + kids = jsonNewObjectType( JSON_ARRAY ); - osrfLogDebug( OSRF_LOG_MARK, "Search for %s return %d linked objects", - osrfHashGet( kid_link, "class" ), kids->size ); - - // Traverse the result set - jsonObject* X = NULL; - if( link_map->size > 0 && kids->size > 0 ) { - X = kids; - kids = jsonNewObjectType( JSON_ARRAY ); - - jsonObject* _k_node; - unsigned long res_idx = 0; - while((_k_node = jsonObjectGetIndex( X, res_idx++ ) )) { - jsonObjectPush( - kids, - jsonObjectClone( - jsonObjectGetIndex( - _k_node, - (unsigned long) atoi( + jsonObject* _k_node; + unsigned long res_idx = 0; + while((_k_node = jsonObjectGetIndex( X, res_idx++ ) )) { + jsonObjectPush( + kids, + jsonObjectClone( + jsonObjectGetIndex( + _k_node, + (unsigned long) atoi( + osrfHashGet( osrfHashGet( osrfHashGet( osrfHashGet( - osrfHashGet( - oilsIDL(), - osrfHashGet( kid_link, "class" ) - ), - "fields" + oilsIDL(), + osrfHashGet( kid_link, "class" ) ), - osrfStringArrayGetString( link_map, 0 ) + "fields" ), - "array_position" - ) + osrfStringArrayGetString( link_map, 0 ) + ), + "array_position" ) ) ) - ); - } // end while loop traversing X - } - - if( !strcmp( osrfHashGet( kid_link, "reltype" ), "has_a" ) - || !strcmp( osrfHashGet( kid_link, "reltype" ), "might_have" )) { - osrfLogDebug(OSRF_LOG_MARK, "Storing fleshed objects in %s", - osrfHashGet( kid_link, "field" )); - jsonObjectSetIndex( - cur, - (unsigned long) atoi( osrfHashGet( field, "array_position" ) ), - jsonObjectClone( jsonObjectGetIndex( kids, 0 )) + ) ); - } + } // end while loop traversing X + } - if( !strcmp( osrfHashGet( kid_link, "reltype" ), "has_many" )) { - // has_many - osrfLogDebug( OSRF_LOG_MARK, "Storing fleshed objects in %s", - osrfHashGet( kid_link, "field" ) ); - jsonObjectSetIndex( - cur, - (unsigned long) atoi( osrfHashGet( field, "array_position" ) ), - jsonObjectClone( kids ) - ); - } + if( !strcmp( osrfHashGet( kid_link, "reltype" ), "has_a" ) + || !strcmp( osrfHashGet( kid_link, "reltype" ), "might_have" )) { + osrfLogDebug(OSRF_LOG_MARK, "Storing fleshed objects in %s", + osrfHashGet( kid_link, "field" )); + jsonObjectSetIndex( + cur, + (unsigned long) atoi( osrfHashGet( field, "array_position" ) ), + jsonObjectClone( jsonObjectGetIndex( kids, 0 )) + ); + } - if( X ) { - jsonObjectFree( kids ); - kids = X; - } + if( !strcmp( osrfHashGet( kid_link, "reltype" ), "has_many" )) { + // has_many + osrfLogDebug( OSRF_LOG_MARK, "Storing fleshed objects in %s", + osrfHashGet( kid_link, "field" ) ); + jsonObjectSetIndex( + cur, + (unsigned long) atoi( osrfHashGet( field, "array_position" ) ), + jsonObjectClone( kids ) + ); + } + if( X ) { jsonObjectFree( kids ); + kids = X; + } - osrfLogDebug( OSRF_LOG_MARK, "Fleshing of %s complete", - osrfHashGet( kid_link, "field" ) ); - osrfLogDebug( OSRF_LOG_MARK, "%s", jsonObjectToJSON( cur )); + jsonObjectFree( kids ); - } // end while loop traversing list of fleshable fields - } // end while loop traversing res_list - jsonObjectFree( flesh_blob ); - osrfStringArrayFree( link_fields ); - } + osrfLogDebug( OSRF_LOG_MARK, "Fleshing of %s complete", + osrfHashGet( kid_link, "field" ) ); + osrfLogDebug( OSRF_LOG_MARK, "%s", jsonObjectToJSON( cur )); + + } // end while loop traversing list of fleshable fields + } // end while loop traversing res_list + jsonObjectFree( flesh_blob ); + osrfStringArrayFree( link_fields ); } } -- 2.11.0