def create_aggregate(self, name, num_args, cls): try: step_callback, final_callback = self.__aggregates[cls] except KeyError: @_ffi.callback("void(sqlite3_context*, int, sqlite3_value**)") def step_callback(context, argc, c_params): res = _lib.sqlite3_aggregate_context(context, _ffi.sizeof("size_t")) aggregate_ptr = _ffi.cast("size_t[1]", res) if not aggregate_ptr[0]: try: aggregate = cls() except Exception: msg = b"user-defined aggregate's '__init__' " b"method raised error" _lib.sqlite3_result_error(context, msg, len(msg)) return aggregate_id = id(aggregate) self.__aggregate_instances[aggregate_id] = aggregate aggregate_ptr[0] = aggregate_id else: aggregate = self.__aggregate_instances[aggregate_ptr[0]] params = _convert_params(context, argc, c_params) try: aggregate.step(*params) except Exception: msg = b"user-defined aggregate's 'step' " b"method raised error" _lib.sqlite3_result_error(context, msg, len(msg)) @_ffi.callback("void(sqlite3_context*)") def final_callback(context): res = _lib.sqlite3_aggregate_context(context, _ffi.sizeof("size_t")) aggregate_ptr = _ffi.cast("size_t[1]", res) if aggregate_ptr[0]: aggregate = self.__aggregate_instances[aggregate_ptr[0]] try: val = aggregate.finalize() except Exception: msg = b"user-defined aggregate's 'finalize' " b"method raised error" _lib.sqlite3_result_error(context, msg, len(msg)) else: _convert_result(context, val) finally: del self.__aggregate_instances[aggregate_ptr[0]] self.__aggregates[cls] = (step_callback, final_callback) if isinstance(name, unicode): name = name.encode("utf-8") ret = _lib.sqlite3_create_function( self._db, name, num_args, _lib.SQLITE_UTF8, _ffi.NULL, _ffi.NULL, step_callback, final_callback ) if ret != _lib.SQLITE_OK: raise self._get_exception(ret)
def create_function(self, name, num_args, callback): try: closure = self.__func_cache[callback] except KeyError: @_ffi.callback("void(sqlite3_context*, int, sqlite3_value**)") def closure(context, nargs, c_params): _function_callback(callback, context, nargs, c_params) self.__func_cache[callback] = closure if isinstance(name, unicode): name = name.encode('utf-8') ret = _lib.sqlite3_create_function(self._db, name, num_args, _lib.SQLITE_UTF8, _ffi.NULL, closure, _ffi.NULL, _ffi.NULL) if ret != _lib.SQLITE_OK: raise self.OperationalError("Error creating function")
def create_aggregate(self, name, num_args, cls): try: step_callback, final_callback = self.__aggregates[cls] except KeyError: @_ffi.callback("void(sqlite3_context*, int, sqlite3_value**)") def step_callback(context, argc, c_params): res = _lib.sqlite3_aggregate_context(context, _ffi.sizeof("size_t")) aggregate_ptr = _ffi.cast("size_t[1]", res) if not aggregate_ptr[0]: try: aggregate = cls() except Exception: msg = (b"user-defined aggregate's '__init__' " b"method raised error") _lib.sqlite3_result_error(context, msg, len(msg)) return aggregate_id = id(aggregate) self.__aggregate_instances[aggregate_id] = aggregate aggregate_ptr[0] = aggregate_id else: aggregate = self.__aggregate_instances[aggregate_ptr[0]] params = _convert_params(context, argc, c_params) try: aggregate.step(*params) except Exception: msg = (b"user-defined aggregate's 'step' " b"method raised error") _lib.sqlite3_result_error(context, msg, len(msg)) @_ffi.callback("void(sqlite3_context*)") def final_callback(context): res = _lib.sqlite3_aggregate_context(context, _ffi.sizeof("size_t")) aggregate_ptr = _ffi.cast("size_t[1]", res) if aggregate_ptr[0]: aggregate = self.__aggregate_instances[aggregate_ptr[0]] try: val = aggregate.finalize() except Exception: msg = (b"user-defined aggregate's 'finalize' " b"method raised error") _lib.sqlite3_result_error(context, msg, len(msg)) else: _convert_result(context, val) finally: del self.__aggregate_instances[aggregate_ptr[0]] self.__aggregates[cls] = (step_callback, final_callback) if isinstance(name, unicode): name = name.encode('utf-8') ret = _lib.sqlite3_create_function(self._db, name, num_args, _lib.SQLITE_UTF8, _ffi.NULL, _ffi.NULL, step_callback, final_callback) if ret != _lib.SQLITE_OK: raise self._get_exception(ret)