예제 #1
0
    def add(self, tag):
        self.logger.debug('add(): %s', repr(tag))

        # Need to give a tag, but it cannot have an ID
        if not isinstance(tag, Tag):
            raise ObjectCubeException('Function requires valid Tag')
        if tag.id is not None:
            raise ObjectCubeException('Function must not get Tag id')

        # Build the SQL expression, starting with required attributes
        sql_attributes = 'VALUE, DESCRIPTION, TYPE, MUTABLE'
        sql_values = '%s, %s, %s, %s'
        params = (tag.value, tag.description, tag.type, tag.mutable)

        # Build the SQL expression, continuing with optional attributes
        if tag.concept_id is not None:
            sql_attributes += ', CONCEPT_ID'
            sql_values += ',%s'
            params += (tag.concept_id,)
        if tag.plugin_id is not None:
            sql_attributes += ', PLUGIN_ID'
            sql_values += ',%s'
            params += (tag.plugin_id,)

        sql = 'INSERT INTO TAGS (' + \
              sql_attributes + \
              ') VALUES (' \
              + sql_values + \
              ') RETURNING *'
        return execute_sql_fetch_single(Tag, sql, params)
예제 #2
0
    def add(self, tagging):
        self.logger.debug('add(): %s ', repr(tagging))

        if not isinstance(tagging, Tagging):
            raise ObjectCubeException('Function requires valid tagging')
        if tagging.id is not None:
            raise ObjectCubeException('Function must not get Tagging id')
        if tagging.plugin_set_id and not tagging.plugin_id:
            raise ObjectCubeException('Cannot have plugin set w/o plugin')

        # Build the SQL expression, starting with required attributes
        sql_attributes = 'TAG_ID, OBJECT_ID'
        sql_values = '%s, %s'
        params = (tagging.tag_id, tagging.object_id)

        # Build the SQL expression, continuing with optional attributes
        if tagging.meta:
            sql_attributes += ', META'
            sql_values += ', %s'
            params += (tagging.meta, )
        if tagging.plugin_id:
            sql_attributes += ', PLUGIN_ID'
            sql_values += ',%s'
            params += (tagging.plugin_id, )
        if tagging.plugin_set_id:
            sql_attributes += ', PLUGIN_SET_ID'
            sql_values += ',%s'
            params += (tagging.plugin_set_id, )

        sql = 'INSERT INTO TAGGINGS (' + \
              sql_attributes + \
              ') VALUES (' \
              + sql_values + \
              ') RETURNING *'
        return execute_sql_fetch_single(Tagging, sql, params)
예제 #3
0
    def update(self, tagging):
        self.logger.debug('update(): %s', repr(tagging))

        if not isinstance(tagging, Tagging):
            raise ObjectCubeException('Function requires valid tagging')
        if not tagging.id:
            raise ObjectCubeException('Function requires valid id')

        # Get the old tag to verify that it exists,
        # and then run some business logic checks
        old = self.retrieve_by_id(tagging.id)
        if not old:
            raise ObjectCubeException('No Tag found to update')
        if tagging.tag_id != old.tag_id \
                or tagging.object_id != old.object_id \
                or tagging.plugin_id != old.plugin_id \
                or tagging.plugin_set_id != old.plugin_set_id:
            raise ObjectCubeException('Can only update meta')

        if tagging.meta:
            sql = 'UPDATE TAGGINGS ' \
                  'SET META = %s ' \
                  'WHERE ID = %s ' \
                  'RETURNING *'
            params = (tagging.meta, tagging.id)
        else:
            sql = 'UPDATE TAGGINGS ' \
                  'SET META = NULL ' \
                  'WHERE ID = %s ' \
                  'RETURNING *'
            params = (tagging.id, )
        return execute_sql_fetch_single(Tagging, sql, params)
예제 #4
0
    def update_or_create(self, root):
        self.logger.debug('replace_or_create_dimension(): %s', repr(root))

        if not isinstance(root, DimensionNode):
            raise ObjectCubeException('Function requires valid root')

        # Make the tree correct, this checks the structure
        # If the structure is not ok, then an exception is raised
        # which can safely be passed to the caller
        self._calculate_borders(root)

        # Retrieve the old tree, if it exists, for safekeeping, then delete it
        old_tree = self.retrieve_dimension(root)
        if old_tree:
            self._delete_all(old_tree)

        # Then we write the new tree
        # If it fails then we reinstall the old tree and raise exception
        # Otherwise return the new tree and be happy :)
        try:
            self._write_nodes(root)
        except:
            self._delete_all(root)
            self._write_nodes(old_tree)
            raise ObjectCubeException('Could not replace with illegal tree')

        # Return the result
        return self.retrieve_dimension(root)
