package SQL::Translator::Parser::SQLite;
# -------------------------------------------------------------------
-# $Id: SQLite.pm,v 1.1 2003-10-03 00:20:51 kycl4rk Exp $
-# -------------------------------------------------------------------
-# Copyright (C) 2003 Ken Y. Clark <kclark@cpan.org>,
-# darren chamberlain <darren@cpan.org>,
-# Chris Mungall <cjm@fruitfly.org>
+# Copyright (C) 2002-2009 SQLFairy Authors
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
trigger-step ::=
update-statement | insert-statement |
- delete-statement | select-statemen
+ delete-statement | select-statement
CREATE VIEW
use strict;
use vars qw[ $DEBUG $VERSION $GRAMMAR @EXPORT_OK ];
-$VERSION = sprintf "%d.%02d", q$Revision: 1.1 $ =~ /(\d+)\.(\d+)/;
+$VERSION = '1.99';
$DEBUG = 0 unless defined $DEBUG;
use Data::Dumper;
$GRAMMAR = q!
{
- my ( %tables, $table_order, @table_comments );
+ my ( %tables, $table_order, @table_comments, @views, @triggers );
}
#
# won't cause the failure needed to know that the parse, as a whole,
# failed. -ky
#
-startrule : statement(s) eofile { \%tables }
+startrule : statement(s) eofile {
+ $return = {
+ tables => \%tables,
+ views => \@views,
+ triggers => \@triggers,
+ }
+}
eofile : /^\Z/
statement : begin_transaction
| commit
+ | drop
| comment
| create
| <error>
-begin_transaction : /begin transaction/i SEMICOLON
+begin_transaction : /begin/i TRANSACTION(?) SEMICOLON
commit : /commit/i SEMICOLON
+drop : /drop/i TABLE <commit> table_name SEMICOLON
+
comment : /^\s*(?:#|-{2}).*\n/
{
my $comment = $item[1];
#
# Create Trigger
-create : CREATE TEMPORARY(?) TRIGGER NAME before_or_after(?) database_event ON table_name trigger_action
+create : CREATE TEMPORARY(?) TRIGGER NAME before_or_after(?) database_event ON table_name trigger_action SEMICOLON
{
my $table_name = $item[8]->{'name'};
- push @{ $tables{ $table_name }{'triggers'} }, {
+ push @triggers, {
name => $item[4],
is_temporary => $item[2][0] ? 1 : 0,
when => $item[5][0],
instead_of => 0,
- db_event => $item[6],
+ db_events => [ $item[6] ],
action => $item[9],
+ on_table => $table_name,
}
}
create : CREATE TEMPORARY(?) TRIGGER NAME instead_of database_event ON view_name trigger_action
{
my $table_name = $item[8]->{'name'};
- push @{ $tables{ $table_name }{'triggers'} }, {
+ push @triggers, {
name => $item[4],
is_temporary => $item[2][0] ? 1 : 0,
when => undef,
instead_of => 1,
- db_event => $item[6],
+ db_events => [ $item[6] ],
action => $item[9],
+ on_table => $table_name,
}
}
}
}
-for_each : /FOR EACH ROW/i | /FOR EACH STATEMENT/i
+for_each : /FOR EACH ROW/i
when : WHEN expr { $item[2] }
-trigger_step : /(select|delete|insert|update)/i /[^;]+/ SEMICOLON
+string :
+ /'(\\.|''|[^\\\'])*'/
+
+nonstring : /[^;\'"]+/
+
+statement_body : (string | nonstring)(s?)
+
+trigger_step : /(select|delete|insert|update)/i statement_body SEMICOLON
{
- $return = join( ' ', $item[1], $item[2] )
+ $return = join( ' ', $item[1], join ' ', @{ $item[2] || [] } )
}
before_or_after : /(before|after)/i { $return = lc $1 }
view_name : qualified_name
#
+# Create View
+#
+create : CREATE TEMPORARY(?) VIEW view_name AS select_statement
+ {
+ push @views, {
+ name => $item[4]->{'name'},
+ sql => $item[6],
+ is_temporary => $item[2][0] ? 1 : 0,
+ }
+ }
+
+select_statement : SELECT /[^;]+/ SEMICOLON
+ {
+ $return = join( ' ', $item[1], $item[2] );
+ }
+
+#
# Tokens
#
BEGIN_C : /begin/i
END_C : /end/i
+TRANSACTION: /transaction/i
+
CREATE : /create/i
TEMPORARY : /temp(orary)?/i { 1 }
TRIGGER : /trigger/i
+VIEW : /view/i
+
+SELECT : /select/i
+
ON : /on/i
+AS : /as/i
+
WORD : /\w+/
WHEN : /when/i
SEMICOLON : ';'
-NAME : /'?(\w+)'?/ { $return = $1 }
+NAME : /'?(\w+)'?/ { $return = $1 }
-VALUE : /[-+]?\.?\d+(?:[eE]\d+)?/
+VALUE : /[-+]?\.?\d+(?:[eE]\d+)?/
{ $item[1] }
| /'.*?'/
{
}
| /NULL/
{ 'NULL' }
+ | /CURRENT_TIMESTAMP/i
+ { 'CURRENT_TIMESTAMP' }
!;
warn Dumper( $result ) if $DEBUG;
my $schema = $translator->schema;
- my @tables = sort {
- $result->{ $a }->{'order'} <=> $result->{ $b }->{'order'}
- } keys %{ $result };
+ my @tables =
+ map { $_->[1] }
+ sort { $a->[0] <=> $b->[0] }
+ map { [ $result->{'tables'}{ $_ }->{'order'}, $_ ] }
+ keys %{ $result->{'tables'} };
for my $table_name ( @tables ) {
- my $tdata = $result->{ $table_name };
+ my $tdata = $result->{'tables'}{ $table_name };
my $table = $schema->add_table(
name => $tdata->{'name'},
) or die $schema->error;
reference_table => $cdata->{'reference_table'},
reference_fields => $cdata->{'reference_fields'},
match_type => $cdata->{'match_type'} || '',
- on_delete => $cdata->{'on_delete_do'},
- on_update => $cdata->{'on_update_do'},
+ on_delete => $cdata->{'on_delete'} || $cdata->{'on_delete_do'},
+ on_update => $cdata->{'on_update'} || $cdata->{'on_update_do'},
) or die $table->error;
}
}
+ for my $def ( @{ $result->{'views'} || [] } ) {
+ my $view = $schema->add_view(
+ name => $def->{'name'},
+ sql => $def->{'sql'},
+ );
+ }
+
+ for my $def ( @{ $result->{'triggers'} || [] } ) {
+ my $view = $schema->add_trigger(
+ name => $def->{'name'},
+ perform_action_when => $def->{'when'},
+ database_events => $def->{'db_events'},
+ action => $def->{'action'},
+ on_table => $def->{'on_table'},
+ );
+ }
+
return 1;
}