3 @brief Excecute a specified SQL query and return the results.
9 #include "opensrf/utils.h"
10 #include "opensrf/log.h"
11 #include "opensrf/string_array.h"
12 #include "opensrf/osrf_json.h"
13 #include "openils/oils_buildq.h"
15 static jsonObject* get_row( BuildSQLState* state );
16 static jsonObject* get_date_column( dbi_result result, int col_idx );
19 @brief Execute the current SQL statement and return the first row.
20 @param state Pointer to the query-building context.
21 @return Pointer to a newly-allocated jsonObject representing the row, if there is one; or
24 The returned row is a JSON_ARRAY of column values, of which each is a JSON_STRING,
25 JSON_NUMBER, or JSON_NULL.
27 jsonObject* oilsFirstRow( BuildSQLState* state ) {
33 dbi_result_free( state->result );
36 state->result = dbi_conn_query( state->dbhandle, OSRF_BUFFER_C_STR( state->sql ));
37 if( !state->result ) {
40 (void) dbi_conn_error( state->dbhandle, &msg );
41 osrfLogError( OSRF_LOG_MARK, sqlAddMsg( state,
42 "Unable to execute query: %s",msg ? msg : "No description available" ));
47 if( dbi_result_first_row( state->result ))
48 return get_row( state );
50 dbi_result_free( state->result );
52 return NULL; // No rows returned
57 @brief Return the next row from a previously executed SQL statement.
58 @param state Pointer to the query-building context.
59 @return Pointer to a newly-allocated jsonObject representing the row, if there is one; or
62 The returned row is a JSON_ARRAY of column values, of which each is a JSON_STRING,
63 JSON_NUMBER, or JSON_NULL.
65 jsonObject* oilsNextRow( BuildSQLState* state ) {
67 if( !state || !state->result )
71 if( dbi_result_next_row( state->result ))
72 return get_row( state );
74 dbi_result_free( state->result );
76 return NULL; // No next row returned
81 @brief Construct a JSON representation of a returned row.
82 @param state Pointer to the query-building context.
83 @return Pointer to a newly-allocated jsonObject representing the row.
85 static jsonObject* get_row( BuildSQLState* state ) {
86 unsigned int col_count = dbi_result_get_numfields( state->result );
87 jsonObject* row = jsonNewObjectType( JSON_ARRAY );
90 for( i = 1; i <= col_count; ++i ) {
92 if( dbi_result_field_is_null_idx( state->result, i )) {
93 jsonObjectPush( row, jsonNewObjectType( JSON_NULL ));
94 continue; // Column is null
97 jsonObject* col_value = NULL;
98 int type = dbi_result_get_field_type_idx( state->result, i );
100 case DBI_TYPE_INTEGER : {
101 long long value = dbi_result_get_longlong_idx( state->result, i );
102 col_value = jsonNewNumberObject( (double) value );
105 case DBI_TYPE_DECIMAL : {
106 double value = dbi_result_get_double_idx( state->result, i );
107 col_value = jsonNewNumberObject( value );
110 case DBI_TYPE_STRING : {
111 const char* value = dbi_result_get_string_idx( state->result, i );
112 col_value = jsonNewObject( value );
115 case DBI_TYPE_BINARY : {
116 osrfLogError( OSRF_LOG_MARK, "Binary types not supported; column set to null" );
117 col_value = jsonNewObjectType( JSON_NULL );
120 case DBI_TYPE_DATETIME : {
121 col_value = get_date_column( state->result, i );
125 osrfLogError( OSRF_LOG_MARK,
126 "Unrecognized column type %d; column set to null", type );
127 col_value = jsonNewObjectType( JSON_NULL );
130 jsonObjectPush( row, col_value );
137 @brief Translate a date column into a string.
138 @param result Reference to the current returned row.
139 @param col_idx Column number (starting with 1) within the row.
140 @return Pointer to a newly-allocated JSON_STRING containing a formatted date string.
142 The calling code is responsible for freeing the returned jsonObject by calling
145 static jsonObject* get_date_column( dbi_result result, int col_idx ) {
147 time_t timestamp = dbi_result_get_datetime_idx( result, col_idx );
148 char timestring[ 256 ] = "";
149 int attr = dbi_result_get_field_attribs_idx( result, col_idx );
152 if( !( attr & DBI_DATETIME_DATE )) {
153 gmtime_r( ×tamp, &gmdt );
154 strftime( timestring, sizeof( timestring ), "%T", &gmdt );
155 } else if( !( attr & DBI_DATETIME_TIME )) {
156 localtime_r( ×tamp, &gmdt );
157 strftime( timestring, sizeof( timestring ), "%F", &gmdt );
159 localtime_r( ×tamp, &gmdt );
160 strftime( timestring, sizeof( timestring ), "%FT%T%z", &gmdt );
163 return jsonNewObject( timestring );