Exemplo n.º 1
0
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
Exemplo n.º 2
0
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
Exemplo n.º 3
0
def execute_select_no_table(tree):
    """Execute SELECT that doesn't read from a table.
    SELECT VERSION() or similar."""
    result_columns = prepare_columns(tree)
    result_set = ResultSet(result_columns)

    result_row = Row(eval_row(result_columns, Row(()), tree))

    result_set.add_row(result_row)
    return result_set
Exemplo n.º 4
0
def show_tables(etcd_client, tree, db):
    """
    Execute SHOW [FULL] TABLES query#

    :param etcd_client: etcd client
    :type etcd_client: pyetcd.client.Client
    :param db: Current database
    :type db: str
    :param tree: Parse tree
    :type tree: SQLTree
    :return: ResultSet instance
    :rtype: ResultSet
    """
    columns = ColumnSet().add(Column('Tables_in_%s' % db))
    if tree.options['full']:
        columns.add(Column('Table_type'))

    result_set = ResultSet(columns)

    try:
        etcd_response = etcd_client.read('/%s' % db)
    except EtcdKeyNotFound:
        raise OperationalError('No database selected')

    try:
        for node in etcd_response.node['nodes']:
            table_name = node['key'].replace('/%s/' % db, '', 1)
            row = (table_name, )
            if tree.options['full']:
                row += ('BASE TABLE', )
            result_set.add_row(Row(row))
    except KeyError:
        pass

    return result_set
def test_eval_identifier():
    cs = ColumnSet()
    cs.add(Column('id'))
    cs.add(Column('name'))

    row = Row((5, 'aaa'))

    assert eval_identifier((cs, row), 'id')[1] == 5
    assert eval_identifier((cs, row), 'name')[1] == 'aaa'
Exemplo n.º 6
0
def test_cursor_fetchone(etcdb_connection):
    cursor = etcdb_connection.cursor()

    columns = ColumnSet().add(Column('VERSION()'))
    rs = ResultSet(columns)
    rs.add_row(Row(('2.3.7', )))
    cursor._result_set = rs

    row = cursor.fetchone()
    assert isinstance(row, tuple)
    assert row == ('2.3.7', )
Exemplo n.º 7
0
def get_row_by_primary_key(
        etcd_client,
        db,
        table,
        primary_key,  # pylint: disable=too-many-arguments
        wait=False,
        wait_index=None):
    """
    Read row from etcd by its primary key value.

    :param etcd_client:
    :type etcd_client: Client
    :param db:
    :param table:
    :param primary_key: Primary key value.
    :param wait: If True it will wait for a change in the key
    :type wait: bool
    :param wait_index: When waiting you can specify index to wait for.
    :type wait_index: int
    :return: Row
    :rtype: Row
    """
    key = "/{db}/{tbl}/{pk}".format(db=db, tbl=table, pk=primary_key)
    kwargs = {}
    if wait:
        kwargs['wait'] = True
        if wait_index:
            kwargs['waitIndex'] = wait_index
    if kwargs:
        etcd_response = etcd_client.read(key, **kwargs)
    else:
        etcd_response = etcd_client.read(key)
    row = ()
    for _, value in json.loads(etcd_response.node['value']).iteritems():
        row += (value, )

    try:
        etcd_index = etcd_response.x_etcd_index
    except AttributeError:
        etcd_index = 0
    return Row(row,
               etcd_index=etcd_index,
               modified_index=etcd_response.node['modifiedIndex'])
Exemplo n.º 8
0
def show_databases(etcd_client):
    """
    Execute SHOW [FULL] TABLES query

    :param etcd_client: etcd client
    :type etcd_client: pyetcd.client.Client
    :return: ResultSet instance
    :rtype: ResultSet
    """
    etcd_response = etcd_client.read('/')
    columns = ColumnSet().add(Column('Database'))
    result_set = ResultSet(columns)
    try:
        for node in etcd_response.node['nodes']:
            val = node['key'].lstrip('/')
            result_set.add_row(Row((val, )))

    except KeyError:
        pass
    return result_set
Exemplo n.º 9
0
def group_result_set(func, result_set, table_row, tree, pos):
    """Apply a group function to result set and return an aggregated row.

    :param func: Aggregation function.
    :type func: callable
    :param result_set: Result set to aggregate.
    :type result_set: ResultSet
    :param table_row: Table row to base aggregated row on.
    :type table_row: Row
    :param tree: Parsing tree.
    :type tree: SQLTree
    :param pos: Aggregate function position in the resulting row.
    :type pos: int
    :return: Result set with aggregated row.
    :rtype: ResultSet"""
    group_value = func(result_set)
    values = list(eval_row(result_set.columns, table_row, tree))
    values[pos] = group_value
    row = Row(tuple(values))
    return ResultSet(prepare_columns(tree), [row])
Exemplo n.º 10
0
import mock
import pytest
from pyetcd import EtcdResult, EtcdKeyNotFound

