Use self.photodb.sql_ methods instead of running own cursors.
All in the name of centralization. Also improved SQLness of Tag.convert_to_synonym.
This commit is contained in:
		
							parent
							
								
									2edb9a1d57
								
							
						
					
					
						commit
						144e97d365
					
				
					 1 changed files with 90 additions and 79 deletions
				
			
		|  | @ -87,11 +87,12 @@ class GroupableMixin: | ||||||
| 
 | 
 | ||||||
|         # Groupables are only allowed to have 1 parent. |         # Groupables are only allowed to have 1 parent. | ||||||
|         # Unlike photos which can exist in multiple albums. |         # Unlike photos which can exist in multiple albums. | ||||||
|         cur = self.photodb.sql.cursor() |         parent_row = self.photodb.sql_select_one( | ||||||
|         cur.execute('SELECT parentid FROM %s WHERE memberid == ?' % self.group_table, [member.id]) |             'SELECT parentid FROM %s WHERE memberid == ?' % self.group_table, | ||||||
|         fetch = cur.fetchone() |             [member.id] | ||||||
|         if fetch is not None: |         ) | ||||||
|             parent_id = fetch[0] |         if parent_row is not None: | ||||||
|  |             parent_id = parent_row[0] | ||||||
|             if parent_id == self.id: |             if parent_id == self.id: | ||||||
|                 return |                 return | ||||||
|             that_group = self.group_getter(id=parent_id) |             that_group = self.group_getter(id=parent_id) | ||||||
|  | @ -154,37 +155,32 @@ class GroupableMixin: | ||||||
|             self.photodb.commit() |             self.photodb.commit() | ||||||
| 
 | 
 | ||||||
|     def get_children(self): |     def get_children(self): | ||||||
|         cur = self.photodb.sql.cursor() |         child_rows = self.photodb.sql_select( | ||||||
|  |             'SELECT memberid FROM %s WHERE parentid == ?' % self.group_table, | ||||||
|  |             [self.id] | ||||||
|  |         ) | ||||||
|  |         child_ids = [row[0] for row in child_rows] | ||||||
|  |         children = [self.group_getter(id=child_id) for child_id in child_ids] | ||||||
| 
 | 
 | ||||||
|         cur.execute('SELECT memberid FROM %s WHERE parentid == ?' % self.group_table, [self.id]) |  | ||||||
|         fetches = cur.fetchall() |  | ||||||
|         results = [] |  | ||||||
|         for fetch in fetches: |  | ||||||
|             memberid = fetch[0] |  | ||||||
|             child = self.group_getter(id=memberid) |  | ||||||
|             results.append(child) |  | ||||||
|         if isinstance(self, Tag): |         if isinstance(self, Tag): | ||||||
|             results.sort(key=lambda x: x.name) |             children.sort(key=lambda x: x.name) | ||||||
|         else: |         else: | ||||||
|             results.sort(key=lambda x: x.id) |             children.sort(key=lambda x: x.id) | ||||||
|         return results |         return children | ||||||
| 
 | 
 | ||||||
|     def get_parent(self): |     def get_parent(self): | ||||||
|         ''' |         ''' | ||||||
|         Return the group of which this is a member, or None. |         Return the group of which this is a member, or None. | ||||||
|         Returned object will be of the same type as calling object. |         Returned object will be of the same type as calling object. | ||||||
|         ''' |         ''' | ||||||
|         cur = self.photodb.sql.cursor() |         parent_row = self.photodb.sql_select_one( | ||||||
|         cur.execute( |             'SELECT parentid FROM %s WHERE memberid == ?' % self.group_table, | ||||||
|             'SELECT * FROM %s WHERE memberid == ?' % self.group_table, |  | ||||||
|             [self.id] |             [self.id] | ||||||
|         ) |         ) | ||||||
|         fetch = cur.fetchone() |         if parent_row is None: | ||||||
|         if fetch is None: |  | ||||||
|             return None |             return None | ||||||
| 
 | 
 | ||||||
|         parentid = fetch[self.group_sql_index['parentid']] |         return self.group_getter(id=parent_row[0]) | ||||||
|         return self.group_getter(id=parentid) |  | ||||||
| 
 | 
 | ||||||
