Пример #1
0
    def __init__(self, columns, rows=None):

        if not isinstance(columns, ColumnSet):
            raise ProgrammingError('%s must be ColumnSet' % columns)

        if columns.empty:
            raise ProgrammingError('columns must not be empty')
        self.columns = columns
        if rows:
            self.rows = rows
            for row in self.rows:
                self._update_print_width(row)
        else:
            self.rows = []

        self._pos = 0
Пример #2
0
    def get_table_row(self, tree, pk):
        db = self._get_current_db(tree)
        table = tree.table

        if pk:
            key = "/{db}/{tbl}/{pk}".format(db=db, tbl=table, pk=pk)
            etcd_response = self.connection.client.read(key)
            full_row = json.loads(etcd_response.node['value'])
            row = ()
            for e in tree.expressions:
                field_name = e['name']
                field = None
                if e['type'] == 'function':
                    field = self._eval_function(e['name'], db=db, tbl=table)
                if e['type'] == 'variable':
                    field = self._eval_variable(e['name'])
                if e['type'] == 'field':
                    try:
                        field = full_row[field_name]
                    except KeyError:
                        raise ProgrammingError('Error: Field %s not found' %
                                               field_name)
                row += (field, )
            return row

        else:  # One row if pk is None
            row = ()
            for e in tree.expressions:
                field = None
                if e['type'] == 'function':
                    field = self._eval_function(e['name'], db=db, tbl=table)
                if e['type'] == 'variable':
                    field = self._eval_variable(e['name'])
                row += (field, )
            return row
Пример #3
0
 def __init__(self, row, etcd_index=0, modified_index=0):
     if not isinstance(row, tuple):
         raise ProgrammingError('%s must be tuple')
     self._row = row
     self._field_position = 0
     self._etcd_index = etcd_index
     self._modified_index = modified_index
Пример #4
0
    def add(self, column):
        """Add column to ColumnSet

        :param column: Column instance
        :type column: Column
        :return: Updated CoulmnSet instance
        :rtype: ColumnSet
        """
        if isinstance(column, Column):
            self._columns.append(column)
        else:
            raise ProgrammingError('%s must be Column type' % column)
        return self
Пример #5
0
def create_database(etcd_client, tree):
    """
    Create database.

    :param etcd_client: Etcd client
    :type etcd_client: Client
    :param tree: Parsing tree
    :type tree: SQLTree
    """
    try:
        etcd_client.mkdir('/%s' % tree.db)
    except EtcdNodeExist:
        raise ProgrammingError("Can't create database '%s'; database exists" %
                               tree.db)
Пример #6
0
def create_table(etcd_client, tree, db=None):
    """
    Create table.

    :param etcd_client: Etcd client
    :type etcd_client: Client
    :param tree: Parsing tree
    :type tree: SQLTree
    :param db: Database name to use if not defined in the parsing tree.
    :type db: str
    :raise ProgrammingError: If primary key is not defined,
        or the primary key is NULL-able.
    :raise OperationalError: if database is not selected or table exists.
    """
    database_exists_or_raise(etcd_client, db)

    pk_field = None
    for field_name, value in tree.fields.iteritems():
        try:
            if value['options']['primary']:
                pk_field = field_name
        except KeyError:
            pass

    if not pk_field:
        raise ProgrammingError('Primary key must be defined')

    if tree.fields[pk_field]['options']['nullable']:
        raise ProgrammingError('Primary key must be NOT NULL')

    try:
        full_table_name = '/%s/%s' % (db, tree.table)
        etcd_client.mkdir(full_table_name)
        etcd_client.write(full_table_name + "/_fields",
                          json.dumps(tree.fields))
    except EtcdNodeExist:
        raise OperationalError("Table '%s' already exists" % tree.table)
Пример #7
0
    def _execute_create_table(self, tree):
        db = self._get_current_db(tree)

        pk_field = None
        for field_name, value in tree.fields.iteritems():
            try:
                if value['options']['primary']:
                    pk_field = field_name
            except KeyError:
                pass

        if not pk_field:
            raise ProgrammingError('Primary key must be defined')

        if tree.fields[pk_field]['options']['nullable']:
            raise ProgrammingError('Primary key must be NOT NULL')

        try:
            table_name = '/%s/%s' % (db, tree.table)
            self.connection.client.mkdir(table_name)
            self.connection.client.write(table_name + "/_fields",
                                         json.dumps(tree.fields))
        except EtcdNodeExist as err:
            raise ProgrammingError("Failed to create table: %s" % err)
Пример #8
0
    def _execute_desc_table(self, tree):
        db = self._get_current_db(tree)

        table = tree.table

        key = '/{db}/{table}/_fields'.format(db=db, table=table)
        try:
            etcd_result = self.connection.client.read(key)
        except EtcdKeyNotFound:
            raise ProgrammingError(
                'Table `{db}`.`{table}` doesn\'t exist'.format(db=db,
                                                               table=table))

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

        for k, v in fields.iteritems():
            field_type = v['type']

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

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

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

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

            extra = ''
            if 'auto_increment' in v['options'] and v['options'][
                    'auto_increment']:
                extra = 'auto_increment'

            row = (k, field_type, nullable, indexes, default_value, extra)
            rows += (row, )

        return ('Field', 'Type', 'Null', 'Key', 'Default', 'Extra'), rows
