X-Git-Url: https://git.jsancho.org/?p=datasette-pytables.git;a=blobdiff_plain;f=datasette_pytables%2F__init__.py;h=50180fdc5c35c1d6ae93d817080dabd6d824ed9d;hp=9b2061890d6fe0eb03e01a425f8d7eecabdda4b0;hb=b61c78ff44e9c719615cc6955c63cb732be55847;hpb=5a6c3f4c97b3d7e598cbca4d9dfe9602cbe3406b diff --git a/datasette_pytables/__init__.py b/datasette_pytables/__init__.py index 9b20618..50180fd 100644 --- a/datasette_pytables/__init__.py +++ b/datasette_pytables/__init__.py @@ -1,4 +1,6 @@ import tables +import sqlparse +from collections import OrderedDict _connector_type = 'pytables' @@ -26,3 +28,97 @@ def inspect(path): h5file.close() return h5tables, views, _connector_type + +def _parse_sql(sql): + parsed = sqlparse.parse(sql) + stmt = parsed[0] + parsed_sql = {} + current_keyword = "" + for token in stmt.tokens: + if token.is_keyword: + if current_keyword in parsed_sql and parsed_sql[current_keyword] == '': + # Check composed keywords like 'order by' + del parsed_sql[current_keyword] + current_keyword += " " + str(token) + else: + current_keyword = str(token) + parsed_sql[current_keyword] = "" + elif type(token) is sqlparse.sql.Where: + parsed_sql['where'] = token + else: + if not token.is_whitespace: + parsed_sql[current_keyword] += str(token) + return parsed_sql + +class Connection: + def __init__(self, path): + self.path = path + self.h5file = tables.open_file(path) + + def execute(self, sql, params=None, truncate=False): + rows = [] + truncated = False + description = [] + + parsed_sql = _parse_sql(sql) + table = self.h5file.get_node(parsed_sql['from'][1:-1]) + table_rows = [] + fields = parsed_sql['select'].split(',') + + # Use 'where' statement or get all the rows + if 'where' in parsed_sql: + query = '' + start = 0 + end = table.nrows + for condition in parsed_sql['where'].get_sublists(): + if str(condition) == '"rowid"=:p0': + start = int(params['p0']) + end = start + 1 + if query: + table_rows = table.where(query, start, end) + else: + table_rows = table.iterrows(start, end) + else: + table_rows = table.iterrows() + + # Prepare rows + if len(fields) == 1 and fields[0] == 'count(*)': + rows.append(Row({fields[0]: table.nrows})) + else: + for table_row in table_rows: + row = Row() + for field in fields: + if field == 'rowid': + row[field] = table_row.nrow + elif field == '*': + for col in table.colnames: + value = table_row[col] + if type(value) is bytes: + value = value.decode('utf-8') + row[col] = value + else: + row[field] = table_row[field] + rows.append(row) + + # Prepare query description + for field in fields: + if field == '*': + for col in table.colnames: + description.append((col,)) + else: + description.append((field,)) + + if truncate: + return rows, truncated, tuple(description) + else: + return rows + +class Row(OrderedDict): + def __getitem__(self, label): + if type(label) is int: + return super(OrderedDict, self).__getitem__(list(self.keys())[label]) + else: + return super(OrderedDict, self).__getitem__(label) + + def __iter__(self): + return self.values().__iter__()