From 085fa8ac4891f4df63cf2ac41b0c36b01fe1d3bb Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Mon, 19 Apr 2004 23:11:49 +0000 Subject: [PATCH] Update to my2pg 1.28, from: http://www.omnistarinc.com/~fonin/downloads.php#my2pg --- contrib/mysql/my2pg.pl | 487 +++++++++++++++++++++++------------------ 1 file changed, 271 insertions(+), 216 deletions(-) diff --git a/contrib/mysql/my2pg.pl b/contrib/mysql/my2pg.pl index dafc106027..b24e09d1dc 100755 --- a/contrib/mysql/my2pg.pl +++ b/contrib/mysql/my2pg.pl @@ -35,17 +35,26 @@ # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # -# $My2pg: my2pg.pl,v 1.27 2001/12/06 19:32:20 fonin Exp $ -# $PostgreSQL: pgsql/contrib/mysql/my2pg.pl,v 1.11 2003/11/29 22:39:26 pgsql Exp $ +# $My2pg: my2pg.pl,v 1.28 2001/12/06 19:32:20 fonin Exp $ +# $Id: my2pg.pl,v 1.12 2004/04/19 23:11:49 momjian Exp $ # # $Log: my2pg.pl,v $ -# Revision 1.11 2003/11/29 22:39:26 pgsql +# Revision 1.12 2004/04/19 23:11:49 momjian +# Update to my2pg 1.28, from: # -# make sure the $Id tags are converted to $PostgreSQL as well ... +# http://www.omnistarinc.com/~fonin/downloads.php#my2pg # -# Revision 1.10 2003/01/07 22:18:43 momjian -# Upgrade to my2pg 1.9 +# Revision 1.28 2002/11/30 12:03:48 fonin +# PostgreSQL does not support indexes on the partial length of column, +# e.g. +# CREATE INDEX i_index ON table (column(16)); +# will not work. Fixed. +# +# Added command-line option -s that prevents my2pg from attempting convert +# the data (currently only timestamps). +# +# Better timestamps conversion. # # Revision 1.27 2002/07/16 14:54:07 fonin # Bugfix - didn't quote the fields inside PRIMARY KEY with -d option. @@ -162,7 +171,7 @@ my $chareg=''; # CHAR conversion regexps my $dq=''; # double quote # parse command line -getopts('nhd',\%opts); +getopts('nhds',\%opts); # output syntax if($opts{h} ne '') { @@ -179,10 +188,17 @@ if($opts{d} ne '') { $dq='"'; } +if($opts{s} ne '') { + $safe_data_conv=1; +} +else { + $safe_data_conv=0; +} + $|=1; print("------------------------------------------------------------------"); -print("\n-- My2Pg 1.27 translated dump"); +print("\n-- My2Pg 1.28 translated dump"); print("\n--"); print("\n------------------------------------------------------------------"); @@ -213,86 +229,86 @@ print LIBTYPES "\n#define ADD_COMMA if(strcmp(result,\"\")!=0) strcat(result,\", # reading STDIN... my $tabledef=0; # we are outside a table definition while (<>) { - - if(!$tabledef && /^CREATE TABLE \S+/i){ - $tabledef=1; - } elsif($tabledef && /^\) type=\w*;/i){ # /^\w/i - $tabledef=0; - } + if(!$tabledef && /^CREATE TABLE \S+/i){ + $tabledef=1; + } elsif($tabledef && /^\) type=\w*;/i){ # /^\w/i + $tabledef=0; + } # Comments start with -- in SQL if(/^#/) {# !/insert into.*\(.*#.*\)/i, in mysqldump output s/#/--/; } - if($tabledef){################################## + if($tabledef) { # Convert numeric types - s/tinyint\(\d+\)/INT2/i; - s/smallint\(\d+\)/INT2/i; - s/mediumint\(\d+\)/INT4/i; - s/bigint\(\d+\)/INT8/i; - s/int\(\d+\)/INT4/i; - s/float(\(\d+,\d*\))/DECIMAL$1/i; - s/double precision/FLOAT8 /i; - s/([\W])double(\(\d+,\d*\))/$1DECIMAL$2/i; - s/([\W])double[\W]/$1FLOAT8 /i; - s/([\W])real[\W]/$1FLOAT8 /i; - s/([\W])real(\(\d+,\d*\))/$1DECIMAL$2/i; + s/tinyint\(\d+\)/INT2/i; + s/smallint\(\d+\)/INT2/i; + s/mediumint\(\d+\)/INT4/i; + s/bigint\(\d+\)/INT8/i; + s/int\(\d+\)/INT4/i; + s/float(\(\d+,\d*\))/DECIMAL$1/i; + s/double precision/FLOAT8 /i; + s/([\W])double(\(\d+,\d*\))/$1DECIMAL$2/i; + s/([\W])double[\W]/$1FLOAT8 /i; + s/([\W])real[\W]/$1FLOAT8 /i; + s/([\W])real(\(\d+,\d*\))/$1DECIMAL$2/i; # Convert string types - s/\w*blob$chareg/text/i; - s/mediumtext$chareg/text/i; - s/tinytext$chareg/text/i; - s/\stext\s+not\s+null/ TEXT DEFAULT '' NOT NULL/i; - s/(.*?char\(.*?\))$chareg/$1/i; + s/\w*blob$chareg/text/i; + s/mediumtext$chareg/text/i; + s/tinytext$chareg/text/i; + s/\stext\s+not\s+null/ TEXT DEFAULT '' NOT NULL/i; + s/(.*?char\(.*?\))$chareg/$1/i; # Old and New are reserved words in Postgres - s/^(\s+)Old /${1}MyOld /; - s/^(\s+)New /${1}MyNew /; + s/^(\s+)Old /${1}MyOld /; + s/^(\s+)New /${1}MyNew /; # Convert DATE types - s/datetime/TIMESTAMP/; - s/timestamp\(\d+\)/TIMESTAMP/i; - s/ date / DATE /i; - s/,(\d{4})(\d{2})(\d{2}),/,'$1-$2-$3 00:00:00',/g; + s/datetime/TIMESTAMP/; + s/timestamp\(\d+\)/TIMESTAMP/i; + s/ date / DATE /i; + if((/date/ig || /time/ig) && /[,(]\d{4}(\d{2})(\d{2})[,)]/ && + $1>=0 && $1<=12 && $2>=0 && $2<=31) { + s/,(\d{4})(\d{2})(\d{2}),/,'$1-$2-$3 00:00:00',/g; + } # small hack - convert "default" to uppercase, because below we # enclose all lowercase words in double quotes - if(!/^INSERT/) { - s/default/DEFAULT/; - } + if(!/^INSERT/) { + s/default/DEFAULT/; + } # Change all AUTO_INCREMENT fields to SERIAL ones with a pre-defined sequence - if(/([\w\d]+)\sint.*auto_increment/i) { - $tmpseq=new_name("$table_name"."_"."$+"."_SEQ",28); - $seq{$table_name}=$tmpseq; - $primary{$table_name}=$+; - s/(int.*?) .*AUTO_INCREMENT/$1 DEFAULT nextval\('$tmpseq'\)/i; - #s/(int.*?)DEFAULT\s*?'.*?'(.*?)AUTO_INCREMENT/$1$2DEFAULT nextval\('$tmpseq'\)/i; - } + if(/([\w\d]+)\sint.*auto_increment/i) { + $tmpseq=new_name("$table_name"."_"."$+"."_SEQ",28); + $seq{$table_name}=$tmpseq; + $primary{$table_name}=$+; + s/(int.*?) .*AUTO_INCREMENT/$1 DEFAULT nextval\('$tmpseq'\)/i; + } # convert UNSIGNED to CHECK constraints - if(/^\s+?([\w\d_]+).*?unsigned/i) { - $check.=",\n CHECK ($dq$1$dq>=0)"; - } - s/unsigned//i; + if(/^\s+?([\w\d_]+).*?unsigned/i) { + $check.=",\n CHECK ($dq$1$dq>=0)"; + } + s/unsigned//i; # Limited ENUM support - little heuristic - s/enum\('N','Y'\)/BOOL/i; - s/enum\('Y','N'\)/BOOL/i; + s/enum\('N','Y'\)/BOOL/i; + s/enum\('Y','N'\)/BOOL/i; # ENUM support - if(/^\s+?([\w\d_]+).*?enum\((.*?)\)/i) { - my $enumlist=$2; - my @item; - $item[0]=''; - while($enumlist=~s/'([\d\w_]+)'//i) { - $item[++$#item]=$1; - } + if(/^\s+?([\w\d_]+).*?enum\((.*?)\)/i) { + my $enumlist=$2; + my @item; + $item[0]=''; + while($enumlist=~s/'([\d\w_]+)'//i) { + $item[++$#item]=$1; + } # forming identifier name - $typename=new_name('enum_'.$table_name.'_'.$item[1],28); -# $typename=lc('enum_'.$table_name.'_'.$item[1]); + $typename=new_name('enum_'.$table_name.'_'.$item[1],28); # creating input type function - my $func_in=" + my $func_in=" int2* $typename"."_in (char *str) { int2* result; @@ -301,34 +317,34 @@ int2* $typename"."_in (char *str) { result=(int2*)palloc(sizeof(int2)); *result=-1;"; - for(my $i=0;$i<=$#item;$i++) { - $func_in.=" + for(my $i=0;$i<=$#item;$i++) { + $func_in.=" if(strcmp(str,\"$item[$i]\")==0) { *result=$i; }"; - } - $func_in.=" + } + $func_in.=" if(*result == -1) { elog(ERROR,\"$typename"."_in: incorrect input value\"); return NULL; } return (result); }\n"; - $types.="\n---"; - $types.="\n--- Types for table ".uc($table_name); - $types.="\n---\n"; - print LIBTYPES "\n/*"; - print LIBTYPES "\n * Types for table ".uc($table_name); - print LIBTYPES "\n */\n"; - - $types.="\nCREATE FUNCTION $typename"."_in (opaque) + $types.="\n---"; + $types.="\n--- Types for table ".uc($table_name); + $types.="\n---\n"; + print LIBTYPES "\n/*"; + print LIBTYPES "\n * Types for table ".uc($table_name); + print LIBTYPES "\n */\n"; + + $types.="\nCREATE FUNCTION $typename"."_in (opaque) RETURNS $typename AS '$libtypename' LANGUAGE 'c' WITH (ISCACHABLE);\n"; # creating output function - my $func_out=" + my $func_out=" char* $typename"."_out (int2 *outvalue) { char* result; @@ -337,13 +353,13 @@ char* $typename"."_out (int2 *outvalue) { result=(char*)palloc(10); switch (*outvalue) {"; - for(my $i=0;$i<=$#item;$i++) { - $func_out.=" + for(my $i=0;$i<=$#item;$i++) { + $func_out.=" case $i: strcpy(result,\"$item[$i]\"); break;"; - } - $func_out.=" + } + $func_out.=" default : elog(ERROR,\"$typename"."_out: incorrect stored value\"); return NULL; @@ -351,7 +367,7 @@ char* $typename"."_out (int2 *outvalue) { } return result; }\n"; - $func_out.="\nbool $typename"."_eq(int2* a, int2* b) { + $func_out.="\nbool $typename"."_eq(int2* a, int2* b) { return (*a==*b); } @@ -375,19 +391,19 @@ bool $typename"."_ge(int2* a, int2* b) { return (*a>=*b); }\n"; - $types.="\nCREATE FUNCTION $typename"."_out (opaque) + $types.="\nCREATE FUNCTION $typename"."_out (opaque) RETURNS opaque AS '$libtypename' LANGUAGE 'c' WITH (ISCACHABLE);\n"; - $types.="\nCREATE TYPE $typename ( + $types.="\nCREATE TYPE $typename ( internallength = 2, input = $typename\_in, output = $typename\_out );\n"; - $types.="\nCREATE FUNCTION $typename"."_eq ($typename,$typename) + $types.="\nCREATE FUNCTION $typename"."_eq ($typename,$typename) RETURNS bool AS '$libtypename' LANGUAGE 'c'; @@ -460,32 +476,31 @@ CREATE OPERATOR <> ( procedure = $typename"."_ne );\n"; - print LIBTYPES $func_in; - print LIBTYPES $func_out; - s/enum\(.*?\)/$typename/i; - } + print LIBTYPES $func_in; + print LIBTYPES $func_out; + s/enum\(.*?\)/$typename/i; + } # SET support - if(/^\s+?([\w\d_]+).*?set\((.*?)\)/i) { - my $setlist=$2; - my @item; - $item[0]=''; - my $maxlen=0; # maximal string length - while($setlist=~s/'([\d\w_]+)'//i) { - $item[++$#item]=$1; - $maxlen+=length($item[$#item])+1; - } - $maxlen+=1; - my $typesize=int($#item/8); - if($typesize<2) { - $typesize=2; - } - $internalsize=$typesize; - $typesize='int'.$typesize; -# $typename=lc('set_'.$table_name.'_'.$item[1]); - $typename=new_name('set_'.$table_name.'_'.$item[1],28); + if(/^\s+?([\w\d_]+).*?set\((.*?)\)/i) { + my $setlist=$2; + my @item; + $item[0]=''; + my $maxlen=0; # maximal string length + while($setlist=~s/'([\d\w_]+)'//i) { + $item[++$#item]=$1; + $maxlen+=length($item[$#item])+1; + } + $maxlen+=1; + my $typesize=int($#item/8); + if($typesize<2) { + $typesize=2; + } + $internalsize=$typesize; + $typesize='int'.$typesize; + $typename=new_name('set_'.$table_name.'_'.$item[1],28); # creating input type function - my $func_in=" + my $func_in=" $typesize* $typename"."_in (char *str) { $typesize* result; char* token; @@ -498,14 +513,14 @@ $typesize* $typename"."_in (char *str) { if(strcmp(str,\"\")==0) return result; for(token=strtok(str,\",\");token!=NULL;token=strtok(NULL,\",\")) {"; - for(my $i=0,my $j=1;$i<=$#item;$i++,$j*=2) { - $func_in.=" + for(my $i=0,my $j=1;$i<=$#item;$i++,$j*=2) { + $func_in.=" if(strcmp(token,\"$item[$i]\")==0) { *result|=$j; continue; }"; - } - $func_in.=" + } + $func_in.=" } if(*result == 0) { @@ -515,20 +530,20 @@ $typesize* $typename"."_in (char *str) { return (result); }\n"; - $types.="\n---"; - $types.="\n--- Types for table ".uc($table_name); - $types.="\n---\n"; - print LIBTYPES "\n/*"; - print LIBTYPES "\n * Types for table ".uc($table_name); - print LIBTYPES "\n */\n"; - - $types.="\nCREATE FUNCTION $typename"."_in (opaque) + $types.="\n---"; + $types.="\n--- Types for table ".uc($table_name); + $types.="\n---\n"; + print LIBTYPES "\n/*"; + print LIBTYPES "\n * Types for table ".uc($table_name); + print LIBTYPES "\n */\n"; + + $types.="\nCREATE FUNCTION $typename"."_in (opaque) RETURNS $typename AS '$libtypename' LANGUAGE 'c';\n"; # creating output function - my $func_out=" + my $func_out=" char* $typename"."_out ($typesize *outvalue) { char* result; int i; @@ -540,16 +555,16 @@ char* $typename"."_out ($typesize *outvalue) { strcpy(result,\"\"); for(i=1;i<=2 << (sizeof(int2)*8);i*=2) { switch (*outvalue & i) {"; - for(my $i=0,$j=1;$i<=$#item;$i++,$j*=2) { - $func_out.=" + for(my $i=0,$j=1;$i<=$#item;$i++,$j*=2) { + $func_out.=" case $j:"; - if($item[$i] ne '') { - $func_out.="ADD_COMMA;"; - } - $func_out.="strcat(result,\"$item[$i]\"); + if($item[$i] ne '') { + $func_out.="ADD_COMMA;"; + } + $func_out.="strcat(result,\"$item[$i]\"); break;"; - } - $func_out.=" + } + $func_out.=" default : break; } @@ -557,7 +572,7 @@ char* $typename"."_out ($typesize *outvalue) { return result; }\n"; - $func_out.="\nbool $typename"."_eq($typesize* a, $typesize* b) { + $func_out.="\nbool $typename"."_eq($typesize* a, $typesize* b) { return (*a==*b); } @@ -574,18 +589,18 @@ $typesize find_in_set($typesize *a, $typesize *b) { \n"; - $types.="\nCREATE FUNCTION $typename"."_out (opaque) + $types.="\nCREATE FUNCTION $typename"."_out (opaque) RETURNS opaque AS '$libtypename' LANGUAGE 'c';\n"; - $types.="\nCREATE TYPE $typename ( + $types.="\nCREATE TYPE $typename ( internallength = $internalsize, input = $typename\_in, output = $typename\_out );\n"; - $types.="\nCREATE FUNCTION $typename"."_eq ($typename,$typename) + $types.="\nCREATE FUNCTION $typename"."_eq ($typename,$typename) RETURNS bool AS '$libtypename' LANGUAGE 'c'; @@ -612,10 +627,10 @@ CREATE OPERATOR <> ( \n"; - print LIBTYPES $func_in; - print LIBTYPES $func_out; - s/set\(.*?\)/$typename/i; - } + print LIBTYPES $func_in; + print LIBTYPES $func_out; + s/set\(.*?\)/$typename/i; + } # Change multy-field keys to multi-field indices # MySQL Dump usually ends the CREATE TABLE statement like this: @@ -632,71 +647,80 @@ CREATE OPERATOR <> ( # ); # CREATE INDEX offer_id ON bids (offer_id,user_id,the_time); # CREATE INDEX bid_value ON bids (bid_value); - if (s/CREATE TABLE (.*) /CREATE TABLE $dq$1$dq /i) { - if($oldtable ne $table_name) { - $oldtable=$table_name; - $j=-1; - $check=''; - - if($seq{$table_name} ne '') { - print "\n\n--"; - print "\n-- Sequences for table ".uc($table_name); - print "\n--\n"; - print "\nCREATE SEQUENCE ".$seq{$table_name}.";\n\n"; - } - - print $types; - $types=''; - $dump=~s/,\n\).*;/\n\);/gmi; + if (s/CREATE TABLE (.*) /CREATE TABLE $dq$1$dq /i) { + if($oldtable ne $table_name) { + $oldtable=$table_name; + $j=-1; + $check=''; + + if($seq{$table_name} ne '') { + print "\n\n--"; + print "\n-- Sequences for table ".uc($table_name); + print "\n--\n"; + print "\nCREATE SEQUENCE ".$seq{$table_name}.";\n\n"; + } + + print $types; + $types=''; + $dump=~s/,\n\).*;/\n\);/gmi; # removing table options after closing bracket: # ) TYPE=ISAM PACK_KEYS=1; - $dump=~s/\n\).*/\n\);/gmi; - print $dump; - $dump=''; - } - $table_name=$1; - } + $dump=~s/\n\).*/\n\);/gmi; + print $dump; + $dump=''; + } + $table_name=$1; + } # output CHECK constraints instead UNSIGNED modifiers - if(/PRIMARY KEY\s+\((.*)\)/i) { - my $tmpfld=$1; - $tmpfld=~s/,/","/g if $dq; - $tmpfld=~s/ //g; - s/PRIMARY KEY\s+(\(.*\))/PRIMARY KEY \($dq$tmpfld$dq\)/i; - s/(PRIMARY KEY \(.*\)).*/$1$check\n/i; - } + if(/PRIMARY KEY\s+\((.*)\)/i) { + my $tmpfld=$1; + $tmpfld=~s/,/","/g if $dq; + $tmpfld=~s/ //g; + s/PRIMARY KEY\s+(\(.*\))/PRIMARY KEY \($dq$tmpfld$dq\)/i; + s/(PRIMARY KEY \(.*\)).*/$1$check\n/i; + } - if(/^\s*KEY ([\w\d_]+)\s*\((.*)\).*/i) { - my $tmpfld=$2; my $ky=$1; - $tmpfld=~s/\s*,\s*/","/g if $dq; - $index{$table_name}[++$j]="CREATE INDEX ${ky}_$table_name\_index ON $dq$table_name$dq ($dq$tmpfld$dq);"; - } - if(/^\s*UNIQUE.*?([\w\d_]+)\s*\((.*)\).*/i) { - my $tmpfld=$2; my $ky=$1; - $tmpfld=~s/,/","/g if $dq; - $index{$table_name}[++$j]="CREATE UNIQUE INDEX ${ky}_$table_name\_index ON $dq$table_name$dq ($dq$tmpfld$dq);"; - } - s/^\s*UNIQUE (.+).*(\(.*\)).*\n//i; - s/^\s*KEY (.+).*(\(.*\)).*\n//i; + if(/^\s*KEY ([\w\d_]+)\s*\((.*)\).*/i) { + my $tmpfld=$2; my $ky=$1; + $tmpfld=~s/\s*,\s*/","/g if $dq; + $tmpfld=~s/(\(\d+\))//g; + $index{$table_name}[++$j]="CREATE INDEX ${ky}_$table_name\_index ON $dq$table_name$dq ($dq$tmpfld$dq);"; + } + if(/^\s*UNIQUE.*?([\w\d_]+)\s*\((.*)\).*/i) { + my $tmpfld=$2; my $ky=$1; + $tmpfld=~s/,/","/g if $dq; + $tmpfld=~s/(\(\d+\))//g; + $index{$table_name}[++$j]="CREATE UNIQUE INDEX ${ky}_$table_name\_index ON $dq$table_name$dq ($dq$tmpfld$dq);"; + } + s/^\s*UNIQUE (.+).*(\(.*\)).*\n//i; + s/^\s*KEY (.+).*(\(.*\)).*\n//i; - if($dq && !/^\s*(PRIMARY KEY|UNIQUE |KEY |CREATE TABLE |\);)/i){ - s/\s([A-Za-z_\d]+)\s/ $dq$+$dq /; - } - } ####if($tabledef)############################### + if($dq && !/^\s*(PRIMARY KEY|UNIQUE |KEY |CREATE TABLE|INSERT INTO|\);)/i) { + s/\s([A-Za-z_\d]+)\s/ $dq$+$dq /; + } + } # end of if($tabledef) - if($dq && !s/INSERT INTO\s+?(.*?)\s+?/INSERT INTO $dq$1$dq /i) { -# Quote lowercase identifiers in double quotes - #while(!/^--/ && s/\s([A-Za-z_\d]+[a-z][A-Za-z_\d]*)\s/ $dq$+$dq /) {;} - } + s/INSERT INTO\s+?(.*?)\s+?/INSERT INTO $dq$1$dq /i; +# if not defined -s command-line option (safe data conversion), +# attempting to convert timestamp data + if(!$safe_data_conv) { # Fix timestamps - s/'0000-00-00/'0001-01-01/g; -# may work wrong !!! - s/([,(])00000000000000(?=[,)])/$1'00010101 000000'/g; - s/([,(])(\d{8})(\d{6})(?=[,)])/$1'$2 $3'/g; - s/([,(])(\d{4})(\d{2})(\d{2})(?=[,)])/$1'$2-$3-$4 00:00:00'/g; -# --------------------------------------------------- -# -------------------------------------------------- + s/'0000-00-00/'0001-01-01/g; +# may corrupt data !!! + s/([,(])00000000000000(?=[,)])/$1'00010101 000000'/g; + if(/[,(]\d{4}(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})[,)]/ && + $1>=0 && $1<=12 && $2>=0 && $2<=31 && $3>=0 && $3<=23 && + $4>=0 && $4<=59 && $5>=0 && $5<=59) { + s/([,(])(\d{8})(\d{6})(?=[,)])/$1'$2 $3'/g; + } + if(/[,(]\d{4}(\d{2})(\d{2})[,)]/ && + $2>=0 && $2<=12 && $3>=0 && $3<=31) { + s/([,(])(\d{4})(\d{2})(\d{2})(?=[,)])/$1'$2-$3-$4 00:00:00'/g; + } + } + $dump.=$_; } @@ -738,7 +762,7 @@ close(LIBTYPES); open(MAKE,">Makefile"); print MAKE "# -# My2Pg \$Revision: 1.11 $ \translated dump +# My2Pg \$Revision: 1.12 $ \translated dump # Makefile # @@ -784,7 +808,7 @@ sub usage() { print < +Copyright (c) 2000-2002 Max Rudensky Copyright (c) 2000 Valentine Danilchuk This program is distributed in the hope that it will be useful, @@ -793,12 +817,13 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the code source for license details. SYNTAX: - my2pg [-hnd] + my2pg [-hnds] OPTIONS: h - this help n - convert *CHAR NOT NULL DEFAULT '' types to *CHAR NULL - d - double quotes around table and column names + d - double quotes around table and column names + s - do not attempt to convert data (timestamps at the moment) EOF ; } @@ -810,7 +835,7 @@ my2pg - MySQL -> PostgreSQL dump conversion utility. =head1 SYNTAX - mysqldump db | ./my2pg.pl [-n] > pgsqldump.sql + mysqldump db | ./my2pg.pl [-nds] > pgsqldump.sql vi libtypes.c make psql database < pgsqldump.txt @@ -818,11 +843,11 @@ where =over 4 -=item B +=item F - file suitable for loading into PostgreSQL. -=item B +=item F - C source for emulated MySQL types (ENUM, SET) generated by B @@ -835,7 +860,7 @@ B performs such conversions: =over 4 -=item Type conversion. +=item * Type conversion. It tries to find proper Postgres type for each column. @@ -844,30 +869,30 @@ ENUM and SET types implemented via user types (C source for such types can be found in B file); -=item Identifiers double-quotation. +=item * Encloses identifiers into double quotes. All column and table names should be enclosed to double-quotes to prevent -interferension with reserved words; +conflict with reserved SQL keywords; -=item Converting +=item * Converting AUTO_INCREMENT fields to SERIAL. Actually, creating the sequence and setting default value to nextval('seq'), well, you know :) -=item Converting +=item * Converting KEY(field) to CREATE INDEX i_field on table (field); -=item The same +=item * The same for UNIQUE keys; -=item Indices +=item * Indices are creating AFTER rows insertion (to speed up the load); -=item Translates '#' +=item * Translates '#' MySQL comments to ANSI SQL '--' @@ -895,18 +920,23 @@ Add double quotes around table and column names Show usage banner. +=item -s + +Do not attempt to convert data. Currently my2pg only tries to convert +date and time data. + =back =head1 SIDE EFFECTS =over 4 -=item creates +=item * creates file B in current directory overwriting existed file without any checks; -=item the same +=item * the same for Makefile. @@ -914,26 +944,42 @@ for Makefile. =head1 BUGS -This program is still beta. Testers wanted. Known bugs are: =over 4 -=item Poor doublequotation. +=item * Possible problems with the timestamp data. + +PostgreSQL does not accept incorrect date/time values like B<2002-00-15>, +while MySQL does not care about that. Currently my2pg cannot handle this +issue. You should care yourself to convert such a data. + +=item * Use -s option if your numeric data are broken during conversion. + +My2pg attempts to convert MySQL timestamps of the form B to +B and B to B. It performs +some heuristic checks to ensure that the month,day,hour,minutes and seconds have +values from the correct range (0..12, 0..31, 0..23, 0..59, 0..59 respectively). +It is still possible that your numeric values that satisfy these conditions +will get broken. + +=item * Possible problems with enclosing identifiers in double quotes. All identifiers such as table and column names should be enclosed in double quotes. Program can't handle upper-case identifiers, like DBA. Lower-case identifiers are OK. -=item SET type emulation is not full. LIKE operation on +=item * SET type emulation is not full. LIKE operation on SETs, raw integer input values should be implemented -=item B generated during output is +=item * B + +generated during output is platform-dependent and surely works only on Linux/gcc (FreeBSD/gcc probably works as well - not tested) -=item Generated B contain line +=item * Generated B contain line #include @@ -944,16 +990,25 @@ include path, you need to check it before compiling. =head1 AUTHORS -B<(c) 2000 Maxim V. Rudensky (fonin@ziet.zhitomir.ua)> -B<(c) 2000 Valentine V. Danilchuk (valdan@ziet.zhitomir.ua)> +B<(c) 2000-2002 Maxim V. Rudensky (fonin@ziet.zhitomir.ua)> (developer, maintainer) + +B<(c) 2000 Valentine V. Danilchuk (valdan@ziet.zhitomir.ua)> (original script) =head1 CREDITS +Great thanks to all those people who provided feedback and make development +of this tool easier. + Jeff Waugh + Joakim Lemström || + Yunliang Yu + Brad Hilton +If you are not listed here please write to me. + =head1 LICENSE B -- 2.40.0