1 """@namespace IMP.EMageFit.database
2 Utility functions to manage SQL databases with sqlite3.
5 import sqlite3
as sqlite
10 log = logging.getLogger(
"Database")
15 """ Class to manage a SQL database built with sqlite3 """
19 self.connection =
None
25 def create(self, filename, overwrite=False):
26 """ Creates a database by simply connecting to the file """
27 log.info(
"Creating database")
28 if overwrite
and os.path.exists(filename):
30 sqlite.connect(filename)
33 """ Connects to the database in filename """
34 if not os.path.isfile(filename):
35 raise IOError(
"Database file not found: %s" % filename)
36 self.connection = sqlite.connect(filename)
37 self.cursor = self.connection.cursor()
40 """ Checks if the class is connected to the database filename """
41 if self.connection
is None:
42 raise ValueError(
"The database has not been created "
43 "or connection not established ")
46 """ Creates a table. It expects a sorted dictionary
47 of (data_field,typename) entries """
48 log.info(
"Creating table %s", table_name)
50 sql_command =
"CREATE TABLE %s (" % (table_name)
51 for name, data_type
in zip(column_names, column_types):
52 sql_typename = get_sql_type_name(data_type)
53 sql_command +=
"%s %s," % (name, sql_typename)
56 sql_command = sql_command[0:n - 1] +
")"
57 log.debug(sql_command)
58 self.cursor.execute(sql_command)
59 self.connection.commit()
63 Delete a table if it exists
65 log.info(
"Deleting table %s", table_name)
67 sql_command =
"DROP TABLE IF EXISTS %s" % (table_name)
68 log.debug(sql_command)
69 self.cursor.execute(sql_command)
70 self.connection.commit()
73 """ Inserts information in a given table of the database.
74 The info must be a list of tuples containing as many values
75 as columns in the table
76 Conversion of values is done AUTOMATICALLY after checking the
77 types stored in the table
81 tuple_format =
"(" +
"?," * (n - 1) +
"?)"
82 sql_command =
"INSERT INTO %s VALUES %s " % (table_name, tuple_format)
88 y = [apply_type(i)
for i, apply_type
in zip(x, types)]
89 self.cursor.execute(sql_command, y)
90 self.connection.commit()
93 """ Inserts information in a given table of the database.
94 The info must be a list of tuples containing as many values
95 as columns in the table
96 Conversion of values is done AUTOMATICALLY after checking the
97 types stored in the table
100 log.warning(
"Inserting empty data")
104 tuple_format =
"(" +
"?," * (n - 1) +
"?)"
105 sql_command =
"INSERT INTO %s VALUES %s " % (table_name, tuple_format)
109 for i
in range(len(data)):
110 data[i] = [apply_type(d)
for d, apply_type
in zip(data[i], types)]
111 self.cursor.executemany(sql_command, data)
112 self.connection.commit()
115 """ Retrieves data from the database using the sql_command
116 returns the records as a list of tuples"""
118 log.debug(
"Retrieving data: %s" % sql_command)
119 self.cursor.execute(sql_command)
120 return self.cursor.fetchall()
127 """ updates the register in the table identified by the condition
128 values for the condition fields
131 sql_command =
"UPDATE %s SET " % (table_name)
132 for field, value
in zip(updated_fields, updated_values):
133 sql_command +=
"%s=%s," % (field, value)
134 sql_command = sql_command.rstrip(
",") +
" WHERE "
136 sql_command = sql_command + s
138 log.debug(
"Updating %s: %s", table_name, sql_command)
139 self.cursor.execute(sql_command)
140 self.connection.commit()
143 condition_fields, condition_values):
144 """ creates a view of the given table where the values are selected
145 using the condition values. See the help for update_data()
151 sql_command =
'CREATE VIEW %s AS SELECT * FROM %s WHERE ' % (
152 view_name, table_name)
154 condition_fields, condition_values)
155 sql_command += condition
156 log.info(
"Creating view %s", sql_command)
157 self.cursor.execute(sql_command)
159 def create_view_of_best_records(
169 sql_command =
"""CREATE VIEW %s AS SELECT * FROM %s
170 ORDER BY %s ASC LIMIT %d """ % (view_name, table_name,
172 log.info(
"Creating view %s", sql_command)
173 self.cursor.execute(sql_command)
176 """ Removes a view from the database """
177 self.cursor.execute(
'DROP VIEW %s' % view_name)
179 def get_table(self, table_name, fields=False, orderby=False):
180 """ Returns th fields requested from the table """
181 fields = self.get_fields_string(fields)
182 sql_command =
"SELECT %s FROM %s " % (fields, table_name)
184 sql_command +=
" ORDER BY %s ASC" % orderby
188 def get_fields_string(self, fields, field_delim=","):
190 return field_delim.join(fields)
194 """ Closes the database """
197 self.connection.close()
200 """ creates a condition applying each value to each field
203 for field, value
in zip(fields, values):
204 s +=
"%s=%s AND " % (field, value)
212 Gets info about a table and returns all the types in it
215 sql_command =
"PRAGMA table_info(%s)" % name
216 self.cursor.execute(sql_command)
217 info = self.cursor.fetchall()
222 elif row[2] ==
"DOUBLE":
224 elif row[2][0:7] ==
"VARCHAR":
230 Get the names of the columns for a given table
233 sql_command =
"PRAGMA table_info(%s)" % name
234 self.cursor.execute(sql_command)
235 info = self.cursor.fetchall()
236 return [row[1]
for row
in info]
238 def execute_sql_command(self, sql_command):
240 self.cursor.execute(sql_command)
241 self.connection.commit()
245 Add a column to a table
246 column - the name of the column.
247 data_type - the type: int, float, str
249 sql_typename = get_sql_type_name(data_type)
250 sql_command =
"ALTER TABLE %s ADD %s %s" % (
251 table, column, sql_typename)
252 self.execute_sql_command(sql_command)
256 Add columns to the database. If check=True, columns with names
257 already in the database are skipped. If check=False no check
258 is done and trying to add a column that already exists will
263 for name, dtype
in zip(names, types):
264 if name
not in col_names:
267 for name, dtype
in zip(names, types):
270 def get_tables_names(self):
271 sql_command =
""" SELECT tbl_name FROM sqlite_master """
273 names = [d[0]
for d
in data]
278 Prompt for tables so the user can choose one
282 tables = self.get_tables_names()
285 while say
not in (
'n',
'y'):
286 say = input(
"Use table %s (y/n) " % t)
291 return table_name, columns
293 def drop_columns(self, table, columns):
298 names_txt =
", ".join(cnames)
300 "CREATE TEMPORARY TABLE backup(%s);" % names_txt,
301 "INSERT INTO backup SELECT %s FROM %s" % (names_txt, table),
302 "DROP TABLE %s;" % table,
303 "CREATE TABLE %s(%s);" % (table, names_txt),
304 "INSERT INTO %s SELECT * FROM backup;" % table,
305 "DROP TABLE backup;",
307 for command
in sql_command:
310 self.cursor.execute(command)
314 """ Prints the data recovered from a database """
316 line = delimiter.join([str(x)
for x
in row])
321 """writes data to a file. The output file is expected to be a python
323 w = csv.writer(output_file, delimiter=delimiter)
328 def get_sql_type_name(data_type):
331 elif data_type == float:
333 elif data_type == str:
340 def open(fn_database):
342 db.connect(fn_database)
346 def read_data(fn_database, sql_command):
348 db.connect(fn_database)
349 data = db.retrieve_data(sql_command)
355 """ Return indices that sort the list ls"""
356 pairs = sorted([(element, i)
for i, element
in enumerate(ls)])
357 indices = [p[1]
for p
in pairs]
363 Reads a table from a set of database files into a single file
364 Makes sure to reorder all column names if necessary before merging
369 names = db.get_table_column_names(tbl)
370 types = db.get_table_types(tbl)
372 sorted_names = [names[i]
for i
in indices]
373 sorted_types = [types[i]
for i
in indices]
374 log.info(
"Merging databases. Saving to %s", fn_output)
376 out_db.create(fn_output, overwrite=
True)
377 out_db.connect(fn_output)
378 out_db.create_table(tbl, sorted_names, sorted_types)
380 log.debug(
"Reading %s", fn)
382 names = sorted(db.get_table_column_names(tbl))
383 they_are_sorted =
",".join(names)
384 log.debug(
"Retrieving %s", they_are_sorted)
385 sql_command =
"SELECT %s FROM %s" % (they_are_sorted, tbl)
386 data = db.retrieve_data(sql_command)
387 out_db.store_data(tbl, data)
def get_table_column_names
Get the names of the columns for a given table.
def close
Closes the database.
Class to manage a SQL database built with sqlite3.
def get_table_types
Gets info about a table and returns all the types in it.
def get_sorting_indices
Return indices that sort the list ls.
def store_data
Inserts information in a given table of the database.
def get_condition_string
creates a condition applying each value to each field
def create_table
Creates a table.
def retrieve_data
Retrieves data from the database using the sql_command returns the records as a list of tuples...
def create
Creates a database by simply connecting to the file.
def print_data
Prints the data recovered from a database.
def get_table
Returns th fields requested from the table.
def drop_table
Delete a table if it exists.
def create_view
creates a view of the given table where the values are selected using the condition values...
def connect
Connects to the database in filename.
def add_column
Add a column to a table column - the name of the column.
def store_dataV1
Inserts information in a given table of the database.
def select_table
Prompt for tables so the user can choose one.
def merge_databases
Reads a table from a set of database files into a single file Makes sure to reorder all column names ...
def add_columns
Add columns to the database.
def drop_view
Removes a view from the database.
def update_data
updates the register in the table identified by the condition values for the condition fields ...
def check_if_is_connected
Checks if the class is connected to the database filename.
def write_data
writes data to a file.