Changeset: 5abe110d77bd for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=5abe110d77bd
Modified Files:
        clients/mapilib/mapi.c
        clients/mapilib/mapi.h
        clients/odbc/driver/SQLConnect.c
        clients/odbc/driver/SQLExecute.c
        clients/odbc/driver/SQLPrepare.c
        sql/backends/monet5/sql_result.mx
        sql/backends/monet5/sql_scenario.c
        sql/server/sql_mvc.c
        sql/server/sql_mvc.h
Branch: Aug2011
Log Message:

ODBC needs the declared size of columns in result sets.
This was implemented by adding a header to result sets giving this
information.  But since only (for now) ODBC needs it, the header is
only added when the client asks for it explicitly (using a new "X"
command).


diffs (217 lines):

diff --git a/clients/mapilib/mapi.c b/clients/mapilib/mapi.c
--- a/clients/mapilib/mapi.c
+++ b/clients/mapilib/mapi.c
@@ -846,6 +846,8 @@ struct MapiColumn {
        char *columnname;
        char *columntype;
        int columnlength;
+       int digits;
+       int scale;
 };
 
 /* information about bound columns */
@@ -3498,6 +3500,19 @@ mapi_setAutocommit(Mapi mid, int autocom
 }
 
 MapiMsg
+mapi_set_size_header(Mapi mid, int value)
+{
+       if (mid->languageId != LANG_SQL) {
+               mapi_setError(mid, "size header only supported in SQL", 
"mapi_toggle_size_header", MERROR);
+               return MERROR;
+       }
+       if (value)
+               return mapi_Xcommand(mid, "sizeheader", "1");
+       else
+               return mapi_Xcommand(mid, "sizeheader", "0");
+}
+
+MapiMsg
 mapi_trace(Mapi mid, int flag)
 {
        mapi_clrError(mid);
@@ -3804,6 +3819,16 @@ parse_header_line(MapiHdl hdl, char *lin
                                anchors[i] = NULL;
                        }
                }
+       } else if (strcmp(tag, "typesizes") == 0) {
+               for (i = 0; i < n; i++) {
+                       if (anchors[i]) {
+                               char *p;
+                               result->fields[i].digits = atoi(anchors[i]);
+                               p = strchr(anchors[i], ' ');
+                               if (p)
+                                       result->fields[i].scale = atoi(p + 1);
+                       }
+               }
        }
 
        /* clean up */
@@ -5267,6 +5292,30 @@ mapi_get_len(MapiHdl hdl, int fnr)
        return 0;
 }
 
