1

With reference to Import MySQL dump to PostgreSQL database. An unknown developer has offered there to use the following script to import MySQL database to PostgreSQL

import MySQLdb
#from magic import Connect #Private mysql connect information - I COMMENTED THIS LINE to use direct connection
db = MySQLdb.connect(host="localhost", # your host, usually localhost
                     user="USER", # your username
                      passwd="PASS", # your password
                      db="w3i") # name of the data base
import psycopg2

dbx=Connect()
DB=psycopg2.connect("dbname='w3i'")
DC=DB.cursor()

mysql='''show tables from w3i'''
dbx.execute(mysql); ts=dbx.fetchall(); tables=[]
for table in ts: tables.append(table[0])
for table in tables:
    mysql='''describe w3i.%s'''%(table)
    dbx.execute(mysql); rows=dbx.fetchall()
    psql='drop table %s'%(table)
    DC.execute(psql); DB.commit()

    psql='create table %s ('%(table)
    for row in rows:
        name=row[0]; type=row[1]
        if 'int' in type: type='int8'
        if 'blob' in type: type='bytea'
        if 'datetime' in type: type='timestamptz'
        psql+='%s %s,'%(name,type)
    psql=psql.strip(',')+')'
    print psql
    try: DC.execute(psql); DB.commit()
    except: pass

    msql='''select * from w3i.%s'''%(table)
    dbx.execute(msql); rows=dbx.fetchall()
    n=len(rows); print n; t=n
    if n==0: continue #skip if no data

    cols=len(rows[0])
    for row in rows:
        ps=', '.join(['%s']*cols)
        psql='''insert into %s values(%s)'''%(table, ps)
        DC.execute(psql,(row))
        n=n-1
        if n%1000==1: DB.commit(); print n,t,t-n
    DB.commit()

As you can see - I changed line 2 to direct connection with MySQL

But now I have the following error

python postgres.py
Traceback (most recent call last):
  File "postgres.py", line 9, in <module>
    dbx=Connect()
NameError: name 'Connect' is not defined

Thanks in advance for a hint how to solve it !

Community
  • 1
  • 1
Serge
  • 679
  • 1
  • 9
  • 23

2 Answers2

1

EDIT : I forgot the cursor ...

EDIT2 : original script did not correctly process fields of TINYTEXT, MEDIUMTEXT or LONGTEXT type => added a conversion to PostgreSQL TEXT type

EDIT3 : the original script did not process ENUM fields, choked on non 7 bits characters, and had a wrong error management

You commented out line 2 where Connect was defined, but you left line 9 where Connect() is used untouched, so the error.

As you now explicitely connect to MySQL, you should replace dbx = Connect() with :

dbx = db.cursor()

It should now give (with the conversion of TEXT types line 28):

import MySQLdb
#from magic import Connect #Private mysql connect information - I COMMENTED THIS LINE to use direct connection
db = MySQLdb.connect(host="localhost", # your host, usually localhost
                     user="USER", # your username
                      passwd="PASS", # your password
                      db="w3i") # name of the data base
import psycopg2

# set client_encoding if different that PostgreSQL database default
encoding = 'Latin1'

dbx=db.cursor()
DB=psycopg2.connect("dbname='w3i'")
DC=DB.cursor()
DC.execute("set client_encoding = " + encoding)

mysql='''show tables from w3i'''
dbx.execute(mysql); ts=dbx.fetchall(); tables=[]
for table in ts: tables.append(table[0])
for table in tables:
    mysql='''describe w3i.%s'''%(table)
    dbx.execute(mysql); rows=dbx.fetchall()
    psql='drop table %s'%(table)
    DC.execute(psql); DB.commit()

    psql='create table %s ('%(table)
    for row in rows:
        name=row[0]; type=row[1]
        if 'int' in type: type='int8'
        if 'blob' in type: type='bytea'
        if 'datetime' in type: type='timestamptz'
        if 'text' in type: type='text'
        if 'enum' in type:
            type = 'varchar'
            print ("warning : conversion of enum to varchar %s(%s)" % (table, name))
        psql+='%s %s,'%(name,type)
    psql=psql.strip(',')+')'
    print psql
    try: DC.execute(psql); DB.commit()
    except Exception as e:
        print e
        DB.rollback()

Above script convert enum to VARCHAR. If you have only one enum type you can try to create it PostgreSQL side :

