| ... | ... | 
                  @@ -11,7 +11,7 @@ my $builder = Module::Build->new(  | 
              
| 11 | 11 | 
                  'Test::More' => 0,  | 
              
| 12 | 12 | 
                  },  | 
              
| 13 | 13 | 
                       requires => {
                 | 
              
| 14 | 
                  - 'Object::Simple' => 2.0701,  | 
              |
| 14 | 
                  + 'Object::Simple' => 2.0702,  | 
              |
| 15 | 15 | 
                  'DBI' => 1.605,  | 
              
| 16 | 16 | 
                  },  | 
              
| 17 | 17 | 
                  add_to_cleanup => [ 'DBI-Custom-*' ],  | 
              
| ... | ... | 
                  @@ -12,6 +12,7 @@ use DBI::Custom::Result;  | 
              
| 12 | 12 | 
                   sub user        : ClassObjectAttr { initialize => {clone => 'scalar'} }
                 | 
              
| 13 | 13 | 
                   sub password    : ClassObjectAttr { initialize => {clone => 'scalar'} }
                 | 
              
| 14 | 14 | 
                   sub data_source : ClassObjectAttr { initialize => {clone => 'scalar'} }
                 | 
              
| 15 | 
                  +sub database    : ClassObjectAttr { initialize => {clone => 'scalar'} }
                 | 
              |
| 15 | 16 | 
                   | 
              
| 16 | 17 | 
                   sub dbi_option : ClassObjectAttr { initialize => {clone => 'hash', 
                 | 
              
| 17 | 18 | 
                                                                     default => sub { {} } } }
                 | 
              
