parse postgresql error log for value too long and rewrite schema
authorDobrica Pavlinusic <dpavlin@rot13.org>
Thu, 17 Jan 2013 15:20:06 +0000 (16:20 +0100)
committerDobrica Pavlinusic <dpavlin@rot13.org>
Thu, 17 Jan 2013 15:20:06 +0000 (16:20 +0100)
pgsql-fix-value-too-long.pl [new file with mode: 0755]

diff --git a/pgsql-fix-value-too-long.pl b/pgsql-fix-value-too-long.pl
new file mode 100755 (executable)
index 0000000..ffe2e7f
--- /dev/null
@@ -0,0 +1,55 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+use autodie;
+use Data::Dump qw(dump);
+
+# 1. dump errors with:
+# 
+
+my ( $errors, $dump ) = @ARGV;
+die "usage: $0 errors.log dump.sql" unless -r $errors && -r $dump;
+
+my $fix;
+my $type;
+
+open(my $f, '<', $errors);
+while(<$f>) {
+       if ( m/ERROR:  value too long for type (.+)/ ) {
+               $type = $1;
+       } elsif ( m/CONTEXT:  COPY (\w+), line \d+, column (\w+)/ ) {
+               $fix->{$1}->{$2} = $type;
+               $type = undef;
+       }
+}
+
+warn "# fix ",dump($fix);
+
+my $in_create_table = 0;
+
+my $d;
+if ( $dump =~ m/\.gz/i ) {
+       open($d, '-|', "zcat $dump");
+} else {
+       open($d, '<', $dump);
+}
+
+while(<$d>) {
+       if ( m/CREATE TABLE (\w+)/ ) {
+               $in_create_table = $1;
+       } elsif ( $in_create_table && m/;/ ) {
+               $in_create_table = 0;
+       }
+
+       if ( $in_create_table && exists $fix->{$in_create_table} ) {
+               my $column = $1 if /^\s+(\w+)/;
+               if ( my $type = $fix->{$in_create_table}->{$column} ) {
+                       warn "FIX: [$_] $type\n";
+                       s/\Q$type\E/text/ || die "can't FIX $_ $type";
+                       chomp;
+                       $_ .= " -- FIXME $type\n";
+               }
+       }
+
+       print;
+}