# # The Pyrocko Developers, 21st Century # ---|P------/S----------~Lg----------
global g_icount
query_args=''' :param obj: Object providing ``tmin``, ``tmax`` and ``codes`` to be used to constrain the query. Direct arguments override those from ``obj``. :type obj: any object with attributes ``tmin``, ``tmax`` and ``codes``
:param tmin: Start time of query interval. :type tmin: timestamp
:param tmax: End time of query interval. :type tmax: timestamp
:param time: Time instant to query. Equivalent to setting ``tmin`` and ``tmax`` to the same value. :type time: timestamp
:param codes: Pattern of content codes to query. :type codes: :py:class:`tuple` of :py:class:`str` ''', file_formats=', '.join( "``'%s'``" % fmt for fmt in io.supported_formats()))
''' Database backed file selection (base class for :py:class:`~pyrocko.squirrel.base.Squirrel`).
:param database: Database instance or file path to database. :type database: :py:class:`~pyrocko.squirrel.database.Database` or :py:class:`str`
:param persistent: If given a name, create a persistent selection. :type persistent: :py:class:`str`
A selection in this context represents the list of files available to the application. Instead of using :py:class:`Selection` directly, user applications should usually use its subclass :py:class:`~pyrocko.squirrel.base.Squirrel` which adds content indices to the selection and provides high level data querying.
By default, a temporary table in the database is created to hold the names of the files in the selection. This table is only visible inside the application which created it. If a name is given to ``persistent``, a named selection is created, which is visible also in other applications using the same database.
Besides the filename references, desired content kind masks and file format indications are stored in the selection's database table to make the user choice regarding these options persistent on a per-file basis. Book-keeping on whether files are unknown, known or if modification checks are forced is handled in the selection's file-state table.
Paths of files can be added to the selection using the :py:meth:`add` method and removed with :py:meth:`remove`. :py:meth:`undig_grouped` can be used to iterate over all content known to the selection. '''
raise error.SquirrelError( 'invalid persistent selection name: %s' % persistent)
else:
''' INSERT OR IGNORE INTO persistent VALUES (?) ''', (persistent,))
'db': 'main' if self._persistent else 'temp', 'file_states': self.name + '_file_states', 'bulkinsert': self.name + '_bulkinsert'}
''' CREATE TABLE IF NOT EXISTS %(db)s.%(file_states)s ( file_id integer PRIMARY KEY, file_state integer, kind_mask integer, format text) ''')))
''' CREATE INDEX IF NOT EXISTS %(db)s.%(file_states)s_index_file_state ON %(file_states)s (file_state) '''))
else: self._conn.commit()
''' Get the database to which this selection belongs.
:returns: :py:class:`~pyrocko.squirrel.database.Database` object '''
''' Destroy the tables assoctiated with this selection. ''' 'DROP TABLE %(db)s.%(file_states)s'))
''' DELETE FROM persistent WHERE name == ? ''', (self.name[5:],))
self._delete()
self, paths, kind_mask=model.g_kind_mask_all, format='detect'):
''' Add files to the selection.
:param paths: Paths to files to be added to the selection. :type paths: iterator yielding :py:class:`str` objects
:param kind_mask: Content kinds to be added to the selection. :type kind_mask: :py:class:`int` (bit mask)
:param format: File format identifier or ``'detect'`` to enable auto-detection (available: %(file_formats)s). :type format: str '''
paths = [paths]
# short non-iterator paths: can do without temp table
''' INSERT OR IGNORE INTO files VALUES (NULL, ?, NULL, NULL, NULL) ''', ((x,) for x in paths))
''' DELETE FROM %(db)s.%(file_states)s WHERE file_id IN ( SELECT files.file_id FROM files WHERE files.path == ? ) AND kind_mask != ? OR format != ? '''), ( (path, kind_mask, format) for path in paths))
''' INSERT OR IGNORE INTO %(db)s.%(file_states)s SELECT files.file_id, 0, ?, ? FROM files WHERE files.path = ? '''), ((kind_mask, format, path) for path in paths))
''' UPDATE %(db)s.%(file_states)s SET file_state = 1 WHERE file_id IN ( SELECT files.file_id FROM files WHERE files.path == ? ) AND file_state != 0 '''), ((path,) for path in paths))
else:
''' CREATE TEMP TABLE temp.%(bulkinsert)s (path text) '''))
'INSERT INTO temp.%(bulkinsert)s VALUES (?)'), ((x,) for x in paths))
''' INSERT OR IGNORE INTO files SELECT NULL, path, NULL, NULL, NULL FROM temp.%(bulkinsert)s '''))
''' DELETE FROM %(db)s.%(file_states)s WHERE file_id IN ( SELECT files.file_id FROM temp.%(bulkinsert)s INNER JOIN files ON temp.%(bulkinsert)s.path == files.path) AND kind_mask != ? OR format != ? '''), (kind_mask, format))
''' INSERT OR IGNORE INTO %(db)s.%(file_states)s SELECT files.file_id, 0, ?, ? FROM temp.%(bulkinsert)s INNER JOIN files ON temp.%(bulkinsert)s.path == files.path '''), (kind_mask, format))
''' UPDATE %(db)s.%(file_states)s SET file_state = 1 WHERE file_id IN ( SELECT files.file_id FROM temp.%(bulkinsert)s INNER JOIN files ON temp.%(bulkinsert)s.path == files.path) AND file_state != 0 '''))
'DROP TABLE temp.%(bulkinsert)s'))
''' Remove files from the selection.
:param paths: Paths to files to be removed from the selection. :type paths: :py:class:`list` of :py:class:`str` ''' paths = [paths]
''' DELETE FROM %(db)s.%(file_states)s WHERE %(db)s.%(file_states)s.file_id IN (SELECT files.file_id FROM files WHERE files.path == ?) '''), ((path,) for path in paths))
''' Iterate over all file paths currently belonging to the selection.
:yields: File paths. '''
sql = self._sql(''' SELECT files.path FROM %(db)s.%(file_states)s INNER JOIN files ON files.file_id = %(db)s.%(file_states)s.file_id ORDER BY %(db)s.%(file_states)s.file_id ''')
for values in self._conn.execute(sql): yield values[0]
''' Get all file paths currently belonging to the selection.
:returns: List of file paths. ''' return list(self.iter_paths())
''' Set file states to "known" (2). ''' ''' UPDATE %(db)s.%(file_states)s SET file_state = 2 WHERE file_state < 2 '''))
''' Set file states to "request force check" (1). ''' ''' UPDATE %(db)s.%(file_states)s SET file_state = 1 '''))
''' Get inventory of cached content for all files in the selection.
:param skip_unchanged: If ``True`` only inventory of modified files is yielded (:py:meth:`flag_modified` must be called beforehand). :type skip_unchanged: bool
This generator yields tuples ``((format, path), nuts)`` where ``path`` is the path to the file, ``format`` is the format assignation or ``'detect'`` and ``nuts`` is a list of :py:class:`~pyrocko.squirrel.model.Nut` objects representing the contents of the file. '''
WHERE %(db)s.%(file_states)s.file_state == 0 ''' else:
SELECT COUNT() FROM %(db)s.%(file_states)s ''' + where), ())[0]
SELECT %(db)s.%(file_states)s.format, files.path, files.format, files.mtime, files.size, nuts.file_segment, nuts.file_element, kind_codes.kind_id, kind_codes.codes, nuts.tmin_seconds, nuts.tmin_offset, nuts.tmax_seconds, nuts.tmax_offset, kind_codes.deltat FROM %(db)s.%(file_states)s LEFT OUTER JOIN files ON %(db)s.%(file_states)s.file_id = files.file_id LEFT OUTER JOIN nuts ON files.file_id = nuts.file_id LEFT OUTER JOIN kind_codes ON nuts.kind_codes_id == kind_codes.kind_codes_id ''' + where + ''' ORDER BY %(db)s.%(file_states)s.file_id ''')
''' Mark files which have been modified.
:param check: If ``True`` query modification times of known files on disk. If ``False``, only flag unknown files. :type check: bool
Assumes file state is 0 for newly added files, 1 for files added again to the selection (forces check), or 2 for all others (no checking is done for those).
Sets file state to 0 for unknown or modified files, 2 for known and not modified files. '''
UPDATE %(db)s.%(file_states)s SET file_state = 0 WHERE ( SELECT mtime FROM files WHERE files.file_id == %(db)s.%(file_states)s.file_id) IS NULL AND file_state == 1 ''')
UPDATE %(db)s.%(file_states)s SET file_state = 2 WHERE file_state == 1 ''')
SELECT files.file_id, files.path, files.format, files.mtime, files.size FROM %(db)s.%(file_states)s INNER JOIN files ON %(db)s.%(file_states)s.file_id == files.file_id WHERE %(db)s.%(file_states)s.file_state == 1 ORDER BY %(db)s.%(file_states)s.file_id ''')
size_db) in self._conn.execute(sql):
except io.UnknownFormat: continue
else:
# could better use callback function here...
UPDATE %(db)s.%(file_states)s SET file_state = ? WHERE file_id = ? ''')
'Selection', ] |