from etcdb import ProgrammingError
from etcdb.execute.dml.show import show_databases, show_tables, desc_table
from etcdb.resultset import ResultSet, ColumnSet, Column, Row
from etcdb.sqlparser.sql_tree import SQLTree


@pytest.mark.parametrize('content, rows', [(
    '{"action":"get","node":{"dir":true,"nodes":[{"key":"/foo","dir":true,"modifiedIndex":2102,"createdIndex":2102},{"key":"/bar","dir":true,"modifiedIndex":2152,"createdIndex":2152}]}}',
    [Row(('foo', )), Row(
        ('bar', ))]), ('{"action":"get","node":{"dir":true}}', [])])
def test_show_databases(content, rows):

    response = mock.Mock()
    response.content = content
    etcd_response = EtcdResult(response)

    etcd_client = mock.Mock()
    etcd_client.read.return_value = etcd_response

    cols = ColumnSet()
    cols.add(Column('Database'))

    # print(cols)

    rs = ResultSet(cols, rows)
    # noinspection PyTypeChecker
    result = show_databases(etcd_client)
Exemplo n.º 11
0
def desc_table(etcd_client, tree, db):
    """
    Execute DESC table query#

    :param etcd_client: etcd client
    :type etcd_client: pyetcd.client.Client
    :param tree: Parse tree
    :type tree: SQLTree
    :param db: Current database
    :type db: str
    :return: ResultSet instance
    :rtype: ResultSet
    """
    key = '/{db}/{table}/_fields'.format(db=db, table=tree.table)
    try:
        etcd_result = etcd_client.read(key)
    except EtcdKeyNotFound:
        raise ProgrammingError('Table `{db}`.`{table}` '
                               'doesn\'t exist'.format(db=db,
                                                       table=tree.table))
    columns = ColumnSet()
    columns.add(Column('Field'))
    columns.add(Column('Type'))
    columns.add(Column('Null'))
    columns.add(Column('Key'))
    columns.add(Column('Default'))
    columns.add(Column('Extra'))

    result_set = ResultSet(columns)

    fields = json.loads(etcd_result.node['value'])

    for key, value in fields.iteritems():
        field_type = value['type']

        if value['options']['nullable']:
            nullable = 'YES'
        else:
            nullable = 'NO'

        indexes = ''
        if 'primary' in value['options'] and value['options']['primary']:
            indexes = 'PRI'

        if 'unique' in value['options'] and value['options']['unique']:
            indexes = 'UNI'

        try:
            default_value = value['options']['default']
        except KeyError:
            default_value = ''

        extra = ''
        if 'auto_increment' in value['options'] \
                and value['options']['auto_increment']:
            extra = 'auto_increment'

        result_set.add_row(
            Row((key, field_type, nullable, indexes, default_value, extra)))

    return result_set
Exemplo n.º 12
0
        ColumnSet().add(Column('id')).add(Column('COUNT(*)'))
    )
])
def test_prepare_columns(expressions, cs):
    tree = SQLTree()
    tree.expressions = expressions
    actual_cs = prepare_columns(tree)
    print('Expected: %s' % cs)
    print('Actual: %s' % actual_cs)
    assert actual_cs == cs


@pytest.mark.parametrize('cs, row, expressions, result', [
    (
        ColumnSet().add(Column('id')).add(Column('name')),
        Row((1, 'aaa')),
        [
            (
                ('bool_primary',
                 ('predicate',
                  ('bit_expr',
                   ('simple_expr',
                    ('IDENTIFIER', 'id')
                    )
                   )
                  )
                 ),
                None),
            (
                ('bool_primary',
                 ('predicate',
Exemplo n.º 13
0
    rows = ()
    while True:
        row = cursor.fetchone()
        if row:
            assert isinstance(row, tuple)
            rows += (row, )
        else:
            break
    assert result == rows


@pytest.mark.parametrize('rows, result', [
    (
        [
            Row(('information_schema',)),
            Row(('mysql',)),
            Row(('performance_schema',)),
            Row(('sys',)),
            Row(('test',))
        ],
        (
            ('information_schema',),
            ('mysql',),
            ('performance_schema',),
            ('sys',),
            ('test',)
        ),
    ),
    (
        [],
Exemplo n.º 14
0
import pytest

from etcdb.eval_expr import etcdb_count, eval_expr
from etcdb.resultset import ResultSet, ColumnSet, Column, Row
from etcdb.sqlparser.sql_tree import SQLTree


@pytest.mark.parametrize('rows, count', [([], 0), (None, 0), ([Row(
    ('1', ))], 1), ([
        Row(('1', )),
        Row(('2', )),
        Row(('3', )),
    ], 3)])
def test_etcdb_count(rows, count):
    cs = ColumnSet().add(Column('id'))
    rs = ResultSet(cs, rows)
    assert etcdb_count(rs) == count


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')]