Changeset: 5bffc2dd12df for MonetDB URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=5bffc2dd12df Modified Files: clients/mapilib/mapi.c sql/backends/monet5/sql_result.c Branch: protocol Log Message:
Change decimal result set transfer: transfer underlying type + scale instead of converting to double. diffs (213 lines): diff --git a/clients/mapilib/mapi.c b/clients/mapilib/mapi.c --- a/clients/mapilib/mapi.c +++ b/clients/mapilib/mapi.c @@ -835,6 +835,7 @@ struct MapiColumn { int scale; void *null_value; char* buffer_ptr; + char *dynamic_write_buf; char write_buf[50]; mapi_converter converter; }; @@ -1628,6 +1629,8 @@ close_result(MapiHdl hdl) free(result->fields[i].columnname); if (result->fields[i].columntype) free(result->fields[i].columntype); + if (result->fields[i].dynamic_write_buf) + free(result->fields[i].dynamic_write_buf); } free(result->fields); } @@ -4063,12 +4066,11 @@ parse_header_line(MapiHdl hdl, char *lin */ static char* mapi_convert_varchar(struct MapiColumn *col) { - // FIXME write_buf needs to be variable per column if we want to keep this varchar representation, not limited to 50 - memcpy(col->write_buf, col->buffer_ptr, col->columnlength); - col->write_buf[col->columnlength] = '\0'; - if (strcmp(col->write_buf, (char*)col->null_value) == 0) + memcpy(col->dynamic_write_buf, col->buffer_ptr, col->columnlength); + col->dynamic_write_buf[col->columnlength] = '\0'; + if (strcmp(col->dynamic_write_buf, (char*)col->null_value) == 0) return NULL; - return (char*) col->write_buf; + return (char*) col->dynamic_write_buf; } @@ -4122,6 +4124,43 @@ static char* mapi_convert_tinyint(struct return (char*) col->write_buf; } +static lng _scales(int scale) { + if (scale == 0) { + return 1; + } else { + return 10 * _scales(scale - 1); + } +} + +#define DEC2_STRING(tpe, scale) { \ + double val = *((tpe*) col->buffer_ptr); \ + if (*((tpe*) col->buffer_ptr) == *((tpe*)col->null_value)) return NULL; \ + if (scale) { \ + val = val / _scales(scale); \ + } \ + sprintf(col->write_buf, "%f", val); \ + return (char*) col->write_buf; \ +} + +static char* mapi_convert_decimal(struct MapiColumn *col) { + switch(col->columnlength) { + case sizeof(signed char): + DEC2_STRING(signed char, col->scale); + case sizeof(short): + DEC2_STRING(short, col->scale); + case sizeof(int): + DEC2_STRING(int, col->scale); + case sizeof(lng): + DEC2_STRING(lng, col->scale); +#ifdef HAVE_HGE + case sizeof(hge): + DEC2_STRING(hge, col->scale); +#endif + } + fprintf(stderr, "Unrecognized typelen for decimal.\n"); + return NULL; +} + static char* mapi_convert_double(struct MapiColumn *col) { char *dummy; if (*((double*) col->buffer_ptr) == *((double*)col->null_value)) return NULL; @@ -4286,6 +4325,8 @@ read_into_cache(MapiHdl hdl, int lookahe result->rows_read = 0; result->cur_row = 0; + assert(result->fields); + for (i = 0; i < nr_cols; i++) { lng col_info_length; char *table_name, *col_name, *type_sql_name; @@ -4311,6 +4352,13 @@ read_into_cache(MapiHdl hdl, int lookahe return mid->error; } + if (strcasecmp(type_sql_name, "decimal") == 0) { + // decimal type, read the scale as well + if (!mnstr_readInt(mid->from, &result->fields[i].scale)) { + return mid->error; + } + } + if (!mnstr_readInt(mid->from, &null_len)) { return mid->error; } @@ -4331,9 +4379,12 @@ read_into_cache(MapiHdl hdl, int lookahe result->fields[i].tablename = table_name; result->fields[i].columntype = type_sql_name; result->fields[i].columnlength = typelen; + result->fields[i].dynamic_write_buf = NULL; + result->fields[i].converter = NULL; if (strcasecmp(type_sql_name, "varchar") == 0) { result->fields[i].converter = (mapi_converter) mapi_convert_varchar; + result->fields[i].dynamic_write_buf = malloc(result->fields[i].columnlength * sizeof(char)); } else if (strcasecmp(type_sql_name, "clob") == 0) { // var length strings result->fields[i].converter = (mapi_converter) mapi_convert_clob; @@ -4346,7 +4397,7 @@ read_into_cache(MapiHdl hdl, int lookahe } else if (strcasecmp(type_sql_name, "boolean") == 0) { result->fields[i].converter = (mapi_converter) mapi_convert_boolean; } else if (strcasecmp(type_sql_name, "decimal") == 0) { - result->fields[i].converter = (mapi_converter) mapi_convert_double; + result->fields[i].converter = (mapi_converter) mapi_convert_decimal; } else if (strcasecmp(type_sql_name, "double") == 0) { result->fields[i].converter = (mapi_converter) mapi_convert_double; } else if (strcasecmp(type_sql_name, "date") == 0) { @@ -5633,10 +5684,11 @@ mapi_fetch_row(MapiHdl hdl) #ifndef HAVE_LIBPROTOBUF // TODO: complain #else + Mhapi__QueryResult *res; bs2_resetbuf(hdl->mid->from); mnstr_readChr(hdl->mid->from, &dummy); buf = bs2_buffer(hdl->mid->from); - Mhapi__QueryResult *res = mhapi__query_result__unpack(NULL, buf.len + buf.pos, (const uint8_t *) buf.buf); + res = mhapi__query_result__unpack(NULL, buf.len + buf.pos, (const uint8_t *) buf.buf); assert(res); assert(res->row_count <= result->row_count); assert(res->n_columns == (size_t) result->fieldcnt); @@ -5714,7 +5766,6 @@ mapi_fetch_row(MapiHdl hdl) } else { for (i = 0; i < (size_t) result->fieldcnt; i++) { if (result->fields[i].columnlength < 0) { - printf("Bla2\n"); // variable-length column if (hdl->mid->protobuf_res) { result->fields[i].buffer_ptr = ((Mhapi__QueryResult*) hdl->mid->protobuf_res)->columns[i]->string_values[result->cur_row]; diff --git a/sql/backends/monet5/sql_result.c b/sql/backends/monet5/sql_result.c --- a/sql/backends/monet5/sql_result.c +++ b/sql/backends/monet5/sql_result.c @@ -1917,7 +1917,7 @@ static int mvc_export_resultset_prot10(r int retval = -1; iterators[i] = bat_iterator(BATdescriptor(c->b)); - if (strcasecmp(c->type.type->sqlname, "decimal") == 0) { + /*if (strcasecmp(c->type.type->sqlname, "decimal") == 0) { str res = MAL_SUCCEED; int bat_type = ATOMstorage(iterators[i].b->ttype); int hpos = c->type.scale; @@ -1956,7 +1956,7 @@ static int mvc_export_resultset_prot10(r fres = -1; goto cleanup; } - } + }*/ if (ATOMvarsized(mtype)) { // FIXME support other types than string @@ -1983,6 +1983,15 @@ static int mvc_export_resultset_prot10(r fres = -1; goto cleanup; } + + if (strcasecmp(c->type.type->sqlname, "decimal") == 0) { + // if the type is a decimal, we write the scale as a 4-byte integer as well + if (!mnstr_writeInt(s, c->type.scale)) { + fres = -1; + goto cleanup; + } + } + // write NULL values for this column to the stream // NULL values are encoded as <size:int> <NULL value> (<size> is always <typelen> for fixed size columns) if (!mnstr_writeInt(s, nil_len)) { @@ -2039,7 +2048,7 @@ static int mvc_export_resultset_prot10(r if (varsized == 0) { // no varsized elements, so we can immediately compute the amount of elements row = srow + bytes_left / fixed_lengths; - row = row > count ? count : row; + row = row > (size_t) count ? (size_t) count : row; } else { // every varsized member has an 8-byte header indicating the length of the header in the block // subtract this from the amount of bytes left @@ -2113,15 +2122,16 @@ static int mvc_export_resultset_prot10(r for (i = 0; i < (size_t) t->nr_cols; i++) { res_col *c = t->cols + i; int local_type = ATOMstorage(c->type.type->localtype); + Mhapi__QueryResult__Column *col; msg.columns[i] = malloc(sizeof(Mhapi__QueryResult__Column)); assert(msg.columns[i]); - Mhapi__QueryResult__Column *col = msg.columns[i]; + col = msg.columns[i]; mhapi__query_result__column__init(col); - if (strcasecmp(c->type.type->sqlname, "decimal") == 0) { + /*if (strcasecmp(c->type.type->sqlname, "decimal") == 0) { local_type = TYPE_dbl; - } + }*/ switch (local_type) { case TYPE_str: { _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list