From d8231344f78cbc8caed932db01d2ecd070688dec Mon Sep 17 00:00:00 2001
From: "Thomas G. Lockhart" <lockhart@fourpalms.org>
Date: Wed, 20 Dec 2000 17:20:24 +0000
Subject: [PATCH] Utility to convert MySQL schema dumps to SQL92 and PostgreSQL
 conventions.

---
 contrib/mysql/mysql2pgsql | 276 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 276 insertions(+)
 create mode 100755 contrib/mysql/mysql2pgsql

diff --git a/contrib/mysql/mysql2pgsql b/contrib/mysql/mysql2pgsql
new file mode 100755
index 00000000000..0f73b0a27e7
--- /dev/null
+++ b/contrib/mysql/mysql2pgsql
@@ -0,0 +1,276 @@
+# -*- perl -*-
+# mysql2pgsql
+# Take a MySQL schema dump and turn it into SQL92 and PostgreSQL form.
+# Thomas Lockhart, (c) 2000, PostgreSQL Inc.
+# Thanks to Tim Perdue at SourceForge.Net for testing and feedback.
+#
+
+eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
+    & eval 'exec perl -S $0 $argv:q'
+    if 0;
+
+use IO::File;
+use Getopt::Long;
+
+my $progname = "mysql2pgsql";
+my $version = "0.3";
+
+GetOptions("debug!", "verbose!", "version", "path=s", "help");
+
+my $debug = $opt_debug || 0;
+my $verbose = $opt_verbose || 0;
+my $pathfrom = $opt_path || "";
+
+$pathfrom = "$pathfrom/" if ($pathfrom =~ /.*[^\/]$/);
+
+print "$0: $progname version $version\n"
+    if ($opt_version || $opt_help);
+print "\t(c) 2000 Thomas Lockhart PostgreSQL Inc.\n"
+    if ($opt_version && $opt_verbose || $opt_help);
+
+if ($opt_help) {
+    print "$0 --verbose --version --help --path=dir infile ...\n";
+    exit;
+}
+
+while (@ARGV) {
+    my $ostem;
+
+    $iname = shift @ARGV;
+    $ostem = $iname;
+    $ostem = $1 if ($ostem =~ /.+\/([^\/]+)$/);
+    $ostem = $1 if ($ostem =~ /(.+)[.][^.]*$/);
+
+    $oname = "$ostem.sql92";
+    $pname = "$ostem.init";
+
+    print "$iname $oname $pname\n" if ($debug);
+
+    TransformDumpFile($iname, $oname, $pname);
+}
+
+exit;
+
+sub TransformDumpFile {
+    local ($iname, $oname, $pname) = @_;
+    local @dlines;
+    local @slines;
+    local @plines;
+    local @tables; # list of tables created
+    local %pkeys;
+    local %pseqs;
+    local %sequences;
+
+    open(IN, "<$iname") || die "Unable to open file $iname";
+
+    while (<IN>) {
+		chomp;
+		push @dlines, $_;
+    }
+
+    print "Calling CreateSchema with $#dlines lines\n" if ($debug);
+    @slines = CreateSchema(@dlines);
+
+    open(OUT, ">$oname") || die "Unable to open output file $oname";
+
+    foreach (@slines) {
+		print "> $_" if ($debug);
+		print OUT "$_";
+    }
+    close(OUT);
+
+    return if (! defined($pname));
+
+    @plines = PopulateSchema(@tables);
+
+    open(OUT, ">$pname") || die "Unable to open output file $pname";
+
+    foreach (@plines) {
+		print "> $_" if ($debug);
+		print OUT "$_";
+    }
+    close(OUT);
+}
+
+sub PopulateSchema {
+    local @tables = @_;
+    local @out;
+    local $pkey;
+    local $pseq;
+
+    foreach (@tables) {
+		$table = $_;
+		$tpath = "$pathfrom$table";
+
+		print "Table is $table\n" if ($debug);
+		push @out, "\n";
+		push @out, "copy $table from '$tpath.txt';\n";
+		if (defined($pkeys{$table})) {
+			foreach ($pkeys{$table}) {
+				$pkey = $_;
+				$pseq = $pseqs{$table};
+
+				print "Key for $table is $pkey on $pseq\n" if ($debug);
+
+#		//push @out, "\$value = select max($pkey) from $table;\n";
+				push @out, "select setval ('$pseq', (select max($pkey) from $table));\n";
+			}
+		}
+    }
+
+    return @out;
+}
+
+sub CreateSchema {
+    local @lines = @_;
+    local @out;
+
+#    undef $last;
+    local %knames;
+
+    push @out, "--\n";
+    push @out, "-- Generated from mysql2pgsql\n";
+    push @out, "-- (c) 2000, Thomas Lockhart, PostgreSQL Inc.\n";
+    push @out, "--\n";
+    push @out, "\n";
+
+    while (@lines) {
+		$_ = shift @lines;
+		print "< $_\n" if ($debug);
+		# Replace hash comments with SQL9x standard syntax
+		$_ = "-- $1" if (/^[\#](.*)/);
+
+		# Found a CREATE TABLE statement?
+		if (/(create\s+table)\s+(\w+)\s+([(])\s*$/i) {
+			$table = $2;
+			$table = "\"$1\"" if ($table =~ /^(user)$/);
+			push @tables, $table;
+			push @tabledef, "create table $table (";
+#	push @out, "$_\n";
+
+			while (@lines) {
+				$_ = shift @lines;
+				print "< $_\n" if ($debug);
+
+				# Replace int(11) with SQL9x standard syntax
+				while (/int\(\d*\)/gi) {
+					$_ = "$`integer$'";
+				}
+
+				# Replace float(10,2) with SQL9x standard syntax
+				while (/(float)\((\d+),\s*(\d+)\)/gi) {
+					$_ = "$`$1($2)$'";
+				}
+
+				# Replace smallinteger with SQL9x syntax
+				while (/smallinteger/gi) {
+					$_ = "$`integer$'";
+				}
+
+				# Replace mediumtext with PostgreSQL syntax
+				while (/(longtext|mediumtext|blob|largeblob)/gi) {
+					$_ = "$`text$'";
+				}
+
+				# Replace integer ... auto_increment with PostgreSQL syntax
+				while (/(\s*)(\w+)\s+integer\s+(.*)\s+auto_increment/gi) {
+					$serid = $table . "_pk_seq";
+					push @out, "-- serial identifier $serid will likely be truncated\n"
+						if (length($serid) >= 32);
+
+					if (length($serid) >= 32) {
+						$excess=(length($serid)-31);
+						$serid = substr($table,0,-($excess)) . "_pk_seq";
+						push @out, "-- serial identifier $serid was truncated\n";
+					}
+                    push @out, "CREATE SEQUENCE $serid;\n\n";
+					$pkeys{$table} = $2;
+					$pseqs{$table} = $serid;
+					push @out, "-- key is $pkeys{$table}, sequence is $pseqs{$table}\n" if ($debug);
+					$_ = "$`$1$2 integer default nextval('$serid') $3$'";
+				}
+
+				# Replace date with double-quoted name
+#	    while (/^(\s*)(date|time)(\s+)/gi) {
+#		$_ = "$1\"$2\"$3$'";
+#	    }
+
+				# Found "KEY"? Then remove it from the CREATE TABLE statement
+				# and instead write a CREATE INDEX statement.
+				if (/^\s*key\s+(\w+)\s*[(](\w[()\w\d,\s]*)[)][,]?/i) {
+					$iname = $1;
+					$column = $2;
+					$iname = $1 if ($iname =~ /^idx_(\w[\_\w\d]+)/);
+					# Sheesh, there can be upper bounds on index string sizes?
+					# Get rid of the length specifier (e.g. filename(45) -> filename)
+					while ($column =~ /(\w[\w\d])[(]\d+[)]/g) {
+						$column = "$`$1$'";
+					}
+#		$column = $1 if ($column =~ /(\w+)[(]\d+[)]/);
+#		push @out, "Index on $table($column) is $iname\n";
+					if (defined($knames{$iname})) {
+						push @out, "-- $iname already exists";
+#		    sprintf($iname, "idx_%_%s", $table, $iname);
+#		    $iname = "idx_" . $table . "_" . $column;
+						# Do not bother with more to the name; it will be too big anyway
+						$iname = $table . "_" . $column;
+						push @out, "; use $iname instead\n";
+					}
+					$knames{$iname} = $iname;
+					$keydef{$column} = $iname;
+#		push @out, "! $_\n";
+#		$last = $tabledef[$#tabledef];
+#		push @out, "? $#tabledef $last\n";
+#		push @out, "match $1\n" if ($last =~ /(.*),\s*$/);
+					# Remove the trailing comma from the previous line, if necessary
+					$tabledef[$#tabledef] = $1
+						if (($#tabledef > 0) && ($tabledef[$#tabledef] =~ /(.*),\s*$/));
+#		push @out, "? $tabledef[$#tabledef]\n";
+
+					# If this is the end of the statement, save it and exit loop
+				} elsif (/^\s*[)]\;/) {
+				push @tabledef, $_;
+#		push @out, "< $_\n";
+				last;
+
+				# Otherwise, just save the line
+			} else {
+#		push @out, "$last\n" if (defined($last));
+#		$last = $_;
+				push @tabledef, $_;
+#		push @out, "$_\n";
+			}
+		}
+
+			foreach $t (@tabledef) {
+				push @out, "$t\n";
+			}
+			undef @tabledef;
+
+			foreach $k (keys %keydef) {
+				push @out, "create index $keydef{$k} on $table ($k);\n";
+			}
+			undef %keydef;
+
+		} else {
+			push @out, "$_\n";
+		}
+    }
+
+#    push @out, "$last\n" if (defined($last));
+
+    foreach (keys %pkeys) {
+		my $val = $pkeys{$_};
+		print "key is $val\n" if ($debug);
+    }
+
+    return @out;
+}
+
+sub StripComma {
+    local $line = shift @_;
+
+    $line = "$1" if ($line =~ /(.*)[,]\s*$/);
+
+    return $line;
+}
-- 
GitLab