dbengine.py 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. import records
  2. import re
  3. from babel.numbers import parse_decimal, NumberFormatError
  4. schema_re = re.compile(r'\((.+)\)')
  5. num_re = re.compile(r'[-+]?\d*\.\d+|\d+')
  6. agg_dict = {0:"", 1:"AVG", 2:"MAX", 3:"MIN", 4:"COUNT", 5:"SUM"}
  7. cond_op_dict = {0:">", 1:"<", 2:"==", 3:"!="}
  8. cond_rela_dict = {0:"and",1:"or",-1:""}
  9. class DBEngine:
  10. def __init__(self, fdb):
  11. self.db = records.Database('sqlite:///{}'.format(fdb))
  12. self.conn = self.db.get_connection()
  13. def execute(self, table_id, select_index, aggregation_index, conditions, condition_relation, lower=True):
  14. if not table_id.startswith('Table'):
  15. table_id = 'Table_{}'.format(table_id.replace('-', '_'))
  16. wr = ""
  17. if condition_relation == 1 or condition_relation == 0:
  18. wr = " AND "
  19. elif condition_relation == 2:
  20. wr = " OR "
  21. table_info = self.conn.query('SELECT sql from sqlite_master WHERE tbl_name = :name', name=table_id).all()[0].sql
  22. schema_str = schema_re.findall(table_info)[0]
  23. schema = {}
  24. for tup in schema_str.split(','):
  25. c, t = tup.split(' ')
  26. schema[c] = t
  27. tmp = ""
  28. for sel, agg in zip(select_index, aggregation_index):
  29. select_str = 'col_{}'.format(sel+1)
  30. agg_str = agg_dict[agg]
  31. if agg:
  32. tmp += '{}({}),'.format(agg_str, select_str)
  33. else:
  34. tmp += '({}),'.format(select_str)
  35. tmp = tmp[:-1]
  36. where_clause = []
  37. where_map = {}
  38. for col_index, op, val in conditions:
  39. if lower and (isinstance(val, str) or isinstance(val, str)):
  40. val = val.lower()
  41. if schema['col_{}'.format(col_index+1)] == 'real' and not isinstance(val, (int, float)):
  42. try:
  43. val = float(parse_decimal(val, locale='en_US'))
  44. except NumberFormatError as e:
  45. try:
  46. val = float(num_re.findall(val)[0]) # need to understand and debug this part.
  47. except:
  48. # Although column is of number, selected one is not number. Do nothing in this case.
  49. pass
  50. where_clause.append('col_{} {} :col_{}'.format(col_index+1, cond_op_dict[op], col_index+1))
  51. where_map['col_{}'.format(col_index+1)] = val
  52. where_str = ''
  53. if where_clause:
  54. where_str = 'WHERE ' + wr.join(where_clause)
  55. query = 'SELECT {} FROM {} {}'.format(tmp, table_id, where_str)
  56. out = self.conn.query(query, **where_map)
  57. return out.as_dict()