[open-ils-commits] r13035 - trunk/Open-ILS/src/c-apps (scottmk)

svn at svn.open-ils.org svn at svn.open-ils.org
Sat May 2 12:28:53 EDT 2009


Author: scottmk
Date: 2009-05-02 12:28:51 -0400 (Sat, 02 May 2009)
New Revision: 13035

Modified:
   trunk/Open-ILS/src/c-apps/oils_cstore.c
Log:
Introduce a new syntax for specifying an ORDER BY clause
(while retaining the old syntax).  For example:

{
    "select":{ "au":[ "family_name", "id" ] },
    "from": "au",
    "order_by":
    [
        {
            "class":"au",
            "field":"family_name",
            "direction":"D"
        },
        {
            "class":"au",
            "field":"id"
        }
    ]
}

This syntax is more flexible than the old syntax, because columns
from the same table don't have to be grouped together.

Planned but not yet implemented: "transform" and "params" tag for
passing a column through a transforming function.


Modified: trunk/Open-ILS/src/c-apps/oils_cstore.c
===================================================================
--- trunk/Open-ILS/src/c-apps/oils_cstore.c	2009-05-02 03:15:40 UTC (rev 13034)
+++ trunk/Open-ILS/src/c-apps/oils_cstore.c	2009-05-02 16:28:51 UTC (rev 13035)
@@ -3385,8 +3385,137 @@
 		// Build an ORDER BY clause, if there is one
 		if( NULL == order_hash )
 			;  // No ORDER BY? do nothing
