[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