Пример #1
0
    def extract(rcol: monetdbe_column,
                r: int,
                text_factory: Optional[Callable[[str], Any]] = None):
        """
        Extracts values from a monetdbe_column.

        The text_factory is optional, and wraps the value with a custom user supplied text function.
        """

        type_info = monet_c_type_map[rcol.type]
        col = ffi.cast(f"monetdbe_column_{type_info.c_string_type} *", rcol)
        if col.is_null(col.data + r):
            return None
        else:
            col_data = col.data[r]
            if rcol.sql_type.name != ffi.NULL and ffi.string(
                    rcol.sql_type.name).decode() == 'decimal':
                col_data = Decimal(col_data) / (Decimal(10)**
                                                rcol.sql_type.scale)
            if type_info.py_converter:
                result = type_info.py_converter(col_data)
                if rcol.type == lib.monetdbe_str and text_factory:
                    return text_factory(result)
                return result
            return col_data
Пример #2
0
    def open(self):

        if not self.dbdir:
            url = ffi.NULL
        else:
            url = str(self.dbdir).encode()

        p_connection = ffi.new("monetdbe_database *")

        p_options = ffi.new("monetdbe_options *")
        p_options.memorylimit = self.memorylimit
        p_options.querytimeout = self.querytimeout
        p_options.sessiontimeout = self.sessiontimeout
        p_options.nr_threads = self.nr_threads

        result_code = lib.monetdbe_open(p_connection, url, p_options)
        connection = p_connection[0]

        errors = {
            0: "OK",
            -1: "Allocation failed",
            -2: "Error in DB",
        }

        if result_code:
            if result_code == -2:
                error = ffi.string(lib.monetdbe_error(connection)).decode()
                lib.monetdbe_close(connection)
            else:
                error = errors.get(result_code, "unknown error")
            raise exceptions.OperationalError(
                f"Failed to open database: {error} (code {result_code})")

        return connection
Пример #3
0
def check_error(raw: char_p) -> None:
    """
    Raises:
         exceptions.Error: or subclass in case of error, which exception depends on the error type.
    """
    if not raw:
        return

    decoded = ffi.string(raw).decode()
    _logger.error(decoded)
    match = error_matcher.match(decoded)

    if not match:
        for error_code, other_matcher in other_matchers:
            other_match = other_matcher.match(decoded)
            if other_match:
                exception = errors[error_code]
                msg = other_match.groups()[0]
                break
        else:
            # the error string is in an unknown format
            exception = exceptions.DatabaseError
            msg = decoded
    else:
        _, _, code, msg = match.groups()
        exception = errors.get(code, exceptions.DatabaseError)

    raise exception(msg)
Пример #4
0
    def get_columns(self, table: str, schema: str = 'sys') -> Iterator[Tuple[str, int]]:
        count_p = ffi.new('size_t *')
        names_p = ffi.new('char ***')
        types_p = ffi.new('int **')

        lib.monetdbe_get_columns(self._connection, schema.encode(), table.encode(), count_p, names_p, types_p)

        for i in range(count_p[0]):
            name = ffi.string(names_p[0][i]).decode()
            type_ = types_p[0][i]
            yield name, type_
Пример #5
0
    def get_columns(self,
                    table: str,
                    schema: str = 'sys') -> Iterator[Tuple[str, int]]:
        self._switch()
        count_p = ffi.new('size_t*')
        columns_p = ffi.new('monetdbe_column**')

        lib.monetdbe_get_columns(self._monetdbe_database, schema.encode(),
                                 table.encode(), count_p, columns_p)

        for i in range(count_p[0]):
            name = ffi.string(columns_p[0][i].name).decode()
            type_ = columns_p[0][i].type
            yield name, type_
Пример #6
0
def check_error(msg: ffi.CData) -> None:
    """
    Raises:
         exceptions.Error: or subclass in case of error, which exception depends on the error type.
    """
    if msg:
        decoded = ffi.string(msg).decode()
        _logger.error(decoded)
        match = error_match.match(decoded)

        if not match:
            raise exceptions.OperationalError(decoded)

        _, _, error, msg = match.groups()

        if error not in errors:
            ...

        exception = errors.get(error, exceptions.DatabaseError)
        raise exception(msg)
Пример #7
0
def make_blob(blob: ffi.CData) -> str:
    if blob:
        return ffi.string(blob.data[0:blob.size])
    else:
        return ""
Пример #8
0
def make_string(blob: ffi.CData) -> str:
    if blob:
        return ffi.string(blob).decode()
    else:
        return ""
Пример #9
0
def make_string(blob: char_p) -> str:
    if blob:
        return ffi.string(blob).decode()
    else:
        return ""
Пример #10
0
def version() -> str:
    return ffi.string(lib.monetdbe_version()).decode()