Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Oracle producer add missing functions #143

Merged
merged 19 commits into from
Feb 23, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
ca601db
Added support for CURRENT_TIMESTAMP as a default value when parsing O…
hazardv Aug 10, 2022
0d8ce8f
Added tests to verify changes to oracle parser.
hazardv Aug 10, 2022
dbd1da1
Split the creation of contraints out from the creation of the table a…
hazardv Aug 18, 2022
929ae33
Missing a few small things
hazardv Aug 18, 2022
ed59a4d
Added drop_field to Oracle.pm and added alter constraint testing.
hazardv Aug 19, 2022
cdb544f
Added drop_table functionality along with related tests.
hazardv Aug 22, 2022
22a15de
Make sure the sqlt_args actually get passed in to the SQL::Translator…
hazardv Aug 24, 2022
ab42ef8
Removed batch alter stuff from Oracle.pm. It was just complicating th…
hazardv Aug 24, 2022
df7e62f
All quoting is working consistent to how it works for MySQL and SQLSe…
hazardv Aug 25, 2022
c90a599
Fixed issue with drop FK constraint syntax
hazardv Sep 7, 2022
b371f16
Fixed restriction stopping change of NOT NULL to NULL for non CLOB fi…
hazardv Sep 8, 2022
b14da74
Removed commented out section of code.
hazardv Sep 9, 2022
d2d080c
fixed issue with alter_drop_constraint when dropping unnamed primary …
hazardv Sep 26, 2022
2d47b5c
Reverted change to passing of $options and fixed test plan.
hazardv Sep 29, 2022
b4a8ca7
Added debug statements to figure out constraint order issue
hazardv Oct 5, 2022
a32992d
Separated FK_defs out so things would play nice and modified 51-xml-t…
hazardv Oct 5, 2022
090b5b4
Corrected quoting on index fields, updated 51-xml-to-oracle_quoted.t …
hazardv Oct 5, 2022
74c0312
Corrected changes previously made to 55-oracle-producer.t in error.
hazardv Oct 5, 2022
2a66d69
Removed some unnecessary debug comments.
hazardv Oct 5, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
206 changes: 114 additions & 92 deletions lib/SQL/Translator/Producer/Oracle.pm
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ $DEBUG = 0 unless defined $DEBUG;

use base 'SQL::Translator::Producer';
use SQL::Translator::Schema::Constants;
use SQL::Translator::Utils qw(header_comment);
use SQL::Translator::Utils qw(debug header_comment);
use Data::Dumper;