|     @decorators.transaction |     @decorators.transaction | ||||||
|     def join_group(self, group, *, commit=True): |     def join_group(self, group, *, commit=True): | ||||||
|  | @ -437,12 +433,11 @@ class Album(ObjectBase, GroupableMixin): | ||||||
|             self.photodb.commit() |             self.photodb.commit() | ||||||
| 
 | 
 | ||||||
|     def get_associated_directories(self): |     def get_associated_directories(self): | ||||||
|         cur = self.photodb.sql.cursor() |         directory_rows = self.photodb.sql_select( | ||||||
|         cur.execute( |  | ||||||
|             'SELECT directory FROM album_associated_directories WHERE albumid == ?', |             'SELECT directory FROM album_associated_directories WHERE albumid == ?', | ||||||
|             [self.id] |             [self.id] | ||||||
|         ) |         ) | ||||||
|         directories = [x[0] for x in cur.fetchall()] |         directories = [x[0] for x in directory_rows] | ||||||
|         directories = [pathclass.Path(x) for x in directories] |         directories = [pathclass.Path(x) for x in directories] | ||||||
|         return directories |         return directories | ||||||
| 
 | 
 | ||||||
|  | @ -459,12 +454,12 @@ class Album(ObjectBase, GroupableMixin): | ||||||
|     def has_photo(self, photo): |     def has_photo(self, photo): | ||||||
|         if not isinstance(photo, Photo): |         if not isinstance(photo, Photo): | ||||||
|             raise TypeError('`photo` must be of type %s' % Photo) |             raise TypeError('`photo` must be of type %s' % Photo) | ||||||
|         cur = self.photodb.sql.cursor() | 
 | ||||||
|         cur.execute( |         rel_row = self.photodb.sql_select_one( | ||||||
|             'SELECT * FROM album_photo_rel WHERE albumid == ? AND photoid == ?', |             'SELECT 1 FROM album_photo_rel WHERE albumid == ? AND photoid == ?', | ||||||
|             [self.id, photo.id] |             [self.id, photo.id] | ||||||
|         ) |         ) | ||||||
|         return cur.fetchone() is not None |         return rel_row is not None | ||||||
| 
 | 
 | ||||||
|     @decorators.required_feature('album.edit') |     @decorators.required_feature('album.edit') | ||||||
|     # GroupableMixin.join_group already has @transaction. |     # GroupableMixin.join_group already has @transaction. | ||||||
|  | @ -666,9 +661,7 @@ class Photo(ObjectBase): | ||||||
|         ''' |         ''' | ||||||
|         Reload the row from the database and do __init__ with them. |         Reload the row from the database and do __init__ with them. | ||||||
|         ''' |         ''' | ||||||
|         cur = self.photodb.sql.cursor() |         row = self.photodb.sql_select_one('SELECT * FROM photos WHERE id == ?', [self.id]) | ||||||
|         cur.execute('SELECT * FROM photos WHERE id == ?', [self.id]) |  | ||||||
|         row = cur.fetchone() |  | ||||||
|         self.__init__(self.photodb, row) |         self.__init__(self.photodb, row) | ||||||
| 
 | 
 | ||||||
|     def __repr__(self): |     def __repr__(self): | ||||||
|  | @ -863,10 +856,11 @@ class Photo(ObjectBase): | ||||||
|         ''' |         ''' | ||||||
|         Return the albums of which this photo is a member. |         Return the albums of which this photo is a member. | ||||||
|         ''' |         ''' | ||||||
|         cur = self.photodb.sql.cursor() |         album_rows = self.photodb.sql_select( | ||||||
|         cur.execute('SELECT albumid FROM album_photo_rel WHERE photoid == ?', [self.id]) |             'SELECT albumid FROM album_photo_rel WHERE photoid == ?', | ||||||
|         fetches = cur.fetchall() |             [self.id] | ||||||
|         albums = [self.photodb.get_album(id=fetch[0]) for fetch in fetches] |         ) | ||||||
|  |         albums = [self.photodb.get_album(id=row[0]) for row in album_rows] | ||||||
|         return albums |         return albums | ||||||
| 
 | 
 | ||||||