DC.execute("DROP TYPE IF EXISTS enumtyp CASCADE")
DC.execute("CREATE TYPE enumtyp AS ENUM( ... )"

where enumtyp is the name of the type and ... is the list of (textual) values (don't forget to add an empty value if the field can be empty in MySQL)

Then you replace enum with enumtyp by replacing line type = 'varchar' with :

        if 'enum' in type:
            type = 'enumtyp'
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
  • You way seems to be closer to a solution, but using #dbx=Connect() I have error File "postgres.py", line 14, in db.execute(mysql); ts=db.fetchall(); tables=[] AttributeError: 'Connection' object has no attribute 'execute' ...may be any other ideas ? – Serge Nov 20 '14 at 11:14
  • @Serge : Looks like I forgot the cursor ... should work better now :-) – Serge Ballesta Nov 20 '14 at 11:21
  • Yes :) we go closer...now it actually tries to do something but now I see error on File "postgres.py", line 20, in DC.execute(psql); DB.commit() psycopg2.ProgrammingError: table "categories" does not exist What is could be ? – Serge Nov 20 '14 at 11:32
  • 1
    @Serge : This one I know ! As you are migrating tables from MySQL to PostgreSQL, at beginning they do not exist. You must replace line 19 `psql='drop table %s'%(table)` with `psql='drop table if exists %s'%(table)` – Serge Ballesta Nov 20 '14 at 12:44
  • ...and it works ! but till next error...now it looks like create table categories (id int8,name varchar(255),alternates mediumtext) 0 Traceback (most recent call last): File "postgres.py", line 20, in DC.execute(psql); DB.commit() psycopg2.InternalError: current transaction is aborted, commands ignored until end of transaction block ...I regret we can't catch the author of this script to ask him what he meant writing this code ! ...from one point of view it could be a good instrument of import MySQL>PostgreSQL - but now I've no any idea what else to try... – Serge Nov 20 '14 at 13:24
  • @Serge : Script author never used `MEDIUMTEXT` fields (I never used `TEXT` either under PostgreSQL). I added a line for converting them to `TEXT` type. Good luck ... two *Serge* working together cannot fail :-) – Serge Ballesta Nov 20 '14 at 13:56
  • I can't believe :)) we have reached line 44 in the code. First of all, SERGE :) I've missed line 28 `if 'text' in type: type='text'` - but when I added the one - an about last error has arised as `Traceback (most recent call last): File "post.py", line 44, in DC.execute(psql,(row)) psycopg2.InternalError: current transaction is aborted, commands ignored until end of transaction block` – Serge Nov 20 '14 at 16:49
  • This error is due to a previous one. IMHO the cause is the conversion of MEDIUMTEXT to TEXT. – Serge Ballesta Nov 20 '14 at 17:54
  • I'm just afraid this script is bad :( that's a pity because idea was very good...but I'm not Python-master to correct the code in a right way. I've noted that with all your correctations - the import was good while it was importing two first but EMPTY tables, but when third table with real data "happenned" - again same issue `File "post.py", line 46, in DC.execute(psql,(row)) psycopg2.InternalError: current transaction is aborted, commands ignored until end of transaction block` Script is bad :( that's true... – Serge Nov 20 '14 at 19:08
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/65307/discussion-between-serge-ballesta-and-serge). – Serge Ballesta Nov 20 '14 at 19:16
  • Sorry I lost the chat and cannot connect back. I will propose a solution in a while ... – Serge Ballesta Nov 20 '14 at 19:43
0

as reported in the answer you cite:

from magic import Connect #Private mysql connect information

Connect() is (I assume) a method feeding parameters to connect to a specific db.

You thus have either to implement on your own this magic module, with references to your specific parameters, or to specify which connection you want to setup, namely MySQLdb.connect(...) or psycopg2.connect(...)

  • You're right, I've installed python-magic for magic - but I have no any idea or hint how to create Connect under python-magic...this is why I try to use a direct MySql connection – Serge Nov 20 '14 at 11:10
  • I don't think this was the case. python-magic is for something else. Make your own module and wrap the connection to the database into a method Connect() – Marco Milanesio Nov 20 '14 at 13:07
  • I wish I could if I could know :) how to write a Python module...by the way - when I was trying without python-magic - it even did not start anything...so python-magic definitely has a matter here. Another question how to write this "Connect" so that magic could import the one – Serge Nov 20 '14 at 13:28