[open-ils-commits] r16455 - in trunk/Open-ILS: include/openils src/c-apps (scottmk)

svn at svn.open-ils.org svn at svn.open-ils.org
Wed May 19 21:25:17 EDT 2010


Author: scottmk
Date: 2010-05-19 21:25:15 -0400 (Wed, 19 May 2010)
New Revision: 16455

Modified:
   trunk/Open-ILS/include/openils/oils_buildq.h
   trunk/Open-ILS/src/c-apps/buildSQL.c
   trunk/Open-ILS/src/c-apps/oils_qstore.c
Log:
Implement new param_list method, which returns a list of
bind variables so that the client can populate them.

M    Open-ILS/include/openils/oils_buildq.h
M    Open-ILS/src/c-apps/oils_qstore.c
M    Open-ILS/src/c-apps/buildSQL.c


Modified: trunk/Open-ILS/include/openils/oils_buildq.h
===================================================================
--- trunk/Open-ILS/include/openils/oils_buildq.h	2010-05-19 19:37:05 UTC (rev 16454)
+++ trunk/Open-ILS/include/openils/oils_buildq.h	2010-05-20 01:25:15 UTC (rev 16455)
@@ -224,6 +224,10 @@
 
 jsonObject* oilsNextRow( BuildSQLState* state );
 
+jsonObject* oilsBindVarList( osrfHash* bindvar_list );
+
+int oilsApplyBindValues( BuildSQLState* state, jsonObject* bindings );
+
 #ifdef __cplusplus
 }
 #endif