|     def get_tags(self): |     def get_tags(self): | ||||||
|  | @ -891,21 +885,22 @@ class Photo(ObjectBase): | ||||||
|         tag = self.photodb.get_tag(name=tag) |         tag = self.photodb.get_tag(name=tag) | ||||||
| 
 | 
 | ||||||
|         if check_children: |         if check_children: | ||||||
|             tags = tag.walk_children() |             tag_options = tag.walk_children() | ||||||
|         else: |         else: | ||||||
|             tags = [tag] |             tag_options = [tag] | ||||||
| 
 | 
 | ||||||
|         cur = self.photodb.sql.cursor() |         tag_by_id = {t.id: t for t in tag_options} | ||||||
|         for tag in tags: |         tag_option_ids = helpers.sql_listify(tag_by_id) | ||||||
|             cur.execute( |         rel_row = self.photodb.sql_select_one( | ||||||
|                 'SELECT * FROM photo_tag_rel WHERE photoid == ? AND tagid == ?', |             'SELECT tagid FROM photo_tag_rel WHERE photoid == ? AND tagid IN %s' % tag_option_ids, | ||||||
|                 [self.id, tag.id] |             [self.id] | ||||||
|         ) |         ) | ||||||
|             if cur.fetchone() is not None: |  | ||||||
|                 return tag |  | ||||||
| 
 | 
 | ||||||
|  |         if rel_row is None: | ||||||
|             return False |             return False | ||||||
| 
 | 
 | ||||||
|  |         return tag_by_id[rel_row[0]] | ||||||
|  | 
 | ||||||
|     def make_thumbnail_filepath(self): |     def make_thumbnail_filepath(self): | ||||||
|         ''' |         ''' | ||||||
|         Create the filepath that should be the location of our thumbnail. |         Create the filepath that should be the location of our thumbnail. | ||||||
|  | @ -1247,36 +1242,51 @@ class Tag(ObjectBase, GroupableMixin): | ||||||
|         ''' |         ''' | ||||||
|         mastertag = self.photodb.get_tag(name=mastertag) |         mastertag = self.photodb.get_tag(name=mastertag) | ||||||
| 
 | 
 | ||||||
|         # Migrate the old tag's synonyms to the new one |  | ||||||
|         # UPDATE is safe for this operation because there is no chance of duplicates. |  | ||||||
|         self.photodb._cached_frozen_children = None |         self.photodb._cached_frozen_children = None | ||||||
| 
 | 
 | ||||||
|  |         # Migrate the old tag's synonyms to the new one | ||||||
|  |         # UPDATE is safe for this operation because there is no chance of duplicates. | ||||||
|         data = { |         data = { | ||||||
|             'mastername': (self.name, mastertag.name), |             'mastername': (self.name, mastertag.name), | ||||||
|         } |         } | ||||||
|         self.photodb.sql_update(table='tag_synonyms', pairs=data, where_key='mastername') |         self.photodb.sql_update(table='tag_synonyms', pairs=data, where_key='mastername') | ||||||
| 
 | 
 | ||||||
|         # Iterate over all photos with the old tag, and swap them to the new tag |         # Because these were two separate tags, perhaps in separate trees, it | ||||||
|         # if they don't already have it. |         # is possible for a photo to have both at the moment. | ||||||
|         cur = self.photodb.sql.cursor() |         # | ||||||
|         cur.execute('SELECT photoid FROM photo_tag_rel WHERE tagid == ?', [self.id]) |         # If they already have both, the deletion of the syn rel will happen | ||||||
|         fetches = cur.fetchall() |         #    when the syn tag is deleted. | ||||||
|  |         # If they only have the syn, we will UPDATE it to the master. | ||||||
|  |         # If they only have the master, nothing needs to happen. | ||||||
| 
 | 
 | ||||||
