]> git.gir.st - tmk_keyboard.git/blob - tmk_core/tool/mbed/mbed-sdk/workspace_tools/test_mysql.py
Merge commit '4d116a04e94cf0d19317d5b44e4fa9f34a3e5594'
[tmk_keyboard.git] / tmk_core / tool / mbed / mbed-sdk / workspace_tools / test_mysql.py
1 """
2 mbed SDK
3 Copyright (c) 2011-2014 ARM Limited
4
5 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 Author: Przemyslaw Wirkus <Przemyslaw.Wirkus@arm.com>
18 """
19
20 import re
21 import MySQLdb as mdb
22
23 # Imports from TEST API
24 from workspace_tools.test_db import BaseDBAccess
25
26
27 class MySQLDBAccess(BaseDBAccess):
28 """ Wrapper for MySQL DB access for common test suite interface
29 """
30 def __init__(self):
31 BaseDBAccess.__init__(self)
32 self.DB_TYPE = 'mysql'
33
34 def detect_database(self, verbose=False):
35 """ detect database and return VERION data structure or string (verbose=True)
36 """
37 query = 'SHOW VARIABLES LIKE "%version%"'
38 rows = self.select_all(query)
39 if verbose:
40 result = []
41 for row in rows:
42 result.append("\t%s: %s"% (row['Variable_name'], row['Value']))
43 result = "\n".join(result)
44 else:
45 result = rows
46 return result
47
48 def parse_db_connection_string(self, str):
49 """ Parsing SQL DB connection string. String should contain:
50 - DB Name, user name, password, URL (DB host), name
51 Function should return tuple with parsed (host, user, passwd, db) or None if error
52 E.g. connection string: 'mysql://username:password@127.0.0.1/db_name'
53 """
54 result = BaseDBAccess().parse_db_connection_string(str)
55 if result is not None:
56 (db_type, username, password, host, db_name) = result
57 if db_type != 'mysql':
58 result = None
59 return result
60
61 def is_connected(self):
62 """ Returns True if we are connected to database
63 """
64 return self.db_object is not None
65
66 def connect(self, host, user, passwd, db):
67 """ Connects to DB and returns DB object
68 """
69 try:
70 self.db_object = mdb.connect(host=host, user=user, passwd=passwd, db=db)
71 # Let's remember connection credentials
72 self.db_type = self.DB_TYPE
73 self.host = host
74 self.user = user
75 self.passwd = passwd
76 self.db = db
77 except mdb.Error, e:
78 print "Error %d: %s"% (e.args[0], e.args[1])
79 self.db_object = None
80 self.db_type = None
81 self.host = None
82 self.user = None
83 self.passwd = None
84 self.db = None
85
86 def connect_url(self, db_url):
87 """ Connects to database using db_url (database url parsing),
88 store host, username, password, db_name
89 """
90 result = self.parse_db_connection_string(db_url)
91 if result is not None:
92 (db_type, username, password, host, db_name) = result
93 if db_type == self.DB_TYPE:
94 self.connect(host, username, password, db_name)
95
96 def reconnect(self):
97 """ Reconnects to DB and returns DB object using stored host name,
98 database name and credentials (user name and password)
99 """
100 self.connect(self.host, self.user, self.passwd, self.db)
101
102 def disconnect(self):
103 """ Close DB connection
104 """
105 if self.db_object:
106 self.db_object.close()
107 self.db_object = None
108 self.db_type = None
109
110 def escape_string(self, str):
111 """ Escapes string so it can be put in SQL query between quotes
112 """
113 con = self.db_object
114 result = con.escape_string(str)
115 return result if result else ''
116
117 def select_all(self, query):
118 """ Execute SELECT query and get all results
119 """
120 con = self.db_object
121 cur = con.cursor(mdb.cursors.DictCursor)
122 cur.execute(query)
123 rows = cur.fetchall()
124 return rows
125
126 def insert(self, query, commit=True):
127 """ Execute INSERT query, define if you want to commit
128 """
129 con = self.db_object
130 cur = con.cursor()
131 cur.execute(query)
132 if commit:
133 con.commit()
134 return cur.lastrowid
135
136 def get_next_build_id(self, name, desc='', location='', type=None, status=None):
137 """ Insert new build_id (DB unique build like ID number to send all test results)
138 """
139 if status is None:
140 status = self.BUILD_ID_STATUS_STARTED
141
142 if type is None:
143 type = self.BUILD_ID_TYPE_TEST
144
145 query = """INSERT INTO `%s` (%s_name, %s_desc, %s_location, %s_type_fk, %s_status_fk)
146 VALUES ('%s', '%s', '%s', %d, %d)"""% (self.TABLE_BUILD_ID,
147 self.TABLE_BUILD_ID,
148 self.TABLE_BUILD_ID,
149 self.TABLE_BUILD_ID,
150 self.TABLE_BUILD_ID,
151 self.TABLE_BUILD_ID,
152 self.escape_string(name),
153 self.escape_string(desc),
154 self.escape_string(location),
155 type,
156 status)
157 index = self.insert(query) # Provide inserted record PK
158 return index
159
160 def get_table_entry_pk(self, table, column, value, update_db=True):
161 """ Checks for entries in tables with two columns (<TABLE_NAME>_pk, <column>)
162 If update_db is True updates table entry if value in specified column doesn't exist
163 """
164 # TODO: table buffering
165 result = None
166 table_pk = '%s_pk'% table
167 query = """SELECT `%s`
168 FROM `%s`
169 WHERE `%s`='%s'"""% (table_pk,
170 table,
171 column,
172 self.escape_string(value))
173 rows = self.select_all(query)
174 if len(rows) == 1:
175 result = rows[0][table_pk]
176 elif len(rows) == 0 and update_db:
177 # Update DB with new value
178 result = self.update_table_entry(table, column, value)
179 return result
180
181 def update_table_entry(self, table, column, value):
182 """ Updates table entry if value in specified column doesn't exist
183 Locks table to perform atomic read + update
184 """
185 result = None
186 con = self.db_object
187 cur = con.cursor()
188 cur.execute("LOCK TABLES `%s` WRITE"% table)
189 table_pk = '%s_pk'% table
190 query = """SELECT `%s`
191 FROM `%s`
192 WHERE `%s`='%s'"""% (table_pk,
193 table,
194 column,
195 self.escape_string(value))
196 cur.execute(query)
197 rows = cur.fetchall()
198 if len(rows) == 0:
199 query = """INSERT INTO `%s` (%s)
200 VALUES ('%s')"""% (table,
201 column,
202 self.escape_string(value))
203 cur.execute(query)
204 result = cur.lastrowid
205 con.commit()
206 cur.execute("UNLOCK TABLES")
207 return result
208
209 def update_build_id_info(self, build_id, **kw):
210 """ Update additional data inside build_id table
211 Examples:
212 db.update_build_id_info(build_id, _status_fk=self.BUILD_ID_STATUS_COMPLETED, _shuffle_seed=0.0123456789):
213 """
214 if len(kw):
215 con = self.db_object
216 cur = con.cursor()
217 # Prepare UPDATE query
218 # ["`mtest_build_id_pk`=[value-1]", "`mtest_build_id_name`=[value-2]", "`mtest_build_id_desc`=[value-3]"]
219 set_list = []
220 for col_sufix in kw:
221 assign_str = "`%s%s`='%s'"% (self.TABLE_BUILD_ID, col_sufix, self.escape_string(str(kw[col_sufix])))
222 set_list.append(assign_str)
223 set_str = ', '.join(set_list)
224 query = """UPDATE `%s`
225 SET %s
226 WHERE `mtest_build_id_pk`=%d"""% (self.TABLE_BUILD_ID,
227 set_str,
228 build_id)
229 cur.execute(query)
230 con.commit()
231
232 def insert_test_entry(self, build_id, target, toolchain, test_type, test_id, test_result, test_output, test_time, test_timeout, test_loop, test_extra=''):
233 """ Inserts test result entry to database. All checks regarding existing
234 toolchain names in DB are performed.
235 If some data is missing DB will be updated
236 """
237 # Get all table FK and if entry is new try to insert new value
238 target_fk = self.get_table_entry_pk(self.TABLE_TARGET, self.TABLE_TARGET + '_name', target)
239 toolchain_fk = self.get_table_entry_pk(self.TABLE_TOOLCHAIN, self.TABLE_TOOLCHAIN + '_name', toolchain)
240 test_type_fk = self.get_table_entry_pk(self.TABLE_TEST_TYPE, self.TABLE_TEST_TYPE + '_name', test_type)
241 test_id_fk = self.get_table_entry_pk(self.TABLE_TEST_ID, self.TABLE_TEST_ID + '_name', test_id)
242 test_result_fk = self.get_table_entry_pk(self.TABLE_TEST_RESULT, self.TABLE_TEST_RESULT + '_name', test_result)
243
244 con = self.db_object
245 cur = con.cursor()
246
247 query = """ INSERT INTO `%s` (`mtest_build_id_fk`,
248 `mtest_target_fk`,
249 `mtest_toolchain_fk`,
250 `mtest_test_type_fk`,
251 `mtest_test_id_fk`,
252 `mtest_test_result_fk`,
253 `mtest_test_output`,
254 `mtest_test_time`,
255 `mtest_test_timeout`,
256 `mtest_test_loop_no`,
257 `mtest_test_result_extra`)
258 VALUES (%d, %d, %d, %d, %d, %d, '%s', %.2f, %.2f, %d, '%s')"""% (self.TABLE_TEST_ENTRY,
259 build_id,
260 target_fk,
261 toolchain_fk,
262 test_type_fk,
263 test_id_fk,
264 test_result_fk,
265 self.escape_string(test_output),
266 test_time,
267 test_timeout,
268 test_loop,
269 self.escape_string(test_extra))
270 cur.execute(query)
271 con.commit()
Imprint / Impressum