+int
+mapi_get_digits(MapiHdl hdl, int fnr)
+{
+       struct MapiResultSet *result;
+
+       mapi_hdl_check0(hdl, "mapi_get_digits");
+       if ((result = hdl->result) != 0 && fnr >= 0 && fnr < result->fieldcnt)
+               return result->fields[fnr].digits;
+       mapi_setError(hdl->mid, "Illegal field number", "mapi_get_digits", 
MERROR);
+       return 0;
+}
+
+int
+mapi_get_scale(MapiHdl hdl, int fnr)
+{
+       struct MapiResultSet *result;
+
+       mapi_hdl_check0(hdl, "mapi_get_scale");
+       if ((result = hdl->result) != 0 && fnr >= 0 && fnr < result->fieldcnt)
+               return result->fields[fnr].scale;
+       mapi_setError(hdl->mid, "Illegal field number", "mapi_get_scale", 
MERROR);
+       return 0;
+}
+
 char *
 mapi_get_query(MapiHdl hdl)
 {
diff --git a/clients/mapilib/mapi.h b/clients/mapilib/mapi.h
--- a/clients/mapilib/mapi.h
+++ b/clients/mapilib/mapi.h
@@ -165,6 +165,7 @@ mapi_export int mapi_get_trace(Mapi mid)
 mapi_export int mapi_get_autocommit(Mapi mid);
 mapi_export MapiMsg mapi_log(Mapi mid, const char *nme);
 mapi_export MapiMsg mapi_setAutocommit(Mapi mid, int autocommit);
+mapi_export MapiMsg mapi_set_size_header(Mapi mid, int value);
 mapi_export char *mapi_result_error(MapiHdl hdl);
 mapi_export MapiMsg mapi_next_result(MapiHdl hdl);
 mapi_export MapiMsg mapi_needmore(MapiHdl hdl);
@@ -232,6 +233,8 @@ mapi_export char *mapi_get_table(MapiHdl
 mapi_export char *mapi_get_name(MapiHdl hdl, int fnr);
 mapi_export char *mapi_get_type(MapiHdl hdl, int fnr);
 mapi_export int mapi_get_len(MapiHdl hdl, int fnr);
+mapi_export int mapi_get_digits(MapiHdl hdl, int fnr);
+mapi_export int mapi_get_scale(MapiHdl hdl, int fnr);
 mapi_export char *mapi_get_query(MapiHdl hdl);
 mapi_export int mapi_get_querytype(MapiHdl hdl);
 mapi_export int mapi_get_tableid(MapiHdl hdl);
diff --git a/clients/odbc/driver/SQLConnect.c b/clients/odbc/driver/SQLConnect.c
--- a/clients/odbc/driver/SQLConnect.c
+++ b/clients/odbc/driver/SQLConnect.c
@@ -234,6 +234,7 @@ SQLConnect_(ODBCDbc *dbc,
                dbc->dbname = schema ? strdup(schema) : NULL;
                mapi_setAutocommit(mid, dbc->sql_attr_autocommit == 
SQL_AUTOCOMMIT_ON);
                set_timezone(mid);
+               mapi_set_size_header(mid, 1);
        }
 
        return rc;
diff --git a/clients/odbc/driver/SQLExecute.c b/clients/odbc/driver/SQLExecute.c
--- a/clients/odbc/driver/SQLExecute.c
+++ b/clients/odbc/driver/SQLExecute.c
@@ -216,7 +216,8 @@ ODBCInitResult(ODBCStmt *stmt)
                rec->sql_desc_base_table_name = (SQLCHAR *) strdup(s ? s : "");
                rec->sql_desc_table_name = (SQLCHAR *) strdup(s ? s : "");
 
-               rec->sql_desc_length = mapi_get_len(hdl, i);
+               if ((rec->sql_desc_length = mapi_get_digits(hdl, i)) == 0)
+                       rec->sql_desc_length = mapi_get_len(hdl, i);
 
                rec->sql_desc_local_type_name = (SQLCHAR *) strdup("");
                rec->sql_desc_catalog_name = (SQLCHAR *) strdup("");
@@ -235,6 +236,11 @@ ODBCInitResult(ODBCStmt *stmt)
                rec->sql_desc_length = ODBCLength(rec, SQL_DESC_LENGTH);
                rec->sql_desc_display_size = ODBCLength(rec, 
SQL_DESC_DISPLAY_SIZE);
                rec->sql_desc_octet_length = ODBCLength(rec, 
SQL_DESC_OCTET_LENGTH);
+               if (rec->sql_desc_length == 0) {
+                       rec->sql_desc_length = SQL_NO_TOTAL;
+                       rec->sql_desc_display_size = SQL_NO_TOTAL;
+                       rec->sql_desc_octet_length = SQL_NO_TOTAL;
+               }
 
                rec++;
        }
diff --git a/clients/odbc/driver/SQLPrepare.c b/clients/odbc/driver/SQLPrepare.c
--- a/clients/odbc/driver/SQLPrepare.c
+++ b/clients/odbc/driver/SQLPrepare.c
@@ -257,6 +257,11 @@ SQLPrepare_(ODBCStmt *stmt,
                rec->sql_desc_length = ODBCLength(rec, SQL_DESC_LENGTH);
                rec->sql_desc_display_size = ODBCLength(rec, 
SQL_DESC_DISPLAY_SIZE);
                rec->sql_desc_octet_length = ODBCLength(rec, 
SQL_DESC_OCTET_LENGTH);
+               if (rec->sql_desc_length == 0) {
+                       rec->sql_desc_length = SQL_NO_TOTAL;
+                       rec->sql_desc_display_size = SQL_NO_TOTAL;
+                       rec->sql_desc_octet_length = SQL_NO_TOTAL;
+               }
        }
 
        /* update the internal state */
diff --git a/sql/backends/monet5/sql_result.mx 
b/sql/backends/monet5/sql_result.mx
--- a/sql/backends/monet5/sql_result.mx
+++ b/sql/backends/monet5/sql_result.mx
@@ -1199,6 +1199,23 @@ mvc_export_head(mvc *m, stream *s, int r
        if (mnstr_write(s, " # length\n", 10, 1) != 1)
                return export_error(order);
 
+       if (m->sizeheader) {
+               if (mnstr_write(s, "% ", 2, 1) != 1)
+                       return export_error(order);
+               for (i = 0; i < t->nr_cols; i++) {
+                       res_col *c = t->cols + i;
+
+                       if (mnstr_printf(s, "%u %u",
+                                        c->type.digits, c->type.scale) < 0)
+                               return export_error(order);
+                       if (i + 1 < t->nr_cols &&
+                           mnstr_write(s, ",\t", 2, 1) != 1)
+                               return export_error(order);
+               }
+               if (mnstr_write(s, " # typesizes\n", 13, 1) != 1)
+                       return export_error(order);
+       }
+
        if ( order)
                BBPunfix(order->batCacheid);
        return res;
diff --git a/sql/backends/monet5/sql_scenario.c 
b/sql/backends/monet5/sql_scenario.c
--- a/sql/backends/monet5/sql_scenario.c
+++ b/sql/backends/monet5/sql_scenario.c
@@ -1208,6 +1208,12 @@ SQLparser(Client c)
                        in->pos = in->len;      /* HACK: should use parsed 
lenght */
                        return NULL;
                }
+               if (strncmp(in->buf + in->pos, "sizeheader", 10) == 0) {
+                       v = (int) strtol(in->buf + in->pos + 10, NULL, 10);
+                       m->sizeheader = v != 0;
+                       in->pos = in->len;      /* HACK: should use parsed 
lenght */
+                       return NULL;
+               }
                if( strncmp(in->buf + in->pos,"quit",4)==0 ) {
                        c->mode = FINISHING;
                        return NULL;
diff --git a/sql/server/sql_mvc.c b/sql/server/sql_mvc.c
--- a/sql/server/sql_mvc.c
+++ b/sql/server/sql_mvc.c
@@ -61,6 +61,8 @@ mvc_init(char *dbname, int debug, store_
                m->caching = 0;
                /* disable history */
                m->history = 0;
+               /* disable size header */
+               m->sizeheader = 0;
                mvc_trans(m);
                s = m->session->schema = mvc_bind_schema(m, "sys");
                assert(m->session->schema != NULL);
diff --git a/sql/server/sql_mvc.h b/sql/server/sql_mvc.h
--- a/sql/server/sql_mvc.h
+++ b/sql/server/sql_mvc.h
@@ -105,6 +105,7 @@ typedef struct mvc {
        int caching;            /* cache current query ? */
        int history;            /* queries statistics are kept  */
        int reply_size;         /* reply size */
+       int sizeheader;         /* print size header in result set */
        int debug;
 
        char emode;             /* execution mode */
_______________________________________________
Checkin-list mailing list
[email protected]
http://mail.monetdb.org/mailman/listinfo/checkin-list

Reply via email to