template<> StrVec GncDbiProviderImpl<DbType::DBI_MYSQL>::get_index_list (dbi_conn conn) { StrVec retval; const char* errmsg; auto tables = get_table_list(conn, ""); for (auto table_name : tables) { auto result = dbi_conn_queryf (conn, "SHOW INDEXES IN %s WHERE Key_name != 'PRIMARY'", table_name.c_str()); if (dbi_conn_error (conn, &errmsg) != DBI_ERROR_NONE) { PWARN ("Index Table Retrieval Error: %s on table %s\n", errmsg, table_name.c_str()); continue; } while (dbi_result_next_row (result) != 0) { std::string index_name {dbi_result_get_string_idx (result, 3)}; retval.push_back(index_name + " " + table_name); } dbi_result_free (result); } return retval; }
time_t SMSDDBI_GetDate(GSM_SMSDConfig * Config, SQL_result *res, unsigned int field) { unsigned int type; const char *date; field++; type = dbi_result_get_field_type_idx(res->dbi, field); switch (type) { case DBI_TYPE_INTEGER: case DBI_TYPE_DECIMAL: #ifdef DBI_TYPE_XDECIMAL case DBI_TYPE_XDECIMAL: #endif return SMSDDBI_GetNumber(Config, res, field); case DBI_TYPE_STRING: date = dbi_result_get_string_idx(res->dbi, field); return SMSDSQL_ParseDate(Config, date); case DBI_TYPE_DATETIME: return dbi_result_get_datetime_idx(res->dbi, field); case DBI_TYPE_ERROR: default: SMSD_Log(DEBUG_ERROR, Config, "Wrong field type for date from DBI: %d", type); return -1; } }
/** @brief Return a boolean value from a database result. @param result The database result. @param i Index of the column in the result, starting with 1 ); @return 1 if true, or 0 for false. Null values and error conditions are interpreted as FALSE. */ static int oils_result_get_bool_idx( dbi_result result, int i ) { if( result ) { const char* str = dbi_result_get_string_idx( result, i ); return (str && *str == 't' ) ? 1 : 0; } else return 0; }
gboolean SMSDDBI_GetBool(GSM_SMSDConfig * Config, SQL_result *res, unsigned int field) { unsigned int type; const char *value; int num; field++; type = dbi_result_get_field_type_idx(res->dbi, field); switch (type) { case DBI_TYPE_INTEGER: case DBI_TYPE_DECIMAL: #ifdef DBI_TYPE_XDECIMAL case DBI_TYPE_XDECIMAL: #endif num = SMSDDBI_GetNumber(Config, res, field); if (num == -1) { return -1; } else if (num == 0) { return FALSE; } else { return TRUE; } case DBI_TYPE_STRING: value = dbi_result_get_string_idx(res->dbi, field); return GSM_StringToBool(value); case DBI_TYPE_ERROR: default: SMSD_Log(DEBUG_ERROR, Config, "Wrong field type for boolean from DBI: %d", type); return -1; } }
static xmlNodePtr query_doc(dbi_result *result, char *query_name) { char *elt; unsigned long mylong; char buffer[100]; unsigned int i; xmlDocPtr doc = NULL; xmlNodePtr top_query = NULL, query_row = NULL; doc = xmlNewDoc(BAD_CAST "1.0"); top_query = xmlNewNode(NULL, BAD_CAST query_name); xmlDocSetRootElement(doc, top_query); while (dbi_result_next_row(result)) { query_row = xmlNewChild(top_query, NULL, BAD_CAST query_name,NULL); for (i=1; i < dbi_result_get_numfields(result) + 1; i++) { elt = strdup(dbi_result_get_field_name(result,i)); if (dbi_result_get_field_type_idx(result,i) == 3) { if (dbi_result_get_string_idx(result,i)) { xmlNewChild(query_row, NULL, BAD_CAST elt, BAD_CAST dbi_result_get_string_idx(result,i)); } } if (dbi_result_get_field_type_idx(result,i) == 1) { if (dbi_result_get_ulonglong_idx(result,i)) { mylong = dbi_result_get_ulonglong_idx(result,i); sprintf(buffer, "%ld", mylong); xmlNewChild(query_row, NULL, BAD_CAST elt, BAD_CAST buffer); } } } } return xmlDocGetRootElement(doc); xmlFreeDoc(doc); xmlCleanupParser(); }
static int cdbi_result_get_field (dbi_result res, /* {{{ */ unsigned int index, char *buffer, size_t buffer_size) { unsigned short src_type; src_type = dbi_result_get_field_type_idx (res, index); if (src_type == DBI_TYPE_ERROR) { ERROR ("dbi plugin: cdbi_result_get: " "dbi_result_get_field_type_idx failed."); return (-1); } if (src_type == DBI_TYPE_INTEGER) { long long value; value = dbi_result_get_longlong_idx (res, index); ssnprintf (buffer, buffer_size, "%lli", value); } else if (src_type == DBI_TYPE_DECIMAL) { double value; value = dbi_result_get_double_idx (res, index); ssnprintf (buffer, buffer_size, "%63.15g", value); } else if (src_type == DBI_TYPE_STRING) { const char *value; value = dbi_result_get_string_idx (res, index); if (value == NULL) sstrncpy (buffer, "", buffer_size); else if (strcmp ("ERROR", value) == 0) return (-1); else sstrncpy (buffer, value, buffer_size); } /* DBI_TYPE_BINARY */ /* DBI_TYPE_DATETIME */ else { const char *field_name; field_name = dbi_result_get_field_name (res, index); if (field_name == NULL) field_name = "<unknown>"; ERROR ("dbi plugin: Column `%s': Don't know how to handle " "source type %hu.", field_name, src_type); return (-1); } return (0); } /* }}} int cdbi_result_get_field */
static double rrd_fetch_dbi_double(dbi_result *result,int idx) { char *ptmp=""; double value=DNAN; /* get the attributes for this filed */ unsigned int attr=dbi_result_get_field_attribs_idx(result,idx); unsigned int type=dbi_result_get_field_type_idx(result,idx); /* return NAN if NULL */ if(dbi_result_field_is_null_idx(result,idx)) { return DNAN; } /* do some conversions */ switch (type) { case DBI_TYPE_STRING: ptmp=(char*)dbi_result_get_string_idx(result,idx); value=strtod(ptmp,NULL); break; case DBI_TYPE_INTEGER: if (attr & DBI_INTEGER_SIZE1) { value=dbi_result_get_char_idx(result,idx); } else if (attr & DBI_INTEGER_SIZE2) { value=dbi_result_get_short_idx(result,idx); } else if (attr & DBI_INTEGER_SIZE3) { value=dbi_result_get_int_idx(result,idx); } else if (attr & DBI_INTEGER_SIZE4) { value=dbi_result_get_int_idx(result,idx); } else if (attr & DBI_INTEGER_SIZE8) { value=dbi_result_get_longlong_idx(result,idx); } else { value=DNAN; if (getenv("RRDDEBUGSQL")) { fprintf(stderr,"RRDDEBUGSQL: %li: column %i unsupported attribute flags %i for type INTEGER\n",time(NULL),idx,attr ); } } break; case DBI_TYPE_DECIMAL: if (attr & DBI_DECIMAL_SIZE4) { value=dbi_result_get_float_idx(result,idx); } else if (attr & DBI_DECIMAL_SIZE8) { value=dbi_result_get_double_idx(result,idx); } else { value=DNAN; if (getenv("RRDDEBUGSQL")) { fprintf(stderr,"RRDDEBUGSQL: %li: column %i unsupported attribute flags %i for type DECIMAL\n",time(NULL),idx,attr ); } } break; case DBI_TYPE_BINARY: attr=dbi_result_get_field_length_idx(result,idx); ptmp=(char*)dbi_result_get_binary_copy_idx(result,idx); ptmp[attr-1]=0; /* check for "known" libdbi error */ if (strncmp("ERROR",ptmp,5)==0) { if (!getenv("RRD_NO_LIBDBI_BUG_WARNING")) { fprintf(stderr,"rrdtool_fetch_libDBI: you have possibly triggered a bug in libDBI by using a (TINY,MEDIUM,LONG) TEXT field with mysql\n this may trigger a core dump in at least one version of libdbi\n if you are not touched by this bug and you find this message annoying\n please set the environment-variable RRD_NO_LIBDBI_BUG_WARNING to ignore this message\n"); } } /* convert to number */ value=strtod(ptmp,NULL); /* free pointer */ free(ptmp); break; case DBI_TYPE_DATETIME: value=dbi_result_get_datetime_idx(result,idx); break; default: if (getenv("RRDDEBUGSQL")) { fprintf(stderr,"RRDDEBUGSQL: %li: column %i unsupported type: %i with attribute %i\n",time(NULL),idx,type,attr ); } value=DNAN; break; } return value; }
//******************************************************************* // Get the results of the MySQL query into our probe_def structure //******************************************************************* static void mysql_set_def_fields(trx *t, struct probe_def *probedef, dbi_result result) { struct mysql_def *def = (struct mysql_def *) probedef; if (dbi_result_next_row(result)) { def->ipaddress = dbi_result_get_string_copy_idx(result, 0); def->description = dbi_result_get_string_copy_idx(result, 1); def->server = dbi_result_get_uint_idx(result, 2); def->yellow = dbi_result_get_float_idx(result, 3); def->red = dbi_result_get_float_idx(result, 4); def->contact = dbi_result_get_float_idx(result, 5); if (dbi_result_get_string_idx(result, 6)) { strcpy(def->hide, dbi_result_get_string_idx(result, 6)); } else { strcpy(def->hide, "no"); } if (dbi_result_get_string_idx(result, 7)) { strcpy(def->email, dbi_result_get_string_idx(result, 7)); } else { strcpy(def->email, ""); } if (dbi_result_get_string_idx(result, 8)) { strcpy(def->sms, dbi_result_get_string_idx(result, 8)); } else { strcpy(def->sms, ""); } def->delay = dbi_result_get_uint_idx(result, 9); def->dbname = dbi_result_get_string_copy_idx(result, 10); def->dbuser = dbi_result_get_string_copy_idx(result, 11); def->dbpasswd = dbi_result_get_string_copy_idx(result, 12); def->query = dbi_result_get_string_copy_idx(result, 13); } }
const char *dbi_result_get_string(dbi_result Result, const char *fieldname) { const char *ERROR = "ERROR"; unsigned int fieldidx; dbi_error_flag errflag; fieldidx = _find_field(RESULT, fieldname, &errflag); if (errflag != DBI_ERROR_NONE) { dbi_conn_t *conn = RESULT->conn; _error_handler(conn, DBI_ERROR_BADNAME); return ERROR; } return dbi_result_get_string_idx(Result, fieldidx+1); }
/** * SQL callback. Return an integer from a query * * @param return_integer integer pointer cast to void* which holds the integer to be returned * @param result dbi_result pointer * @return 0 (always, due to SQLite policy, may change in the future) */ int tagsistant_return_integer(void *return_integer, dbi_result result) { uint32_t *buffer = (uint32_t *) return_integer; *buffer = 0; unsigned int type = dbi_result_get_field_type_idx(result, 1); if (type == DBI_TYPE_INTEGER) { unsigned int size = dbi_result_get_field_attribs_idx(result, 1); unsigned int is_unsigned = size & DBI_INTEGER_UNSIGNED; size = size & DBI_INTEGER_SIZEMASK; switch (size) { case DBI_INTEGER_SIZE8: if (is_unsigned) *buffer = dbi_result_get_ulonglong_idx(result, 1); else *buffer = dbi_result_get_longlong_idx(result, 1); break; case DBI_INTEGER_SIZE4: case DBI_INTEGER_SIZE3: if (is_unsigned) *buffer = dbi_result_get_uint_idx(result, 1); else *buffer = dbi_result_get_int_idx(result, 1); break; case DBI_INTEGER_SIZE2: if (is_unsigned) *buffer = dbi_result_get_ushort_idx(result, 1); else *buffer = dbi_result_get_short_idx(result, 1); break; case DBI_INTEGER_SIZE1: if (is_unsigned) *buffer = dbi_result_get_uchar_idx(result, 1); else *buffer = dbi_result_get_char_idx(result, 1); break; } } else if (type == DBI_TYPE_DECIMAL) { return (0); } else if (type == DBI_TYPE_STRING) { const gchar *int_string = dbi_result_get_string_idx(result, 1); *buffer = atoi(int_string); dbg('s', LOG_INFO, "tagsistant_return_integer called on non integer field"); } dbg('s', LOG_INFO, "Returning integer: %d", *buffer); return (0); }
static StrVec conn_get_table_list (dbi_conn conn, const std::string& dbname, const std::string& table) { StrVec retval; const char* tableptr = (table.empty() ? nullptr : table.c_str()); auto tables = dbi_conn_get_table_list (conn, dbname.c_str(), tableptr); while (dbi_result_next_row (tables) != 0) { std::string table_name {dbi_result_get_string_idx (tables, 1)}; retval.push_back(table_name); } dbi_result_free (tables); return retval; }
/* checks mysql sql_options and adjusts if necessary */ static void adjust_sql_options (dbi_conn connection) { dbi_result result = dbi_conn_query( connection, "SELECT @@sql_mode"); if (result == nullptr) { const char* errmsg; int err = dbi_conn_error(connection, &errmsg); PERR("Unable to read sql_mode %d : %s", err, errmsg); return; } dbi_result_first_row(result); std::string str{dbi_result_get_string_idx(result, 1)}; dbi_result_free(result); if (str.empty()) { const char* errmsg; int err = dbi_conn_error(connection, &errmsg); if (err) PERR("Unable to get sql_mode %d : %s", err, errmsg); else PINFO("Sql_mode isn't set."); return; } PINFO("Initial sql_mode: %s", str.c_str()); if(str.find(SQL_OPTION_TO_REMOVE) == std::string::npos) return; std::string adjusted_str{adjust_sql_options_string(str)}; PINFO("Setting sql_mode to %s", adjusted_str.c_str()); std::string set_str{"SET sql_mode=" + std::move(adjusted_str)}; dbi_result set_result = dbi_conn_query(connection, set_str.c_str()); if (set_result) { dbi_result_free(set_result); } else { const char* errmsg; int err = dbi_conn_error(connection, &errmsg); PERR("Unable to set sql_mode %d : %s", err, errmsg); } }
int dbiw_res_get_string_ndx(db_wrap_result * self, unsigned int ndx, char const ** val, size_t * len) { RES_DECL(DB_WRAP_E_BAD_ARG); if (! val) return DB_WRAP_E_BAD_ARG; char const * str = dbi_result_get_string_idx(dbires, ndx +1); if (len) { *len = (str && *str) ? strlen(str) : 0; } if (!str || (0==strcmp("ERROR",str))) { /* libdbi is JUST WRONG here. The convention of using the string "ERROR" to report an error is downright broken, because it prohibits that string as a value in my db. */ return DB_WRAP_E_CHECK_DB_ERROR; } *val = str; return 0; }
template<> StrVec GncDbiProviderImpl<DbType::DBI_SQLITE>::get_index_list (dbi_conn conn) { StrVec retval; const char* errmsg; dbi_result result = dbi_conn_query (conn, "SELECT name FROM sqlite_master WHERE type = 'index' AND name NOT LIKE 'sqlite_autoindex%'"); if (dbi_conn_error (conn, &errmsg) != DBI_ERROR_NONE) { PWARN ("Index Table Retrieval Error: %s\n", errmsg); return retval; } while (dbi_result_next_row (result) != 0) { std::string index_name {dbi_result_get_string_idx (result, 1)}; retval.push_back(index_name); } dbi_result_free (result); return retval; }
template<> StrVec GncDbiProviderImpl<DbType::DBI_PGSQL>::get_index_list (dbi_conn conn) { StrVec retval; const char* errmsg; PINFO ("Retrieving postgres index list\n"); auto result = dbi_conn_query (conn, "SELECT relname FROM pg_class AS a INNER JOIN pg_index AS b ON (b.indexrelid = a.oid) INNER JOIN pg_namespace AS c ON (a.relnamespace = c.oid) WHERE reltype = '0' AND indisprimary = 'f' AND nspname = 'public'"); if (dbi_conn_error (conn, &errmsg) != DBI_ERROR_NONE) { PWARN("Index Table Retrieval Error: %s\n", errmsg); return retval; } while (dbi_result_next_row (result) != 0) { std::string index_name {dbi_result_get_string_idx (result, 1)}; retval.push_back(index_name); } dbi_result_free (result); return retval; }
static SelectItem* constructSelectItem( BuildSQLState* state, dbi_result result ) { // Get the column values int id = dbi_result_get_int_idx( result, 1 ); int stored_query_id = dbi_result_get_int_idx( result, 2 ); int seq_no = dbi_result_get_int_idx( result, 3 ); int expression_id = dbi_result_get_int_idx( result, 4 ); const char* column_alias = dbi_result_get_string_idx( result, 5 ); int grouped_by = oils_result_get_bool_idx( result, 6 ); // Construct an Expression Expression* expression = getExpression( state, expression_id ); if( !expression ) { osrfLogError( OSRF_LOG_MARK, sqlAddMsg( state, "Unable to fetch expression for id = %d", expression_id )); return NULL; }; // Allocate a SelectItem: from the free list if possible, from the heap if necessary SelectItem* sel; if( free_select_item_list ) { sel = free_select_item_list; free_select_item_list = free_select_item_list->next; } else sel = safe_malloc( sizeof( SelectItem ) ); sel->next = NULL; sel->id = id; sel->stored_query_id = stored_query_id; sel->seq_no = seq_no; sel->expression = expression; sel->column_alias = column_alias ? strdup( column_alias ) : NULL; sel->grouped_by = grouped_by; return sel; }
const char *SMSDDBI_GetString(GSM_SMSDConfig * Config, SQL_result *res, unsigned int col) { return dbi_result_get_string_idx(res->dbi, col+1); }
static StoredQ* constructStoredQ( BuildSQLState* state, dbi_result result ) { // Get the column values from the result int id = dbi_result_get_int_idx( result, 1 ); const char* type_str = dbi_result_get_string_idx( result, 2 ); QueryType type; if( !strcmp( type_str, "SELECT" )) type = QT_SELECT; else if( !strcmp( type_str, "UNION" )) type = QT_UNION; else if( !strcmp( type_str, "INTERSECT" )) type = QT_INTERSECT; else if( !strcmp( type_str, "EXCEPT" )) type = QT_EXCEPT; else { osrfLogError( OSRF_LOG_MARK, sqlAddMsg( state, "Invalid query type \"%s\"", type_str )); return NULL; } int use_all = oils_result_get_bool_idx( result, 3 ); int use_distinct = oils_result_get_bool_idx( result, 4 ); int from_clause_id; if( dbi_result_field_is_null_idx( result, 5 ) ) from_clause_id = -1; else from_clause_id = dbi_result_get_int_idx( result, 5 ); int where_clause_id; if( dbi_result_field_is_null_idx( result, 6 ) ) where_clause_id = -1; else where_clause_id = dbi_result_get_int_idx( result, 6 ); int having_clause_id; if( dbi_result_field_is_null_idx( result, 7 ) ) having_clause_id = -1; else having_clause_id = dbi_result_get_int_idx( result, 7 ); FromRelation* from_clause = NULL; if( QT_SELECT == type ) { // A SELECT query needs a FROM clause; go get it if( from_clause_id != -1 ) { from_clause = getFromRelation( state, from_clause_id ); if( !from_clause ) { osrfLogError( OSRF_LOG_MARK, sqlAddMsg( state, "Unable to construct FROM clause for id = %d", from_clause_id )); return NULL; } } } else { // Must be one of UNION, INTERSECT, or EXCEPT if( from_clause_id != -1 ) osrfLogWarning( OSRF_LOG_MARK, sqlAddMsg( state, "FROM clause found and ignored for %s query in query #%d", type_str, id )); } // If this is a SELECT query, we need a SELECT list. Go get one. SelectItem* select_list = NULL; QSeq* child_list = NULL; if( QT_SELECT == type ) { select_list = getSelectList( state, id ); if( !select_list ) { osrfLogWarning( OSRF_LOG_MARK, sqlAddMsg( state, "No SELECT list found for query id = %d", id )); fromRelationFree( from_clause ); return NULL; } } else { // Construct child queries of UNION, INTERSECT, or EXCEPT query child_list = loadChildQueries( state, id, type_str ); if( !child_list ) { osrfLogWarning( OSRF_LOG_MARK, sqlAddMsg( state, "Unable to load child queries for %s query # %d", type_str, id )); state->error = 1; fromRelationFree( from_clause ); return NULL; } } // Get the WHERE clause, if there is one Expression* where_clause = NULL; if( where_clause_id != -1 ) { where_clause = getExpression( state, where_clause_id ); if( ! where_clause ) { // shouldn't happen due to foreign key constraint osrfLogError( OSRF_LOG_MARK, sqlAddMsg( state, "Unable to fetch WHERE expression for query id = %d", id )); 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( 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; if( free_storedq_list ) { sq = free_storedq_list; free_storedq_list = free_storedq_list->next; } else sq = safe_malloc( sizeof( StoredQ ) ); // Populate the StoredQ sq->next = NULL; sq->id = id; sq->type = type; sq->use_all = use_all; sq->use_distinct = use_distinct; sq->from_clause = from_clause; sq->where_clause = where_clause; sq->select_list = select_list; sq->child_list = child_list; sq->order_by_list = order_by_list; return sq; }
static FromRelation* constructFromRelation( BuildSQLState* state, dbi_result result ) { // Get the column values from the result int id = dbi_result_get_int_idx( result, 1 ); const char* type_str = dbi_result_get_string_idx( result, 2 ); FromRelationType type; if( !strcmp( type_str, "RELATION" )) type = FRT_RELATION; else if( !strcmp( type_str, "SUBQUERY" )) type = FRT_SUBQUERY; else if( !strcmp( type_str, "FUNCTION" )) type = FRT_FUNCTION; 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 ); int subquery_id; if( dbi_result_field_is_null_idx( result, 5 ) ) subquery_id = -1; else 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; else function_call_id = dbi_result_get_int_idx( result, 6 ); 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; else parent_relation_id = dbi_result_get_int_idx( result, 8 ); 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 ); if( !join_type_str ) join_type = JT_NONE; else if( !strcmp( join_type_str, "INNER" ) ) join_type = JT_INNER; else if( !strcmp( join_type_str, "LEFT" ) ) join_type = JT_LEFT; else if( !strcmp( join_type_str, "RIGHT" ) ) join_type = JT_RIGHT; else if( !strcmp( join_type_str, "FULL" ) ) join_type = JT_FULL; else join_type = JT_NONE; // shouldn't happen due to database constraint int on_clause_id; if( dbi_result_field_is_null_idx( result, 11 ) ) on_clause_id = -1; else on_clause_id = dbi_result_get_int_idx( result, 11 ); StoredQ* subquery = NULL; switch ( type ) { case FRT_RELATION : break; case FRT_SUBQUERY : if( -1 == subquery_id ) { osrfLogWarning( OSRF_LOG_MARK, sqlAddMsg( state, "Internal error: no subquery specified for FROM relation # %d", id )); state->error = 1; return NULL; } if( ! table_alias ) { osrfLogWarning( OSRF_LOG_MARK, sqlAddMsg( state, "Subquery needs alias in FROM relation # %d", id )); state->error = 1; return NULL; } subquery = getStoredQuery( state, subquery_id ); if( ! subquery ) { osrfLogWarning( OSRF_LOG_MARK, sqlAddMsg( state, "Unable to load subquery for FROM relation # %d", id )); state->error = 1; return NULL; } break; case FRT_FUNCTION : osrfLogWarning( OSRF_LOG_MARK, sqlAddMsg( state, "Functions in FROM clause not yet supported" )); state->error = 1; return NULL; } FromRelation* join_list = getJoinList( state, id ); if( state->error ) { osrfLogWarning( OSRF_LOG_MARK, sqlAddMsg( state, "Unable to load join list for FROM relation # %d", id )); return NULL; } Expression* on_clause = NULL; if( on_clause_id != -1 ) { on_clause = getExpression( state, on_clause_id ); if( !on_clause ) { osrfLogWarning( OSRF_LOG_MARK, sqlAddMsg( state, "Unable to load ON condition for FROM relation # %d", id )); joinListFree( join_list ); return NULL; } else PRINT( "\tGot an ON condition\n" ); } // Allocate a FromRelation: from the free list if possible, from the heap if necessary FromRelation* fr; if( free_from_relation_list ) { fr = free_from_relation_list; free_from_relation_list = free_from_relation_list->next; } else fr = safe_malloc( sizeof( FromRelation ) ); // Populate the FromRelation fr->next = NULL; fr->id = id; fr->type = type; fr->table_name = table_name ? strdup( table_name ) : NULL; fr->class_name = class_name ? strdup( class_name ) : NULL; fr->subquery_id = subquery_id; fr->subquery = subquery; fr->function_call_id = function_call_id; fr->table_alias = table_alias ? strdup( table_alias ) : NULL; fr->parent_relation_id = parent_relation_id; fr->seq_no = seq_no; fr->join_type = join_type; fr->on_clause = on_clause; fr->join_list = join_list; return fr; }
static Expression* constructExpression( BuildSQLState* state, dbi_result result ) { int id = dbi_result_get_int_idx( result, 1 ); const char* type_str = dbi_result_get_string_idx( result, 2 ); ExprType type; if( !strcmp( type_str, "xbet" )) type = EXP_BETWEEN; else if( !strcmp( type_str, "xbool" )) type = EXP_BOOL; else if( !strcmp( type_str, "xcase" )) type = EXP_CASE; else if( !strcmp( type_str, "xcast" )) type = EXP_CAST; else if( !strcmp( type_str, "xcol" )) type = EXP_COLUMN; else if( !strcmp( type_str, "xex" )) type = EXP_EXIST; else if( !strcmp( type_str, "xfld" )) type = EXP_FIELD; else if( !strcmp( type_str, "xfunc" )) 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" )) type = EXP_NUMBER; else if( !strcmp( type_str, "xop" )) type = EXP_OPERATOR; else if( !strcmp( type_str, "xstr" )) type = EXP_STRING; else if( !strcmp( type_str, "xsubq" )) type = EXP_SUBQUERY; else type = EXP_NULL; // shouldn't happen due to database constraint int parenthesize = oils_result_get_bool_idx( result, 3 ); int parent_expr_id; if( dbi_result_field_is_null_idx( result, 4 )) parent_expr_id = -1; else parent_expr_id = dbi_result_get_int_idx( result, 4 ); int seq_no = dbi_result_get_int_idx( result, 5 ); const char* literal = dbi_result_get_string_idx( result, 6 ); const char* table_alias = dbi_result_get_string_idx( result, 7 ); const char* column_name = dbi_result_get_string_idx( result, 8 ); int left_operand_id; if( dbi_result_field_is_null_idx( result, 9 )) left_operand_id = -1; else left_operand_id = dbi_result_get_int_idx( result, 9 ); const char* operator = dbi_result_get_string_idx( result, 10 ); int right_operand_id; if( dbi_result_field_is_null_idx( result, 11 )) right_operand_id = -1; else right_operand_id = dbi_result_get_int_idx( result, 11 ); int function_id; if( dbi_result_field_is_null_idx( result, 12 )) function_id = -1; else function_id = dbi_result_get_int_idx( result, 12 ); int subquery_id; if( dbi_result_field_is_null_idx( result, 13 )) subquery_id = -1; else subquery_id = dbi_result_get_int_idx( result, 13 ); int cast_type_id; if( dbi_result_field_is_null_idx( result, 14 )) cast_type_id = -1; else cast_type_id = dbi_result_get_int_idx( result, 14 ); Expression* left_operand = NULL; Expression* right_operand = NULL; StoredQ* subquery = NULL; if( EXP_OPERATOR == type ) { // Load left and/or right operands if( -1 == left_operand_id && -1 == right_operand_id ) { osrfLogWarning( OSRF_LOG_MARK, sqlAddMsg( state, "Expression # %d is an operator with no operands", id )); state->error = 1; return NULL; } if( left_operand_id != -1 ) { left_operand = getExpression( state, left_operand_id ); if( !left_operand ) { osrfLogWarning( OSRF_LOG_MARK, sqlAddMsg( state, "Unable to get left operand in expression # %d", id )); state->error = 1; return NULL; } } if( right_operand_id != -1 ) { right_operand = getExpression( state, right_operand_id ); if( !right_operand ) { osrfLogWarning( OSRF_LOG_MARK, sqlAddMsg( state, "Unable to get right operand in expression # %d", id )); state->error = 1; expressionFree( left_operand ); return NULL; } } } else if( EXP_IN == type ) { if( -1 == left_operand_id ) { osrfLogWarning( OSRF_LOG_MARK, sqlAddMsg( state, "IN condition has no left operand in expression # %d", id )); state->error = 1; return NULL; } else { left_operand = getExpression( state, left_operand_id ); if( !left_operand ) { osrfLogWarning( OSRF_LOG_MARK, sqlAddMsg( state, "Unable to get left operand for IN condition in expression # %d", id )); state->error = 1; return NULL; } } if( -1 == subquery_id ) { // To do: load IN list of subexpressions osrfLogWarning( OSRF_LOG_MARK, sqlAddMsg( state, "IN lists not yet supported for expression # %d", id )); state->error = 1; return NULL; } else { subquery = getStoredQuery( state, subquery_id ); if( !subquery ) { osrfLogWarning( OSRF_LOG_MARK, sqlAddMsg( state, "Unable to load subquery for IN expression # %d", id )); state->error = 1; return NULL; } } } else if( EXP_EXIST == type ) { if( -1 == subquery_id ) { osrfLogWarning( OSRF_LOG_MARK, sqlAddMsg( state, "Internal error: No subquery found for EXIST expression # %d", id )); state->error = 1; return NULL; } else { subquery = getStoredQuery( state, subquery_id ); if( !subquery ) { osrfLogWarning( OSRF_LOG_MARK, sqlAddMsg( state, "Unable to load subquery for EXIST expression # %d", id )); state->error = 1; return NULL; } } } else if( EXP_SUBQUERY == type ) { if( -1 == subquery_id ) { osrfLogWarning( OSRF_LOG_MARK, sqlAddMsg( state, "Subquery expression # %d has no query id", id )); state->error = 1; return NULL; } else { // Load a subquery, if there is one subquery = getStoredQuery( state, subquery_id ); if( !subquery ) { osrfLogWarning( OSRF_LOG_MARK, sqlAddMsg( state, "Unable to load subquery for expression # %d", id )); state->error = 1; return NULL; } if( subquery->select_list && subquery->select_list->next ) { osrfLogWarning( OSRF_LOG_MARK, sqlAddMsg( state, "Subquery # %d as expression returns more than one column", subquery_id )); state->error = 1; return NULL; } PRINT( "\tExpression is subquery %d\n", subquery_id ); } } // Allocate an Expression: from the free list if possible, from the heap if necessary Expression* exp = NULL; if( free_expression_list ) { exp = free_expression_list; free_expression_list = free_expression_list->next; } else exp = safe_malloc( sizeof( Expression ) ); // Populate the Expression exp->next = NULL; exp->id = id; exp->type = type; exp->parenthesize = parenthesize; exp->parent_expr_id = parent_expr_id; exp->seq_no = seq_no; exp->literal = literal ? strdup( literal ) : NULL; exp->table_alias = table_alias ? strdup( table_alias ) : NULL; exp->column_name = column_name ? strdup( column_name ) : NULL; exp->left_operand = left_operand; exp->op = operator ? strdup( operator ) : NULL; exp->right_operand = right_operand; exp->function_id = function_id; exp->subquery_id = subquery_id; exp->subquery = subquery; exp->cast_type_id = subquery_id; return exp; }