예제 #5
0
    def resolve(self, tagging):
        self.logger.debug('resolve(): %s', repr(tagging))

        if not isinstance(tagging, Tagging):
            raise ObjectCubeException('Function requires valid Tagging')
        if not tagging.plugin_set_id:
            raise ObjectCubeException('Function requires valid plugin set id')

        if tagging.id:
            db_tagging = self.update(tagging)
        else:
            db_tagging = self.add(tagging)

        # Delete all the other ones in the set
        # It is possible that this deletes nothing, which is OK
        # This could happen, for example, when confirming a tagging
        # without alternatives
        sql = 'DELETE ' \
              'FROM TAGGINGS ' \
              'WHERE PLUGIN_SET_ID = %s ' \
              '  AND NOT ID = %s ' \
              'RETURNING *'
        params = (db_tagging.plugin_set_id, db_tagging.id)
        execute_sql_fetch_single(Tagging, sql, params)
        return db_tagging
예제 #6
0
    def delete(self, root):
        self.logger.debug('delete(): %s', repr(root))

        if not isinstance(root, DimensionNode):
            raise ObjectCubeException('Function requires valid root node')

        if not self._read_tree(root):
            raise ObjectCubeException('No dimension found to delete')

        self._delete_all(root)
        return None
예제 #7
0
    def add(self, concept):
        self.logger.debug('add(): %s', repr(concept))

        if not isinstance(concept, Concept):
            raise ObjectCubeException('Function requires valid concept')
        if concept.id is not None:
            raise ObjectCubeException('Function must not get id')

        sql = 'INSERT INTO ' \
              'CONCEPTS (TITLE, DESCRIPTION) ' \
              'VALUES (%s, %s) ' \
              'RETURNING *'
        params = (concept.title, concept.description)
        return execute_sql_fetch_single(Concept, sql, params)
예제 #8
0
    def add(self, object_):
        self.logger.debug('add(): %s', repr(object_))

        if not isinstance(object_, Object):
            raise ObjectCubeException('Function requires valid Object')
        if object_.id is not None:
            raise ObjectCubeException('Function must not get id')

        sql = 'INSERT ' \
              'INTO OBJECTS (NAME, DIGEST) ' \
              'VALUES (%s, %s) ' \
              'RETURNING *'
        params = (object_.name, object_.digest)
        return execute_sql_fetch_single(Object, sql, params)
예제 #9
0
    def add(self, plugin):
        self.logger.debug('add(): %s', repr(plugin))

        if not isinstance(plugin, Plugin):
            raise ObjectCubeException('Function requires valid plugin')
        if plugin.id is not None:
            raise ObjectCubeException('Function must not get id')

        sql = 'INSERT ' \
              'INTO PLUGINS (NAME, MODULE) ' \
              'VALUES (%s, %s) ' \
              'RETURNING *'
        params = (plugin.name, plugin.module)
        return execute_sql_fetch_single(Plugin, sql, params)
예제 #10
0
    def delete_by_id(self, id_):
        self.logger.debug('delete_by_id(): %s', repr(id_))

        if not isinstance(id_, LongType):
            raise ObjectCubeException('Function requires valid id')

        sql = 'DELETE FROM TAGGINGS ' \
              'WHERE ID = %s' \
              'RETURNING *'
        params = (id_, )
        db_tagging = execute_sql_fetch_single(Tagging, sql, params)

        if not db_tagging:
            raise ObjectCubeException('No Tagging found to delete')
        return None
예제 #11
0
    def delete_by_id(self, id_):
        self.logger.debug('delete_by_id(): %s', repr(id_))

        if not isinstance(id_, LongType):
            raise ObjectCubeException('Function requires valid id')

        sql = 'DELETE ' \
              'FROM CONCEPTS ' \
              'WHERE ID = %s ' \
              'RETURNING *'
        params = (id_, )
        db_concept = execute_sql_fetch_single(Concept, sql, params)

        if not db_concept:
            raise ObjectCubeException('No Concept found to delete')
        return None
예제 #12
0
    def retrieve_dimension(self, root):
        self.logger.debug('retrieve_dimension(): %s', repr(root))

        if not isinstance(root, DimensionNode):
            raise ObjectCubeException('Function requires valid root node')

        return self._read_tree(root)
