# 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.
my $dq=''; # double quote
# parse command line
-getopts('nhd',\%opts);
+getopts('nhds',\%opts);
# output syntax
if($opts{h} 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------------------------------------------------------------------");
# 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;
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;
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;
}
return result;
}\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);
}\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';
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;
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) {
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;
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;
}
return result;
}\n";
- $func_out.="\nbool $typename"."_eq($typesize* a, $typesize* b) {
+ $func_out.="\nbool $typename"."_eq($typesize* a, $typesize* b) {
return (*a==*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';
\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:
# );
# 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;
-#<Hackzone> ---------------------------------------------------
-#</Hackzone> --------------------------------------------------
+ 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.=$_;
}
open(MAKE,">Makefile");
print MAKE "#
-# My2Pg \$Revision: 1.11 $ \translated dump
+# My2Pg \$Revision: 1.12 $ \translated dump
# Makefile
#
print <<EOF
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>
This program is distributed in the hope that it will be useful,
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
;
}
=head1 SYNTAX
- mysqldump db | ./my2pg.pl [-n] > pgsqldump.sql
+ mysqldump db | ./my2pg.pl [-nds] > pgsqldump.sql
vi libtypes.c
make
psql database < pgsqldump.txt
=over 4
-=item B<pgsqldump.sql>
+=item F<pgsqldump.sql>
- 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>
=over 4
-=item Type conversion.
+=item * Type conversion.
It tries to find proper Postgres
type for each column.
(C source for such types can be found in
B<libtypes.c> 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 '--'
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<libtypes.c> in current directory
overwriting existed file without any checks;
-=item the same
+=item * the same
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<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
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<Makefile> generated during output is
+=item * B<Makefile>
+
+generated during output is
platform-dependent and surely works only on
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>
=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 <jaw@ic.net>
+
Joakim Lemström <jocke@bytewize.com> || <buddyh19@hotmail.com>
+
Yunliang Yu <yu@math.duke.edu>
+
Brad Hilton <bhilton@vpop.net>
+If you are not listed here please write to me.
+
=head1 LICENSE
B<BSD>