Modified: trunk/Open-ILS/src/c-apps/buildSQL.c
===================================================================
--- trunk/Open-ILS/src/c-apps/buildSQL.c	2010-05-19 19:37:05 UTC (rev 16454)
+++ trunk/Open-ILS/src/c-apps/buildSQL.c	2010-05-20 01:25:15 UTC (rev 16455)
@@ -31,6 +31,78 @@
 static inline void decr_indent( BuildSQLState* state );
 
 /**
+	@brief Create a jsonObject representing the current list of bind variables.
+	@param bindvar_list Pointer to the bindvar_list member of a BuildSQLState.
+	@return Pointer to the newly created jsonObject.
+
+	The returned jsonObject is a (possibly empty) JSON_HASH, keyed on the names of the bind
+	variables.  The data for each is another level of JSON_HASH with a fixed set of tags:
+	- "label"
+	- "type"
+	- "description"
+	- "default_value" (as a jsonObject)
+	- "actual_value" (as a jsonObject)
+
+	Any non-existent values are represented as JSON_NULLs.
+
+	The calling code is responsible for freeing the returned jsonOjbect by calling
+	jsonObjectFree().
+*/
+jsonObject* oilsBindVarList( osrfHash* bindvar_list ) {
+	jsonObject* list = jsonNewObjectType( JSON_HASH );
+
+	if( bindvar_list && osrfHashGetCount( bindvar_list )) {
+		// Traverse our internal list of bind variables
+		BindVar* bind = NULL;
+		osrfHashIterator* iter = osrfNewHashIterator( bindvar_list );
+		while(( bind = osrfHashIteratorNext( iter ))) {
+			// Create an hash to represent the bind variable
+			jsonObject* bind_obj = jsonNewObjectType( JSON_HASH );
+
+			// Add an entry for each attribute
+			jsonObject* attr = jsonNewObject( bind->label );
+			jsonObjectSetKey( bind_obj, "label", attr );
+
+			const char* type = NULL;
+			switch( bind->type ) {
+				case BIND_STR :
+					type = "string";
+					break;
+				case BIND_NUM :
+					type = "number";
+					break;
+				case BIND_STR_LIST :
+					type = "string_list";
+					break;
+				case BIND_NUM_LIST :
+					type = "number_list";
+					break;
+				default :
+					type = "(invalid)";
+					break;
+			}
+			attr = jsonNewObject( type );
+			jsonObjectSetKey( bind_obj, "type", attr );
+
+			attr = jsonNewObject( bind->description );
+			jsonObjectSetKey( bind_obj, "description", attr );
+
+			attr = jsonObjectClone( bind->default_value );
+			jsonObjectSetKey( bind_obj, "default_value", attr );
+
+			attr = jsonObjectClone( bind->actual_value );
+			jsonObjectSetKey( bind_obj, "actual_value", attr );
+
+			// Add the bind variable to the list
+			jsonObjectSetKey( list, osrfHashIteratorKey( iter ), bind_obj );
+		}
+		osrfHashIteratorFree( iter );
+	}
+
+	return list;
+}
+
+/**
 	@brief Apply values to bind variables, overriding the defaults, if any.
 	@param state Pointer to the query-building context.
 	@param bindings A JSON_HASH of values.
@@ -60,7 +132,10 @@
 		const char* var_name = iter->key;
 		BindVar* bind = osrfHashGet( state->bindvar_list, var_name );
 		if( bind ) {
-			;
+			// Apply or replace the value for the specified variable
+			if( bind->actual_value )
+				jsonObjectFree( bind->actual_value );
+			bind->actual_value = jsonObjectClone( value );
 		} else {
 			osrfLogError( OSRF_LOG_MARK, sqlAddMsg( state,
 				"Can't assign value to bind variable \"%s\": no such variable", var_name ));
@@ -216,9 +291,9 @@
 		decr_indent( state );
 	}
 
-    // To do: build GROUP BY clause, if there is one
+	// To do: build GROUP BY clause, if there is one
 
-    // Build HAVING clause, if there is one
+	// Build HAVING clause, if there is one
 	if( query->having_clause ) {
 		add_newline( state );
 		buffer_add( state->sql, "HAVING" );
@@ -232,7 +307,7 @@
 		}
 		decr_indent( state );
 	}
-	
+
 	// Build ORDER BY clause, if there is one
 	if( query->order_by_list ) {
 		buildOrderBy( state, query->order_by_list );

Modified: trunk/Open-ILS/src/c-apps/oils_qstore.c
===================================================================
--- trunk/Open-ILS/src/c-apps/oils_qstore.c	2010-05-19 19:37:05 UTC (rev 16454)
+++ trunk/Open-ILS/src/c-apps/oils_qstore.c	2010-05-20 01:25:15 UTC (rev 16455)
@@ -86,43 +86,49 @@
 	OSRF_BUFFER_ADD( method_name, modulename );
 	OSRF_BUFFER_ADD( method_name, ".prepare" );
 	osrfAppRegisterMethod( modulename, OSRF_BUFFER_C_STR( method_name ),
-			"doPrepare", "", 1, 0 );
+		"doPrepare", "", 1, 0 );
 
 	buffer_reset( method_name );
 	OSRF_BUFFER_ADD( method_name, modulename );
 	OSRF_BUFFER_ADD( method_name, ".columns" );
 	osrfAppRegisterMethod( modulename, OSRF_BUFFER_C_STR( method_name ),
-						   "doColumns", "", 1, 0 );
+		"doColumns", "", 1, 0 );
 
 	buffer_reset( method_name );
 	OSRF_BUFFER_ADD( method_name, modulename );
+	OSRF_BUFFER_ADD( method_name, ".param_list" );
+	osrfAppRegisterMethod( modulename, OSRF_BUFFER_C_STR( method_name ),
+		"doParamList", "", 1, 0 );
+
+	buffer_reset( method_name );
+	OSRF_BUFFER_ADD( method_name, modulename );
 	OSRF_BUFFER_ADD( method_name, ".bind_param" );
 	osrfAppRegisterMethod( modulename, OSRF_BUFFER_C_STR( method_name ),
-			"doBindParam", "", 2, 0 );
+		"doBindParam", "", 2, 0 );
 
 	buffer_reset( method_name );
 	OSRF_BUFFER_ADD( method_name, modulename );
 	OSRF_BUFFER_ADD( method_name, ".execute" );
 	osrfAppRegisterMethod( modulename, OSRF_BUFFER_C_STR( method_name ),
-			"doExecute", "", 1, OSRF_METHOD_STREAMING );
+		"doExecute", "", 1, OSRF_METHOD_STREAMING );
 
 	buffer_reset( method_name );
 	OSRF_BUFFER_ADD( method_name, modulename );
 	OSRF_BUFFER_ADD( method_name, ".sql" );
 	osrfAppRegisterMethod( modulename, OSRF_BUFFER_C_STR( method_name ),
-			"doSql", "", 1, OSRF_METHOD_STREAMING );
+		"doSql", "", 1, OSRF_METHOD_STREAMING );
 
 	buffer_reset( method_name );
 	OSRF_BUFFER_ADD( method_name, modulename );
 	OSRF_BUFFER_ADD( method_name, ".finish" );
 	osrfAppRegisterMethod( modulename, OSRF_BUFFER_C_STR( method_name ),
-			"doFinish", "", 1, 0 );
+		"doFinish", "", 1, 0 );
 
 	buffer_reset( method_name );
 	OSRF_BUFFER_ADD( method_name, modulename );
 	OSRF_BUFFER_ADD( method_name, ".messages" );
 	osrfAppRegisterMethod( modulename, OSRF_BUFFER_C_STR( method_name ),
-			"doMessages", "", 1, 0 );
+		"doMessages", "", 1, 0 );
 
 	return 0;
 }
@@ -256,6 +262,46 @@
 	}
 }
 
+int doParamList( osrfMethodContext* ctx ) {
+	if(osrfMethodVerifyContext( ctx )) {
+		osrfLogError( OSRF_LOG_MARK,  "Invalid method context" );
+		return -1;
+	}
+
+	// Get the query token from a method parameter
+	const jsonObject* token_obj = jsonObjectGetIndex( ctx->params, 0 );
+	if( token_obj->type != JSON_STRING ) {
+		osrfAppSessionStatus( ctx->session, OSRF_STATUS_BADREQUEST, "osrfMethodException",
+			ctx->request, "Invalid parameter; query token must be a string" );
+		return -1;
+	}
+	const char* token = jsonObjectGetString( token_obj );
+
+	// Look up the query token in the session-level userData
+	CachedQuery* query = search_token( ctx, token );
+	if( !query ) {
+		osrfAppSessionStatus( ctx->session, OSRF_STATUS_BADREQUEST, "osrfMethodException",
+			ctx->request, "Invalid query token" );
+		return -1;
+	}
+
+	osrfLogInfo( OSRF_LOG_MARK, "Returning list of bind variables for token %s", token );
+
+	osrfAppRespondComplete( ctx, oilsBindVarList( query->state->bindvar_list ) );
+	return 0;
+}
+
+/**
+	@brief Implement the bind_param method.
+	@param ctx Pointer to the current method context.
+	@return Zero if successful, or -1 if not.
+
+	Method parameters:
+	- query token, as previously returned by the .prepare method.
+	- hash of bind variable values, keyed on bind variable names.
+
+	Returns: Nothing.
+*/
 int doBindParam( osrfMethodContext* ctx ) {
 	if(osrfMethodVerifyContext( ctx )) {
 		osrfLogError( OSRF_LOG_MARK,  "Invalid method context" );



More information about the open-ils-commits mailing list