예제 #13
0
    def delete_by_set_id(self, plugin_set_id):
        self.logger.debug('delete_by_set_id(): %s', repr(plugin_set_id))

        if not isinstance(plugin_set_id, LongType):
            raise ObjectCubeException('Function requires valid plugin set id')

        sql = 'DELETE ' \
              'FROM TAGGINGS ' \
              'WHERE PLUGIN_SET_ID = %s ' \
              'RETURNING *'
        params = (plugin_set_id, )
        db_tagging = execute_sql_fetch_single(Tagging, sql, params)

        if not db_tagging:
            raise ObjectCubeException('No Tagging found to delete')
        return None
예제 #14
0
    def retrieve_roots_by_tag_id(self, tag_id):
        self.logger.debug('retrieve_dimension_roots_by_tag(): %s',
                          repr(tag_id))

        if not isinstance(tag_id, LongType):
            raise ObjectCubeException('Function requires valid Tag id')

        return self._read_roots(tag_id)
예제 #15
0
    def delete(self, object_):
        self.logger.debug('delete(): %s', repr(object_))

        if not isinstance(object_, Object):
            raise ObjectCubeException('Function requires valid Object')
        if not object_.id:
            raise ObjectCubeException('Function requires valid id')

        sql = 'DELETE ' \
              'FROM OBJECTS ' \
              'WHERE ID = %s ' \
              'RETURNING *'
        params = (object_.id, )
        db_object = execute_sql_fetch_single(Object, sql, params)

        if not db_object:
            raise ObjectCubeException('No Object found to delete')
        return None
예제 #16
0
    def update(self, object_):
        self.logger.debug('update(): %s', repr(object_))

        if not isinstance(object_, Object):
            raise ObjectCubeException('Function requires valid Object')
        if not object_.id:
            raise ObjectCubeException('Function requires valid id')

        sql = 'UPDATE OBJECTS ' \
              'SET NAME = %s, DIGEST = %s ' \
              'WHERE ID = %s ' \
              'RETURNING *'
        params = (object_.name, object_.digest, object_.id)
        db_object = execute_sql_fetch_single(Object, sql, params)

        if not db_object:
            raise ObjectCubeException('No Object found to update')
        return db_object
예제 #17
0
    def delete(self, concept):
        self.logger.debug('delete(): %s', repr(concept))

        if not isinstance(concept, Concept):
            raise ObjectCubeException('Function requires valid Concept')
        if not concept.id:
            raise ObjectCubeException('Function requires valid Concept id')

        sql = 'DELETE ' \
              'FROM CONCEPTS ' \
              'WHERE ID = %s ' \
              'RETURNING *'
        params = (concept.id, )
        db_concept = execute_sql_fetch_single(Concept, sql, params)

        if not db_concept:
            raise ObjectCubeException('No Concept found to delete')
        return None
예제 #18
0
    def update(self, concept):
        self.logger.debug('update(): %s', repr(concept))

        if not isinstance(concept, Concept):
            raise ObjectCubeException('Function requires valid Concept')
        if not concept.id:
            raise ObjectCubeException('Function requires valid Concept id')

        sql = 'UPDATE CONCEPTS ' \
              'SET TITLE=%s, DESCRIPTION=%s ' \
              'WHERE ID=%s ' \
              'RETURNING *'
        params = (concept.title, concept.description, concept.id)
        db_concept = execute_sql_fetch_single(Concept, sql, params)

        if not db_concept:
            raise ObjectCubeException('No Concept found to update')
        return db_concept
예제 #19
0
    def delete(self, tag):
        self.logger.debug('delete(): %s', repr(tag))

        if not isinstance(tag, Tag):
            raise ObjectCubeException('Function requires valid Tag')
        if not tag.id:
            raise ObjectCubeException('Function requires valid Tag id')

        sql = 'DELETE ' \
              'FROM tags ' \
              'WHERE id = %s ' \
              'RETURNING *'
        params = (tag.id,)
        db_tag = execute_sql_fetch_single(Tag, sql, params)

        if not db_tag:
            raise ObjectCubeException('No Tag found to delete')
        return None
예제 #20
0
    def retrieve_by_title(self, title):
        self.logger.debug('retrieve_or_create(): %s', repr(title))

        if not isinstance(title, UnicodeType):
            raise ObjectCubeException('Function requires valid title')

        sql = 'SELECT * ' \
              'FROM CONCEPTS ' \
              'WHERE TITLE = %s'
        params = (title, )
        return execute_sql_fetch_single(Concept, sql, params)
