From: KUBO Takehiro Date: 2003-11-22T11:49:33+09:00 Subject: Re: Ruby DBI Access "Brent Harris" writes: > I am accessing an Oracle Database, and I would like for Ruby to be able to > get the exact size of the returned columns. How can I do this dynamically > if the only thing I'm given is an SQL statement? You can get the data size, if you use one of the following: Ruby9i: (I havn't use it. I just look at the codes.) low-level APIs of oracle module: ORAcursor#describe(pos) low-level APIs of oci8 module: param = OCIStmt#paramGet(pos) param.attrGet(OCI_ATTR_DATA_SIZE) param.attrGet(OCI_ATTR_SCALE) param.attrGet(OCI_ATTR_PRECISION) dbd_oracle returns larger size. The others can't do. But above three APIs don't return the exact size, but return the internal data size. Even though the datatype is 'CHAR', the retrieved string may be larger of smaller than the stored string data if the charsets of the client and the server are different. While looking at Ruby9i source code, I found a bug in it. According to the OCI manual, the datatype of OCI_ATTR_DATA_SIZE is ub4. But it is ub2 in fact. The original code works on a little-endian CPU, but not on a big-endian CPU. --- varchar.c.orig 2003-07-07 09:13:18.000000000 +0900 +++ varchar.c 2003-11-22 11:01:31.000000000 +0900 @@ -18,7 +18,7 @@ Data_Get_Struct(self, oci9_define_buf, bp); VALUE str; oci9_handle *parm_h; - ub4 col_size; + ub2 col_size; if (argc == 1) switch (TYPE(argv[0])) @@ -32,7 +32,6 @@ Data_Get_Struct(rb_ary_entry(argv[0], 2), oci9_handle, parm_h); if (OCIAttrGet(parm_h->ptr, OCI_DTYPE_PARAM, (dvoid*) &col_size, 0, OCI_ATTR_DATA_SIZE, err_h)) error_raise("Could not get column size", "varchar_initialize", __FILE__, __LINE__); - col_size &= 0x0000ffff; /* XXX high bytes getting corrupted */ rb_hash_aset(rb_iv_get(self, "@column_info"), rb_str_new2("size"), INT2FIX(col_size)); /* prepare to receive varchar of length col_size */ bp->val = ALLOC_N(char, col_size + 1); -- KUBO Takehiro kubo@jiubao.org