| ... | ... | 
                  @@ -183,7 +183,11 @@ sub create_query {
                 | 
              
| 183 | 183 | 
                   | 
              
| 184 | 184 | 
                  # Prepare statement handle  | 
              
| 185 | 185 | 
                       my $sth = eval{$self->dbh->prepare($query->{sql})};
                 | 
              
| 186 | 
                  - croak($@) if $@;  | 
              |
| 186 | 
                  +    if ($@) {
                 | 
              |
| 187 | 
                  +        my $sql = $query->{sql} || '';
                 | 
              |
| 188 | 
                  + my $message = "<Created SQL>\n$sql\n";  | 
              |
| 189 | 
                  +        croak("$@$message");
                 | 
              |
| 190 | 
                  + }  | 
              |
| 187 | 191 | 
                   | 
              
| 188 | 192 | 
                  # Set statement handle  | 
              
| 189 | 193 | 
                  $query->sth($sth);  | 
              
| ... | ... | 
                  @@ -193,7 +197,7 @@ sub create_query {
                 | 
              
| 193 | 197 | 
                   | 
              
| 194 | 198 | 
                  # Set no filter keys when binding  | 
              
| 195 | 199 | 
                  $query->no_bind_filters($self->no_bind_filters);  | 
              
| 196 | 
                  -  | 
              |
| 200 | 
                  +  | 
              |
| 197 | 201 | 
                  # Set fetch filter  | 
              
| 198 | 202 | 
                  $query->fetch_filter($self->fetch_filter);  | 
              
| 199 | 203 | 
                   | 
              
| ... | ... | 
                  @@ -207,6 +211,14 @@ sub execute {
                 | 
              
| 207 | 211 | 
                  my ($self, $query, $params) = @_;  | 
              
| 208 | 212 | 
                       $params ||= {};
                 | 
              
| 209 | 213 | 
                   | 
              
| 214 | 
                  + # First argument is SQL template  | 
              |
| 215 | 
                  +    if (!ref $query) {
                 | 
              |
| 216 | 
                  + my $template = $query;  | 
              |
| 217 | 
                  + $query = $self->create_query($template);  | 
              |
| 218 | 
                  + my $query_edit_cb = $_[3];  | 
              |
| 219 | 
                  + $query_edit_cb->($query) if ref $query_edit_cb eq 'CODE';  | 
              |
| 220 | 
                  + }  | 
              |
| 221 | 
                  +  | 
              |
| 210 | 222 | 
                  # Create bind value  | 
              
| 211 | 223 | 
                  my $bind_values = $self->_build_bind_values($query, $params);  | 
              
| 212 | 224 | 
                   | 
              
| ... | ... | 
                  @@ -294,9 +306,9 @@ sub _build_bind_values {
                 | 
              
| 294 | 306 | 
                   | 
              
| 295 | 307 | 
                           unless ($found) {
                 | 
              
| 296 | 308 | 
                  require Data::Dumper;  | 
              
| 297 | 
                  - my $key_info_dump = Data::Dumper->Dump([$key_info], ['*key_info']);  | 
              |
| 309 | 
                  + my $key_info_dump = Data::Dumper->Dump([$key_info], ['*key_info']);  | 
              |
| 298 | 310 | 
                  my $params_dump = Data::Dumper->Dump([$params], ['*params']);  | 
              
| 299 | 
                  -            croak("Key not found\n\n" . 
                 | 
              |
| 311 | 
                  +            croak("Key not found in your parameters\n" . 
                 | 
              |
| 300 | 312 | 
                  "<Key information>\n$key_info_dump\n\n" .  | 
              
| 301 | 313 | 
                  "<Your parameters>\n$params_dump\n");  | 
              
| 302 | 314 | 
                  }  | 
              
| ... | ... | 
                  @@ -20,7 +20,8 @@ sub test {
                 | 
              
| 20 | 20 | 
                   | 
              
| 21 | 21 | 
                  # Varialbes for test  | 
              
| 22 | 22 | 
                   our $CREATE_TABLE = {
                 | 
              
| 23 | 
                  - 0 => 'create table table1 (key1 char(255), key2 char(255));'  | 
              |
| 23 | 
                  + 0 => 'create table table1 (key1 char(255), key2 char(255));',  | 
              |
| 24 | 
                  + 1 => 'create table table1 (key1 char(255), key2 char(255), key3 char(255), key4 char(255), key5 char(255));'  | 
              |
| 24 | 25 | 
                  };  | 
              
| 25 | 26 | 
                   | 
              
| 26 | 27 | 
                   our $SELECT_TMPL = {
                 | 
              
| ... | ... | 
                  @@ -111,6 +112,7 @@ $result = $dbi->execute($query);  | 
              
| 111 | 112 | 
                  @rows = $result->fetch_all;  | 
              
| 112 | 113 | 
                  is_deeply(\@rows, [[1, 2], [3, 4]], "$test : fetch_all_hash list context");  | 
              
| 113 | 114 | 
                   | 
              
| 115 | 
                  +  | 
              |
| 114 | 116 | 
                  test 'Insert query return value';  | 
              
| 115 | 117 | 
                  $dbi->reconnect;  | 
              
| 116 | 118 | 
                   $dbi->do($CREATE_TABLE->{0});
                 | 
              
| ... | ... | 
                  @@ -119,6 +121,28 @@ $query = $dbi->create_query($tmpl);  | 
              
| 119 | 121 | 
                   $ret_val = $dbi->execute($query, {key1 => 1, key2 => 2});
                 | 
              
| 120 | 122 | 
                  ok($ret_val, $test);  | 
              
| 121 | 123 | 
                   | 
              
| 124 | 
                  +  | 
              |
| 125 | 
                  +test 'Direct execute';  | 
              |
| 126 | 
                  +$dbi->reconnect;  | 
              |
| 127 | 
                  +$dbi->do($CREATE_TABLE->{0});
                 | 
              |
| 128 | 
                  +$insert_tmpl = "insert into table1 {insert key1 key2}";
                 | 
              |
| 129 | 
                  +$dbi->execute($insert_tmpl, {key1 => 1, key2 => 2}, sub {
                 | 
              |
| 130 | 
                  + my $query = shift;  | 
              |
| 131 | 
                  +    $query->bind_filter(sub {
                 | 
              |
| 132 | 
                  + my ($key, $value) = @_;  | 
              |
| 133 | 
                  +        if ($key eq 'key2') {
                 | 
              |
| 134 | 
                  + return $value + 1;  | 
              |
| 135 | 
                  + }  | 
              |
| 136 | 
                  + return $value;  | 
              |
| 137 | 
                  + });  | 
              |
| 138 | 
                  +});  | 
              |
| 139 | 
                  +  | 
              |
| 140 | 
                  +$result = $dbi->execute($SELECT_TMPL->{0});
                 | 
              |
| 141 | 
                  +  | 
              |
| 142 | 
                  +$rows = $result->fetch_all_hash;  | 
              |
| 143 | 
                  +is_deeply($rows, [{key1 => 1, key2 => 3}], $test);
                 | 
              |
| 144 | 
                  +  | 
              |
| 145 | 
                  +  | 
              |
| 122 | 146 | 
                  test 'Filter';  | 
              
| 123 | 147 | 
                  $dbi->reconnect;  | 
              
| 124 | 148 | 
                   $dbi->do($CREATE_TABLE->{0});
                 | 
              
| ... | ... | 
                  @@ -148,6 +172,17 @@ $result = $dbi->execute($select_query);  | 
              
| 148 | 172 | 
                  $rows = $result->fetch_all_hash;  | 
              
| 149 | 173 | 
                   is_deeply($rows, [{key1 => 2, key2 => 6}], "$test : bind_filter fetch_filter");
                 | 
              
| 150 | 174 | 
                   | 
              
| 175 | 
                  +  | 
              |
| 176 | 
                  +$dbi->do("delete from table1;");
                 | 
              |
| 177 | 
                  +$insert_query->no_bind_filters('key1');
                 | 
              |
| 178 | 
                  +$select_query->no_fetch_filters('key2');
                 | 
              |
| 179 | 
                  +  | 
              |
| 180 | 
                  +$dbi->execute($insert_query, {key1 => 1, key2 => 2});
                 | 
              |
| 181 | 
                  +$result = $dbi->execute($select_query);  | 
              |
| 182 | 
                  +$rows = $result->fetch_all_hash;  | 
              |
| 183 | 
                  +is_deeply($rows, [{key1 => 1, key2 => 2}], 'no_fetch_filters no_bind_filters');
                 | 
              |
| 184 | 
                  +  | 
              |
| 185 | 
                  +  | 
              |
| 151 | 186 | 
                  $dbi->reconnect;  | 
              
| 152 | 187 | 
                   $dbi->do($CREATE_TABLE->{0});
                 | 
              
| 153 | 188 | 
                   $insert_tmpl  = "insert into table1 {insert table1.key1 table1.key2}";
                 | 
              
| ... | ... | 
                  @@ -168,59 +203,37 @@ $result = $dbi->execute($select_query);  | 
              
| 168 | 203 | 
                  $rows = $result->fetch_all_hash;  | 
              
| 169 | 204 | 
                   is_deeply($rows, [{key1 => 3, key2 => 2}], "$test : insert with table name");
                 | 
              
| 170 | 205 | 
                   | 
              
| 206 | 
                  +test 'DBI::Custom::SQL::Template';  | 
              |
| 207 | 
                  +$dbi->reconnect;  | 
              |
| 208 | 
                  +$dbi->do($CREATE_TABLE->{1});
                 | 
              |
| 209 | 
                  +$sth = $dbi->prepare("insert into table1 (key1, key2, key3, key4, key5) values (?, ?, ?, ?, ?);");
                 | 
              |
| 210 | 
                  +$sth->execute(1, 2, 3, 4, 5);  | 
              |
| 211 | 
                  +$sth->execute(6, 7, 8, 9, 10);  | 
              |
| 171 | 212 | 
                   | 
              
| 172 | 
                  -__END__  | 
              |
| 173 | 
                  -  | 
              |
| 174 | 
                  -$dbi->fetch_filter(sub {
                 | 
              |
| 175 | 
                  - my ($key, $value, $type, $sth, $i) = @_;  | 
              |
| 176 | 
                  -    if ($key eq 'key1' && $value == 1 && $type =~ /char/i && $i == 0 && $sth->{TYPE}->[$i] eq $type) {
                 | 
              |
| 177 | 
                  - return $value * 3;  | 
              |
| 178 | 
                  - }  | 
              |
| 179 | 
                  - return $value;  | 
              |
| 180 | 
                  -});  | 
              |
| 181 | 
                  -  | 
              |
| 182 | 
                  -$result = $dbi->execute("select key1, key2 from table1");
                 | 
              |
| 183 | 
                  -  | 
              |
| 184 | 
                  -$rows = $result->fetch_all;  | 
              |
| 185 | 
                  -  | 
              |
| 186 | 
                  -is_deeply($rows, [[3, 2], [3, 4]], 'fetch_filter array');  | 
              |
| 187 | 
                  -  | 
              |
| 188 | 
                  -  | 
              |
| 189 | 
                  -$result = $dbi->execute("select key1, key2 from table1");
                 | 
              |
| 190 | 
                  -  | 
              |
| 213 | 
                  +$tmpl = "select * from table1 where {= key1} and {<> key2} and {< key3} and {> key4} and {>= key5};";
                 | 
              |
| 214 | 
                  +$query = $dbi->create_query($tmpl);  | 
              |
| 215 | 
                  +$result = $dbi->execute($query, {key1 => 1, key2 => 3, key3 => 4, key4 => 3, key5 => 5});
                 | 
              |
| 191 | 216 | 
                  $rows = $result->fetch_all_hash;  | 
              
| 217 | 
                  +is_deeply($rows, [{key1 => 1, key2 => 2, key3 => 3, key4 => 4, key5 => 5}], "$test : basic tag1");
                 | 
              |
| 192 | 218 | 
                   | 
              
| 193 | 
                  -is_deeply($rows, [{key1 => 3, key2 => 2}, {key1 => 3, key2 => 4}], 'fetch_filter hash');
                 | 
              |
| 194 | 
                  -  | 
              |
| 195 | 
                  -  | 
              |
| 196 | 
                  -  | 
              |
| 197 | 
                  -# Expand place holer  | 
              |
| 198 | 
                  -my $dbi = DBI::Custom->new;  | 
              |
| 199 | 
                  -my $tmpl   = "select * from table where {= key1} && {<> key2} && {< k3} && {> k4} && {>= k5} && {<= k6} && {like k7}";
                 | 
              |
| 200 | 
                  -my $params = {key1 => 'a', key2 => 'b', k3 => 'c', k4 => 'd', k5 => 'e', k6 => 'f', k7 => 'g'};
                 | 
              |
| 219 | 
                  +$tmpl = "select * from table1 where {<= key1} and {like key2};";
                 | 
              |
| 220 | 
                  +$query = $dbi->create_query($tmpl);  | 
              |
| 221 | 
                  +$result = $dbi->execute($query, {key1 => 1, key2 => '%2%'});
                 | 
              |
| 222 | 
                  +$rows = $result->fetch_all_hash;  | 
              |
| 223 | 
                  +is_deeply($rows, [{key1 => 1, key2 => 2, key3 => 3, key4 => 4, key5 => 5}], "$test : basic tag2");
                 | 
              |
| 201 | 224 | 
                   | 
              
| 202 | 
                  -$dbi->filters(filter => sub {
                 | 
              |
| 203 | 
                  - my ($key, $value) = @_;  | 
              |
| 204 | 
                  -    if ($key eq 'key1' && $value eq 'a') {
                 | 
              |
| 205 | 
                  - return uc $value;  | 
              |
| 206 | 
                  - }  | 
              |
| 207 | 
                  - return $value;  | 
              |
| 208 | 
                  -});  | 
              |
| 209 | 225 | 
                   | 
              
| 210 | 
                  -my ($sql, @bind_values) = $dbi->_create_sql($tmpl, $params, $dbi->filters->{filter});
                 | 
              |
| 226 | 
                  +$dbi->do("delete from table1");
                 | 
              |
| 227 | 
                  +$insert_tmpl = 'insert into table1 {insert key1 key2 key3 key4 key5}';
                 | 
              |
| 228 | 
                  +$dbi->execute($insert_tmpl, {key1 => 1, key2 => 2, key3 => 3, key4 => 4, key5 => 5});
                 | 
              |
| 211 | 229 | 
                   | 
              
| 212 | 
                  -is($sql, "select * from table where key1 = ? && key2 <> ? && k3 < ? && k4 > ? && k5 >= ? && k6 <= ? && k7 like ?;", 'sql template2');  | 
              |
| 213 | 
                  -is_deeply(\@bind, ['A', 'b', 'c', 'd', 'e', 'f', 'g'], 'sql template bind2' );  | 
              |
| 230 | 
                  +$select_tmpl = 'select * from table1';  | 
              |
| 231 | 
                  +$result = $dbi->execute($select_tmpl);  | 
              |
| 232 | 
                  +$rows = $result->fetch_all_hash;  | 
              |
| 233 | 
                  +is_deeply($rows, [{key1 => 1, key2 => 2, key3 => 3, key4 => 4, key5 => 5}], "$test insert tag");
                 | 
              |
| 214 | 234 | 
                   | 
              
| 215 | 
                  -# Expand place holer upper case  | 
              |
| 216 | 
                  -my $dbi = DBI::Custom->new;  | 
              |
| 217 | 
                  -$dbi->sql_template->upper_case(1);  | 
              |
| 218 | 
                  -my $tmpl   = "select * from table where {like k7}";
                 | 
              |
| 219 | 
                  -my $params = {k7 => 'g'};
                 | 
              |
| 220 | 235 | 
                   | 
              
| 221 | 
                  -($sql, @bind_values) = $dbi->_create_sql($tmpl, $params);  | 
              |
| 222 | 
                  -is($sql, "select * from table where k7 LIKE ?;", 'sql template2');  | 
              |
| 223 | 
                  -is_deeply(\@bind, ['g'], 'sql template bind2' );  | 
              |
| 236 | 
                  +__END__  | 
              |
| 224 | 237 | 
                   | 
              
| 225 | 238 | 
                  # Insert values  | 
              
| 226 | 239 | 
                  $dbi = DBI::Custom->new;  | 
              
| ... | ... | 
                  @@ -258,3 +271,5 @@ is_deeply(\@bind, ['A', 'b'], 'sql template bind' );  | 
              
| 258 | 271 | 
                   | 
              
| 259 | 272 | 
                  $dbi->disconnnect;  | 
              
| 260 | 273 | 
                   | 
              
| 274 | 
                  +# Tag 'in' is easy to wrong  | 
              |
| 275 | 
                  +  |