예제 #21
0
    def retrieve_by_id(self, id_):
        self.logger.debug('retrieve_by_id(): %s', repr(id_))

        if not isinstance(id_, LongType):
            raise ObjectCubeException('Function requires valid id')

        sql = 'SELECT * ' \
              'FROM TAGGINGS ' \
              'WHERE ID = %s'
        params = (id_, )
        return execute_sql_fetch_single(Tagging, sql, params)
예제 #22
0
    def retrieve_by_name(self, name):
        self.logger.debug('retrieve_by_name(): %s', repr(name))

        if not isinstance(name, UnicodeType):
            raise ObjectCubeException('Function requires valid name')

        sql = 'SELECT  ID, NAME, MODULE ' \
              'FROM PLUGINS ' \
              'WHERE NAME = %s'
        params = (name, )
        return execute_sql_fetch_single(Plugin, sql, params)
예제 #23
0
    def add(self, root):
        self.logger.debug('add(): %s', repr(root))

        if not isinstance(root, DimensionNode):
            raise ObjectCubeException('Function requires valid node')

        # Construct a valid tree, first in memory, then on disk
        self._calculate_borders(root)
        self._write_nodes(root)

        # Return a valid tree from disk to make sure
        return self.retrieve_dimension(root)
예제 #24
0
    def retrieve_or_create(self, tag):
        self.logger.debug('retrieve_or_create(): %s', repr(tag))

        # Need to give a tag, but cannot have ID
        if not isinstance(tag, Tag):
            raise ObjectCubeException('Function requires valid Tag')
        if tag.id is not None:
            raise ObjectCubeException('Function must not get Tag id')

        # For the retrieval part, the following are REQUIRED attributes:
        # VALUE (always set), TYPE (always set), CONCEPT_ID, PLUGIN_ID
        # We need to check their existence but the type will be correct
        if not tag.concept_id:
            raise ObjectCubeException('Function requires valid concept_id')
        if not tag.plugin_id:
            raise ObjectCubeException('Function requires valid plugin_id')

        # Try to retrieve the single tag from the database
        sql = 'SELECT * ' \
              'FROM TAGS ' \
              'WHERE VALUE = %s ' \
              '  AND TYPE = %s ' \
              '  AND CONCEPT_ID = %s ' \
              '  AND PLUGIN_ID = %s ' \
              'OFFSET %s LIMIT %s'
        params = (tag.value, tag.type, tag.concept_id, tag.plugin_id, 0L, 2L)
        tags = execute_sql_fetch_multiple(Tag, sql, params)

        # Check for duplicates, this should not happen
        if len(tags) > 1:
            raise ObjectCubeException('Panic: No plugin duplicates allowed')

        # If the single tag exists, return it
        if len(tags) == 1:
            return tags[0]

        # Tag does not exist; create it
        # Should be safe to use add() as all parameters have been checked
        # Can still give errors on foreign keys, but that is normal
        return self.add(tag)
예제 #25
0
    def retrieve_or_create(self, concept):
        self.logger.debug('retrieve_or_create(): %s', repr(concept))

        if not isinstance(concept, Concept):
            raise ObjectCubeException('Function requires valid Concept')

        # Try to retrieve a concept with the title
        db_concept = self.retrieve_by_title(concept.title)

        # If concept was found return it, otherwise add and return
        if db_concept:
            return db_concept
        else:
            return self.add(concept)
예제 #26
0
def execute_sql_fetch_multiple(value_object_class, sql, params):
    logger.debug('Execute SQL, return multiple values')
    logger.debug('SQL command: ' + repr(sql) + ' Parameters: ' + repr(params))
    try:
        with Connection() as c:
            with c.cursor(cursor_factory=NamedTupleCursor) as cursor:
                cursor.execute(sql, params)

                return_list = []
                for row in cursor.fetchall():
                    return_list.append(value_object_class(**row._asdict()))
                return return_list
    except Exception as ex:
        raise ObjectCubeException(ex.message)
예제 #27
0
def execute_sql_fetch_single(value_object_class, sql, params=()):
    logger.debug('Execute SQL, return single value')
    logger.debug('SQL command: ' + repr(sql) + ' Parameters: ' + repr(params))
    try:
        with Connection() as c:
            with c.cursor(cursor_factory=NamedTupleCursor) as cursor:
                cursor.execute(sql, params)
                row = cursor.fetchone()
                if row:
                    return value_object_class(**row._asdict())
                else:
                    return None
    except Exception as ex:
        logger.error(ex.message)
        raise ObjectCubeException(ex.message)
