[ruby-oci8-devel] Clear binds

KUBO Takehiro kubo at jiubao.org
Mon Dec 24 08:23:23 EST 2007


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);
    ........
}

-- 
KUBO Takehiro <kubo at jiubao.org>


More information about the ruby-oci8-devel mailing list