[open-ils-commits] r16922 - in trunk/Open-ILS: examples include/openils src/c-apps src/sql/Pg src/sql/Pg/upgrade (scottmk)

svn at svn.open-ils.org svn at svn.open-ils.org
Tue Jul 13 16:10:42 EDT 2010


Author: scottmk
Date: 2010-07-13 16:10:37 -0400 (Tue, 13 Jul 2010)
New Revision: 16922

Added:
   trunk/Open-ILS/src/sql/Pg/upgrade/0336.schema.query-limit-offset-fkey.sql
Modified:
   trunk/Open-ILS/examples/fm_IDL.xml
   trunk/Open-ILS/include/openils/oils_buildq.h
   trunk/Open-ILS/src/c-apps/buildSQL.c
   trunk/Open-ILS/src/c-apps/oils_storedq.c
   trunk/Open-ILS/src/sql/Pg/002.schema.config.sql
   trunk/Open-ILS/src/sql/Pg/008.schema.query.sql
Log:
Qstore: support LIMIT and OFFSET clauses.

Also: add some links to the IDL, that should have been there
in the first place.

M    Open-ILS/include/openils/oils_buildq.h
M    Open-ILS/src/c-apps/oils_storedq.c
M    Open-ILS/src/c-apps/buildSQL.c
M    Open-ILS/src/sql/Pg/002.schema.config.sql
M    Open-ILS/src/sql/Pg/008.schema.query.sql
A    Open-ILS/src/sql/Pg/upgrade/0336.schema.query-limit-offset-fkey.sql
M    Open-ILS/examples/fm_IDL.xml


Modified: trunk/Open-ILS/examples/fm_IDL.xml
===================================================================
--- trunk/Open-ILS/examples/fm_IDL.xml	2010-07-13 19:27:19 UTC (rev 16921)
+++ trunk/Open-ILS/examples/fm_IDL.xml	2010-07-13 20:10:37 UTC (rev 16922)
@@ -6793,13 +6793,18 @@
 			<field reporter:label="Query type" name="type" reporter:datatype="text"/>
 			<field reporter:label="Use ALL" name="use_all" reporter:datatype="bool"/>
 			<field reporter:label="Use DISTINCT" name="use_distinct" reporter:datatype="bool"/>
-			<field reporter:label="FROM Clause" name="from_clause" reporter:datatype="int"/>
-			<field reporter:label="WHERE Clause" name="where_clause" reporter:datatype="int"/>
-			<field reporter:label="HAVING Clause" name="having_clause" reporter:datatype="int"/>
-			<field reporter:label="LIMIT count" name="limit_count" reporter:datatype="int"/>
-			<field reporter:label="OFFSET count" name="offset_count" reporter:datatype="int"/>
+			<field reporter:label="FROM Clause" name="from_clause" reporter:datatype="link"/>
+			<field reporter:label="WHERE Clause" name="where_clause" reporter:datatype="link"/>
+			<field reporter:label="HAVING Clause" name="having_clause" reporter:datatype="link"/>
+			<field reporter:label="LIMIT count" name="limit_count" reporter:datatype="link"/>
+			<field reporter:label="OFFSET count" name="offset_count" reporter:datatype="link"/>
 		</fields>
 		<links>
+			<link field="from_clause" reltype="has_a" key="id" map="" class="qfr"/>
+			<link field="having_clause" reltype="has_a" key="id" map="" class="qxp"/>
+			<link field="where_clause" reltype="has_a" key="id" map="" class="qxp"/>
+			<link field="limit_count" reltype="has_a" key="id" map="" class="qxp"/>
+			<link field="offset_count" reltype="has_a" key="id" map="" class="qxp"/>
 		</links>
 		<permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
 		</permacrud>

Modified: trunk/Open-ILS/include/openils/oils_buildq.h
===================================================================
--- trunk/Open-ILS/include/openils/oils_buildq.h	2010-07-13 19:27:19 UTC (rev 16921)
+++ trunk/Open-ILS/include/openils/oils_buildq.h	2010-07-13 20:10:37 UTC (rev 16922)
@@ -90,6 +90,8 @@
 	QSeq*         child_list;
 	Expression*   having_clause;
 	OrderItem*    order_by_list;
