VALUE rb_drizzle_query_row_next(VALUE self) { net_drizzle_query_st *context; Data_Get_Struct(self, net_drizzle_query_st, context); if ( context->query->result == NULL ) { // hmm. It should raise some Exception? return Qnil; } drizzle_row_t row = drizzle_row_next(context->query->result); if ( row == NULL ) { return Qnil; } uint16_t cnt = drizzle_result_column_count(context->query->result); VALUE result = rb_ary_new2(cnt); int i; for( i = 0; i < cnt; i++ ) { if ( row[i] ) { // FIXME: hmm. it may not be "UTF-8" string. rb_ary_push(result, rb_utf8_str_new(row[i], strlen(row[i]))); } else { rb_ary_push(result, Qnil); } } return result; }
static PyObject* get_desc(result_t *r, drizzle_con_st *con, drizzle_result_st *result) { int status = 1, desclen = 0; uint16_t size = 0; drizzle_return_t ret; drizzle_column_st column; drizzle_column_st *c; PyObject *c_info = NULL; PyObject *desc = NULL; drizzle_column_type_t *types = NULL; size = drizzle_result_column_count(result); DEBUG("column count:%d" , size); r->column_count = size; types = PyMem_Malloc(sizeof(drizzle_column_type_t) * size); if (types == NULL) { return NULL; } r->types = types; desc = PyTuple_New(size); if (desc == NULL) { return NULL; } while (1) { c = drizzle_column_read(result, &column, &ret); status = io_wait(con, ret); if (status == -1) { goto error; } if (c == NULL) { break; } else { c_info = get_column_desc(desclen, types, &column); if (c_info == NULL) { goto error; } PyTuple_SetItem(desc, desclen, c_info); c_info = NULL; drizzle_column_free(c); desclen++; } } return desc; error: if (c) { drizzle_column_free(c); } if (c_info) { Py_DECREF(c_info); } if (desc) { Py_DECREF(desc); } return NULL; }
VALUE downpour_wrap_row(VALUE self, drizzle_result_st *self_ptr, drizzle_row_t row) { // No more rows to read :-) if(row == NULL) return Qnil; ResultExtraInfo *extra_info = downpour_get_extra_pointer(self); return to_results_array(row, drizzle_result_column_count(self_ptr), extra_info->columns); }
static VALUE get_columns_in_array(drizzle_result_st *self_ptr, VALUE self, ResultExtraInfo *extra_info) { int i, number_of_columns = drizzle_result_column_count(self_ptr); VALUE array = rb_ary_new2(number_of_columns); for (i = 0; i < number_of_columns; i++) rb_ary_push(array, downpour_column_constructor(extra_info->columns[i], self)); return array; }
static ResultExtraInfo *extra_info(drizzle_result_st *self_ptr) { buffer_column_if_needed(self_ptr); ResultExtraInfo *result = drizzle_alloc(ResultExtraInfo); int i, number_of_columns = drizzle_result_column_count(self_ptr); result->columns = malloc(sizeof(drizzle_column_st *) * (number_of_columns + 1)); for (i = 0; i < number_of_columns; i++) { result->columns[i] = next_column(self_ptr); } result->columns[number_of_columns] = NULL; return result; }
/* NOTE that both db_context_t and sql_result_t have a drizzle_result_t, dbc->drizzle_result_set and sql_result->result_set When calling drizzle_query_str, second argment is a drizzle_result_t type. so in dbt2_sql_execute, we will use sql_result->result_set. Other routines will use dbc->drizzle_result_set but do not do anything with the results */ int dbt2_sql_execute(struct db_context_t *dbc, char * query, struct sql_result_t * sql_result, char * query_name) { sql_result->result_set= NULL; sql_result->num_columns= 0; sql_result->num_rows= 0; sql_result->query=query; sql_result->result_set= drizzle_query_str(dbc->drizzle_con, NULL, query, &drizzle_return); if (drizzle_return != DRIZZLE_RETURN_OK) { LOG_ERROR_MESSAGE("drizzle_query %s failed: %s\n", query, drizzle_con_error(dbc->drizzle_con)); return 0; } else { drizzle_return = drizzle_result_buffer(sql_result->result_set); if (drizzle_return != DRIZZLE_RETURN_OK) { printf("drizzle_result_buffer:%s\n", drizzle_con_error(dbc->drizzle_con)); return 0; /* if we have rows return then we have a SELECT statement */ } if (sql_result->result_set->row_count) { sql_result->num_columns= drizzle_result_column_count(sql_result->result_set); sql_result->num_rows= sql_result->result_set->row_count; } else /* else we have INSERT, UPDATE, DELETE statements */ { sql_result->num_rows = drizzle_result_affected_rows(sql_result->result_set); } } return 1; }
int main(int argc, char *argv[]) { (void) argc; (void) argv; drizzle_row_t row; int num_fields; drizzle_result_st *result; int table_size; #ifdef TEST_PREPARED_STATEMENTS drizzle_stmt_st *sth; #endif drizzle_st *con= drizzle_create(getenv("MYSQL_SERVER"), getenv("MYSQL_PORT") ? atoi("MYSQL_PORT") : DRIZZLE_DEFAULT_TCP_PORT, getenv("MYSQL_USER"), getenv("MYSQL_PASSWORD"), getenv("MYSQL_SCHEMA"), 0); ASSERT_NOT_NULL_(con, "Drizzle connection object creation error"); drizzle_return_t driz_ret= drizzle_connect(con); if (driz_ret == DRIZZLE_RETURN_COULD_NOT_CONNECT) { char error[DRIZZLE_MAX_ERROR_SIZE]; strncpy(error, drizzle_error(con), DRIZZLE_MAX_ERROR_SIZE); drizzle_quit(con); SKIP_IF_(driz_ret == DRIZZLE_RETURN_COULD_NOT_CONNECT, "%s(%s)", error, drizzle_strerror(driz_ret)); } ASSERT_EQ_(DRIZZLE_RETURN_OK, driz_ret, "drizzle_connect(): %s(%s)", drizzle_error(con), drizzle_strerror(driz_ret)); CHECKED_QUERY("DROP SCHEMA IF EXISTS test_nulls"); CHECKED_QUERY("CREATE SCHEMA test_nulls"); driz_ret= drizzle_select_db(con, "test_nulls"); ASSERT_EQ_(DRIZZLE_RETURN_OK, driz_ret, "USE test_nulls"); CHECKED_QUERY("create table test_nulls.t1 (a int, b int, c int, d int, e int, f int, g int, h int, i int, j int, k int)"); #define NCOLS 11 char *querybuf = calloc(256 + 60*64, 1); strcpy(querybuf, "insert into test_nulls.t1 values "); char *p = querybuf + strlen(querybuf); for(int sym = 0; sym < 64; sym++) { int cn = 0; *p++ = '('; #define APPENDMAYBE(b) if (sym & b) { strcpy(p, "NULL"); p += 4; } else { p += sprintf(p, "%d", sym*NCOLS + cn); } APPENDMAYBE(0x01); *p++ = ','; cn++; APPENDMAYBE(0x02); *p++ = ','; cn++; APPENDMAYBE(0x04); cn++; p += sprintf(p, ",%d,%d,%d,%d,", sym*NCOLS + 3, sym*NCOLS + 4, sym*NCOLS + 5, sym*NCOLS + 6); cn += 4; APPENDMAYBE(0x08); cn++; p += sprintf(p, ",%d,", sym*NCOLS + 8); cn++; APPENDMAYBE(0x10); *p++ = ','; cn++; APPENDMAYBE(0x20); cn++; *p++ = ')'; if (sym < 63) *p++ = ','; #undef APPENDMAYBE } CHECKED_QUERY(querybuf); #ifdef TEST_PREPARED_STATEMENTS strcpy(querybuf, "insert into test_nulls.t1 values (?,?,?,?,?,?,?,?,?,?,?)"); sth = drizzle_stmt_prepare(con, querybuf, strlen(querybuf), &driz_ret); ASSERT_EQ_(driz_ret, DRIZZLE_RETURN_OK, "Error (%s): %s, preparing \"%s\"", drizzle_strerror(driz_ret), drizzle_error(con), querybuf); for(int sym = 0; sym < 64; sym++) { // driz_ret= drizzle_stmt_reset(sth); // ASSERT_EQ_(driz_ret, DRIZZLE_RETURN_OK, "Error (%s): %s, resetting statement", drizzle_strerror(driz_ret), drizzle_error(con)); #define SETMAYBE(cn,b) if (sym & b) driz_ret = drizzle_stmt_set_null(sth, cn); else SETALWAYS(cn); #define SETALWAYS(cn) driz_ret = drizzle_stmt_set_short(sth, cn, sym*NCOLS + cn + 1000, 0) ASSERT_EQ(driz_ret, DRIZZLE_RETURN_OK); SETMAYBE(0,0x01); SETMAYBE(1,0x02); SETMAYBE(2,0x04); SETALWAYS(3); SETALWAYS(4); SETALWAYS(5); SETALWAYS(6); SETMAYBE(7,0x08); SETALWAYS(8); SETMAYBE(9,0x10); SETMAYBE(10,0x20); #undef SETMAYBE driz_ret = drizzle_stmt_execute(sth); ASSERT_EQ_(driz_ret, DRIZZLE_RETURN_OK, "Error (%s): %s, executing insert, sym=%d", drizzle_strerror(driz_ret), drizzle_error(con), sym); driz_ret = drizzle_stmt_buffer(sth); ASSERT_EQ_(driz_ret, DRIZZLE_RETURN_OK, "Error (%s): %s, buffering result, sym=%d", drizzle_strerror(driz_ret), drizzle_error(con), sym); // ASSERT_EQ(drizzle_stmt_affected_rows, 1); } ASSERT_EQ(drizzle_stmt_close(sth), DRIZZLE_RETURN_OK); table_size = 128; #else table_size = 64; #endif CHECKED_QUERY("select a,b,c,d,e,f,g,h,i,j,k from test_nulls.t1 order by e"); drizzle_result_buffer(result); num_fields= drizzle_result_column_count(result); ASSERT_EQ_(num_fields, NCOLS, "Bad number of fields, expected %d, got %d", 11, num_fields); int cur_row = 0; char nbuf[16]; while ((row = drizzle_row_next(result))) { cur_row ++; int sym, rowbase; /* 'sym' is the value used to decide which fields have NULLs or not. * 'rowbase' is the number that would be stored in the first field of this * row (assuming it's non-NULL). */ if (cur_row <= 64) { sym = cur_row - 1; rowbase = sym*NCOLS; } else { sym = cur_row - 65; rowbase = 1000 + sym*NCOLS; } #define NULLMAYBE(cn, b) if (sym & b) { ASSERT_NULL_(row[cn], "Column %d, row %d should be NULL", cn+1, cur_row); } else { ASSERT_NOT_NULL_(row[cn], "Column %d, row %d should not be NULL", cn+1, cur_row); sprintf(nbuf, "%d", rowbase+cn); ASSERT_STREQ(row[cn], nbuf); } #define NULLNEVER(cn) NULLMAYBE(cn, 0) NULLMAYBE(0, 0x01); NULLMAYBE(1, 0x02); NULLMAYBE(2, 0x04); NULLNEVER(3); NULLNEVER(4); NULLNEVER(5); NULLNEVER(6); NULLMAYBE(7, 0x08); NULLNEVER(8); NULLMAYBE(9, 0x10); NULLMAYBE(10, 0x20); #undef NULLMAYBE #undef NULLNEVER } ASSERT_EQ(cur_row, table_size); drizzle_result_free(result); #ifdef TEST_PREPARED_STATEMENTS strcpy(querybuf, "select a,b,c,d,e,f,g,h,i,j,k from test_nulls.t1 order by e"); sth = drizzle_stmt_prepare(con, querybuf, strlen(querybuf), &driz_ret); ASSERT_EQ_(driz_ret, DRIZZLE_RETURN_OK, "Error (%s): %s, preparing \"%s\"", drizzle_strerror(driz_ret), drizzle_error(con), querybuf); driz_ret = drizzle_stmt_execute(sth); ASSERT_EQ_(driz_ret, DRIZZLE_RETURN_OK, "Error (%s): %s, executing \"%s\"", drizzle_strerror(driz_ret), drizzle_error(con), querybuf); cur_row = 0; for (;;) { driz_ret = drizzle_stmt_fetch(sth); if (driz_ret == DRIZZLE_RETURN_ROW_END) break; cur_row ++; ASSERT_EQ_(driz_ret, DRIZZLE_RETURN_OK, "Error (%s): %s, fetching row #%d", drizzle_strerror(driz_ret), drizzle_error(con), cur_row); /* 'sym' is the value used to decide which fields have NULLs or not. * 'rowbase' is the number that would be stored in the first field of this * row (assuming it's non-NULL). */ int sym, rowbase; if (cur_row <= 64) { sym = cur_row - 1; rowbase = sym*NCOLS; } else { sym = cur_row - 65; rowbase = 1000 + sym*NCOLS; } bool isNull; uint32_t rowvalue; #define GETNULLNESS(cn) isNull = drizzle_stmt_get_is_null(sth, cn, &driz_ret); ASSERT_EQ(driz_ret, DRIZZLE_RETURN_OK); #define NULLNOTNOW(cn) ASSERT_FALSE_(isNull, "Column %d, row %d should not be NULL", cn+1, cur_row); rowvalue = drizzle_stmt_get_int(sth, cn, &driz_ret); ASSERT_EQ(driz_ret,DRIZZLE_RETURN_OK); ASSERT_EQ_(rowvalue, (unsigned)(rowbase + cn), "Column %d, row %d has unexpected data, expected: %d, got: %d", cn+1, cur_row, rowbase+cn, rowvalue); #define NULLMAYBE(cn, b) GETNULLNESS(cn); if (sym & b) { ASSERT_TRUE_(isNull, "Column %d, row %d should be NULL", cn+1, cur_row); } else { NULLNOTNOW(cn); } #define NULLNEVER(cn) GETNULLNESS(cn); NULLNOTNOW(cn); NULLMAYBE(0, 0x01); NULLMAYBE(1, 0x02); NULLMAYBE(2, 0x04); NULLNEVER(3); NULLNEVER(4); NULLNEVER(5); NULLNEVER(6); NULLMAYBE(7, 0x08); NULLNEVER(8); NULLMAYBE(9, 0x10); NULLMAYBE(10, 0x20); #undef NULLMAYBE #undef NULLNEVER #undef GETNULLNESS #undef NULLNOTNOW } ASSERT_EQ_(cur_row, table_size, "Current row not equal to table size, expected %d, got %d", table_size, cur_row); ASSERT_EQ(drizzle_stmt_close(sth), DRIZZLE_RETURN_OK); #endif CHECKED_QUERY("DROP TABLE test_nulls.t1"); ASSERT_EQ_(DRIZZLE_RETURN_OK, driz_ret, "DROP TABLE test_nulls.t1"); CHECKED_QUERY("DROP SCHEMA IF EXISTS test_nulls"); driz_ret= drizzle_quit(con); ASSERT_EQ_(DRIZZLE_RETURN_OK, driz_ret, "%s", drizzle_strerror(driz_ret)); free(querybuf); return EXIT_SUCCESS; }
ngx_int_t ngx_http_drizzle_output_result_header(ngx_http_request_t *r, drizzle_result_st *res) { u_char *pos, *last; ngx_int_t rc; ngx_http_upstream_t *u = r->upstream; const char *errstr; size_t size; uint16_t errstr_len; uint16_t col_count; unsigned last_buf; ngx_http_upstream_drizzle_peer_data_t *dp = u->peer.data; errstr = drizzle_result_error(res); errstr_len = (uint16_t) strlen(errstr); col_count = drizzle_result_column_count(res); size = sizeof(uint8_t) /* endian type */ + sizeof(uint32_t) /* format version */ + sizeof(uint8_t) /* result type */ + sizeof(uint16_t) /* standard error code */ + sizeof(uint16_t) /* driver-specific error code */ + sizeof(uint16_t) /* driver-specific errstr len */ + errstr_len /* driver-specific errstr data */ + sizeof(uint64_t) /* rows affected */ + sizeof(uint64_t) /* insert id */ + sizeof(uint16_t) /* column count */ ; pos = ngx_http_drizzle_request_mem(r, dp, size); if (pos == NULL) { return NGX_ERROR; } last = pos; #if NGX_HAVE_LITTLE_ENDIAN *last++ = 0; #else /* big endian */ *last++ = 1; #endif /* RDS format version */ *(uint32_t *) last = (uint32_t) resty_dbd_stream_version; last += sizeof(uint32_t); /* result type fixed to 0 */ *last++ = 0; /* standard error code * FIXME: define the standard error code set and map * libdrizzle's to it. */ *(uint16_t *) last = drizzle_result_error_code(res); last += sizeof(uint16_t); /* driver-specific error code */ *(uint16_t *) last = drizzle_result_error_code(res); last += sizeof(uint16_t); /* driver-specific errstr len */ *(uint16_t *) last = errstr_len; last += sizeof(uint16_t); /* driver-specific errstr data */ if (errstr_len) { last = ngx_copy(last, (u_char *) errstr, errstr_len); } /* affected rows */ *(uint64_t *) last = drizzle_result_affected_rows(res); last += sizeof(uint64_t); /* insert id */ *(uint64_t *) last = drizzle_result_insert_id(res); last += sizeof(uint64_t); /* column count */ *(uint16_t *) last = col_count; last += sizeof(uint16_t); if ((size_t) (last - pos) != size) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "drizzle: FATAL: output result header buffer error"); return NGX_ERROR; } if (col_count == 0) { /* we suppress row terminator here when there's no columns */ dp->seen_stream_end = 1; if (r == r->main) { last_buf = 1; } else { last_buf = 0; } rc = ngx_http_drizzle_submit_mem(r, dp, size, last_buf); if (rc != NGX_OK) { return NGX_ERROR; } ngx_http_upstream_drizzle_done(r, u, dp, NGX_OK); return NGX_DONE; } return ngx_http_drizzle_submit_mem(r, dp, size, 0 /* last_buf */); }
ngx_int_t ngx_http_drizzle_output_result_header(ngx_http_request_t *r, drizzle_result_st *res) { u_char *pos, *last; ngx_int_t rc; ngx_http_upstream_t *u = r->upstream; const char *errstr; size_t size; uint16_t errstr_len; uint16_t col_count; uint16_t errcode; ngx_http_upstream_drizzle_peer_data_t *dp = u->peer.data; errcode = drizzle_result_error_code(res); if (dp->enable_charset && ! dp->has_set_names) { if (errcode != 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "drizzle: FATAL: failed to set names 'utf8' " "(error %d)", (int) errcode); return NGX_ERROR; } if (dp->drizzle_con && dp->drizzle_res.con) { dd("before drizzle result free"); dd("%p vs. %p", dp->drizzle_res.con, dp->drizzle_con); drizzle_result_free(&dp->drizzle_res); dd("after drizzle result free"); } /* ngx_http_upstream_drizzle_done(r, u, dp, NGX_OK); */ dd("returning DONE when set names"); return NGX_DONE; } errstr = drizzle_result_error(res); errstr_len = (uint16_t) ngx_strlen(errstr); col_count = drizzle_result_column_count(res); size = sizeof(uint8_t) /* endian type */ + sizeof(uint32_t) /* format version */ + sizeof(uint8_t) /* result type */ + sizeof(uint16_t) /* standard error code */ + sizeof(uint16_t) /* driver-specific error code */ + sizeof(uint16_t) /* driver-specific errstr len */ + errstr_len /* driver-specific errstr data */ + sizeof(uint64_t) /* rows affected */ + sizeof(uint64_t) /* insert id */ + sizeof(uint16_t); /* column count */ pos = ngx_http_drizzle_request_mem(r, dp, size); if (pos == NULL) { return NGX_ERROR; } last = pos; #if NGX_HAVE_LITTLE_ENDIAN *last++ = 0; #else /* big endian */ *last++ = 1; #endif /* RDS format version */ *(uint32_t *) last = (uint32_t) resty_dbd_stream_version; last += sizeof(uint32_t); /* result type fixed to 0 */ *last++ = 0; /* standard error code * FIXME: define the standard error code set and map * libdrizzle's to it. */ *(uint16_t *) last = errcode; last += sizeof(uint16_t); /* driver-specific error code */ *(uint16_t *) last = drizzle_result_error_code(res); last += sizeof(uint16_t); /* driver-specific errstr len */ *(uint16_t *) last = errstr_len; last += sizeof(uint16_t); /* driver-specific errstr data */ if (errstr_len) { last = ngx_copy(last, (u_char *) errstr, errstr_len); } /* affected rows */ *(uint64_t *) last = drizzle_result_affected_rows(res); last += sizeof(uint64_t); /* insert id */ *(uint64_t *) last = drizzle_result_insert_id(res); last += sizeof(uint64_t); /* column count */ *(uint16_t *) last = col_count; last += sizeof(uint16_t); if ((size_t) (last - pos) != size) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "drizzle: FATAL: output result header buffer error"); return NGX_ERROR; } if (col_count == 0) { dd("Col count is ZERO"); /* we suppress row terminator here when there's no columns */ dp->seen_stream_end = 1; rc = ngx_http_drizzle_submit_mem(r, dp, size); if (rc != NGX_OK) { return NGX_ERROR; } dd("about to be done..."); ngx_http_upstream_drizzle_done(r, u, dp, NGX_DONE); dd("i am returning DONE"); return NGX_DONE; } return ngx_http_drizzle_submit_mem(r, dp, size); }