def execute_update(etcd_client, tree, db): """Execute UPDATE query""" affected_rows = 0 table_columns = get_table_columns(etcd_client, db, tree.table) for primary_key in list_table(etcd_client, db, tree.table): table_row = get_row_by_primary_key(etcd_client, db, tree.table, primary_key) key = '/{db}/{tbl}/{pk}'.format(db=db, tbl=tree.table, pk=primary_key) row = {} for column in table_columns: index = table_columns.index(column) row[str(column)] = table_row[index] for update_fields in tree.expressions: field_name, field_expression = update_fields field_value = eval_expr(table_row, field_expression) # print('Update %s with %s' % (field_name, field_value[1])) row[field_name] = field_value[1] if tree.where: if eval_expr((table_columns, table_row), tree.where)[1]: _update_key(etcd_client, key, json.dumps(row)) affected_rows += 1 else: _update_key(etcd_client, key, json.dumps(row)) affected_rows += 1 return affected_rows
def execute_select_plain(etcd_client, tree, db): """Execute SELECT that reads rows from table.""" result_columns = prepare_columns(tree) result_set = ResultSet(result_columns) table_columns = get_table_columns(etcd_client, db, tree.table) last_row = None for primary_key in list_table(etcd_client, db, tree.table): table_row = get_row_by_primary_key(etcd_client, db, tree.table, primary_key) if tree.where: expr = tree.where if eval_expr((table_columns, table_row), expr)[1]: row = Row(eval_row(table_columns, table_row, tree), etcd_index=table_row.etcd_index, modified_index=table_row.modified_index) result_set.add_row(row) last_row = table_row else: row = Row(eval_row(table_columns, table_row, tree), etcd_index=table_row.etcd_index, modified_index=table_row.modified_index) result_set.add_row(row) last_row = table_row g_function, pos = group_function(table_columns, last_row, tree) if g_function: result_set = group_result_set(g_function, result_set, last_row, tree, pos) return result_set
def execute_wait(etcd_client, tree, db): """Execute WAIT. :param etcd_client: Etcd client. :type etcd_client: Client :param tree: Parsing tree. :type tree: SQLTree :param db: Current database. :type db: str """ result_columns = prepare_columns(tree) result_set = ResultSet(result_columns) table_columns = get_table_columns(etcd_client, db, tree.table) for primary_key in list_table(etcd_client, db, tree.table): table_row = get_row_by_primary_key(etcd_client, db, tree.table, primary_key) etcd_index = table_row.etcd_index if tree.where: expr = tree.where try: wait_index = tree.options['after'] except KeyError: wait_index = etcd_index + 1 if eval_expr((table_columns, table_row), expr)[1]: start = time.time() while True: if time.time() > start + WAIT_WAIT_TIMEOUT: raise InternalError('Wait timeout %d ' 'seconds expired' % WAIT_WAIT_TIMEOUT) try: new_row = get_row_by_primary_key(etcd_client, db, tree.table, primary_key, wait=True, wait_index=wait_index) break except KeyError: wait_index += 1 row = Row(eval_row(table_columns, new_row, tree), etcd_index=new_row.etcd_index, modified_index=new_row.modified_index) result_set.add_row(row) else: row = Row(eval_row(table_columns, table_row, tree), etcd_index=etcd_index, modified_index=etcd_index) result_set.add_row(row) return result_set
def test_expr_in_simple_expr(): tree = SQLTree() tree.expressions = [(('bool_primary', ('predicate', ('bit_expr', ('simple_expr', ('expr', ('bool_primary', ('predicate', ('bit_expr', ('simple_expr', ('literal', '1')))))))))), 'a')] assert eval_expr(None, tree.expressions[0][0]) == ('1', '1')
def _execute_select(self, tree): db = self._get_current_db(tree) tbl = tree.table rows = () columns = () lock_id = self._get_read_lock(db, tbl) try: function_exists = False variable_exists = False for expression in tree.expressions: columns += (expression['name'], ) if expression['type'] == 'function': function_exists = True if expression['type'] == 'variable': variable_exists = True result_keys = self._get_pks(db, tbl, tree) if function_exists or variable_exists: result_keys.append(None) for pk in result_keys: row = self.get_table_row(tree, pk) if tree.where: if eval_expr((columns, row), tree.where): rows += (row, ) else: rows += (row, ) if tree.order['by'] and tree.order['by'] in columns: pos = columns.index(tree.order['by']) def getKey(item): return item[pos] reverse = False if tree.order['direction'] == 'DESC': reverse = True rows = sorted(rows, reverse=reverse, key=getKey) if tree and tree.limit is not None: rows = rows[:tree.limit] return columns, rows finally: self._release_read_lock(db, tbl, lock_id)
def prepare_columns(tree): """ Generate ColumnSet for query result. ColumnsSet doesn't include a grouping function. :return: Columns of the query result. :rtype: ColumnSet """ columns = ColumnSet() for select_item in tree.expressions: expr, alias = select_item colname, _ = eval_expr(None, tree=expr) if alias: colname = alias columns.add(Column(colname)) return columns
def execute_delete(etcd_client, tree, db): """Execute DELETE query""" affected_rows = 0 table_columns = get_table_columns(etcd_client, db, tree.table) for primary_key in list_table(etcd_client, db, tree.table): table_row = get_row_by_primary_key(etcd_client, db, tree.table, primary_key) key = "/{db}/{tbl}/{pk}".format(db=db, tbl=tree.table, pk=primary_key) if tree.where: expr = tree.where if eval_expr((table_columns, table_row), expr)[1]: _delete_key(etcd_client, key) affected_rows += 1 else: _delete_key(etcd_client, key) affected_rows += 1 return affected_rows
def group_function(table_columns, table_row, tree): """True if resultset should be grouped :return: Grouping function or None and its position. :rtype: tuple(EtcdbFunction, int)""" try: group_position = 0 for select_item in tree.expressions: expr = select_item[0] expr_value = eval_expr((table_columns, table_row), tree=expr)[1] if isinstance(expr_value, EtcdbFunction): if expr_value.group: return expr_value, group_position group_position += 1 return None, None except TypeError: return None, None
def eval_row(table_columns, table_row, tree): """Find values of a row. table_columns are fields in the table. The result columns is taken from tree.expressions. :param table_columns: Columns in the table row. :type table_columns: ColumnSet :param table_row: Input row. :type table_row: Row :param tree: Parsing tree. :type tree: SQLTree """ result_row = () for select_item in tree.expressions: expr = select_item[0] expr_value = eval_expr((table_columns, table_row), tree=expr)[1] if isinstance(expr_value, EtcdbFunction) and not expr_value.group: expr_value = expr_value() result_row += (expr_value, ) return result_row