[open-ils-commits] r16842 - trunk/Open-ILS/src/c-apps (scottmk)
svn at svn.open-ils.org
svn at svn.open-ils.org
Wed Jun 30 22:29:40 EDT 2010
Author: scottmk
Date: 2010-06-30 22:29:38 -0400 (Wed, 30 Jun 2010)
New Revision: 16842
Modified:
trunk/Open-ILS/src/c-apps/buildSQL.c
trunk/Open-ILS/src/c-apps/oils_storedq.c
Log:
1. Support the peculiar syntax of EXTRACT().
2. Repair a regression to make SELECT * work again.
M Open-ILS/src/c-apps/oils_storedq.c
M Open-ILS/src/c-apps/buildSQL.c
Modified: trunk/Open-ILS/src/c-apps/buildSQL.c
===================================================================
--- trunk/Open-ILS/src/c-apps/buildSQL.c 2010-07-01 02:29:21 UTC (rev 16841)
+++ trunk/Open-ILS/src/c-apps/buildSQL.c 2010-07-01 02:29:38 UTC (rev 16842)
@@ -26,6 +26,7 @@
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 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 );
@@ -954,15 +955,22 @@
if( expr->column_name )
buffer_add_char( state->sql, '(' );
- // We rely on the input side to ensure that the function name is available
- buffer_add( state->sql, expr->function_name );
- buffer_add_char( state->sql, '(' );
+ // First, check for some specific functions with peculiar syntax, and treat them
+ // as special exceptions. We rely on the input side to ensure that the function
+ // name is available.
+ if( !strcasecmp( expr->function_name, "EXTRACT" )) {
+ buildExtract( state, expr );
+ } else {
+ // Not a special exception.
+ buffer_add( state->sql, expr->function_name );
+ buffer_add_char( state->sql, '(' );
- // Add the parameters, if any
- buildSeries( state, expr->subexp_list, NULL );
+ // Add the parameters, if any
+ buildSeries( state, expr->subexp_list, NULL );
- buffer_add_char( state->sql, ')' );
-
+ buffer_add_char( state->sql, ')' );
+ }
+
if( expr->column_name ) {
// Add the name of the subfield
buffer_add( state->sql, ").\"" );
@@ -972,6 +980,81 @@
}
/**
+ @brief Build a call to the EXTRACT function, with its peculiar syntax.
+ @param state Pointer to the query-building context.
+ @param exp Pointer to an Expression representing an EXTRACT call.
+*/
+static void buildExtract( BuildSQLState* state, const Expression* expr ) {
+
+ const Expression* arg = expr->subexp_list;
+
+ // Sanity checks
+ if( !arg ) {
+ sqlAddMsg( state,
+ "No arguments supplied to EXTRACT function in expression # %d", expr->id );
+ state->error = 1;
+ return;
+ } else if( arg->type != EXP_STRING ) {
+ sqlAddMsg( state,
+ "First argument to EXTRACT is not a string in expression # %d", expr->id );
+ state->error = 1;
+ return;
+ } else {
+ // check the first argument against a list of valid values
+ if( strcasecmp( arg->literal, "century" )
+ && strcasecmp( arg->literal, "day" )
+ && strcasecmp( arg->literal, "decade" )
+ && strcasecmp( arg->literal, "dow" )
+ && strcasecmp( arg->literal, "doy" )
+ && strcasecmp( arg->literal, "epoch" )
+ && strcasecmp( arg->literal, "hour" )
+ && strcasecmp( arg->literal, "isodow" )
+ && strcasecmp( arg->literal, "isoyear" )
+ && strcasecmp( arg->literal, "microseconds" )
+ && strcasecmp( arg->literal, "millennium" )
+ && strcasecmp( arg->literal, "milliseconds" )
+ && strcasecmp( arg->literal, "minute" )
+ && strcasecmp( arg->literal, "month" )
+ && strcasecmp( arg->literal, "quarter" )
+ && strcasecmp( arg->literal, "second" )
+ && strcasecmp( arg->literal, "timezone" )
+ && strcasecmp( arg->literal, "timezone_hour" )
+ && strcasecmp( arg->literal, "timezone_minute" )
+ && strcasecmp( arg->literal, "week" )
+ && strcasecmp( arg->literal, "year" )) {
+ sqlAddMsg( state,
+ "Invalid name \"%s\" as EXTRACT argument in expression # %d",
+ expr->literal, expr->id );
+ state->error = 1;
+ }
+ }
+
+ buffer_add( state->sql, "EXTRACT(" );
+ buffer_add( state->sql, arg->literal );
+ buffer_add( state->sql, " FROM " );
+
+ arg = arg->next;
+ if( !arg ) {
+ sqlAddMsg( state,
+ "Only one argument supplied to EXTRACT function in expression # %d", expr->id );
+ state->error = 1;
+ return;
+ }
+
+ // The second parameter must be of type timestamp, time, or interval. We don't have
+ // a good way of checking it here, so we rely on PostgreSQL to complain if necessary.
+ buildExpression( state, arg );
+ buffer_add_char( state->sql, ')' );
+
+ if( arg->next ) {
+ sqlAddMsg( state,
+ "Too many one arguments supplied to EXTRACT function in expression # %d", expr->id );
+ state->error = 1;
+ return;
+ }
+}
+
+/**
@brief Build a series of expressions separated by a specified operator, or by commas.
@param state Pointer to the query-building context.
@param subexp_list Pointer to the first Expression in a linked list.
Modified: trunk/Open-ILS/src/c-apps/oils_storedq.c
===================================================================
--- trunk/Open-ILS/src/c-apps/oils_storedq.c 2010-07-01 02:29:21 UTC (rev 16841)
+++ trunk/Open-ILS/src/c-apps/oils_storedq.c 2010-07-01 02:29:38 UTC (rev 16842)
@@ -1766,13 +1766,8 @@
}
} else if( EXP_COLUMN == type ) {
- if( !column_name ) {
+ if( column_name && !is_identifier( column_name )) {
osrfLogWarning( OSRF_LOG_MARK, sqlAddMsg( state,
- "No column name for column expression # %d", id ));
- state->error = 1;
- return NULL;
- } else if( !is_identifier( column_name )) {
- osrfLogWarning( OSRF_LOG_MARK, sqlAddMsg( state,
"Column name \"%s\" is invalid identifier for expression # %d",
column_name, id ));
state->error = 1;
More information about the open-ils-commits
mailing list