my %translate = (
Expand Down Expand Up @@ -195,8 +195,9 @@ sub produce {
my $schema = $translator->schema;
my $oracle_version = $translator->producer_args->{oracle_version} || 0;
my $delay_constraints = $translator->producer_args->{delay_constraints};
my ($output, $create, @table_defs, @trigger_defs, @index_defs, @constraint_defs);
my ($output, $create, @table_defs, @fk_defs, @trigger_defs, @index_defs, @constraint_defs);

debug("ORA: Beginning production");
$create .= header_comment unless ($no_comments);
my $qt = 1 if $translator->quote_table_names;
my $qf = 1 if $translator->quote_field_names;
Expand All @@ -212,7 +213,8 @@ sub produce {
}

for my $table ( $schema->get_tables ) {
my ( $table_def, $trigger_def, $index_def, $constraint_def ) = create_table(
debug("ORA: Producing for table " . $table->name);
my ( $table_def, $fk_def, $trigger_def, $index_def, $constraint_def ) = create_table(
$table,
{
add_drop_table => $add_drop_table,
Expand All @@ -224,6 +226,7 @@ sub produce {
}
);
push @table_defs, @$table_def;
push @fk_defs, @$fk_def;
push @trigger_defs, @$trigger_def;
push @index_defs, @$index_def;
push @constraint_defs, @$constraint_def;
Expand All @@ -242,10 +245,10 @@ sub produce {
}

if (wantarray) {
return defined $create ? $create : (), @table_defs, @view_defs, @trigger_defs, @index_defs, @constraint_defs;
return defined $create ? $create : (), @table_defs, @view_defs, @fk_defs, @trigger_defs, @index_defs, @constraint_defs;
}
else {
$create .= join (";\n\n", @table_defs, @view_defs, @index_defs, @constraint_defs);
$create .= join (";\n\n", @table_defs, @view_defs, @fk_defs, @index_defs, @constraint_defs);
$create .= ";\n\n";
# If wantarray is not set we have to add "/" in this statement
# DBI->do() needs them omitted
Expand All @@ -265,127 +268,138 @@ sub create_table {

my $item = '';
my $drop;
my (@create, @field_defs, @constraint_defs, @trigger_defs);
my (@create, @field_defs, @constraint_defs, @fk_defs, @trigger_defs);

push @create, "--\n-- Table: $table_name\n--" unless $options->{no_comments};
push @create, qq[DROP TABLE $table_name_q CASCADE CONSTRAINTS] if $options->{add_drop_table};

my ( %field_name_scope, @field_comments );
for my $field ( $table->get_fields ) {
my ($field_create, $field_defs, $trigger_defs, $field_comments) =
create_field($field, $options, \%field_name_scope);
push @create, @$field_create if ref $field_create;
push @field_defs, @$field_defs if ref $field_defs;
push @trigger_defs, @$trigger_defs if ref $trigger_defs;
push @field_comments, @$field_comments if ref $field_comments;
my ( %field_name_scope, @field_comments );
for my $field ( $table->get_fields ) {
debug("ORA: Creating field " . $field->name . "(" . $field->data_type . ")");
my ($field_create, $field_defs, $trigger_defs, $field_comments) =
create_field($field, $options, \%field_name_scope);
push @create, @$field_create if ref $field_create;
push @field_defs, @$field_defs if ref $field_defs;
push @trigger_defs, @$trigger_defs if ref $trigger_defs;
push @field_comments, @$field_comments if ref $field_comments;
}

#
# Table options
#
my @table_options;
for my $opt ( $table->options ) {
if ( ref $opt eq 'HASH' ) {
my ( $key, $value ) = each %$opt;
if ( ref $value eq 'ARRAY' ) {
push @table_options, "$key\n(\n". join ("\n",
map { " $_->[0]\t$_->[1]" }
map { [ each %$_ ] }
@$value
)."\n)";
}
elsif ( !defined $value ) {
push @table_options, $key;
}
else {
push @table_options, "$key $value";
}
}
}

#
# Table options
#
my @table_options;
for my $opt ( $table->options ) {
#
# Table constraints
#
for my $c ( $table->get_constraints ) {
my $constr = create_constraint($c, $options);
if ($constr) {
if ($c->type eq FOREIGN_KEY) { # FK defs always come later as alters
push @fk_defs, sprintf("ALTER TABLE %s ADD %s", $table_name_q, $constr);
}
else {
push @constraint_defs, $constr;
}
}
}

#
# Index Declarations
#
my @index_defs = ();
for my $index ( $table->get_indices ) {
my $index_name = $index->name || '';
my $index_type = $index->type || NORMAL;
my @fields = map { quote($_, $qf) } $index->fields;
next unless @fields;
debug("ORA: Creating $index_type index on fields (" . join(', ', @fields) . ") named $index_name");
my @index_options;
for my $opt ( $index->options ) {
if ( ref $opt eq 'HASH' ) {
my ( $key, $value ) = each %$opt;
if ( ref $value eq 'ARRAY' ) {
push @table_options, "$key\n(\n". join ("\n",
map { " $_->[0]\t$_->[1]" }
map { [ each %$_ ] }
@$value
@$value
)."\n)";
}
elsif ( !defined $value ) {
push @table_options, $key;
push @index_options, $key;
}
else {
push @table_options, "$key $value";
push @index_options, "$key $value";
}
}
}

#
# Table constraints
#
for my $c ( $table->get_constraints ) {
my $constr = create_constraint($c, $options);
push @constraint_defs, $constr if ($constr);
my $index_options = @index_options
? "\n".join("\n", @index_options) : '';

if ( $index_type eq PRIMARY_KEY ) {
$index_name = $index_name ? mk_name( $index_name )
: mk_name( $table_name, 'pk' );
$index_name = quote($index_name, $qf);
push @field_defs, 'CONSTRAINT '.$index_name.' PRIMARY KEY '.
'(' . join( ', ', @fields ) . ')';
}

#
# Index Declarations
#
my @index_defs = ();
for my $index ( $table->get_indices ) {
my $index_name = $index->name || '';
my $index_type = $index->type || NORMAL;
my @fields = map { quote($_, $qf) } $index->fields;
next unless @fields;

my @index_options;
for my $opt ( $index->options ) {
if ( ref $opt eq 'HASH' ) {
my ( $key, $value ) = each %$opt;
if ( ref $value eq 'ARRAY' ) {
push @table_options, "$key\n(\n". join ("\n",
map { " $_->[0]\t$_->[1]" }
map { [ each %$_ ] }
@$value
)."\n)";
}
elsif ( !defined $value ) {
push @index_options, $key;
}
else {
push @index_options, "$key $value";
}
}
}
my $index_options = @index_options
? "\n".join("\n", @index_options) : '';

if ( $index_type eq PRIMARY_KEY ) {
$index_name = $index_name ? mk_name( $index_name )
: mk_name( $table_name, 'pk' );
$index_name = quote($index_name, $qf);
push @field_defs, 'CONSTRAINT '.$index_name.' PRIMARY KEY '.
'(' . join( ', ', @fields ) . ')';
}
elsif ($index_type eq NORMAL or $index_type eq UNIQUE) {
push @index_defs, create_index($index, $options, $index_options);
}
else {
warn "Unknown index type ($index_type) on table $table_name.\n"
if $WARN;
}
elsif ($index_type eq NORMAL or $index_type eq UNIQUE) {
push @index_defs, create_index($index, $options, $index_options);
}
else {
warn "Unknown index type ($index_type) on table $table_name.\n"
if $WARN;
}
}

if ( my @table_comments = $table->comments ) {
for my $comment ( @table_comments ) {
next unless $comment;
$comment = __PACKAGE__->_quote_string($comment);
push @field_comments, "COMMENT ON TABLE $table_name_q is\n $comment"
unless $options->{no_comments};
}
if ( my @table_comments = $table->comments ) {
for my $comment ( @table_comments ) {
next unless $comment;
$comment = __PACKAGE__->_quote_string($comment);
push @field_comments, "COMMENT ON TABLE $table_name_q is\n $comment"
unless $options->{no_comments};
}
}

my $table_options = @table_options
? "\n".join("\n", @table_options) : '';
my $table_options = @table_options ? "\n".join("\n", @table_options) : '';
debug("Create is @create");
debug("Constraints are @constraint_defs");
debug("Field DEFS: " . join(', ', @field_defs));
push @create, "CREATE TABLE $table_name_q (\n" .
join( ",\n", map { " $_" } @field_defs,
($options->{delay_constraints} ? () : @constraint_defs) ) .
"\n)$table_options";

@constraint_defs = map { "ALTER TABLE $table_name_q ADD $_" }
@constraint_defs;
debug("NOW Create is @create");
@constraint_defs = map { "ALTER TABLE $table_name_q ADD $_" } @constraint_defs;

debug("Now constraint defs are " . join(', ', @constraint_defs));
if ( $WARN ) {
if ( %truncated ) {
warn "Truncated " . keys( %truncated ) . " names:\n";
warn "\t" . join( "\n\t", sort keys %truncated ) . "\n";
}
}

return \@create, \@trigger_defs, \@index_defs, ($options->{delay_constraints} ? \@constraint_defs : []);
return \@create, \@fk_defs, \@trigger_defs, \@index_defs, ($options->{delay_constraints} ? \@constraint_defs : []);
}

sub alter_field {
Expand Down Expand Up @@ -546,6 +560,7 @@ sub create_field {
#
my $default = $field->default_value;
if ( defined $default ) {
debug("ORA: Handling default value: $default");
#
# Wherein we try to catch a string being used as
# a default value for a numerical field. If "true/false,"
Expand Down Expand Up @@ -587,6 +602,7 @@ sub create_field {
# Not null constraint
#
unless ( $field->is_nullable ) {
debug("ORA: Field is NOT NULL");
$field_def .= ' NOT NULL';
}

Expand All @@ -596,6 +612,7 @@ sub create_field {
# Auto_increment
#
if ( $field->is_auto_increment ) {
debug("ORA: Handling auto increment");
my $base_name = $table_name . "_". $field_name;
my $seq_name = quote(mk_name( $base_name, 'sq' ),$qt);
my $trigger_name = quote(mk_name( $base_name, 'ai' ),$qt);
Expand All @@ -621,6 +638,7 @@ sub create_field {
push @field_defs, $field_def;

if ( my $comment = $field->comments ) {
debug("ORA: Handling comment");
$comment =~ __PACKAGE__->_quote_string($comment);
push @field_comments,
"COMMENT ON COLUMN $table_name_q.$field_name_q is\n $comment;"
Expand Down Expand Up @@ -654,15 +672,17 @@ sub create_index {
$index_options = $index_options || '';
my $qf = $options->{quote_field_names} || $options->{quote_identifiers};
my $qt = $options->{quote_table_names} || $options->{quote_identifiers};
my $index_name = $index->name || '';
$index_name = $index_name ? mk_name( $index_name ) : mk_name( $index->table, $index_name || 'i' );
return join(
' ',
map { $_ || () }
'CREATE',
lc $index->type eq 'normal' ? 'INDEX' : $index->type . ' INDEX',
$index->name ? quote($index->name, $qf): '',
$index_name ? quote($index_name, $qf): '',
'ON',
quote($index->table, $qt),
'(' . join( ', ', map { quote($_) } $index->fields ) . ")$index_options"
'(' . join( ', ', map { quote($_, $qf) } $index->fields ) . ")$index_options"
);
}

Expand Down Expand Up @@ -713,6 +733,7 @@ sub create_constraint {
my $definition;

if ( $c->type eq PRIMARY_KEY ) {
debug("ORA: Creating PK constraint on fields (" . join(', ', @fields) . ")");
# create a name if delay_constraints
$name ||= mk_name( $table_name, 'pk' )
if $options->{delay_constraints};
Expand All @@ -736,7 +757,7 @@ sub create_constraint {
else {
$name = mk_name( $table_name, 'u' );
}

debug("ORA: Creating UNIQUE constraint on fields (" . join(', ', @fields) . ") named $name");
$name = quote($name, $qf);

for my $f ( $c->fields ) {
Expand All @@ -756,6 +777,7 @@ sub create_constraint {
$name ||= mk_name( $name || $table_name, 'ck' );
$name = quote($name, $qf);
my $expression = $c->expression || '';
debug("ORA: Creating CHECK constraint on fields (" . join(', ', @fields) . ") named $name");
$definition = "CONSTRAINT $name CHECK ($expression)";
}
elsif ( $c->type eq FOREIGN_KEY ) {
Expand All @@ -770,7 +792,7 @@ sub create_constraint {
}

my $ref_table = quote($c->reference_table,$qt);

debug("ORA: Creating FK constraint on fields (" . join(', ', @fields) . ") named $name referencing $ref_table");
$definition .= " REFERENCES $ref_table";

if ( @rfields ) {
Expand Down
Loading