[open-ils-commits] r16399 - in trunk/Open-ILS: include/openils src/c-apps (scottmk)
svn at svn.open-ils.org
svn at svn.open-ils.org
Thu May 6 14:56:50 EDT 2010
Author: scottmk
Date: 2010-05-06 14:56:46 -0400 (Thu, 06 May 2010)
New Revision: 16399
Modified:
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
Log:
1. Support negation of an expression (except in a few cases where it
doesn't make sense, such as negation of a number or string).
2. Support HAVING clauses. This isn't useful yet because we don't
support GROUP BY yet.
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
Modified: trunk/Open-ILS/include/openils/oils_buildq.h
===================================================================
--- trunk/Open-ILS/include/openils/oils_buildq.h 2010-05-06 18:42:43 UTC (rev 16398)
+++ trunk/Open-ILS/include/openils/oils_buildq.h 2010-05-06 18:56:46 UTC (rev 16399)
@@ -73,6 +73,7 @@
Expression* where_clause;
SelectItem* select_list;
QSeq* child_list;
+ Expression* having_clause;
OrderItem* order_by_list;
};
@@ -127,9 +128,6 @@
EXP_FIELD,
EXP_FUNCTION,
EXP_IN,
- EXP_NOT_BETWEEN,
- EXP_NOT_EXIST,
- EXP_NOT_IN,
EXP_NULL,
EXP_NUMBER,
EXP_OPERATOR,
@@ -154,6 +152,7 @@
int subquery_id;
StoredQ* subquery;
int cast_type_id;
+ int negate; // Boolean
};
struct QSeq_ {
Modified: trunk/Open-ILS/src/c-apps/buildSQL.c
===================================================================
--- trunk/Open-ILS/src/c-apps/buildSQL.c 2010-05-06 18:42:43 UTC (rev 16398)
+++ trunk/Open-ILS/src/c-apps/buildSQL.c 2010-05-06 18:56:46 UTC (rev 16399)
@@ -168,12 +168,27 @@
state->error = 1;
return;
}
- //else
- //buffer_add_char( state->sql, ' ' );
decr_indent( state );
}
- // Build WHERE clause, if there is one
+ // To do: build GROUP BY clause, if there is one
+
+ // Build HAVING clause, if there is one
+ if( query->having_clause ) {
+ add_newline( state );
+ buffer_add( state->sql, "HAVING" );
+ incr_indent( state );
+ add_newline( state );
+ buildExpression( state, query->having_clause );
+ if( state->error ) {
+ sqlAddMsg( state, "Unable to build HAVING clause for query # %d", query->id );
+ state->error = 1;
+ return;
+ }
+ decr_indent( state );
+ }
+
+ // Build ORDER BY clause, if there is one
if( query->order_by_list ) {
buildOrderBy( state, query->order_by_list );
if( state->error ) {
@@ -182,7 +197,11 @@
return;
}
}
-
+
+ // To do: Build LIMIT clause, if there is one
+
+ // To do: Build OFFSET clause, if there is one
+
state->error = 0;
}
@@ -335,7 +354,7 @@
buffer_add( state->sql, effective_alias );
buffer_add_char( state->sql, '\"' );
}
-
+
if( join->on_clause ) {
incr_indent( state );
add_newline( state );
@@ -356,7 +375,7 @@
}
static void buildSelectList( BuildSQLState* state, SelectItem* item ) {
-
+
int first = 1;
while( item ) {
if( !first )
@@ -428,10 +447,16 @@
switch( expr->type ) {
case EXP_BETWEEN :
+ if( expr->negate )
+ buffer_add( state->sql, "NOT " );
+
sqlAddMsg( state, "BETWEEN expressions not yet supported" );
state->error = 1;
break;
case EXP_BOOL :
+ if( expr->negate )
+ buffer_add( state->sql, "NOT " );
+
if( expr->literal ) {
buffer_add( state->sql, expr->literal );
buffer_add_char( state->sql, ' ' );
@@ -439,14 +464,20 @@
buffer_add( state->sql, "FALSE " );
break;
case EXP_CASE :
+ if( expr->negate )
+ buffer_add( state->sql, "NOT " );
+
sqlAddMsg( state, "CASE expressions not yet supported" );
state->error = 1;
break;
- case EXP_CAST : // Type cast
+ case EXP_CAST : // Type cast
sqlAddMsg( state, "Cast expressions not yet supported" );
state->error = 1;
break;
case EXP_COLUMN : // Table column
+ if( expr->negate )
+ buffer_add( state->sql, "NOT " );
+
if( expr->table_alias ) {
buffer_add_char( state->sql, '\"' );
buffer_add( state->sql, expr->table_alias );
@@ -466,6 +497,9 @@
"No subquery found for EXIST expression # %d", expr->id ));
state->error = 1;
} else {
+ if( expr->negate )
+ buffer_add( state->sql, "NOT " );
+
buffer_add( state->sql, "EXISTS (" );
incr_indent( state );
build_Query( state, expr->subquery );
@@ -475,14 +509,23 @@
}
break;
case EXP_FIELD :
+ sqlAddMsg( state, "Field expressions not yet supported" );
+ state->error = 1;
+ break;
case EXP_FUNCTION :
- sqlAddMsg( state, "Expression type not yet supported" );
+ if( expr->negate )
+ buffer_add( state->sql, "NOT " );
+
+ sqlAddMsg( state, "Function expressions not yet supported" );
state->error = 1;
break;
case EXP_IN :
if( expr->left_operand ) {
buildExpression( state, expr->left_operand );
if( !state->error ) {
+ if( expr->negate )
+ buffer_add( state->sql, "NOT " );
+
if( expr->subquery ) {
buffer_add( state->sql, " IN (" );
incr_indent( state );
@@ -497,13 +540,10 @@
}
}
break;
- case EXP_NOT_BETWEEN :
- case EXP_NOT_EXIST :
- case EXP_NOT_IN :
- sqlAddMsg( state, "Expression type not yet supported" );
- state->error = 1;
- break;
case EXP_NULL :
+ if( expr->negate )
+ buffer_add( state->sql, "NOT " );
+
buffer_add( state->sql, "NULL" );
break;
case EXP_NUMBER : // Numeric literal
@@ -516,6 +556,9 @@
}
break;
case EXP_OPERATOR :
+ if( expr->negate )
+ buffer_add( state->sql, "NOT (" );
+
if( expr->left_operand ) {
buildExpression( state, expr->left_operand );
if( state->error ) {
@@ -535,6 +578,10 @@
break;
}
}
+
+ if( expr->negate )
+ buffer_add_char( state->sql, ')' );
+
break;
case EXP_STRING : // String literal
if( !expr->literal ) {
@@ -548,6 +595,9 @@
}
break;
case EXP_SUBQUERY :
+ if( expr->negate )
+ buffer_add( state->sql, "NOT " );
+
if( expr->subquery ) {
buffer_add_char( state->sql, '(' );
incr_indent( state );
@@ -562,7 +612,7 @@
}
break;
}
-
+
if( expr->parenthesize )
buffer_add_char( state->sql, ')' );
}
Modified: trunk/Open-ILS/src/c-apps/oils_storedq.c
===================================================================
--- trunk/Open-ILS/src/c-apps/oils_storedq.c 2010-05-06 18:42:43 UTC (rev 16398)
+++ trunk/Open-ILS/src/c-apps/oils_storedq.c 2010-05-06 18:56:46 UTC (rev 16399)
@@ -225,18 +225,34 @@
}
}
+ Expression* having_clause = NULL;
+ if( having_clause_id != -1 ) {
+ having_clause = getExpression( state, having_clause_id );
+ if( ! having_clause ) {
+ // shouldn't happen due to foreign key constraint
+ osrfLogError( OSRF_LOG_MARK, sqlAddMsg( state,
+ "Unable to fetch HAVING expression for query id = %d", id ));
+ expressionFree( where_clause );
+ freeQSeqList( child_list );
+ fromRelationFree( from_clause );
+ selectListFree( select_list );
+ return NULL;
+ }
+ }
+
// Get the ORDER BY clause, if there is one
OrderItem* order_by_list = getOrderByList( state, id );
if( state->error ) {
osrfLogWarning( OSRF_LOG_MARK, sqlAddMsg( state,
"Unable to load ORDER BY clause for query %d", id ));
+ expressionFree( having_clause );
expressionFree( where_clause );
freeQSeqList( child_list );
fromRelationFree( from_clause );
selectListFree( select_list );
return NULL;
}
-
+
// Allocate a StoredQ: from the free list if possible, from the heap if necessary
StoredQ* sq;
@@ -257,6 +273,7 @@
sq->where_clause = where_clause;
sq->select_list = select_list;
sq->child_list = child_list;
+ sq->having_clause = having_clause;
sq->order_by_list = order_by_list;
return sq;
@@ -407,6 +424,8 @@
orderItemListFree( sq->order_by_list );
sq->order_by_list = NULL;
}
+ if( sq->having_clause )
+ expressionFree( sq->having_clause );
// Stick the empty husk on the free list for potential reuse
sq->next = free_storedq_list;
@@ -851,8 +870,8 @@
Expression* exp = NULL;
dbi_result result = dbi_conn_queryf( state->dbhandle,
- "SELECT id, type, parenthesize, parent_expr, seq_no, literal, table_alias, "
- "column_name, left_operand, operator, right_operand, function_id, subquery, cast_type "
+ "SELECT id, type, parenthesize, parent_expr, seq_no, literal, table_alias, column_name, "
+ "left_operand, operator, right_operand, function_id, subquery, cast_type, negate "
"FROM query.expression WHERE id = %d;", id );
if( result ) {
if( dbi_result_first_row( result ) ) {
@@ -911,12 +930,6 @@
type = EXP_FUNCTION;
else if( !strcmp( type_str, "xin" ))
type = EXP_IN;
- else if( !strcmp( type_str, "xnbet" ))
- type = EXP_NOT_BETWEEN;
- else if( !strcmp( type_str, "xnex" ))
- type = EXP_NOT_EXIST;
- else if( !strcmp( type_str, "xnin" ))
- type = EXP_NOT_IN;
else if( !strcmp( type_str, "xnull" ))
type = EXP_NULL;
else if( !strcmp( type_str, "xnum" ))
@@ -975,6 +988,8 @@
else
cast_type_id = dbi_result_get_int_idx( result, 14 );
+ int negate = oils_result_get_bool_idx( result, 15 );
+
Expression* left_operand = NULL;
Expression* right_operand = NULL;
StoredQ* subquery = NULL;
@@ -1104,6 +1119,7 @@
exp->subquery_id = subquery_id;
exp->subquery = subquery;
exp->cast_type_id = subquery_id;
+ exp->negate = negate;
return exp;
}
More information about the open-ils-commits
mailing list