Пример #9
0
def get_table_columns(etcd_client, db, tbl):
    """
    Get primary key column for table db.tbl.

    :param etcd_client: Etcd client.
    :param db: database name.
    :param tbl: table name.
    :return: Primary key column.
    :rtype: ColumnSet
    :raise ProgrammingError: if table or database doesn't exist
    """
    try:
        response = etcd_client.read('/{db}/{tbl}/_fields'.format(db=db,
                                                                 tbl=tbl))
        _fields = response.node['value']
        return ColumnSet(json.loads(_fields))
    except EtcdKeyNotFound:
        raise ProgrammingError("Table %s.%s doesn't exist" % (db, tbl))
Пример #10
0
    def execute(self, query, args=None):
        """Prepare and execute a database operation (query or command)."""

        if args:
            query %= tuple(["'%s'" % a for a in args])

        self._rows = ()

        try:
            tree = self._sql_parser.parse(query)
        except SQLParserError as err:
            raise ProgrammingError(err)

        if tree.query_type == 'SELECT':
            self._column_names, self._rows = self._execute_select(tree)
        elif tree.query_type == "USE_DATABASE":
            self._db = tree.db
        elif tree.query_type == "SHOW_DATABASES":
            self._column_names, self._rows = self._execute_show_databases()
        elif tree.query_type == "SHOW_TABLES":
            self._column_names, self._rows = self._execute_show_tables(tree)
        elif tree.query_type == "CREATE_DATABASE":
            self._execute_create_database(tree.db)
        elif tree.query_type == "DROP_DATABASE":
            self._execute_drop_database(tree.db)
        elif tree.query_type == "CREATE_TABLE":
            self._execute_create_table(tree)
        elif tree.query_type == "DESC_TABLE":
            self._column_names, self._rows = self._execute_desc_table(tree)
        elif tree.query_type == "INSERT":
            self._execute_insert(tree)
        elif tree.query_type == "UPDATE":
            return self._execute_update(tree)
        elif tree.query_type == "WAIT":
            self._column_names, self._rows = self._execute_wait(tree)

        self._col_infos = self._update_columns(self._column_names, self._rows)
        return len(self._rows)
Пример #11
0
    def execute(self, query, args=None):
        """Prepare and execute a database operation (query or command).

        :param query: Query text.
        :type query: str
        :param args: Optional query arguments.
        :type args: tuple
        :raise ProgrammingError: if query can't be parsed."""

        query = self.morgify(query, args)

        LOG.debug('Executing: %s', query)

        try:
            tree = self._sql_parser.parse(query)
        except SQLParserError as err:
            raise ProgrammingError(err)

        if not self._db:
            self._db = tree.db

        self._result_set = None
        self._rowcount = 0

        if tree.query_type == "SHOW_DATABASES":
            self._result_set = show_databases(self.connection.client)

        elif tree.query_type == "CREATE_DATABASE":
            create_database(self.connection.client, tree)

        elif tree.query_type == "DROP_DATABASE":
            drop_database(self.connection.client, tree)

        elif tree.query_type == "USE_DATABASE":
            self._db = use_database(self.connection.client, tree)

        elif tree.query_type == "CREATE_TABLE":
            create_table(self.connection.client, tree, db=self._db)

        elif tree.query_type == "DROP_TABLE":
            drop_table(self.connection.client, tree, db=self._db)

        elif tree.query_type == "SHOW_TABLES":
            self._result_set = show_tables(self.connection.client,
                                           tree,
                                           db=self._db)
        elif tree.query_type == "DESC_TABLE":
            self._result_set = desc_table(self.connection.client,
                                          tree,
                                          db=self._db)
        elif tree.query_type == "INSERT":
            self._rowcount = insert(self.connection.client, tree, db=self._db)
        elif tree.query_type == 'SELECT':
            self._result_set = execute_select(self.connection.client,
                                              tree,
                                              db=self._db)
        elif tree.query_type == 'WAIT':
            self._result_set = execute_wait(self.connection.client,
                                            tree,
                                            db=self._db)
        elif tree.query_type == "UPDATE":
            self._rowcount = execute_update(self.connection.client,
                                            tree,
                                            db=self._db)
        elif tree.query_type == "DELETE":
            self._rowcount = execute_delete(self.connection.client,
                                            tree,
                                            db=self._db)
        if self._result_set is not None:
            self._rowcount = self._result_set.n_rows
Пример #12
0
 def _execute_create_database(self, db):
     try:
         self.connection.client.mkdir('/%s' % db)
     except EtcdNodeExist as err:
         raise ProgrammingError("Failed to create database: %s" % err)
Пример #13
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