| ... | ... | 
                  @@ -19,6 +20,8 @@ sub dbi_option : ClassObjectAttr { initialize => {clone => 'hash',
                 | 
              
| 19 | 20 | 
                   sub bind_filter  : ClassObjectAttr { initialize => {clone => 'scalar'} }
                 | 
              
| 20 | 21 | 
                   sub fetch_filter : ClassObjectAttr { initialize => {clone => 'scalar'} }
                 | 
              
| 21 | 22 | 
                   | 
              
| 23 | 
                  +sub no_filters   : ClassObjectAttr { initialize => {clone => 'array'} }
                 | 
              |
| 24 | 
                  +  | 
              |
| 22 | 25 | 
                   sub filters : ClassObjectAttr {
                 | 
              
| 23 | 26 | 
                  type => 'hash',  | 
              
| 24 | 27 | 
                  deref => 1,  | 
              
| ... | ... | 
                  @@ -47,6 +50,7 @@ sub dbh          : Attr {}
                 | 
              
| 47 | 50 | 
                   | 
              
| 48 | 51 | 
                   | 
              
| 49 | 52 | 
                  ### Methods  | 
              
| 53 | 
                  +  | 
              |
| 50 | 54 | 
                  # Add filter  | 
              
| 51 | 55 | 
                   sub add_filter {
                 | 
              
| 52 | 56 | 
                  my $invocant = shift;  | 
              
| ... | ... | 
                  @@ -143,44 +147,46 @@ sub run_tranzaction {
                 | 
              
| 143 | 147 | 
                  $self->_auto_commit(1);  | 
              
| 144 | 148 | 
                  }  | 
              
| 145 | 149 | 
                   | 
              
| 146 | 
                  -# Create SQL from SQL template  | 
              |
| 147 | 
                  -sub _create_sql {
                 | 
              |
| 148 | 
                  - my $self = shift;  | 
              |
| 150 | 
                  +sub create_query {
                 | 
              |
| 151 | 
                  + my ($self, $template) = @_;  | 
              |
| 149 | 152 | 
                   | 
              
| 150 | 
                  - my ($sql, @bind) = $self->sql_template->create_sql(@_);  | 
              |
| 153 | 
                  + # Create query from SQL template  | 
              |
| 154 | 
                  + my $query = $self->sql_template->create_query($template);  | 
              |
| 151 | 155 | 
                   | 
              
| 152 | 
                  - return ($sql, @bind);  | 
              |
| 153 | 
                  -}  | 
              |
| 154 | 
                  -  | 
              |
| 155 | 
                  -# Prepare and execute SQL  | 
              |
| 156 | 
                  -sub query {
                 | 
              |
| 157 | 
                  - my ($self, $template, $values, $filter) = @_;  | 
              |
| 156 | 
                  + # Create Query object;  | 
              |
| 157 | 
                  + my $query = DBI::Custom::Query->new($query);  | 
              |
| 158 | 158 | 
                   | 
              
| 159 | 
                  - my $sth_options;  | 
              |
| 159 | 
                  + # connect if not  | 
              |
| 160 | 
                  + $self->connect unless $self->connected;  | 
              |
| 160 | 161 | 
                   | 
              
| 161 | 
                  - # Rearrange when argumets is hash referecne  | 
              |
| 162 | 
                  -    if (ref $template eq 'HASH') {
                 | 
              |
| 163 | 
                  - my $args = $template;  | 
              |
| 164 | 
                  - ($template, $values, $filter, $sth_options)  | 
              |
| 165 | 
                  -          = @{$args}{qw/template values filter sth_options/};
                 | 
              |
| 166 | 
                  - }  | 
              |
| 162 | 
                  + # Prepare statement handle  | 
              |
| 163 | 
                  +    my $sth = $self->dbh->prepare($query->{sql});
                 | 
              |
| 167 | 164 | 
                   | 
              
| 168 | 
                  - $filter ||= $self->bind_filter;  | 
              |
| 165 | 
                  + $query->sth($sth);  | 
              |
| 169 | 166 | 
                   | 
              
| 170 | 
                  - my ($sql, @bind_values) = $self->_create_sql($template, $values, $filter);  | 
              |
| 167 | 
                  + return $query;  | 
              |
| 168 | 
                  +}  | 
              |
| 169 | 
                  +  | 
              |
| 170 | 
                  +sub execute {
                 | 
              |
| 171 | 
                  + my ($self, $query, $params) = @_;  | 
              |
| 171 | 172 | 
                   | 
              
| 172 | 
                  - $self->connect unless $self->connected;  | 
              |
| 173 | 
                  + # Create query if First argument is template  | 
              |
| 174 | 
                  +    if (!ref $query) {
                 | 
              |
| 175 | 
                  + my $template = $query;  | 
              |
| 176 | 
                  + $query = $sefl->create_query($tempalte);  | 
              |
| 177 | 
                  + }  | 
              |
| 173 | 178 | 
                   | 
              
| 174 | 
                  - my $sth = $self->dbh->prepare($sql);  | 
              |
| 179 | 
                  + # Set bind filter  | 
              |
| 180 | 
                  + $query->bind_filter($self->bind_filter) unless $query->bind_filter;  | 
              |
| 175 | 181 | 
                   | 
              
| 176 | 
                  -    if ($sth_options) {
                 | 
              |
| 177 | 
                  -        foreach my $key (keys %$sth_options) {
                 | 
              |
| 178 | 
                  -            $sth->{$key} = $sth_options->{$key};
                 | 
              |
| 179 | 
                  - }  | 
              |
| 180 | 
                  - }  | 
              |
| 182 | 
                  + # Set no filter keys  | 
              |
| 183 | 
                  + $query->no_filters($self->no_filters) unless $query->no_filters;  | 
              |
| 184 | 
                  +  | 
              |
| 185 | 
                  + # Create bind value  | 
              |
| 186 | 
                  + my $bind_values = $self->_build_bind_values($query, $params);  | 
              |
| 181 | 187 | 
                   | 
              
| 182 | 188 | 
                  # Execute  | 
              
| 183 | 
                  - my $ret_val = $sth->execute(@bind_values);  | 
              |
| 189 | 
                  + my $ret_val = $query->sth->execute(@$bind_values);  | 
              |
| 184 | 190 | 
                   | 
              
| 185 | 191 | 
                  # Return resultset if select statement is executed  | 
              
| 186 | 192 | 
                       if ($sth->{NUM_OF_FIELDS}) {
                 | 
              
| ... | ... | 
                  @@ -194,34 +200,67 @@ sub query {
                 | 
              
| 194 | 200 | 
                  return $ret_val;  | 
              
| 195 | 201 | 
                  }  | 
              
| 196 | 202 | 
                   | 
              
| 197 | 
                  -# Prepare and execute raw SQL  | 
              |
| 198 | 
                  -sub query_raw_sql {
                 | 
              |
| 199 | 
                  - my ($self, $sql, @bind_values) = @_;  | 
              |
| 200 | 
                  -  | 
              |
| 201 | 
                  - # Connect  | 
              |
| 202 | 
                  - $self->connect unless $self->connected;  | 
              |
| 203 | 
                  -  | 
              |
| 204 | 
                  - # Add semicolon if not exist;  | 
              |
| 205 | 
                  - $sql .= ';' unless $sql =~ /;$/;  | 
              |
| 203 | 
                  +sub _build_bind_values {
                 | 
              |
| 204 | 
                  + my ($self, $query, $params) = @_;  | 
              |
| 205 | 
                  + my $bind_filter = $query->bind_filter;  | 
              |
| 206 | 
                  +    my $no_filters_map  = $query->_no_filters_map || {};
                 | 
              |
| 206 | 207 | 
                   | 
              
| 207 | 
                  - # Prepare  | 
              |
| 208 | 
                  - my $sth = $self->dbh->prepare($sql);  | 
              |
| 208 | 
                  + # binding values  | 
              |
| 209 | 
                  + my @bind_values;  | 
              |
| 209 | 210 | 
                   | 
              
| 210 | 
                  - # Execute  | 
              |
| 211 | 
                  - my $ret_val = $sth->execute(@bind_values);  | 
              |
| 212 | 
                  -  | 
              |
| 213 | 
                  - # Return resultset if select statement is executed  | 
              |
| 214 | 
                  -    if ($sth->{NUM_OF_FIELDS}) {
                 | 
              |
| 215 | 
                  - my $result_class = $self->result_class;  | 
              |
| 216 | 
                  -        my $result = $result_class->new({
                 | 
              |
| 217 | 
                  - sth => $sth,  | 
              |
| 218 | 
                  - fetch_filter => $self->fetch_filter  | 
              |
| 219 | 
                  - });  | 
              |
| 220 | 
                  - return $result;  | 
              |
| 211 | 
                  + # Filter and sdd bind values  | 
              |
| 212 | 
                  +    foreach my $param_key_info (@$param_key_infos) {
                 | 
              |
| 213 | 
                  +        my $filtering_key = $param_key_info->{key};
                 | 
              |
| 214 | 
                  +        my $access_keys = $param_key_info->{access_keys};
                 | 
              |
| 215 | 
                  +  | 
              |
| 216 | 
                  +        my $original_key = $param_key_info->{original_key} || '';
                 | 
              |
| 217 | 
                  +        my $table        = $param_key_info->{table}        || '';
                 | 
              |
| 218 | 
                  +        my $column       = $param_key_info->{column}       || '';
                 | 
              |
| 219 | 
                  +  | 
              |
| 220 | 
                  + ACCESS_KEYS :  | 
              |
| 221 | 
                  +        foreach my $access_key (@$access_keys) {
                 | 
              |
| 222 | 
                  + my $root_params = $params;  | 
              |
| 223 | 
                  +            for (my $i = 0; $i < @$access_key; $i++) {
                 | 
              |
| 224 | 
                  + my $key = $access_key->[$i];  | 
              |
| 225 | 
                  +  | 
              |
| 226 | 
                  +                croak("'access_keys' each value must be string or array reference")
                 | 
              |
| 227 | 
                  + unless (ref $key eq 'ARRAY' || ($key && !ref $key));  | 
              |
| 228 | 
                  +  | 
              |
| 229 | 
                  +                if ($i == @$access_key - 1) {
                 | 
              |
| 230 | 
                  +                    if (ref $key eq 'ARRAY') {
                 | 
              |
| 231 | 
                  +                        if ($bind_filter && !$no_filters_map->{$original_key}) {
                 | 
              |
| 232 | 
                  + push @bind_values, $bind_filter->($root_params->[$key->[0]], $original_key, $table, $column);  | 
              |
| 233 | 
                  + }  | 
              |
| 234 | 
                  +                        else {
                 | 
              |
| 235 | 
                  + push @bind_values, scalar $root_params->[$key->[0]];  | 
              |
| 236 | 
                  + }  | 
              |
| 237 | 
                  + }  | 
              |
| 238 | 
                  +                    else {
                 | 
              |
| 239 | 
                  +                        next ACCESS_KEYS unless exists $root_params->{$key};
                 | 
              |
| 240 | 
                  +                        if ($bind_filter && !$no_filters_map->{$original_key}) {
                 | 
              |
| 241 | 
                  +                            push @bind_values, scalar $bind_filter->($root_params->{$key}, $original_key, $table, $column);
                 | 
              |
| 242 | 
                  + }  | 
              |
| 243 | 
                  +                        else {
                 | 
              |
| 244 | 
                  +                            push @bind_values, scalar $root_params->{$key};
                 | 
              |
| 245 | 
                  + }  | 
              |
| 246 | 
                  + }  | 
              |
| 247 | 
                  + return @bind_values;  | 
              |
| 248 | 
                  + }  | 
              |
| 249 | 
                  +  | 
              |
| 250 | 
                  +                if ($key eq 'ARRAY') {
                 | 
              |
| 251 | 
                  + $root_params = $root_params->[$key->[0]];  | 
              |
| 252 | 
                  + }  | 
              |
| 253 | 
                  +                else {
                 | 
              |
| 254 | 
                  +                    next ACCESS_KEYS unless exists $root_params->{$key};
                 | 
              |
| 255 | 
                  +                    $root_params = $root_params->{$key};
                 | 
              |
| 256 | 
                  + }  | 
              |
| 257 | 
                  + }  | 
              |
| 258 | 
                  + }  | 
              |
| 259 | 
                  +        croak("Cannot find key");
                 | 
              |
| 221 | 260 | 
                  }  | 
              
| 222 | 
                  - return $ret_val;  | 
              |
| 223 | 261 | 
                  }  | 
              
| 224 | 262 | 
                   | 
              
| 263 | 
                  +  | 
              |
| 225 | 264 | 
                  Object::Simple->build_class;  | 
              
| 226 | 265 | 
                   | 
              
| 227 | 266 | 
                  =head1 NAME  | 
              
| ... | ... | 
                  @@ -237,6 +276,9 @@ Version 0.0101  | 
              
| 237 | 276 | 
                  =head1 SYNOPSIS  | 
              
| 238 | 277 | 
                   | 
              
| 239 | 278 | 
                  my $dbi = DBI::Custom->new;  | 
              
| 279 | 
                  +  | 
              |
| 280 | 
                  + my $query = $dbi->create_query($template);  | 
              |
| 281 | 
                  + $dbi->execute($query);  | 
              |
| 240 | 282 | 
                   | 
              
| 241 | 283 | 
                  =head1 CLASS-OBJECT ACCESSORS  | 
              
| 242 | 284 | 
                   | 
              
| ... | ... | 
                  @@ -41,12 +41,12 @@ sub create_table1 {
                 | 
              
| 41 | 41 | 
                   | 
              
| 42 | 42 | 
                   sub insert {
                 | 
              
| 43 | 43 | 
                  my ($self, @values_list) = @_;  | 
              
| 44 | 
                  - my $table = ref $values_list[0] ? '' : shift;  | 
              |
| 44 | 
                  + my $table = ref $params_list[0] ? '' : shift;  | 
              |
| 45 | 45 | 
                  $table ||= 't1';  | 
              
| 46 | 46 | 
                   | 
              
| 47 | 
                  -    foreach my $values (@values_list) {
                 | 
              |
| 48 | 
                  - my $sql = $self->dbi->query(  | 
              |
| 49 | 
                  -            "insert into $table {insert_values}", {insert_values => $values}
                 | 
              |
| 47 | 
                  +    foreach my $params (@values_list) {
                 | 
              |
| 48 | 
                  + my $sql = $self->dbi->execute(  | 
              |
| 49 | 
                  +            "insert into $table {insert_values}", {insert_values => $params}
                 | 
              |
| 50 | 50 | 
                  );  | 
              
| 51 | 51 | 
                  }  | 
              
| 52 | 52 | 
                  return $self;  | 
              
| ... | ... | 
                  @@ -69,7 +69,7 @@ $t->new->create_table1->insert({k1 => 1, k2 => 2}, {k1 => 3, k2 => 4})->test(sub
                 | 
              
| 69 | 69 | 
                  my @rows;  | 
              
| 70 | 70 | 
                  my $rows;  | 
              
| 71 | 71 | 
                   | 
              
| 72 | 
                  -    $r = $dbi->query("select k1, k2 from t1");
                 | 
              |
| 72 | 
                  +    $r = $dbi->execute("select k1, k2 from t1");
                 | 
              |
| 73 | 73 | 
                   | 
              
| 74 | 74 | 
                  @rows = ();  | 
              
| 75 | 75 | 
                       while (my $row = $r->fetch) {
                 | 
              
| ... | ... | 
                  @@ -78,7 +78,7 @@ $t->new->create_table1->insert({k1 => 1, k2 => 2}, {k1 => 3, k2 => 4})->test(sub
                 | 
              
| 78 | 78 | 
                  is_deeply(\@rows, [[1, 2], [3, 4]], 'fetch');  | 
              
| 79 | 79 | 
                   | 
              
| 80 | 80 | 
                   | 
              
| 81 | 
                  -    $r = $dbi->query("select k1, k2 from t1");
                 | 
              |
| 81 | 
                  +    $r = $dbi->execute("select k1, k2 from t1");
                 | 
              |
| 82 | 82 | 
                   | 
              
| 83 | 83 | 
                  @rows = ();  | 
              
| 84 | 84 | 
                       while (my @row = $r->fetch) {
                 | 
              
| ... | ... | 
                  @@ -87,7 +87,7 @@ $t->new->create_table1->insert({k1 => 1, k2 => 2}, {k1 => 3, k2 => 4})->test(sub
                 | 
              
| 87 | 87 | 
                  is_deeply(\@rows, [[1, 2], [3, 4]], 'fetch list context');  | 
              
| 88 | 88 | 
                   | 
              
| 89 | 89 | 
                   | 
              
| 90 | 
                  -    $r = $dbi->query("select k1, k2 from t1;");
                 | 
              |
| 90 | 
                  +    $r = $dbi->execute("select k1, k2 from t1;");
                 | 
              |
| 91 | 91 | 
                   | 
              
| 92 | 92 | 
                  @rows = ();  | 
              
| 93 | 93 | 
                       while (my $row = $r->fetch_hash) {
                 | 
              
| ... | ... | 
                  @@ -96,7 +96,7 @@ $t->new->create_table1->insert({k1 => 1, k2 => 2}, {k1 => 3, k2 => 4})->test(sub
                 | 
              
| 96 | 96 | 
                       is_deeply(\@rows, [{k1 => 1, k2 => 2}, {k1 => 3, k2 => 4}], 'fetch_hash');
                 | 
              
| 97 | 97 | 
                   | 
              
| 98 | 98 | 
                   | 
              
| 99 | 
                  -    $r = $dbi->query("select k1, k2 from t1;");
                 | 
              |
| 99 | 
                  +    $r = $dbi->execute("select k1, k2 from t1;");
                 | 
              |
| 100 | 100 | 
                   | 
              
| 101 | 101 | 
                  @rows = ();  | 
              
| 102 | 102 | 
                       while (my %row = $r->fetch_hash) {
                 | 
              
| ... | ... | 
                  @@ -105,25 +105,25 @@ $t->new->create_table1->insert({k1 => 1, k2 => 2}, {k1 => 3, k2 => 4})->test(sub
                 | 
              
| 105 | 105 | 
                       is_deeply(\@rows, [{k1 => 1, k2 => 2}, {k1 => 3, k2 => 4}], 'fetch hash list context');
                 | 
              
| 106 | 106 | 
                   | 
              
| 107 | 107 | 
                   | 
              
| 108 | 
                  -    $r = $dbi->query("select k1, k2 from t1");
                 | 
              |
| 108 | 
                  +    $r = $dbi->execute("select k1, k2 from t1");
                 | 
              |
| 109 | 109 | 
                   | 
              
| 110 | 110 | 
                  $rows = $r->fetch_all;  | 
              
| 111 | 111 | 
                  is_deeply($rows, [[1, 2], [3, 4]], 'fetch_all');  | 
              
| 112 | 112 | 
                   | 
              
| 113 | 113 | 
                   | 
              
| 114 | 
                  -    $r = $dbi->query("select k1, k2 from t1");
                 | 
              |
| 114 | 
                  +    $r = $dbi->execute("select k1, k2 from t1");
                 | 
              |
| 115 | 115 | 
                   | 
              
| 116 | 116 | 
                  @rows = $r->fetch_all;  | 
              
| 117 | 117 | 
                  is_deeply(\@rows, [[1, 2], [3, 4]], 'fetch_all list context');  | 
              
| 118 | 118 | 
                   | 
              
| 119 | 119 | 
                   | 
              
| 120 | 
                  -    $r = $dbi->query("select k1, k2 from t1");
                 | 
              |
| 120 | 
                  +    $r = $dbi->execute("select k1, k2 from t1");
                 | 
              |
| 121 | 121 | 
                   | 
              
| 122 | 122 | 
                  @rows = $r->fetch_all_hash;  | 
              
| 123 | 123 | 
                  is_deeply($rows, [[1, 2], [3, 4]], 'fetch_all_hash');  | 
              
| 124 | 124 | 
                   | 
              
| 125 | 125 | 
                   | 
              
| 126 | 
                  -    $r = $dbi->query("select k1, k2 from t1");
                 | 
              |
| 126 | 
                  +    $r = $dbi->execute("select k1, k2 from t1");
                 | 
              |
| 127 | 127 | 
                   | 
              
| 128 | 128 | 
                  @rows = $r->fetch_all;  | 
              
| 129 | 129 | 
                  is_deeply(\@rows, [[1, 2], [3, 4]], 'fetch_all_hash list context');  | 
              
| ... | ... | 
                  @@ -137,14 +137,14 @@ $t->new->create_table1->insert({k1 => 1, k2 => 2}, {k1 => 3, k2 => 4})->test(sub
                 | 
              
| 137 | 137 | 
                  return $value;  | 
              
| 138 | 138 | 
                  });  | 
              
| 139 | 139 | 
                   | 
              
| 140 | 
                  -    $r = $dbi->query("select k1, k2 from t1");
                 | 
              |
| 140 | 
                  +    $r = $dbi->execute("select k1, k2 from t1");
                 | 
              |
| 141 | 141 | 
                   | 
              
| 142 | 142 | 
                  $rows = $r->fetch_all;  | 
              
| 143 | 143 | 
                   | 
              
| 144 | 144 | 
                  is_deeply($rows, [[3, 2], [3, 4]], 'fetch_filter array');  | 
              
| 145 | 145 | 
                   | 
              
| 146 | 146 | 
                   | 
              
| 147 | 
                  -    $r = $dbi->query("select k1, k2 from t1");
                 | 
              |
| 147 | 
                  +    $r = $dbi->execute("select k1, k2 from t1");
                 | 
              |
| 148 | 148 | 
                   | 
              
| 149 | 149 | 
                  $rows = $r->fetch_all_hash;  | 
              
| 150 | 150 | 
                   |