+	Expression*   limit_count;
+	Expression*   offset_count;
 };
 
 typedef enum {

Modified: trunk/Open-ILS/src/c-apps/buildSQL.c
===================================================================
--- trunk/Open-ILS/src/c-apps/buildSQL.c	2010-07-13 19:27:19 UTC (rev 16921)
+++ trunk/Open-ILS/src/c-apps/buildSQL.c	2010-07-13 20:10:37 UTC (rev 16922)
@@ -25,10 +25,12 @@
 static void buildOrderBy( BuildSQLState* state, const OrderItem* ord_list );
 static void buildCase( BuildSQLState* state, const Expression* expr );
 static void buildExpression( BuildSQLState* state, const Expression* expr );
+
 static void buildFunction( BuildSQLState* state, const Expression* exp );
 static int subexp_count( const Expression* expr );
 static void buildTypicalFunction( BuildSQLState* state, const Expression* expr );
 static void buildExtract( BuildSQLState* state, const Expression* expr );
+
 static void buildSeries( BuildSQLState* state, const Expression* subexp_list, const char* op );
 static void buildBindVar( BuildSQLState* state, const BindVar* bind );
 static void buildScalar( BuildSQLState* state, int numeric, const jsonObject* obj );
@@ -262,7 +264,7 @@
 		return;
 	}
 
-	// To do: get SELECT list; just a stub here
+	// Get SELECT list
 	buffer_add( state->sql, "SELECT" );
 	incr_indent( state );
 	buildSelectList( state, query->select_list );
@@ -326,9 +328,19 @@
 		}
 	}
 
-	// To do: Build LIMIT clause, if there is one
+	// Build LIMIT clause, if there is one
+	if( query->limit_count ) {
+		add_newline( state );
+		buffer_add( state->sql, "LIMIT " );
+		buildExpression( state, query->limit_count );
+	}
 
-	// To do: Build OFFSET clause, if there is one
+	// Build OFFSET clause, if there is one
+	if( query->offset_count ) {
+		add_newline( state );
+		buffer_add( state->sql, "OFFSET " );
+		buildExpression( state, query->offset_count );
+	}
 
 	state->error = 0;
 }
@@ -968,7 +980,19 @@
 		buffer_add( state->sql, "LOCALTIME " );
 	else if( !strcasecmp( expr->function_name, "LOCALTIMESTAMP" ) && ! expr->subexp_list )
 		buffer_add( state->sql, "LOCALTIMESTAMP " );
