1#!/usr/bin/env python3
2
3"""Implementation of Engine class."""
4
5import sys
6import logging
7
8from chart.db.exceptions import DatabaseError
9from chart.db.exceptions import ObjectAlreadyExists
10from chart.db.exceptions import ObjectNotFound
11
12# only show the first few characters of each SQL statement if we are executing it
13TRUNC_LINE = 80
14
15class Engine:
16 """Common code for database engines."""
17 def __init__(self):
18 self.db_conn = None
19
20 def process_sql(self, text, execute):
21 """Either display a list of SQL statements or execute them on the database.
22 `table` (str or TableInfo): Ensures the commands go to the correct engine."""
23
24 if execute:
25 cur = self.db_conn.cursor(wrapped=True)
26 for line in text:
27 logging.info(line.replace('\n', ' ').replace('\t', ' ')[:TRUNC_LINE])
28
29 try:
30 self.db_conn.begin()
31 cur.execute(line)
32 self.db_conn.commit() # postgresql needs this, oracle ignores it
33
34 except ObjectAlreadyExists as e:
35 logging.warning(e)
36
37 except ObjectNotFound as e:
38 logging.warning(e)
39
40 except DatabaseError:
41 # except StandardError:
42 self.db_conn.rollback()
43 _, exc_value, _ = sys.exc_info()
44 # just report warnings for table/index already exists
45 # This should use our ObjectAlreadyExists class instead
46 error = str(exc_value).strip()
47 # if (line.startswith('CREATE UNIQUE INDEX')) and
48 # index_exists(error)) or
49 # (line.startswith('ALTER TABLE') and primary_key_exists(error)) or
50 # (line.startswith('CREATE TRIGGER') and trigger_exists(error))):
51
52 # logging.warning(error)
53
54 # else:
55 logging.error(error)
56
57 # except Exception as e:
58 # print(type(e))
59 # raise
60
61 else:
62 for line in text:
63 if line.endswith(';'):
64 print(line)
65
66 else:
67 print(line + ';')
68
69 if line.startswith('CREATE OR REPLACE TRIGGER'):
70 print('/')
71
72 def post_fields(self, _):
73 """Text added to the end of the fields list but before the close bracket of
74 the table. sqlite uses it to define indexes."""
75 return ''
76
77 def sys_suffix(self):
78 """String to be added to the end of a SYS table definition, after the close brackets."""
79 return ''
80
81 def ap_partitions(self):
82 """Canned text to add the partitioning rules."""
83 return ''
84
85 def stats_partitions(self):
86 """Additional text at the end of a stats table definition."""
87 return ''
88
89 def sql_create_view(self, sql, name, source):
90 """Append to `sql` (list of str) the DDL statement(s) needed to create `viewname`.
91
92 SQL statement is given in `source`."""
93 name = self.view_name(name)
94 sql.append('CREATE OR REPLACE VIEW {view} AS {source}'.format(
95 view=name,
96 source=source))