-
Notifications
You must be signed in to change notification settings - Fork 2k
/
db.py
97 lines (80 loc) · 2.99 KB
/
db.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
import sqlalchemy
from pylons import config
_pg_types = {}
_type_names = set()
_engines = {}
def _get_engine(context, data_dict):
''' Get either read or write engine'''
connection_type = data_dict.get('connection_type', 'write')
engine = _engines.get(connection_type)
if not engine:
config_option = 'ckan.datastore_{}_url'.format(connection_type)
url = config.get(config_option)
assert url, 'Config option ' + config_option + ' not defined'
engine = sqlalchemy.create_engine(url)
_engines[connection_type] = engine
return engine
def _cache_types(context, data_dict=None):
if not _pg_types:
connection = context['connection']
results = connection.execute(
'select oid, typname from pg_type;'
)
for result in results:
_pg_types[result[0]] = result[1]
_type_names.add(result[1])
def _get_type(context, oid):
_cache_types(context)
return _pg_types[oid]
def check_fields(context, fields):
_cache_types(context)
## check if fieds are in in _type_names
pass
def create_table(context, data_dict):
'''create table from combination of fields and first row of data'''
check_fields(context, data_dict.get('fields'))
pass
def alter_table(context, data_dict):
'''alter table from combination of fields and first row of data'''
check_fields(context, data_dict.get('fields'))
pass
def insert_data(context, data_dict):
'''insert all data from records'''
pass
def create(context, data_dict):
'''
The first row will be used to guess types not in the fields and the
guessed types will be added to the headers permanently.
Consecutive rows have to conform to the field definitions.
rows can be empty so that you can just set the fields.
fields are optional but needed if you want to do type hinting or
add extra information for certain columns or to explicitly
define ordering.
eg [{"id": "dob", "label": ""Date of Birth",
"type": "timestamp" ,"concept": "day"},
{"name": "some_stuff": ..].
A header items values can not be changed after it has been defined
nor can the ordering of them be changed. They can be extended though.
Any error results in total failure! For now pass back the actual error.
Should be transactional.
'''
engine = _get_engine(context, {'connection_type': 'write'})
context['connection'] = engine.connect()
## close connection at all cost.
try:
## check if table already existes
trans = context['connection'].begin()
result = context['connection'].execute(
'select * from pg_tables where tablename = %s',
data_dict['resource_id']
).fetchone()
if not result:
create_table(context, data_dict)
else:
alter_table(context, data_dict)
insert_data(context, data_dict)
except:
trans.rollback()
raise
finally:
context['connection'].close()