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