-		else if( JSON_HASH == order_hash->type )
-		{
+		else if( JSON_ARRAY == order_hash->type ) {
+			// Array of field specifications, each specification being a
+			// hash to define the class, field, and other details
+			int order_idx = 0;
+			jsonObject* order_spec;
+			while( (order_spec = jsonObjectGetIndex( order_hash, order_idx++ ) ) ) {
+
+				if( JSON_HASH != order_spec->type ) {
+					osrfLogError(OSRF_LOG_MARK,
+						 "%s: Malformed field specification in ORDER BY clause; expected JSON_HASH, found %s",
+						MODULENAME, json_type( order_spec->type ) );
+					if( ctx )
+						osrfAppSessionStatus(
+							 ctx->session,
+							OSRF_STATUS_INTERNALSERVERERROR,
+							"osrfMethodException",
+							ctx->request,
+							"Malformed ORDER BY clause -- see error log for more details"
+						);
+					buffer_free( order_buf );
+					free(core_class);
+					buffer_free(having_buf);
+					buffer_free(group_buf);
+					buffer_free(sql_buf);
+					if (defaultselhash) jsonObjectFree(defaultselhash);
+					return NULL;
+				}
+
+				const char* class =
+						jsonObjectGetString( jsonObjectGetKeyConst( order_spec, "class" ) );
+				const char* field =
+						jsonObjectGetString( jsonObjectGetKeyConst( order_spec, "field" ) );
+				const char* direction =
+						jsonObjectGetString( jsonObjectGetKeyConst( order_spec, "direction" ) );
+
+				if( !direction )
+					direction = "";
+				else if( direction[ 0 ] || 'D' == direction[ 0 ] )
+					direction = " DESC";
+				else
+					direction = " ASC";
+
+				if ( order_buf )
+					buffer_add(order_buf, ", ");
+				else
+					order_buf = buffer_init(128);
+
+				if( !field || !class ) {
+					osrfLogError(OSRF_LOG_MARK,
+						"%s: Missing class or field name in field specification of ORDER BY clause",
+						 MODULENAME );
+					if( ctx )
+						osrfAppSessionStatus(
+							ctx->session,
+							OSRF_STATUS_INTERNALSERVERERROR,
+							"osrfMethodException",
+							ctx->request,
+							"Malformed ORDER BY clause -- see error log for more details"
+						);
+					buffer_free( order_buf );
+					free(core_class);
+					buffer_free(having_buf);
+					buffer_free(group_buf);
+					buffer_free(sql_buf);
+					if (defaultselhash) jsonObjectFree(defaultselhash);
+					return NULL;
+				}
+
+				if (!jsonObjectGetKeyConst( selhash,class ) ) {
+					osrfLogError(OSRF_LOG_MARK, "%s: Invalid class \"%s\" referenced in ORDER BY clause",
+								 MODULENAME, class );
+					if( ctx )
+						osrfAppSessionStatus(
+							ctx->session,
+							OSRF_STATUS_INTERNALSERVERERROR,
+							"osrfMethodException",
+							ctx->request,
+							"Invalid class referenced in ORDER BY clause -- see error log for more details"
+						);
+					free(core_class);
+					buffer_free(having_buf);
+					buffer_free(group_buf);
+					buffer_free(sql_buf);
+					if (defaultselhash) jsonObjectFree(defaultselhash);
+					return NULL;
+				}
+
+				osrfHash* field_def = oilsIDLFindPath( "/%s/fields/%s", class, field );
+				if( !field_def ) {
+					osrfLogError(OSRF_LOG_MARK, "%s: Invalid field \"%s\".%s referenced in ORDER BY clause",
+						 MODULENAME, class, field );
+					if( ctx )
+						osrfAppSessionStatus(
+							ctx->session,
+							OSRF_STATUS_INTERNALSERVERERROR,
+							"osrfMethodException",
+							ctx->request,
+							"Invalid field referenced in ORDER BY clause -- see error log for more details"
+						);
+					free(core_class);
+					buffer_free(having_buf);
+					buffer_free(group_buf);
+					buffer_free(sql_buf);
+					if (defaultselhash) jsonObjectFree(defaultselhash);
+					return NULL;
+				} else if( str_is_true( osrfHashGet( field_def, "virtual" ) ) ) {
+					osrfLogError(OSRF_LOG_MARK, "%s: Virtual field \"%s\" in ORDER BY clause",
+								 MODULENAME, field );
+					if( ctx )
+						osrfAppSessionStatus(
+							ctx->session,
+							OSRF_STATUS_INTERNALSERVERERROR,
+							"osrfMethodException",
+							ctx->request,
+							"Virtual field in ORDER BY clause -- see error log for more details"
+						);
+					buffer_free( order_buf );
+					free(core_class);
+					buffer_free(having_buf);
+					buffer_free(group_buf);
+					buffer_free(sql_buf);
+					if (defaultselhash) jsonObjectFree(defaultselhash);
+					return NULL;
+				}
+
+				buffer_fadd( order_buf, "\"%s\".%s%s", class, field, direction );
+
+			}
+		} else if( JSON_HASH == order_hash->type ) {
+			// This hash is keyed on class name.  Each class has either
+			// an array of field names or a hash keyed on field name.
 			jsonIterator* class_itr = jsonNewIterator( order_hash );
 			while ( (snode = jsonIteratorNext( class_itr )) ) {
 
@@ -3415,6 +3544,9 @@
 
 				if ( snode->type == JSON_HASH ) {
 
+					// Hash is keyed on field names from the current class.  For each field
+					// there is another layer of hash to define the sorting details, if any,
+					// or a string to indicate direction of sorting.
 					jsonIterator* order_itr = jsonNewIterator( snode );
 					while ( (onode = jsonIteratorNext( order_itr )) ) {
 
@@ -3529,6 +3661,7 @@
 
 				} else if ( snode->type == JSON_ARRAY ) {
 
+					// Array is a list of fields from the current class
 					jsonIterator* order_itr = jsonNewIterator( snode );
 					while ( (onode = jsonIteratorNext( order_itr )) ) {
 
@@ -3614,7 +3747,7 @@
 			} // end while
 		} else {
 			osrfLogError(OSRF_LOG_MARK,
-				"%s: Malformed ORDER BY clause; expected JSON_HASH, found %s",
+				"%s: Malformed ORDER BY clause; expected JSON_HASH or JSON_ARRAY, found %s",
 	 			MODULENAME, json_type( order_hash->type ) );
 			if( ctx )
 				osrfAppSessionStatus(



More information about the open-ils-commits mailing list