#!/usr/bin/perl #=============================================================================== # # FILE: yaml_to_sql.pl # # USAGE: ./yaml_to_sql.pl # # DESCRIPTION: Converts SQL file into two-section YAML. # # OPTIONS: # --dump-meta: # Dump meta information (CREATE TABLE) into YAML. # On by default, to invert use --nodump-meta. # --dump-data: (--nodump-data) # Dump data (INSERT INTO) into YAML. # On by default, to invert use --nodump-data. # --only-hashref: # Dump data (INSERT INTO) only in hashref (key: value pairs). # On by default, to invert use --noonly-hashref, then # only inserts with fields will be converted # into hashrefs. # # REQUIREMENTS: Getopt::Long, YAML::Dumper, Tie::IxHash # BUGS: --- # NOTES: --- # AUTHORS: Pavel Boldin (davinchi), # Walery Studennikov (despair), # COMPANY: # VERSION: 1.0 # CREATED: 26.11.2007 18:10:14 SAMT # REVISION: --- #=============================================================================== use strict; use warnings; use YAML::Old; use Tie::IxHash; use Getopt::Long; # config our ($dump_data, $dump_meta, $only_hashref) = (1, 1, 1); # read options GetOptions( 'dump-data!' => \$dump_data, 'dump-meta!' => \$dump_meta, 'only-hashref!' => \$only_hashref) or die "Cannot parse arguments"; our $fname = shift @ARGV or die_help('Cant find filename'); our $outfile = shift @ARGV; # open file my $input = \*STDIN; if ($fname ne '-') { open $input, '<', $fname or die "Cant open $fname for reading: $!"; } our $txt = do { local $/; <$input> }; if ($fname ne '-') { close $input; } die "Output file $outfile already exists" if (defined $outfile && -f $outfile); if (defined $outfile) { open my $output, '>', $outfile or die "Cannot open $outfile for writing: $!"; select($output); } # go! our @commands = split /;\n/, $txt; our ($tname, $extra, @fields, @inserts, @meta) = ('([\w\-_\d]+)'); foreach my $command (@commands) { if ($command =~ /^DROP TABLE IF/io) { # warn "Ignoring DROP TABLE"; next; } if ( $dump_meta && $command =~ /CREATE\s+TABLE\s+(?:IF NOT EXISTS\s+)?`?([\w\-_\d]+)`? \((.*)\)\s*(.*)$/ios) { $tname eq '([\w\-_\d]+)' or die "Two many create tables in one file"; $tname = $1; $extra = $3; my @create_fields = split /,\n/, $2; foreach my $field (@create_fields) { if ( $field =~ /^\s*(PRIMARY|UNIQUE)\s+KEY/o || $field =~ /^\s*INDEX/o ) { $field =~ s/^\s+//g; $field =~ s/\s+$//g; push @meta, $field; } else { $field =~ /`?([\w\d\-_]+)`?\s*(.*)/o or next; push @fields, { $1 => $2 }; } } next; } if ($dump_data && $command =~ /INSERT INTO\s+`?$tname`?(.*)/is) { my $data = $1; if ($2) { die "Insert into table before any create table: $fname"; $tname = $1; $data = $2; } my ($fields, $values) = split /\s+VALUES\s*/, $data; s/^\s*\(\s*//s, s/\s*\);?\s*$//s foreach($fields, $values); # FROM THE DEEP OF SQL::Parser... my @values = do { my $i = -1; my $fields; my $e = '\\'; $e = quotemeta($e); # they are genius, right? $values =~ s~(?[$1]; die "Mismatched single quote: '$sql\n"; } s/$e'/'/g, s/^'(.*)'$/$1/ foreach @$fields; map { /\?(\d+)\?/ ? $fields->[$1] : ( $_ eq "''" ? '' : $_ ) } split /,\s*/, $values; }; if ($fields || $only_hashref) { my @fields; @fields = split /,\s*/, $fields if $fields; @fields = map { keys %$_ } @::fields unless @fields; s/^`//, s/`$// foreach @fields; my $hash; tie %$hash, 'Tie::IxHash'; unless (@fields == @values) { warn "Fields count dont matches values count: $fname command: $command"; next; } @$hash{@fields} = @values; push @inserts, $hash; } else { push @inserts, \@values; } } } die "No table in file $fname" if ($tname eq '([\w\-_\d]+)'); our $first; tie %$first, 'Tie::IxHash'; %$first = ( tablename => $tname, fields => \@fields, meta => \@meta, extra => $extra ); { no warnings 'once'; local $YAML::SortKeys = 0; print Dump($first, \@inserts); } if (defined $outfile) { close(select(STDOUT)); } ########################################################################### # Functions section ########################################################################### sub die_help { print shift, "\n"; print <, C, C and C modules. =pod OSNAMES any =pod SCRIPT CATEGORIES DB =cut