1. Support function calls in the FROM clause.
authorscottmk <scottmk@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Tue, 8 Jun 2010 21:01:27 +0000 (21:01 +0000)
committerscottmk <scottmk@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Tue, 8 Jun 2010 21:01:27 +0000 (21:01 +0000)
2. Support wildcards in the SELECT clause.

WARNING: the presence of a wildcard in the SELECT clause
is likely to disrupt a GROUP BY by renumbering the columns.

Also: the "columns" method currently cannot return the
names of the columns into which a wild card is expanded.

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

git-svn-id: svn://svn.open-ils.org/ILS/trunk@16628 dcc99617-32d9-48b4-a31d-7c20da2025e4

Open-ILS/include/openils/oils_buildq.h
Open-ILS/src/c-apps/buildSQL.c
Open-ILS/src/c-apps/oils_storedq.c

index 78ead41..f9cfe79 100644 (file)
@@ -108,6 +108,7 @@ struct FromRelation_ {
        int              subquery_id;
        StoredQ*         subquery;
        int              function_call_id;
+       Expression*      function_call;
        char*            table_alias;
        int              parent_relation_id;
        int              seq_no;
index 596e0ab..15cc46c 100644 (file)
@@ -372,7 +372,18 @@ static void buildFrom( BuildSQLState* state, const FromRelation* core_from ) {
                        buffer_add_char( state->sql, ')' );
                        break;
                case FRT_FUNCTION :
-                       sqlAddMsg( state, "Functions in FROM clause not yet supported" );
+                       buildFunction( state, core_from->function_call );
+                       if ( state->error ) {
+                               sqlAddMsg( state,
+                                       "Unable to include function call # %d in FROM relation # %d",
+                                       core_from->function_call->id, core_from->id );
+                               return;
+                       }
+                       break;
+               default :
+                       osrfLogError( OSRF_LOG_MARK, sqlAddMsg( state,
+                               "Internal error: Invalid type # %d in FROM relation # %d",
+                               core_from->type, core_from->id ));
                        state->error = 1;
                        return;
        }
@@ -683,9 +694,10 @@ static void buildExpression( BuildSQLState* state, const Expression* expr ) {
                        if( expr->column_name ) {
                                buffer_add( state->sql, expr->column_name );
                        } else {
-                               osrfLogWarning( OSRF_LOG_MARK, sqlAddMsg( state,
-                                       "Column name not present in expression # %d", expr->id ));
-                               state->error = 1;
+                               //osrfLogWarning( OSRF_LOG_MARK, sqlAddMsg( state,
+                               //      "Column name not present in expression # %d", expr->id ));
+                               //state->error = 1;
+                               buffer_add_char( state->sql, '*' );
                        }
                        break;
                case EXP_EXIST :
index a4bcc98..50e6ab8 100644 (file)
@@ -547,30 +547,31 @@ static FromRelation* constructFromRelation( BuildSQLState* state, dbi_result res
        else
                type = FRT_RELATION;     // shouldn't happen due to database constraint
 
-       const char* table_name  = dbi_result_get_string_idx( result, 3 );
-       const char* class_name  = dbi_result_get_string_idx( result, 4 );
+       const char* table_name   = dbi_result_get_string_idx( result, 3 );
+       const char* class_name   = dbi_result_get_string_idx( result, 4 );
 
        int subquery_id;
        if( dbi_result_field_is_null_idx( result, 5 ) )
-               subquery_id          = -1;
+               subquery_id           = -1;
        else
-               subquery_id          = dbi_result_get_int_idx( result, 5 );
+               subquery_id           = dbi_result_get_int_idx( result, 5 );
 
        int function_call_id;
        if( dbi_result_field_is_null_idx( result, 6 ) )
-               function_call_id     = -1;
+               function_call_id      = -1;
        else
-               function_call_id     = dbi_result_get_int_idx( result, 6 );
+               function_call_id      = dbi_result_get_int_idx( result, 6 );
 
-       const char* table_alias  = dbi_result_get_string_idx( result, 7 );
+       Expression* function_call = NULL;
+       const char* table_alias   = dbi_result_get_string_idx( result, 7 );
 
        int parent_relation_id;
        if( dbi_result_field_is_null_idx( result, 8 ) )
-               parent_relation_id   = -1;
+               parent_relation_id    = -1;
        else
-               parent_relation_id   = dbi_result_get_int_idx( result, 8 );
+               parent_relation_id    = dbi_result_get_int_idx( result, 8 );
 
-       int seq_no               = dbi_result_get_int_idx( result, 9 );
+       int seq_no                = dbi_result_get_int_idx( result, 9 );
 
        JoinType join_type;
        const char* join_type_str = dbi_result_get_string_idx( result, 10 );
@@ -620,10 +621,27 @@ static FromRelation* constructFromRelation( BuildSQLState* state, dbi_result res
                        }
                        break;
                case FRT_FUNCTION :
-                       osrfLogWarning( OSRF_LOG_MARK, sqlAddMsg( state,
-                               "Functions in FROM clause not yet supported" ));
-                       state->error = 1;
-                       return NULL;
+                       if( -1 == function_call_id ) {
+                               osrfLogWarning( OSRF_LOG_MARK, sqlAddMsg( state,
+                                       "FROM clause # %d purports to reference a function; not identified", id ));
+                               state->error = 1;
+                               return NULL;
+                       }
+
+                       function_call = getExpression( state, function_call_id );
+                       if( !function_call ) {
+                               osrfLogWarning( OSRF_LOG_MARK, sqlAddMsg( state,
+                                       "Unable to build function call # %d in FROM relation # %d",
+                                       function_call_id, id ));
+                               state->error = 1;
+                               return NULL;
+                       } else if( function_call->type != EXP_FUNCTION ) {
+                               osrfLogWarning( OSRF_LOG_MARK, sqlAddMsg( state,
+                                       "In FROM relation # %d: supposed function call expression # %d "
+                                       "is not a function call", id, function_call_id ));
+                               state->error = 1;
+                               return NULL;
+                       }
        }
 
        FromRelation* join_list = getJoinList( state, id );
@@ -666,6 +684,7 @@ static FromRelation* constructFromRelation( BuildSQLState* state, dbi_result res
        fr->subquery_id = subquery_id;
        fr->subquery = subquery;
        fr->function_call_id = function_call_id;
+       fr->function_call = function_call;
        fr->table_alias = table_alias ? strdup( table_alias ) : NULL;
        fr->parent_relation_id = parent_relation_id;
        fr->seq_no = seq_no;
@@ -757,6 +776,10 @@ static void fromRelationFree( FromRelation* fr ) {
                        storedQFree( fr->subquery );
                        fr->subquery = NULL;
                }
+               if( fr->function_call ) {
+                       expressionFree( fr->function_call );
+                       fr->function_call = NULL;
+               }
                free( fr->table_alias );
                fr->table_alias = NULL;
                if( fr->on_clause ) {