예제 #28
0
    def _calculate_borders(self, root_node, counter=None):
        # Input: Root node of a valid tree structure
        # Output: Nothing
        # Side effect: The left_border and right_border values
        #              are correct in the input tree.
        if counter is None:
            counter = [1L]

        root_node.left_border = counter[0]
        self.logger.debug('_calculate_borders(): %s ', repr(type(counter[0])))
        counter[0] += 1

        if root_node.child_nodes:
            for node in root_node.child_nodes:
                if not isinstance(node, DimensionNode):
                    raise ObjectCubeException('Invalid child in tree')
                self._calculate_borders(node, counter)

        root_node.right_border = counter[0]
        counter[0] += 1
예제 #29
0
    def update(self, tag):
        self.logger.debug('update(): %s', repr(tag))

        # Need to give a tag, must have ID
        if not isinstance(tag, Tag):
            raise ObjectCubeException('Function requires valid Tag')
        if not tag.id:
            raise ObjectCubeException('Function requires valid Tag id')

        # Get the old tag to verify that it exists,
        # and then run some business logic checks
        old = self.retrieve_by_id(tag.id)
        if not old:
            raise ObjectCubeException('No Tag found to update')
        if not old.mutable:
            raise ObjectCubeException('Cannot change a non-mutable concept')
        if tag.plugin_id != old.plugin_id:
            raise ObjectCubeException('Cannot change generating plugin ')
        if old.plugin_id and tag.concept_id != old.concept_id:
            raise ObjectCubeException('Cannot change plugin-generated concept')

        # Build the SQL expression for the attributes that may be changed
        params = tuple()
        attributes = []

        if tag.value != old.value:
            attributes.append('VALUE = %s')
            params += (tag.value, )

        if tag.description != old.description:
            attributes.append('DESCRIPTION = %s')
            params += (tag.description, )

        if tag.concept_id != old.concept_id:
            attributes.append('CONCEPT_ID = %s')
            params += (tag.concept_id, )

        if tag.type != old.type:
            attributes.append('TYPE = %s')
            params += (tag.type, )

        sql_attributes = ', '
        params += (tag.id, )

        sql = 'UPDATE TAGS SET ' + \
              sql_attributes.join(attributes) + \
              ' WHERE ID = %s RETURNING *'
        return execute_sql_fetch_single(Tag, sql, params)
