def get_db_object(session, table, exception_when_missing=True, **kwargs): """Get db object. If not exception_when_missing and the db object can not be found, return None instead of raising exception. """ if not session: raise exception.DatabaseException('session param is None') with session.begin(subtransactions=True): logging.debug( 'session %s get db object %s from table %s', id(session), kwargs, table.__name__) db_object = model_filter( model_query(session, table), table, **kwargs ).first() logging.debug( 'session %s got db object %s', id(session), db_object ) if db_object: return db_object if not exception_when_missing: return None raise exception.RecordNotExists( 'Cannot find the record in table %s: %s' % ( table.__name__, kwargs ) )
def list_db_objects(session, table, order_by=[], **filters): """List db objects. If order by given, the db objects should be sorted by the ordered keys. """ if not session: raise exception.DatabaseException('session param is None') with session.begin(subtransactions=True): logging.debug( 'session %s list db objects by filters %s in table %s', id(session), filters, table.__name__ ) db_objects = model_order_by( model_filter( model_query(session, table), table, **filters ), table, order_by ).all() logging.debug( 'session %s got listed db objects: %s', id(session), db_objects ) return db_objects
def model_query(session, model): """model query. Return sqlalchemy query object. """ if not issubclass(model, models.BASE): raise exception.DatabaseException("model should be sublass of BASE!") return session.query(model)
def add_db_object(session, table, exception_when_existing=True, *args, **kwargs): """Create db object. If not exception_when_existing and the db object exists, Instead of raising exception, updating the existing db object. """ if not session: raise exception.DatabaseException('session param is None') with session.begin(subtransactions=True): logging.debug( 'session %s add object %s atributes %s to table %s', id(session), args, kwargs, table.__name__) argspec = inspect.getargspec(table.__init__) arg_names = argspec.args[1:] arg_defaults = argspec.defaults if not arg_defaults: arg_defaults = [] if not ( len(arg_names) - len(arg_defaults) <= len(args) <= len(arg_names) ): raise exception.InvalidParameter( 'arg names %s does not match arg values %s' % ( arg_names, args) ) db_keys = dict(zip(arg_names, args)) if db_keys: db_object = session.query(table).filter_by(**db_keys).first() else: db_object = None new_object = False if db_object: logging.debug( 'got db object %s: %s', db_keys, db_object ) if exception_when_existing: raise exception.DuplicatedRecord( '%s exists in table %s' % (db_keys, table.__name__) ) else: db_object = table(**db_keys) new_object = True for key, value in kwargs.items(): setattr(db_object, key, value) if new_object: session.add(db_object) session.flush() db_object.initialize() db_object.validate() logging.debug( 'session %s db object %s added', id(session), db_object ) return db_object
def del_db_object(session, db_object): """Delete db object.""" if not session: raise exception.DatabaseException('session param is None') with session.begin(subtransactions=True): logging.debug('session %s delete db object %s', id(session), db_object) session.delete(db_object) logging.debug('session %s db object %s deleted', id(session), db_object) return db_object
def wrapper(*args, **kwargs): user = kwargs.get('user') if user is not None: session = kwargs.get('session') if session is None: raise exception.DatabaseException( 'wrapper check_user_permission does not run in session' ) _check_user_permission(user, permission, session=session) return func(*args, **kwargs) else: return func(*args, **kwargs)
def del_db_objects(session, table, **filters): """delete db objects.""" if not session: raise exception.DatabaseException('session param is None') with session.begin(subtransactions=True): logging.debug('session %s delete db objects by filters %s in table %s', id(session), filters, table.__name__) query = model_filter(model_query(session, table), table, **filters) db_objects = query.all() query.delete(synchronize_session=False) logging.debug('session %s db objects %s deleted', id(session), db_objects) return db_objects
def update_db_object(session, db_object, **kwargs): """Update db object.""" if not session: raise exception.DatabaseException('session param is None') with session.begin(subtransactions=True): logging.debug('session %s update db object %s by value %s', id(session), db_object, kwargs) for key, value in kwargs.items(): setattr(db_object, key, value) session.flush() db_object.update() db_object.validate() logging.debug('session %s db object %s updated', id(session), db_object) return db_object
def update_db_objects(session, table, updates={}, **filters): """Update db objects.""" if not session: raise exception.DatabaseException('session param is None') with session.begin(subtransactions=True): logging.debug('session %s update db objects by filters %s in table %s', id(session), filters, table.__name__) db_objects = model_filter(model_query(session, table), table, **filters).all() for db_object in db_objects: logging.debug('update db object %s: %s', db_object, updates) update_db_object(session, db_object, **updates) logging.debug('session %s db objects %s updated', id(session), db_objects) return db_objects
def current_session(): """Get the current session scope when it is called. :return: database session. :raises: DatabaseException when it is not in session. """ try: return SESSION_HOLDER.session except Exception as error: logging.error('It is not in the session scope') logging.exception(error) if isinstance(error, exception.DatabaseException): raise error else: raise exception.DatabaseException(str(error))
def wrapper(user_id, *args, **kwargs): user = kwargs.get('user') if user is not None: session = kwargs.get('session') if session is None: raise exception.DatabaseException( 'wrapper check_user_admin_or_owner is ' 'not called in session') check_user = _get_user(user_id, session=session) if not user.is_admin and user.id != check_user.id: raise exception.Forbidden( 'User %s is not admin or the owner of user %s.' % (user.email, check_user.email)) return func(user_id, *args, **kwargs) else: return func(user_id, *args, **kwargs)
def session(exception_when_in_session=True): """database session scope. To operate database, it should be called in database session. If not exception_when_in_session, the with session statement support nested session and only the out most session commit/rollback the transaction. """ if not ENGINE: init() nested_session = False if hasattr(SESSION_HOLDER, 'session'): if exception_when_in_session: logging.error('we are already in session') raise exception.DatabaseException('session already exist') else: new_session = SESSION_HOLDER.session nested_session = True logging.log( logsetting.getLevelByName('fine'), 'reuse session %s', nested_session ) else: new_session = SCOPED_SESSION() setattr(SESSION_HOLDER, 'session', new_session) logging.log( logsetting.getLevelByName('fine'), 'enter session %s', new_session ) try: yield new_session if not nested_session: new_session.commit() except Exception as error: if not nested_session: new_session.rollback() logging.error('failed to commit session') logging.exception(error) if isinstance(error, IntegrityError): for item in error.statement.split(): if item.islower(): object = item break raise exception.DuplicatedRecord( '%s in %s' % (error.orig, object) ) elif isinstance(error, OperationalError): raise exception.DatabaseException( 'operation error in database' ) elif isinstance(error, exception.DatabaseException): raise error else: raise exception.DatabaseException(str(error)) finally: if not nested_session: new_session.close() SCOPED_SESSION.remove() delattr(SESSION_HOLDER, 'session') logging.log( logsetting.getLevelByName('fine'), 'exit session %s', new_session )