Here's my patch for SQLite producer sucking. it could use some more tests,
but ENOTUITS. I've used itthough and it worked well for me if that counts
for anything.
--G
On Fri, Jan 16, 2009 at 6:56 AM, Ash Berlin <[email protected]> wrote:
>
> On 16 Jan 2009, at 11:44, Peter Rabbitson wrote:
>
> [email protected] wrote:
>>
>>> Patches to lib/SQL/Translator/Producer/SQLite.pm welcome :P
>>>>
>>>>
>>> Again, as file, previous mail had some additional line breaks
>>>
>>>
>>>
>> Patch seems reasonable. Please provide a diff including tests against
>> current trunk[1]. Fix the currently failing tests in t/48xml-to-sqlite
>> and t/30sqlt-new-diff-sqlite, by explicitly disabling quoting, and then
>> add new ones to test if quoting works correctly. I will bug maints to
>> apply this for you when it's ready.
>>
>> [1] https://sqlfairy.svn.sourceforge.net/svnroot/sqlfairy/trunk/sqlfairy
>>
>
> Sitting waiting for a patch. Let me know when you think its good to apply.
>
> -ash
>
>
> _______________________________________________
> List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
> IRC: irc.perl.org#dbix-class
> SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
> Searchable Archive:
> http://www.grokbase.com/group/[email protected]
>
--
Guillermo Roditi (groditi)
==== Patch <SQLite-field-table-quoting> level 1
Source: [No source]
Target: 43122cfd-0f3f-0410-9171-884ef7c37379:/trunk/sqlfairy:1464
(https://sqlfairy.svn.sourceforge.net/svnroot/sqlfairy)
Log:
properly quote fields and tables in SQLite
=== Changes
==================================================================
--- Changes (revision 1464)
+++ Changes (patch SQLite-field-table-quoting level 1)
@@ -2,6 +2,7 @@
# x.xxxxx xxxx-xx-xx
# ----------------------------------------------------------
* Properly quote absolute table names in the MySQL producer
+* Properly quote tables and fields for SQLite (groditi)
# ----------------------------------------------------------
# 0.09004 2009-02-13
=== lib/SQL/Translator/Producer/SQLite.pm
==================================================================
--- lib/SQL/Translator/Producer/SQLite.pm (revision 1464)
+++ lib/SQL/Translator/Producer/SQLite.pm (patch SQLite-field-table-quoting level 1)
@@ -62,6 +62,9 @@
my $producer_args = $translator->producer_args;
my $sqlite_version = $producer_args->{sqlite_version} || 0;
my $no_txn = $producer_args->{no_transaction};
+ my ($qt, $qf) = ('','');
+ $qt = '"' if $translator->quote_table_names;
+ $qf = '"' if $translator->quote_field_names;
debug("PKG: Beginning production\n");
@@ -70,13 +73,19 @@
$create[0] .= "\n\nBEGIN TRANSACTION" unless $no_txn;
for my $table ( $schema->get_tables ) {
- push @create, create_table($table, { no_comments => $no_comments,
- sqlite_version => $sqlite_version,
- add_drop_table => $add_drop_table,});
- }
+ push @create, create_table($table, {
+ no_comments => $no_comments,
+ quote_table_names => $qt,
+ quote_field_names => $qf,
+ sqlite_version => $sqlite_version,
+ add_drop_table => $add_drop_table,
+ });
+ }
for my $view ( $schema->get_views ) {
push @create, create_view($view, {
+ quote_table_names => $qt,
+ quote_field_names => $qf,
add_drop_view => $add_drop_table,
no_comments => $no_comments,
});
@@ -84,6 +93,8 @@
for my $trigger ( $schema->get_triggers ) {
push @create, create_trigger($trigger, {
+ quote_table_names => $qt,
+ quote_field_names => $qf,
add_drop_trigger => $add_drop_table,
no_comments => $no_comments,
});
@@ -139,8 +150,8 @@
sub create_view {
my ($view, $options) = @_;
my $add_drop_view = $options->{add_drop_view};
-
- my $view_name = $view->name;
+ my $qt = $options->{quote_table_names} || '';
+ my $view_name = quote_table_name($view->name, $qt);
debug("PKG: Looking at view '${view_name}'\n");
# Header. Should this look like what mysqldump produces?
@@ -164,8 +175,9 @@
sub create_table
{
my ($table, $options) = @_;
-
- my $table_name = $table->name;
+ my $qt = $options->{quote_table_names} || '';
+ my $qf = $options->{quote_field_names} || '';
+ my $table_name = quote_table_name($table->name, $qt);
my $no_comments = $options->{no_comments};
my $add_drop_table = $options->{add_drop_table};
my $sqlite_version = $options->{sqlite_version} || 0;
@@ -211,7 +223,7 @@
#
my ( @field_defs, $pk_set );
for my $field ( @fields ) {
- push @field_defs, create_field($field);
+ push @field_defs, create_field($field, {quote_table_names => $qt, quote_field_names => $qf});
}
if (
@@ -227,7 +239,7 @@
#
my $idx_name_default = 'A';
for my $index ( $table->get_indices ) {
- push @index_defs, create_index($index);
+ push @index_defs, create_index($index, {quote_table_names => $qt, quote_field_names => $qf});
}
#
@@ -236,7 +248,7 @@
my $c_name_default = 'A';
for my $c ( $table->get_constraints ) {
next unless $c->type eq UNIQUE;
- push @constraint_defs, create_constraint($c);
+ push @constraint_defs, create_constraint($c, {quote_table_names => $qt, quote_field_names => $qf});
}
$create_table .= join(",\n", map { " $_" } @field_defs ) . "\n)";
@@ -247,8 +259,10 @@
sub create_field
{
my ($field, $options) = @_;
+ $options ||= {};
+ my $qf = $options->{quote_field_names} || '';
- my $field_name = $field->name;
+ my $field_name = $qf.$field->name.$qf;
debug("PKG: Looking at field '$field_name'\n");
my $field_comments = $field->comments
? "-- " . $field->comments . "\n "
@@ -327,9 +341,11 @@
sub create_index
{
my ($index, $options) = @_;
-
+ $options ||= {};
+ my $qt = $options->{quote_table_names} || '';
+ my $qf = $options->{quote_field_names} || '';
my $name = $index->name;
- $name = mk_name($index->table->name, $name);
+ $name = $qf.mk_name($index->table->name, $name).$qf;
my $type = $index->type eq 'UNIQUE' ? "UNIQUE " : '';
@@ -338,8 +354,8 @@
(my $index_table_name = $index->table->name) =~ s/^.+?\.//; # table name may not specify schema
warn "removing schema name from '" . $index->table->name . "' to make '$index_table_name'\n" if $WARN;
my $index_def =
- "CREATE ${type}INDEX $name ON " . $index_table_name .
- ' (' . join( ', ', @fields ) . ')';
+ "CREATE ${type}INDEX $name ON " . quote_table_name($index_table_name,$qt) .
+ ' (' . join( ', ', map { $qf.$_.$qf } @fields ) . ')';
return $index_def;
}
@@ -347,24 +363,27 @@
sub create_constraint
{
my ($c, $options) = @_;
-
+ $options ||= {};
+ my $qt = $options->{quote_table_names} || '';
+ my $qf = $options->{quote_field_names} || '';
my $name = $c->name;
- $name = mk_name($c->table->name, $name);
+ $name = $qf.mk_name($c->table->name, $name).$qf;
my @fields = $c->fields;
(my $index_table_name = $c->table->name) =~ s/^.+?\.//; # table name may not specify schema
warn "removing schema name from '" . $c->table->name . "' to make '$index_table_name'\n" if $WARN;
my $c_def =
- "CREATE UNIQUE INDEX $name ON " . $index_table_name .
- ' (' . join( ', ', @fields ) . ')';
+ "CREATE UNIQUE INDEX $name ON " . quote_table_name($index_table_name, $qt) .
+ ' (' . join( ', ', map { $qf.$_.$qf } @fields ) . ')';
return $c_def;
}
sub create_trigger {
my ($trigger, $options) = @_;
+ $options ||= {};
my $add_drop = $options->{add_drop_trigger};
-
+ my $qt = $options->{quote_table_names} || '';
my $name = $trigger->name;
my @create;
@@ -397,7 +416,7 @@
push @create, "CREATE TRIGGER $name " .
$trigger->perform_action_when . " " .
$events->[0] .
- " on " . $trigger->on_table . " " .
+ " on " . quote_table_name($trigger->on_table, $qt) . " " .
$action;
return @create;
@@ -407,23 +426,24 @@
sub alter_table { } # Noop
sub add_field {
- my ($field) = @_;
-
- return sprintf("ALTER TABLE %s ADD COLUMN %s",
- $field->table->name, create_field($field))
+ my ($field, $options) = @_;
+ $options ||= {};
+ my $qt = $options->{quote_table_names} || '';
+ my $tbl = quote_table_name($field->table->name, $qt);
+ return sprintf("ALTER TABLE %s ADD COLUMN %s", $tbl, create_field($field));
}
sub alter_create_index {
- my ($index) = @_;
-
+ my ($index, $options) = @_;
+ $options ||= {};
# This might cause name collisions
- return create_index($index);
+ return create_index($index, $options);
}
sub alter_create_constraint {
- my ($constraint) = @_;
-
- return create_constraint($constraint) if $constraint->type eq 'UNIQUE';
+ my ($constraint, $options) = @_;
+ $options ||= {};
+ return create_constraint($constraint, $options) if $constraint->type eq 'UNIQUE';
}
sub alter_drop_constraint { alter_drop_index(@_) }
@@ -436,8 +456,10 @@
}
sub batch_alter_table {
- my ($table, $diffs) = @_;
-
+ my ($table, $diffs, $options) = @_;
+ $options ||= {};
+ my $qt = $options->{quote_table_names} || '';
+ my $qf = $options->{quote_field_names} || '';
# If we have any of the following
#
# rename_field
@@ -491,32 +513,44 @@
do {
local $table->{name} = $table_name . '_temp_alter';
# We only want the table - dont care about indexes on tmp table
- my ($table_sql) = create_table($table, {no_comments => 1, temporary_table => 1});
+ my ($table_sql) = create_table($table, {%$options, no_comments => 1, temporary_table => 1});
push @sql,$table_sql;
};
- push @sql, "INSERT INTO @{[$table_name]}_temp_alter SELECT @{[ join(', ', $old_table->get_fields)]} FROM @{[$old_table]}",
- "DROP TABLE @{[$old_table]}",
- create_table($table, { no_comments => 1 }),
- "INSERT INTO @{[$table_name]} SELECT @{[ join(', ', $old_table->get_fields)]} FROM @{[$table_name]}_temp_alter",
- "DROP TABLE @{[$table_name]}_temp_alter";
+ my $temp_tbl = $table_name."_temp_alter";
+ my $fields = join(', ', map { $qf.$_.$qf } $old_table->get_fields);
+ push(@sql,
+ "INSERT INTO ".quote_table_name($temp_tbl,$qt)." SELECT ${fields} FROM ".quote_table_name($old_table, $qt),
+ drop_table($old_table,$options),
+ create_table($table, { %$options, no_comments => 1 }),
+ "INSERT INTO ".quote_table_name($table_name,$qt)." SELECT ${fields} FROM ".quote_table_name($temp_tbl, $qt),
+ drop_table($temp_tbl, $options),
+ );
+
return @sql;
# return join("", @sql, "");
}
+sub quote_table_name {
+ my ($table_name, $qt) = @_;
+ $table_name =~ s/\./$qt.$qt/g;
+ return "${qt}${table_name}${qt}";
+}
+
+
sub drop_table {
- my ($table) = @_;
- return "DROP TABLE $table";
+ my ($table, $options) = @_;
+ $options ||= {};
+ my $qt = $options->{quote_table_names} || '';
+ return "DROP TABLE ".quote_table_name($table,$qt);
}
sub rename_table {
my ($old_table, $new_table, $options) = @_;
-
+ $options ||= {};
my $qt = $options->{quote_table_names} || '';
-
- return "ALTER TABLE $qt$old_table$qt RENAME TO $qt$new_table$qt";
-
+ return "ALTER TABLE ".quote_table_name($old_table, $qt)." RENAME TO ".quote_table_name($new_table,$qt);
}
# No-op. Just here to signify that we are a new style parser.
=== t/56-sqlite-producer.t
==================================================================
--- t/56-sqlite-producer.t (revision 1464)
+++ t/56-sqlite-producer.t (patch SQLite-field-table-quoting level 1)
@@ -2,7 +2,7 @@
# vim: set ft=perl:
use strict;
-use Test::More tests => 2;
+use Test::More tests => 4;
use Test::SQL::Translator qw(maybe_plan);
use FindBin qw/$Bin/;
@@ -33,4 +33,22 @@
my $view_sql_noreplace = "CREATE VIEW view_foo AS
SELECT id, name FROM thing";
is($view1_sql2, $view_sql_noreplace, 'correct "CREATE VIEW" SQL');
+
+
+ my $view1_sql_q = SQL::Translator::Producer::SQLite::create_view(
+ $view2, {%$create_opts, quote_table_names => '"', quote_field_names => '"'}
+ );
+ my $view_sql_noreplace_q = 'CREATE VIEW "view_foo" AS
+ SELECT id, name FROM thing';
+ is($view1_sql_q, $view_sql_noreplace_q, 'correct "CREATE VIEW" SQL');
}
+{
+
+}
+
+
+is(
+ SQL::Translator::Producer::SQLite::quote_table_name('foo.bar','"'),
+ '"foo"."bar"',
+ 'quote_table_name',
+);
==== BEGIN SVK PATCH BLOCK ====
Version: svk v2.0.2 (linux)
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
uVSva8QxLNVQjcb/AcxrI3g=
==== END SVK PATCH BLOCK ====
_______________________________________________
List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
IRC: irc.perl.org#dbix-class
SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
Searchable Archive: http://www.grokbase.com/group/[email protected]