예제 #30
0
class TaggingService(BaseTaggingService):
    def __init__(self):
        super(TaggingService, self).__init__()
        self.logger = getLogger('postgreSQL: TaggingService')

    def count(self):
        self.logger.debug('count()')
        sql = 'SELECT COUNT(1) AS count ' \
              'FROM TAGGINGS'
        return execute_sql_fetch_single(lambda count: count, sql)

    def add(self, tagging):
        self.logger.debug('add(): %s ', repr(tagging))

        if not isinstance(tagging, Tagging):
            raise ObjectCubeException('Function requires valid tagging')
        if tagging.id is not None:
            raise ObjectCubeException('Function must not get Tagging id')
        if tagging.plugin_set_id and not tagging.plugin_id:
            raise ObjectCubeException('Cannot have plugin set w/o plugin')

        # Build the SQL expression, starting with required attributes
        sql_attributes = 'TAG_ID, OBJECT_ID'
        sql_values = '%s, %s'
        params = (tagging.tag_id, tagging.object_id)

        # Build the SQL expression, continuing with optional attributes
        if tagging.meta:
            sql_attributes += ', META'
            sql_values += ', %s'
            params += (tagging.meta, )
        if tagging.plugin_id:
            sql_attributes += ', PLUGIN_ID'
            sql_values += ',%s'
            params += (tagging.plugin_id, )
        if tagging.plugin_set_id:
            sql_attributes += ', PLUGIN_SET_ID'
            sql_values += ',%s'
            params += (tagging.plugin_set_id, )

        sql = 'INSERT INTO TAGGINGS (' + \
              sql_attributes + \
              ') VALUES (' \
              + sql_values + \
              ') RETURNING *'
        return execute_sql_fetch_single(Tagging, sql, params)

    def update(self, tagging):
        self.logger.debug('update(): %s', repr(tagging))

        if not isinstance(tagging, Tagging):
            raise ObjectCubeException('Function requires valid tagging')
        if not tagging.id:
            raise ObjectCubeException('Function requires valid id')

        # Get the old tag to verify that it exists,
        # and then run some business logic checks
        old = self.retrieve_by_id(tagging.id)
        if not old:
            raise ObjectCubeException('No Tag found to update')
        if tagging.tag_id != old.tag_id \
                or tagging.object_id != old.object_id \
                or tagging.plugin_id != old.plugin_id \
                or tagging.plugin_set_id != old.plugin_set_id:
            raise ObjectCubeException('Can only update meta')

        if tagging.meta:
            sql = 'UPDATE TAGGINGS ' \
                  'SET META = %s ' \
                  'WHERE ID = %s ' \
                  'RETURNING *'
            params = (tagging.meta, tagging.id)
        else:
            sql = 'UPDATE TAGGINGS ' \
                  'SET META = NULL ' \
                  'WHERE ID = %s ' \
                  'RETURNING *'
            params = (tagging.id, )
        return execute_sql_fetch_single(Tagging, sql, params)

    def resolve(self, tagging):
        self.logger.debug('resolve(): %s', repr(tagging))

        if not isinstance(tagging, Tagging):
            raise ObjectCubeException('Function requires valid Tagging')
        if not tagging.plugin_set_id:
            raise ObjectCubeException('Function requires valid plugin set id')

        if tagging.id:
            db_tagging = self.update(tagging)
        else:
            db_tagging = self.add(tagging)

        # Delete all the other ones in the set
        # It is possible that this deletes nothing, which is OK
        # This could happen, for example, when confirming a tagging
        # without alternatives
        sql = 'DELETE ' \
              'FROM TAGGINGS ' \
              'WHERE PLUGIN_SET_ID = %s ' \
              '  AND NOT ID = %s ' \
              'RETURNING *'
        params = (db_tagging.plugin_set_id, db_tagging.id)
        execute_sql_fetch_single(Tagging, sql, params)
        return db_tagging

    def delete(self, tagging):
        self.logger.debug('delete(): %s', repr(tagging))

        if not isinstance(tagging, Tagging):
            raise ObjectCubeException('Function requires valid Tagging')
        if not tagging.id:
            raise ObjectCubeException('Function requires valid id')

        sql = 'DELETE FROM TAGGINGS ' \
              'WHERE ID = %s' \
              'RETURNING *'
        params = (tagging.id, )
        db_tagging = execute_sql_fetch_single(Tagging, sql, params)

        if not db_tagging:
            raise ObjectCubeException('No Tagging found to delete')
        return None

    def delete_by_id(self, id_):
        self.logger.debug('delete_by_id(): %s', repr(id_))

        if not isinstance(id_, LongType):
            raise ObjectCubeException('Function requires valid id')

        sql = 'DELETE FROM TAGGINGS ' \
              'WHERE ID = %s' \
              'RETURNING *'
        params = (id_, )
        db_tagging = execute_sql_fetch_single(Tagging, sql, params)

        if not db_tagging:
            raise ObjectCubeException('No Tagging found to delete')
        return None

    def delete_by_set_id(self, plugin_set_id):
        self.logger.debug('delete_by_set_id(): %s', repr(plugin_set_id))

        if not isinstance(plugin_set_id, LongType):
            raise ObjectCubeException('Function requires valid plugin set id')

        sql = 'DELETE ' \
              'FROM TAGGINGS ' \
              'WHERE PLUGIN_SET_ID = %s ' \
              'RETURNING *'
        params = (plugin_set_id, )
        db_tagging = execute_sql_fetch_single(Tagging, sql, params)

        if not db_tagging:
            raise ObjectCubeException('No Tagging found to delete')
        return None

    def retrieve_by_id(self, id_):
        self.logger.debug('retrieve_by_id(): %s', repr(id_))

        if not isinstance(id_, LongType):
            raise ObjectCubeException('Function requires valid id')

        sql = 'SELECT * ' \
              'FROM TAGGINGS ' \
              'WHERE ID = %s'
        params = (id_, )
        return execute_sql_fetch_single(Tagging, sql, params)

    def retrieve(self, offset=0L, limit=10L):
        self.logger.debug('retrieve(): %s / %s', repr(offset), repr(limit))

        if not isinstance(offset, LongType):
            raise ObjectCubeException('Function requires valid offset')
        if not isinstance(limit, LongType):
            raise ObjectCubeException('Function requires valid limit')

        sql = 'SELECT * ' \
              'FROM TAGGINGS ' \
              'OFFSET %s LIMIT %s'
        params = (offset, limit)
        return execute_sql_fetch_multiple(Tagging, sql, params)