-	else
+	else if( !strcasecmp( expr->function_name, "TRIM" )) {
+		int arg_count = subexp_count( expr );
+
+		if( (arg_count != 2 && arg_count != 3 ) || expr->subexp_list->type != EXP_STRING )
+			buildTypicalFunction( state, expr );
+		else {
+			sqlAddMsg( state,
+				"TRIM function not supported in expr # %d; use ltrim() and/or rtrim()",
+				expr->id );
+			state->error = 1;
+			return;
+		}
+	} else
 		buildTypicalFunction( state, expr );     // Not a special exception.
 
 	if( expr->column_name ) {
@@ -985,6 +1009,9 @@
 	@return The number of subexpressions.
 */
 static int subexp_count( const Expression* expr ) {
+	if( !expr )
+		return 0;
+
 	int count = 0;
 	const Expression* sub = expr->subexp_list;
 	while( sub ) {

Modified: trunk/Open-ILS/src/c-apps/oils_storedq.c
===================================================================
--- trunk/Open-ILS/src/c-apps/oils_storedq.c	2010-07-13 19:27:19 UTC (rev 16921)
+++ trunk/Open-ILS/src/c-apps/oils_storedq.c	2010-07-13 20:10:37 UTC (rev 16922)
@@ -184,8 +184,8 @@
 
 	StoredQ* sq = NULL;
 	dbi_result result = dbi_conn_queryf( state->dbhandle,
-		"SELECT id, type, use_all, use_distinct, from_clause, where_clause, having_clause "
-		"FROM query.stored_query WHERE id = %d;", query_id );
+		"SELECT id, type, use_all, use_distinct, from_clause, where_clause, having_clause, "
+		"limit_count, offset_count FROM query.stored_query WHERE id = %d;", query_id );
 	if( result ) {
 		if( dbi_result_first_row( result ) ) {
 			sq = constructStoredQ( state, result );
@@ -270,6 +270,18 @@
 	else
 		having_clause_id = dbi_result_get_int_idx( result, 7 );
 
+	int limit_count_id;
+	if( dbi_result_field_is_null_idx( result, 8 ) )
+		limit_count_id = -1;
+	else
+		limit_count_id = dbi_result_get_int_idx( result, 8 );
+
+	int offset_count_id;
+	if( dbi_result_field_is_null_idx( result, 9 ) )
+		offset_count_id = -1;
+	else
+		offset_count_id = dbi_result_get_int_idx( result, 9 );
+
 	FromRelation* from_clause = NULL;
 	if( QT_SELECT == type ) {
 		// A SELECT query needs a FROM clause; go get it
@@ -327,6 +339,7 @@
 		}
 	}
 
+	// Get the HAVING clause, if there is one
 	Expression* having_clause = NULL;
 	if( having_clause_id != -1 ) {
 		having_clause = getExpression( state, having_clause_id );
@@ -336,8 +349,8 @@
 				"Unable to fetch HAVING expression for query id = %d", id ));
 			expressionFree( where_clause );
 			freeQSeqList( child_list );
+			selectListFree( select_list );
 			fromRelationFree( from_clause );
-			selectListFree( select_list );
 			state->error = 1;
 			return NULL;
 		}
@@ -351,11 +364,46 @@
 		expressionFree( having_clause );
 		expressionFree( where_clause );
 		freeQSeqList( child_list );
+		selectListFree( select_list );
 		fromRelationFree( from_clause );
-		selectListFree( select_list );
 		return NULL;
 	}
 
+	// Get the LIMIT clause, if there is one
+	Expression* limit_count = NULL;
+	if( limit_count_id != -1 ) {
+		limit_count = getExpression( state, limit_count_id );
+		if( ! limit_count ) {
+			// shouldn't happen due to foreign key constraint
+			osrfLogError( OSRF_LOG_MARK, sqlAddMsg( state,
+				"Unable to fetch LIMIT expression for query id = %d", id ));
+			orderItemListFree( order_by_list );
+			freeQSeqList( child_list );
+			selectListFree( select_list );
+			fromRelationFree( from_clause );
+			state->error = 1;
+			return NULL;
+		}
+	}
+
+	// Get the OFFSET clause, if there is one
+	Expression* offset_count = NULL;
+	if( offset_count_id != -1 ) {
+		offset_count = getExpression( state, offset_count_id );
+		if( ! offset_count ) {
+			// shouldn't happen due to foreign key constraint
+			osrfLogError( OSRF_LOG_MARK, sqlAddMsg( state,
+				"Unable to fetch OFFSET expression for query id = %d", id ));
+			expressionFree( limit_count );
+			orderItemListFree( order_by_list );
+			freeQSeqList( child_list );
+			selectListFree( select_list );
+			fromRelationFree( from_clause );
+			state->error = 1;
+			return NULL;
+		}
+	}
+
 	// Allocate a StoredQ: from the free list if possible, from the heap if necessary
 
 	StoredQ* sq;
@@ -378,6 +426,8 @@
 	sq->child_list = child_list;
 	sq->having_clause = having_clause;
 	sq->order_by_list = order_by_list;
+	sq->limit_count = limit_count;
+	sq->offset_count = offset_count;
 
 	return sq;
 }
@@ -535,8 +585,18 @@
 			orderItemListFree( sq->order_by_list );
 			sq->order_by_list = NULL;
 		}
