-
Notifications
You must be signed in to change notification settings - Fork 0
/
access_to_postgresql.py
executable file
·170 lines (121 loc) · 5.22 KB
/
access_to_postgresql.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
import os
import json
import pyodbc
import psycopg2
import time
import sys
# Refer to https://code.google.com/p/pyodbc/wiki/Cursor for information on
# cursor.tables and cursor.columns field names
class Converter:
def __init__(self, access_con_string, pg_con_string, print_SQL):
self.access_cur = pyodbc.connect(access_con_string).cursor()
self.pg_con = psycopg2.connect(pg_con_string)
self.pg_cur = self.pg_con.cursor()
self.print_SQL = print_SQL
self.schema_name = self.get_access_db_name()
def get_access_db_name(self):
# The full path of the database is stored in the table information
# We can parse it to get the file name (to use as scheme_name)
for table in self.access_cur.tables():
return os.path.splitext(os.path.basename(table.table_cat))[0]
def create_schema(self):
SQL = """
CREATE SCHEMA "{schema_name}"
""".format(schema_name=self.schema_name)
if self.print_SQL:
print SQL
self.pg_cur.execute(SQL)
self.pg_con.commit()
def create_tables(self):
# Generate list of tables in schema
table_list = list()
for table in self.access_cur.tables():
if table.table_type == "TABLE":
table_list += [table.table_name, ]
for table in table_list:
SQL = """
CREATE TABLE "{schema}"."{table}"
(
""".format(schema=self.schema_name, table=table)
SQL += self.create_fields(table)
SQL += """
) """
if self.print_SQL:
print SQL
self.pg_cur.execute(SQL)
self.pg_con.commit()
def create_fields(self, table):
postgresql_fields = {
'COUNTER': 'serial', # autoincrement
'VARCHAR': 'text', # text
'LONGCHAR': 'text', # memo
'BYTE': 'integer', # byte
'SMALLINT': 'integer', # integer
'INTEGER': 'bigint', # long integer
'REAL': 'real', # single
'DOUBLE': 'double precision', # double
'DATETIME': 'timestamp', # date/time
'CURRENCY': 'money', # currency
'BIT': 'boolean', # yes/no
}
SQL = ""
field_list = list()
for column in self.access_cur.columns(table=table):
if column.type_name in postgresql_fields:
field_list += ['"' + column.column_name + '"' +
" " + postgresql_fields[column.type_name], ]
elif column.type_name == "DECIMAL":
field_list += ['"' + column.column_name + '"' +
" numeric(" + str(column.column_size) + "," +
str(column.decimal_digits) + ")", ]
else:
print "column " + table + "." + column.column_name +
" has uncatered for type: " + column.type_name
return ",\n ".join(field_list)
def insert_data(self):
# Generate list of tables in schema
table_list = list()
for table in self.access_cur.tables():
if table.table_type == "TABLE":
table_list += [table.table_name, ]
for table in table_list:
data = self.get_access_data(table)
# check that data exists
if data != []:
# Create format string (eg (%s,%s,%s)
# the same size as the number of fields)
format_string = "(" + ",".join(["%s", ]*len(data[0])) + ")\n"
# pre-bind the arguments before executing - for speed
args_string = ','.join(self.pg_cur.mogrify(format_string, x)
for x in data)
SQL = """INSERT INTO "{schema_name}"."{table_name}"
VALUES {value_list}""".format(schema_name=self.schema_name,
table_name=table,
value_list=args_string)
if self.print_SQL:
print SQL
self.pg_cur.execute(SQL)
self.pg_con.commit()
def get_access_data(self, table):
SQL = """SELECT *
FROM {table_name}""".format(table_name=table)
self.access_cur.execute(SQL)
rows = self.access_cur.fetchall()
data = list()
for row in rows:
data += [row, ]
return data
if __name__ == "__main__":
if len(sys.argv) != 2
and os.path.exists(config_path)
and config_path.endswith('.json'):
exit("Requires a config json file")
config_path = os.path.abspath(sys.argv[1])
config_data = json.load(open(config_path))
pg_con_string = config_data['postgresql_connection_string']
print_SQL = config_data['print_SQL']
for access_con_string in config_data['access_connection_strings']:
converter = Converter(access_con_string, pg_con_string, print_SQL)
converter.create_schema()
converter.create_tables()
converter.insert_data()