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)
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 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)
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, 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
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)
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)
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)
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_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
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)
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_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)
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
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
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
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
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
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)
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_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)
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)
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)
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)
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)
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)
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
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)
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)