From ac38faf0bf01c52502c1536ca643f6b5e69322e4 Mon Sep 17 00:00:00 2001
From: scottmk <scottmk@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Date: Wed, 19 May 2010 19:37:05 +0000
Subject: [PATCH] Implement open-ils.qstore.bind_param method, which applies
 actual values to bind variables (overriding default values, if any).

M    Open-ILS/src/c-apps/oils_qstore.c
M    Open-ILS/src/c-apps/buildSQL.c


git-svn-id: svn://svn.open-ils.org/ILS/trunk@16454 dcc99617-32d9-48b4-a31d-7c20da2025e4
---
 Open-ILS/src/c-apps/buildSQL.c    | 42 +++++++++++++++++++++++++++++++++++++++
 Open-ILS/src/c-apps/oils_qstore.c | 38 +++++++++++++++++++++++++++++++----
 2 files changed, 76 insertions(+), 4 deletions(-)

diff --git a/Open-ILS/src/c-apps/buildSQL.c b/Open-ILS/src/c-apps/buildSQL.c
index cc1c5b8010..aeb35eacaa 100644
--- a/Open-ILS/src/c-apps/buildSQL.c
+++ b/Open-ILS/src/c-apps/buildSQL.c
@@ -31,6 +31,48 @@ static inline void incr_indent( BuildSQLState* state );
 static inline void decr_indent( BuildSQLState* state );
 
 /**
+	@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.
+	@return 0 if successful, or 1 if not.
+
+	The @a bindings parameter must be a JSON_HASH.  The keys are the names of bind variables.
+	The values are the corresponding values for the variables.
+*/
+int oilsApplyBindValues( BuildSQLState* state, jsonObject* bindings ) {
+	if( !state ) {
+		osrfLogError( OSRF_LOG_MARK, "NULL pointer to state" );
+		return 1;
+	} else if( !bindings ) {
+		osrfLogError( OSRF_LOG_MARK, sqlAddMsg( state,
+			"Internal error: No pointer to bindings" ));
+		return 1;
+	} else if( bindings->type != JSON_HASH ) {
+		osrfLogError( OSRF_LOG_MARK, sqlAddMsg( state,
+			"Internal error: bindings parameter is not a JSON_HASH" ));
+		return 1;
+	}
+
+	int rc = 0;
+	jsonObject* value = NULL;
+	jsonIterator* iter = jsonNewIterator( bindings );
+	while(( value = jsonIteratorNext( iter ))) {
+		const char* var_name = iter->key;
+		BindVar* bind = osrfHashGet( state->bindvar_list, var_name );
+		if( bind ) {
+			;
+		} else {
+			osrfLogError( OSRF_LOG_MARK, sqlAddMsg( state,
+				"Can't assign value to bind variable \"%s\": no such variable", var_name ));
+			rc = 1;
+		}
+	}
+	jsonIteratorFree( iter );
+
+	return rc;
+}
+
+/**
 	@brief Build an SQL query.
 	@param state Pointer to the query-building context.
 	@param query Pointer to the query to be built.
diff --git a/Open-ILS/src/c-apps/oils_qstore.c b/Open-ILS/src/c-apps/oils_qstore.c
index cf37a33a35..01ab891442 100644
--- a/Open-ILS/src/c-apps/oils_qstore.c
+++ b/Open-ILS/src/c-apps/oils_qstore.c
@@ -211,7 +211,7 @@ int doPrepare( osrfMethodContext* ctx ) {
 }
 
 /**
-	@brief Execute an SQL query and return a result set.
+	@brief Return a list of column names for the SELECT list.
 	@param ctx Pointer to the current method context.
 	@return Zero if successful, or -1 if not.
 
@@ -275,14 +275,44 @@ int doBindParam( osrfMethodContext* ctx ) {
 	CachedQuery* query = search_token( ctx, token );
 	if( !query ) {
 		osrfAppSessionStatus( ctx->session, OSRF_STATUS_BADREQUEST, "osrfMethodException",
-							  ctx->request, "Invalid query token" );
+			ctx->request, "Invalid query token" );
 		return -1;
 	}
 
 	osrfLogInfo( OSRF_LOG_MARK, "Binding parameter(s) for token %s", token );
 
-	osrfAppRespondComplete( ctx, jsonNewObject( "build method not yet implemented" ));
-	return 0;
+	jsonObject* bindings = jsonObjectGetIndex( ctx->params, 1 );
+	if( !bindings ) {
+		osrfAppSessionStatus( ctx->session, OSRF_STATUS_BADREQUEST, "osrfMethodException",
+			ctx->request, "No parameter provided for bind variable values" );
+		return -1;
+	} else if( bindings->type != JSON_HASH ) {
+		osrfAppSessionStatus( ctx->session, OSRF_STATUS_BADREQUEST, "osrfMethodException",
+			ctx->request, "Invalid parameter for bind variable values: not a hash" );
+		return -1;
+	}
+
+	if( 0 == bindings->size ) {
+		// No values to assign; we're done.
+		osrfAppRespondComplete( ctx, NULL );
+		return 0;
+	}
+
+	osrfHash* bindvar_list = query->state->bindvar_list;
+	if( !bindvar_list || osrfHashGetCount( bindvar_list ) == 0 ) {
+		osrfAppSessionStatus( ctx->session, OSRF_STATUS_BADREQUEST, "osrfMethodException",
+			ctx->request, "There are no bind variables to which to assign values" );
+		return -1;
+	}
+
+	if( oilsApplyBindValues( query->state, bindings )) {
+		osrfAppSessionStatus( ctx->session, OSRF_STATUS_BADREQUEST, "osrfMethodException",
+			ctx->request, "Unable to apply values to bind variables" );
+		return -1;
+	} else {
+		osrfAppRespondComplete( ctx, NULL );
+		return 0;
+	}
 }
 
 /**
-- 
2.11.0