[ruby-oci8-devel] Clear binds

Liming Lian liming.lian at oracle.com
Mon Dec 24 22:13:58 EST 2007


Thanks kubo for your valuable comments. I notice two wiki pages for 
developers on ruby-oci8 project website.  Really helpful~

Merry Christmas and Happy New Year!

Liming

> Hi,
>
> Liming Lian <liming.lian at oracle.com> writes:
>
>   
>> Hi,
>>
>> As we discussed at the proposal, all existing binds should be clear from 
>> cursor when new value of max_array_size is set. I have implemented this 
>> by adding functions to stmt.c. I am not sure if I have fully understood 
>> the mechanism of how Ruby-OCI8 works. So I want to hear any comments on 
>> my implementation.
>>     
>
> I wrote indent style in C used in ruby-oci8.
>   http://ruby-oci8.rubyforge.org/en/dev_CodingStyle.html
>
> I won't check indent style in this mail.
>
>   
>> Following is my code added to stmt.c:
>>
>> static ID id_empty;
>> static ID id_clear;
>>
>> static VALUE clear_binds_iterator_proc(VALUE pair, VALUE arg, VALUE self)
>>     
>
> The third argument of rb_iterate() accepts two arguments. Delete last one.
>
>   
>> {
>>     VALUE value = RARRAY(pair)->ptr[1];
>>     
>
> Use PARRAY_PTR(pair) instead of RARRAY(pair)->ptr.
> This macro was added in ruby 1.8.6.
> Your code works fine with ruby 1.9 also. But RArray's internal
> structure may be changed to improve performace in future, as RString's
> strcuture was changed in ruby 1.9.
>
>   
>>     if(!NIL_P(value)) {
>>       oci8_base_free((oci8_base_t*)oci8_get_bind(value));
>>     }
>>
>>     return self;
>> }
>>
>>
>> static VALUE oci8_stmt_clear_binds(VALUE self)
>> {
>>     oci8_stmt_t *stmt = DATA_PTR(self);
>>
>>     if(!RTEST(rb_funcall(stmt->binds, id_empty, 0)))
>>     {
>>       rb_iterate(rb_each, stmt->binds, clear_binds_iterator_proc, (VALUE) NULL);
>>     
>
> stmt->binds is a Hash object. It is better to use each_value instead
> of each.
>
> Add following code and use each_value instead of rb_each.
>   static VALUE each_value(VALUE obj)
>   {
>       return rb_funcall(obj, id_each_value, 0);
>   }
>
>   
>>       rb_funcall(stmt->binds,id_clear,0);
>>     }
>>
>>     return self;
>> }
>>
>> void Init_oci8_stmt(VALUE cOCI8)
>> {
>>   ........
>>   id_empty = rb_intern("empty?");
>>     
>
> Use id_empty_p instead of id_empty.
> Ruby's C source code uses '_p' for methods which end with '?'.
>
>   
>>   id_clear = rb_intern("clear");
>>   ........
>>   rb_define_private_method(cOCIStmt, "__clearBinds", oci8_stmt_clear_binds, 0);
>>     
>
> Use __clear_binds instead of __clearBinds.
> I used CamelCase method names in ruby-oci8 1.0.
> But now I obey ruby's convention. All method words are lower case and
> concatenated by '_'.
> Though, starting '__' is not in ruby's convention....
>
>   
>>   ........
>> }
>>     
>
>
> Here is my code based on yours.
>
> static ID id_empty_p;
> static ID id_clear;
> static ID id_each_value;
>
> static VALUE each_value(VALUE obj)
> {
>     return rb_funcall(obj, id_each_value, 0);
> }
>
> static VALUE clear_binds_iterator_proc(VALUE val, VALUE unused)
> {
>     if (!NIL_P(val)) {
>         oci8_base_free((oci8_base_t*)oci8_get_bind(val));
>     }
>     return Qnil;
> }
>
> static VALUE oci8_stmt_clear_binds(VALUE self)
> {
>     oci8_stmt_t *stmt = DATA_PTR(self);
>
>     if (!RTEST(rb_funcall(stmt->binds, id_empty_p, 0))) {
>         rb_iterate(each_value, stmt->binds, clear_binds_iterator_proc, Qnil);
>         rb_funcall(stmt->binds,id_clear,0);
>     }
>     return self;
> }
>
> void Init_oci8_stmt(VALUE cOCI8)
> {
>     ........
>     id_empty_p = rb_intern("empty?");
>     id_clear = rb_intern("clear");
>     id_each_value = rb_intern("each_value");
>     ........
>     rb_define_private_method(cOCIStmt, "__clear_binds", oci8_stmt_clear_binds, 0);
>     ........
> }
>
>   



More information about the ruby-oci8-devel mailing list