|
@@ -1,77 +1,43 @@
|
1
|
1
|
#-*- coding: utf-8 -*-
|
2
|
2
|
|
3
|
|
-
|
4
|
3
|
import pymysql
|
|
4
|
+
|
5
|
5
|
from leobject.datasources.dummy import DummyDatasource
|
|
6
|
+from leobject.leobject import REL_SUB, REL_SUP
|
|
7
|
+
|
6
|
8
|
from mosql.db import Database, all_to_dicts
|
7
|
9
|
from mosql.query import select, insert, update, delete, join
|
8
|
|
-from leobject.leobject import REL_SUB, REL_SUP
|
|
10
|
+from mosql.util import raw
|
9
|
11
|
import mosql.mysql
|
10
|
12
|
|
11
|
|
-
|
12
|
|
-## SQL DataSource for LeObject
|
|
13
|
+## MySQL DataSource for LeObject
|
13
|
14
|
class LeDataSourceSQL(DummyDatasource):
|
14
|
15
|
|
15
|
16
|
RELATIONS_TABLE_NAME = 'relations'
|
16
|
|
- RELATIONS_POSITIONS_FIELDS = {REL_SUP: 'superior_id', REL_SUB: 'subordinate_id'}
|
|
17
|
+ RELATIONS_POSITIONS_FIELDS = { REL_SUP: 'superior_id', REL_SUB: 'subordinate_id'}
|
17
|
18
|
RELATIONS_NATURE_FIELD = 'nature'
|
|
19
|
+ LODEL_ID_FIELD = 'lodel_id'
|
|
20
|
+ CLASS_TABLE_PREFIX = 'class_'
|
|
21
|
+ OBJECTS_TABLE_NAME = 'object'
|
18
|
22
|
|
19
|
23
|
def __init__(self, module=pymysql, conn_args={'host': '127.0.0.1', 'user':'lodel', 'passwd':'bruno', 'db': 'lodel2'}):
|
20
|
24
|
super(LeDataSourceSQL, self).__init__()
|
21
|
25
|
self.module = module
|
22
|
26
|
self.connection = Database(pymysql, host=conn_args['host'], user=conn_args['user'], passwd=conn_args['passwd'], db=conn_args['db'])
|
23
|
27
|
|
24
|
|
- ## @brief update an existing object's data
|
25
|
|
- # @param letype LeType
|
26
|
|
- # @param leclass LeClass
|
27
|
|
- # @param filters list : list of tuples formatted as (FIELD, OPERATOR, VALUE)
|
28
|
|
- # @param rel_filters list : list of tuples formatted as (('superior'|'subordinate', FIELD), OPERATOR, VALUE)
|
29
|
|
- # @param data dict
|
30
|
|
- # @return bool
|
31
|
|
- # @todo prendre en compte les rel_filters
|
32
|
|
- def update(self, letype, leclass, filters, rel_filters, data):
|
33
|
|
-
|
34
|
|
- query_table_name = leclass.name
|
35
|
|
- where_filters = filters
|
36
|
|
- set_data = data
|
37
|
|
-
|
38
|
|
- prepared_rel_filters = self._prepare_rel_filters(rel_filters)
|
39
|
|
-
|
40
|
|
- # Building the query
|
41
|
|
- query = update(table=query_table_name, where=where_filters, set=set_data)
|
42
|
|
- # Executing the query
|
43
|
|
- with self.connection as cur:
|
44
|
|
- cur.execute(query)
|
45
|
|
- return True
|
46
|
|
-
|
47
|
|
- ## @brief create a new object in the datasource
|
|
28
|
+ ## @brief inserts a new object
|
48
|
29
|
# @param letype LeType
|
49
|
30
|
# @param leclass LeClass
|
50
|
31
|
# @param datas dict : dictionnary of field:value pairs to save
|
51
|
32
|
# @return int : lodel_id of the created object
|
|
33
|
+ # @todo add the returning clause and the insertion in "object"
|
52
|
34
|
def insert(self, letype, leclass, datas):
|
53
|
|
- query_table_name = leclass.name
|
54
|
|
- #building the query
|
|
35
|
+ query_table_name = self._get_table_name_from_class_name(leclass.name)
|
|
36
|
+
|
55
|
37
|
query = insert(query_table_name, datas)
|
56
|
|
- #executing the query
|
57
|
38
|
with self.connection as cur:
|
58
|
39
|
cur.execute(query)
|
59
|
|
- return True
|
60
|
40
|
|
61
|
|
- ## @brief delete an existing object
|
62
|
|
- # @param letype LeType
|
63
|
|
- # @param leclass LeClass
|
64
|
|
- # @param filters list : list of tuples formatted as (FIELD, OPERATOR, VALUE)
|
65
|
|
- # @param relational_filters list : list of tuples formatted as (('superior'|'subordinate', FIELD), OPERATOR, VALUE)
|
66
|
|
- # @return bool : True on success
|
67
|
|
- # @todo prendre en compte les rel_filters
|
68
|
|
- def delete(self, letype, leclass, filters, relational_filters):
|
69
|
|
- query_table_name = leclass.name
|
70
|
|
- prepared_relational_filters = self._prepare_rel_filters(relational_filters)
|
71
|
|
-
|
72
|
|
- query = delete(query_table_name, filters)
|
73
|
|
- with self.connection as cur:
|
74
|
|
- cur.execute(query)
|
75
|
41
|
return True
|
76
|
42
|
|
77
|
43
|
## @brief search for a collection of objects
|
|
@@ -79,26 +45,26 @@ class LeDataSourceSQL(DummyDatasource):
|
79
|
45
|
# @param letype LeType
|
80
|
46
|
# @field_list list
|
81
|
47
|
# @param filters list : list of tuples formatted as (FIELD, OPERATOR, VALUE)
|
82
|
|
- # @param relational_filters list : list of tuples formatted as (('superior'|'subordinate', FIELD), OPERATOR, VALUE)
|
|
48
|
+ # @param relation_filters list : list of tuples formatted as (('superior'|'subordinate', FIELD), OPERATOR, VALUE)
|
83
|
49
|
# @return list
|
84
|
50
|
def get(self, leclass, letype, field_list, filters, relational_filters=None):
|
85
|
51
|
|
86
|
|
- query_table_name = leclass.name
|
87
|
|
- where_filters = self._prepare_filters(filters)
|
|
52
|
+ query_table_name = self._get_table_name_from_class_name(leclass.name)
|
|
53
|
+ where_filters = self._prepare_filters(filters, query_table_name)
|
88
|
54
|
join_fields = {}
|
89
|
55
|
|
90
|
56
|
if relational_filters is not None and len(relational_filters) > 0:
|
91
|
|
- prepared_rel_filters = self._prepare_rel_filters(relational_filters)
|
92
|
|
- for prepared_rel_filter in prepared_rel_filters:
|
93
|
|
- # Definition of the join condition
|
94
|
|
- relation_table_join_field = "%s.%s" % (self.RELATIONS_TABLE_NAME, self.RELATIONS_POSITIONS_FIELD[prepared_rel_filter['position']])
|
95
|
|
- query_table_join_field = "%s.lodel_id" % query_table_name
|
|
57
|
+ rel_filters = self._prepare_rel_filters(relational_filters)
|
|
58
|
+ for rel_filter in rel_filters:
|
|
59
|
+ # join condition
|
|
60
|
+ relation_table_join_field = "%s.%s" % (self.RELATIONS_TABLE_NAME, self.RELATIONS_POSITIONS_FIELDS[rel_filter['position']])
|
|
61
|
+ query_table_join_field = "%s.%s" % (query_table_name, self.LODEL_ID_FIELD)
|
96
|
62
|
join_fields[query_table_join_field] = relation_table_join_field
|
97
|
63
|
# Adding "where" filters
|
98
|
|
- where_filters['%s.%s' % (self.RELATIONS_TABLE_NAME, self.RELATIONS_NATURE_FIELD)] = prepared_rel_filter['nature']
|
99
|
|
- where_filters[prepared_rel_filter['condition_key']] = prepared_rel_filter['condition_value']
|
|
64
|
+ where_filters['%s.%s' % (self.RELATIONS_TABLE_NAME, self.RELATIONS_NATURE_FIELD)] = rel_filter['nature']
|
|
65
|
+ where_filters[rel_filter['condition_key']] = rel_filter['condition_value']
|
100
|
66
|
|
101
|
|
- # Building the query
|
|
67
|
+ # building the query
|
102
|
68
|
query = select(query_table_name, where=where_filters, select=field_list, joins=join(self.RELATIONS_TABLE_NAME, join_fields))
|
103
|
69
|
else:
|
104
|
70
|
query = select(query_table_name, where=where_filters, select=field_list)
|
|
@@ -107,21 +73,79 @@ class LeDataSourceSQL(DummyDatasource):
|
107
|
73
|
with self.connection as cur:
|
108
|
74
|
results = all_to_dicts(cur.execute(query))
|
109
|
75
|
|
110
|
|
- # Returning it as a list of dict
|
111
|
76
|
return results
|
112
|
77
|
|
113
|
|
- ## @brief prepares the filters to be used by the mosql library's functions
|
114
|
|
- # @params filters : (FIELD, OPERATOR, VALUE) tuples
|
115
|
|
- # @return dict : Dictionnary with (FIELD, OPERATOR):VALUE style elements
|
116
|
|
- def _prepare_filters(self, filters):
|
117
|
|
- prepared_filters = {}
|
118
|
|
- if filters is not None and len(filters)>0:
|
119
|
|
- for filter_item in filters:
|
120
|
|
- prepared_filter_key = (filter_item[0], filter_item[1])
|
121
|
|
- prepared_filter_value = filter_item[2]
|
122
|
|
- prepared_filters[prepared_filter_key] = prepared_filter_value
|
|
78
|
+ ## @brief delete an existing object
|
|
79
|
+ # @param letype LeType
|
|
80
|
+ # @param leclass LeClass
|
|
81
|
+ # @param filters list : list of tuples formatted as (FIELD, OPERATOR, VALUE)
|
|
82
|
+ # @param relational_filters list : list of tuples formatted as (('superior'|'subordinate', FIELD), OPERATOR, VALUE)
|
|
83
|
+ # @return bool : True on success
|
|
84
|
+ def delete(self, letype, leclass, filters, relational_filters):
|
|
85
|
+ query_table_name = self._get_table_name_from_class_name(leclass.name)
|
|
86
|
+ prep_filters = self._prepare_filters(filters, query_table_name)
|
|
87
|
+ prep_rel_filters = self._prepare_rel_filters(relational_filters)
|
|
88
|
+
|
|
89
|
+ if len(prep_rel_filters) > 0:
|
|
90
|
+ query = "DELETE %s FROM " % query_table_name
|
|
91
|
+
|
|
92
|
+ for prep_rel_filter in prep_rel_filters:
|
|
93
|
+ query += "%s INNER JOIN %s ON (%s.%s = %s.%s)" % (
|
|
94
|
+ self.RELATIONS_TABLE_NAME,
|
|
95
|
+ query_table_name,
|
|
96
|
+ self.RELATIONS_TABLE_NAME,
|
|
97
|
+ prep_rel_filter['position'],
|
|
98
|
+ query_table_name,
|
|
99
|
+ self.LODEL_ID_FIELD
|
|
100
|
+ )
|
|
101
|
+
|
|
102
|
+ if prep_rel_filter['condition_key'][0] is not None:
|
|
103
|
+ prep_filters[("%s.%s" % (self.RELATIONS_TABLE_NAME, prep_rel_filter['condition_key'][0]), prep_rel_filter['condition_key'][1])] = prep_rel_filter['condition_value']
|
|
104
|
+
|
|
105
|
+ if prep_filters is not None and len(prep_filters) > 0:
|
|
106
|
+ query += " WHERE "
|
|
107
|
+ filter_counter = 0
|
|
108
|
+ for filter_item in prep_filters:
|
|
109
|
+ if filter_counter > 1:
|
|
110
|
+ query += " AND "
|
|
111
|
+ query += "%s %s %s" % (filter_item[0][0], filter_item[0][1], filter_item[1])
|
|
112
|
+ else:
|
|
113
|
+ query = delete(query_table_name, filters)
|
|
114
|
+
|
|
115
|
+ with self.connection as cur:
|
|
116
|
+ cur.execute(query)
|
|
117
|
+
|
|
118
|
+ return True
|
123
|
119
|
|
124
|
|
- return prepared_filters
|
|
120
|
+ ## @brief update an existing object's data
|
|
121
|
+ # @param letype LeType
|
|
122
|
+ # @param leclass LeClass
|
|
123
|
+ # @param filters list : list of tuples formatted as (FIELD, OPERATOR, VALUE)
|
|
124
|
+ # @param rel_filters list : list of tuples formatted as (('superior'|'subordinate', FIELD), OPERATOR, VALUE)
|
|
125
|
+ # @param data dict
|
|
126
|
+ # @return bool
|
|
127
|
+ # @todo prendre en compte les rel_filters
|
|
128
|
+ def update(self, letype, leclass, filters, rel_filters, data):
|
|
129
|
+
|
|
130
|
+ query_table_name = self._get_table_name_from_class_name(leclass.name)
|
|
131
|
+ where_filters = filters
|
|
132
|
+ set_data = data
|
|
133
|
+
|
|
134
|
+ prepared_rel_filters = self._prepare_rel_filters(rel_filters)
|
|
135
|
+
|
|
136
|
+ # Building the query
|
|
137
|
+ query = update(table=query_table_name, where=where_filters, set=set_data)
|
|
138
|
+ # Executing the query
|
|
139
|
+ with self.connection as cur:
|
|
140
|
+ cur.execute(query)
|
|
141
|
+ return True
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+ ## @brief prepares the table name using a "class_" prefix
|
|
145
|
+ # @params classname str
|
|
146
|
+ # @return str
|
|
147
|
+ def _get_table_name_from_class_name(self, classname):
|
|
148
|
+ return classname if self.CLASS_TABLE_PREFIX in classname else "%s%s" % (self.CLASS_TABLE_PREFIX, classname)
|
125
|
149
|
|
126
|
150
|
## @brief prepares the relational filters
|
127
|
151
|
# @params rel_filters : (("superior"|"subordinate"), operator, value)
|
|
@@ -129,7 +153,7 @@ class LeDataSourceSQL(DummyDatasource):
|
129
|
153
|
def _prepare_rel_filters(self, rel_filters):
|
130
|
154
|
prepared_rel_filters = []
|
131
|
155
|
|
132
|
|
- if rel_filters is not None and len(rel_filters)>0:
|
|
156
|
+ if rel_filters is not None and len(rel_filters) > 0:
|
133
|
157
|
for rel_filter in rel_filters:
|
134
|
158
|
rel_filter_dict = {
|
135
|
159
|
'position': REL_SUB if rel_filter[0][0] == REL_SUP else REL_SUB,
|
|
@@ -139,4 +163,20 @@ class LeDataSourceSQL(DummyDatasource):
|
139
|
163
|
}
|
140
|
164
|
prepared_rel_filters.append(rel_filter_dict)
|
141
|
165
|
|
142
|
|
- return prepared_rel_filters
|
|
166
|
+ return prepared_rel_filters
|
|
167
|
+
|
|
168
|
+ ## @brief prepares the filters to be used by the mosql library's functions
|
|
169
|
+ # @params filters : (FIELD, OPERATOR, VALUE) tuples
|
|
170
|
+ # @return dict : Dictionnary with (FIELD, OPERATOR):VALUE style elements
|
|
171
|
+ def _prepare_filters(self, filters, tablename=None):
|
|
172
|
+ prepared_filters = {}
|
|
173
|
+ if filters is not None and len(filters) > 0:
|
|
174
|
+ for filter_item in filters:
|
|
175
|
+ if '.' in filter_item[0]:
|
|
176
|
+ prepared_filter_key = (filter_item[0], filter_item[1])
|
|
177
|
+ else:
|
|
178
|
+ prepared_filter_key = ("%s.%s" % (tablename, filter_item[0]), filter_item[1])
|
|
179
|
+ prepared_filter_value = filter_item[2]
|
|
180
|
+ prepared_filters[prepared_filter_key] = prepared_filter_value
|
|
181
|
+
|
|
182
|
+ return prepared_filters
|