-		if( sq->having_clause )
+		if( sq->having_clause ) {
 			expressionFree( sq->having_clause );
+			sq->having_clause = NULL;
+		}
+		if( sq->limit_count ) {
+			expressionFree( sq->limit_count );
+			sq->limit_count = NULL;
+		}
+		if( sq->offset_count ) {
+			expressionFree( sq->offset_count );
+			sq->offset_count = NULL;
+		}
 
 		// Stick the empty husk on the free list for potential reuse
 		sq->next = free_storedq_list;

Modified: trunk/Open-ILS/src/sql/Pg/002.schema.config.sql
===================================================================
--- trunk/Open-ILS/src/sql/Pg/002.schema.config.sql	2010-07-13 19:27:19 UTC (rev 16921)
+++ trunk/Open-ILS/src/sql/Pg/002.schema.config.sql	2010-07-13 20:10:37 UTC (rev 16922)
@@ -68,7 +68,7 @@
     install_date    TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
 );
 
-INSERT INTO config.upgrade_log (version) VALUES ('0335'); -- dbs
+INSERT INTO config.upgrade_log (version) VALUES ('0336'); -- Scott McKellar
 
 CREATE TABLE config.bib_source (
 	id		SERIAL	PRIMARY KEY,

Modified: trunk/Open-ILS/src/sql/Pg/008.schema.query.sql
===================================================================
--- trunk/Open-ILS/src/sql/Pg/008.schema.query.sql	2010-07-13 19:27:19 UTC (rev 16921)
+++ trunk/Open-ILS/src/sql/Pg/008.schema.query.sql	2010-07-13 20:10:37 UTC (rev 16922)
@@ -39,9 +39,11 @@
 	where_clause  INT,           --REFERENCES query.expression
 	                             --DEFERRABLE INITIALLY DEFERRED,
 	having_clause INT,           --REFERENCES query.expression
+	                             --DEFERRABLE INITIALLY DEFERRED,
+	limit_count   INT,           --REFERENCES query.expression
+	                             --DEFERRABLE INITIALLY DEFERRED,
+	offset_count  INT            --REFERENCES query.expression
 	                             --DEFERRABLE INITIALLY DEFERRED
-	limit_count   INT,
-	offset_count  INT
 );
 
 -- (Foreign keys to be defined later after other tables are created)
@@ -188,6 +190,16 @@
 	REFERENCES query.expression( id )
 	DEFERRABLE INITIALLY DEFERRED;
 
+ALTER TABLE query.stored_query
+	ADD FOREIGN KEY ( limit_count )
+	REFERENCES query.expression( id )
+	DEFERRABLE INITIALLY DEFERRED;
+
+ALTER TABLE query.stored_query
+	ADD FOREIGN KEY ( offset_count )
+	REFERENCES query.expression( id )
+	DEFERRABLE INITIALLY DEFERRED;
+
 CREATE TABLE query.case_branch (
 	id            SERIAL        PRIMARY KEY,
 	parent_expr   INT           NOT NULL REFERENCES query.expression

Added: trunk/Open-ILS/src/sql/Pg/upgrade/0336.schema.query-limit-offset-fkey.sql
===================================================================
--- trunk/Open-ILS/src/sql/Pg/upgrade/0336.schema.query-limit-offset-fkey.sql	                        (rev 0)
+++ trunk/Open-ILS/src/sql/Pg/upgrade/0336.schema.query-limit-offset-fkey.sql	2010-07-13 20:10:37 UTC (rev 16922)
@@ -0,0 +1,15 @@
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0336'); -- Scott McKellar
+
+ALTER TABLE query.stored_query
+    ADD FOREIGN KEY ( limit_count )
+    REFERENCES query.expression( id )
+    DEFERRABLE INITIALLY DEFERRED;
+
+ALTER TABLE query.stored_query
+    ADD FOREIGN KEY ( offset_count )
+    REFERENCES query.expression( id )
+    DEFERRABLE INITIALLY DEFERRED;
+
+COMMIT;



More information about the open-ils-commits mailing list