|         for fetch in fetches: |         # Find photos that have the old tag and DON'T already have the new one. | ||||||
|             photoid = fetch[0] |         query = ''' | ||||||
|             cur.execute( |         SELECT photoid FROM photo_tag_rel p1 | ||||||
|                 'SELECT * FROM photo_tag_rel WHERE photoid == ? AND tagid == ?', |         WHERE tagid == ? | ||||||
|                 [photoid, mastertag.id] |         AND NOT EXISTS ( | ||||||
|  |             SELECT 1 FROM photo_tag_rel p2 | ||||||
|  |             WHERE p1.photoid == p2.photoid | ||||||
|  |             AND tagid == ? | ||||||
|         ) |         ) | ||||||
|             if cur.fetchone() is None: |         ''' | ||||||
|                 data = { |         bindings = [self.id, mastertag.id] | ||||||
|                     'photoid': photoid, |         replace_photoids = [row[0] for row in self.photodb.sql_execute(query, bindings)] | ||||||
|                     'tagid': mastertag.id, |  | ||||||
|                 } |  | ||||||
|                 self.photodb.sql_insert(table='photo_tag_rel', data=data) |  | ||||||
| 
 | 
 | ||||||
|         # Then delete the relationships with the old tag |         # For those photos that only had the syn, simply replace with master. | ||||||
|         self.delete() |         if replace_photoids: | ||||||
|  |             query = ''' | ||||||
|  |             UPDATE photo_tag_rel | ||||||
|  |             SET tagid = ? | ||||||
|  |             WHERE tagid == ? | ||||||
|  |             AND photoid IN %s | ||||||
|  |             ''' % helpers.sql_listify(replace_photoids) | ||||||
|  |             bindings = [mastertag.id, self.id] | ||||||
|  |             self.photodb.sql_execute(query, bindings) | ||||||
|  | 
 | ||||||
|  |         # For photos that have the old tag and DO already have the new one, | ||||||
|  |         # don't worry because the old rels will be deleted when the tag is | ||||||
|  |         # deleted. | ||||||
|  |         self.delete(commit=False) | ||||||
| 
 | 
 | ||||||
|         # Enjoy your new life as a monk. |         # Enjoy your new life as a monk. | ||||||
|         mastertag.add_synonym(self.name, commit=False) |         mastertag.add_synonym(self.name, commit=False) | ||||||
|  | @ -1321,11 +1331,13 @@ class Tag(ObjectBase, GroupableMixin): | ||||||
|             self.photodb.commit() |             self.photodb.commit() | ||||||
| 
 | 
 | ||||||
|     def get_synonyms(self): |     def get_synonyms(self): | ||||||
|         cur = self.photodb.sql.cursor() |         syn_rows = self.photodb.sql_select( | ||||||
|         cur.execute('SELECT name FROM tag_synonyms WHERE mastername == ?', [self.name]) |             'SELECT name FROM tag_synonyms WHERE mastername == ?', | ||||||
|         fetches = [fetch[0] for fetch in cur.fetchall()] |             [self.name] | ||||||
|         fetches.sort() |         ) | ||||||
|         return fetches |         syn_names = [row[0] for row in syn_rows] | ||||||
|  |         syn_names.sort() | ||||||
|  |         return syn_names | ||||||
| 
 | 
 | ||||||
|     @decorators.required_feature('tag.edit') |     @decorators.required_feature('tag.edit') | ||||||
|     # GroupableMixin.join_group already has @transaction. |     # GroupableMixin.join_group already has @transaction. | ||||||
|  | @ -1384,13 +1396,12 @@ class Tag(ObjectBase, GroupableMixin): | ||||||
|         if synname == self.name: |         if synname == self.name: | ||||||
|             raise exceptions.NoSuchSynonym(synname) |             raise exceptions.NoSuchSynonym(synname) | ||||||
| 
 | 
 | ||||||
|         cur = self.photodb.sql.cursor() |         syn_exists = self.photodb.sql_select_one( | ||||||
|         cur.execute( |             'SELECT 1 FROM tag_synonyms WHERE mastername == ? AND name == ?', | ||||||
|             'SELECT * FROM tag_synonyms WHERE mastername == ? AND name == ?', |  | ||||||
|             [self.name, synname] |             [self.name, synname] | ||||||
|         ) |         ) | ||||||
|         fetch = cur.fetchone() | 
 | ||||||
|         if fetch is None: |         if syn_exists is None: | ||||||
|             raise exceptions.NoSuchSynonym(synname) |             raise exceptions.NoSuchSynonym(synname) | ||||||
| 
 | 
 | ||||||
|         self.photodb._cached_frozen_children = None |         self.photodb._cached_frozen_children = None | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue