예제 #1
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
예제 #2
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
예제 #3
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', )
예제 #4
0
def test_show_tables(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('Tables_in_foo'))

    # print(cols)

    rs = ResultSet(cols, rows)
    tree = SQLTree()
    tree.db = 'foo'
    tree.options['full'] = False
    # noinspection PyTypeChecker
    result = show_tables(etcd_client, tree, tree.db)

    print("Expected: \n%s" % rs)
    print("Actual: \n%s" % result)
    # noinspection PyTypeChecker
    assert result == rs
예제 #5
0
def execute_select(etcd_client, tree, db):
    """
    Execute SELECT 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
    """
    if not db:
        raise OperationalError('No database selected')

    if tree.table:
        tree = fix_tree_star(tree, etcd_client, db, tree.table)
        result_set = execute_select_plain(etcd_client, tree, db)
    else:
        result_set = execute_select_no_table(tree)

    if tree.limit is not None:
        result_set = ResultSet(result_set.columns, result_set[:tree.limit])

    return result_set
예제 #6
0
def test_fetch_many(rows, n, result, etcdb_connection):
    cursor = etcdb_connection.cursor()
    rs = ResultSet(ColumnSet().add(Column('Tables')),
                   rows
                   )
    cursor._result_set = rs

    assert cursor.fetchmany(n) == result
예제 #7
0
def test_fetch_all(rows, result, etcdb_connection):
    cursor = etcdb_connection.cursor()
    rs = ResultSet(ColumnSet().add(Column('Tables')),
                   rows
                   )
    cursor._result_set = rs

    # for i in xrange(len(result)):
    assert cursor.fetchall() == result
    assert cursor.fetchall() == ()
예제 #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
예제 #9
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
예제 #10
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
예제 #11
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])
예제 #12
0
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)

    print("Expected: \n%s" % rs)
    print("Actual: \n%s" % result)
    # noinspection PyTypeChecker
    assert result == rs
예제 #13
0
def test_n_rows(cursor):
    rs = ResultSet(ColumnSet().add(Column('foo')))
    cursor._result_set = rs
    assert cursor.n_rows == 0
예제 #14
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
예제 #15
0
        ],
        (EtcdbFunction(etcdb_count, group=True),)

    )

])
def test_eval_row(cs, row, expressions, result):
    tree = SQLTree()
    tree.expressions = expressions

    assert eval_row(cs, row, tree) == result


@pytest.mark.parametrize('rs, row, expressions, result', [
    (
        ResultSet(ColumnSet().add(Column(str(
            EtcdbFunction(etcdb_count, group=True)))), []),
        None,
        [
            (
                ('bool_primary',
                 ('predicate',
                  ('bit_expr',
                   ('simple_expr',
                    ('function_call', 'COUNT')
                    )
                   )
                  )
                 ),
                '__count'
            )
        ],
예제 #16
0
def test_etcdb_count(rows, count):
    cs = ColumnSet().add(Column('id'))
    rs = ResultSet(cs, rows)
    assert etcdb_count(rs) == count