LSST Applications g06d8191974+b5247657d3,g180d380827+b23588344e,g2079a07aa2+86d27d4dc4,g2305ad1205+0130fb9023,g29320951ab+7714a6b20a,g2bbee38e9b+0e5473021a,g337abbeb29+0e5473021a,g33d1c0ed96+0e5473021a,g3a166c0a6a+0e5473021a,g3ddfee87b4+8783ab7716,g48712c4677+72a8b1060b,g487adcacf7+bbaada240a,g50ff169b8f+96c6868917,g52b1c1532d+585e252eca,g591dd9f2cf+ecccb6240b,g5a732f18d5+53520f316c,g5ea96fc03c+33ab2bc355,g64a986408d+b5247657d3,g858d7b2824+b5247657d3,g8a8a8dda67+585e252eca,g99cad8db69+1453026da9,g9ddcbc5298+9a081db1e4,ga1e77700b3+15fc3df1f7,gb0e22166c9+60f28cb32d,gba4ed39666+c2a2e4ac27,gbb8dafda3b+3751ca9c65,gc120e1dc64+c91d1388df,gc28159a63d+0e5473021a,gc3e9b769f7+241adb7c58,gcf0d15dbbd+8783ab7716,gdaeeff99f8+f9a426f77a,ge6526c86ff+acdbe9a537,ge79ae78c31+0e5473021a,gee10cc3b42+585e252eca,gff1a9f87cc+b5247657d3,w.2024.17
LSST Data Management Base Package
Loading...
Searching...
No Matches
Public Member Functions | Static Public Attributes | Protected Member Functions | Protected Attributes | List of all members
lsst.dax.apdb.sql.apdbSqlSchema.ApdbSqlSchema Class Reference
Inheritance diagram for lsst.dax.apdb.sql.apdbSqlSchema.ApdbSqlSchema:
lsst.dax.apdb.apdbSchema.ApdbSchema

Public Member Functions

 __init__ (self, sqlalchemy.engine.Engine engine, str dia_object_index, str htm_index_column, str schema_file, str schema_name="ApdbSchema", str prefix="", str|None namespace=None, bool enable_replica=False)
 
bool empty (self)
 
None makeSchema (self, bool drop=False)
 
sqlalchemy.schema.Table get_table (self, ApdbTables|ExtraTables table_enum)
 
list[sqlalchemy.schema.Column] get_apdb_columns (self, ApdbTables|ExtraTables table_enum)
 
bool has_replica_chunks (self)
 

Static Public Attributes

tuple pixel_id_tables = (ApdbTables.DiaObject, ApdbTables.DiaObjectLast, ApdbTables.DiaSource)
 

Protected Member Functions

bool _check_replica_chunks (self)
 
Mapping[ApdbTables, schema_model.Table_make_apdb_tables (self, str mysql_engine="InnoDB")
 
Mapping[ExtraTables, schema_model.Table_make_extra_tables (self, Mapping[ApdbTables, schema_model.Table] apdb_tables)
 
list[schema_model.Column_replicaChunkColumns (self, ExtraTables table_enum, ApdbTables apdb_enum)
 
list[schema_model.Index_replicaChunkIndices (self, ExtraTables table_enum, Mapping[str, schema_model.Column] column_map)
 
list[schema_model.Constraint_replicaChunkConstraints (self, ExtraTables table_enum, schema_model.Table apdb_table, schema_model.Table parent_table, Mapping[str, schema_model.Column] column_map)
 

Protected Attributes

 _engine
 
 _dia_object_index
 
 _htm_index_column
 
 _prefix
 
 _enable_replica
 
 _metadata
 
 _apdb_tables
 
 _extra_tables
 
 _has_replica_chunks
 
 _metadata_check
 

Detailed Description

Class for management of APDB schema.

Attributes
----------
objects : `sqlalchemy.Table`
    DiaObject table instance
objects_last : `sqlalchemy.Table`
    DiaObjectLast table instance, may be None
sources : `sqlalchemy.Table`
    DiaSource table instance
forcedSources : `sqlalchemy.Table`
    DiaForcedSource table instance
has_replica_chunks : `bool`
    If true then schema has tables for replication chunks.

Parameters
----------
engine : `sqlalchemy.engine.Engine`
    SQLAlchemy engine instance
dia_object_index : `str`
    Indexing mode for DiaObject table, see `ApdbSqlConfig.dia_object_index`
    for details.
htm_index_column : `str`
    Name of a HTM index column for DiaObject and DiaSource tables.
schema_file : `str`
    Name of the YAML schema file.
schema_name : `str`, optional
    Name of the schema in YAML files.
prefix : `str`, optional
    Prefix to add to all schema elements.
namespace : `str`, optional
    Namespace (or schema name) to use for all APDB tables.
enable_replica : `bool`, optional
    If `True` then use additional tables for replica chunks.

Definition at line 80 of file apdbSqlSchema.py.

Constructor & Destructor Documentation

◆ __init__()

lsst.dax.apdb.sql.apdbSqlSchema.ApdbSqlSchema.__init__ ( self,
sqlalchemy.engine.Engine engine,
str dia_object_index,
str htm_index_column,
str schema_file,
str schema_name = "ApdbSchema",
str prefix = "",
str | None namespace = None,
bool enable_replica = False )

Reimplemented from lsst.dax.apdb.apdbSchema.ApdbSchema.

Definition at line 120 of file apdbSqlSchema.py.

130 ):
131 super().__init__(schema_file, schema_name)
132
133 self._engine = engine
134 self._dia_object_index = dia_object_index
135 self._htm_index_column = htm_index_column
136 self._prefix = prefix
137 self._enable_replica = enable_replica
138
139 self._metadata = sqlalchemy.schema.MetaData(schema=namespace)
140
141 # Add pixelId column and index to tables that need it
142 for table in self.pixel_id_tables:
143 tableDef = self.tableSchemas.get(table)
144 if not tableDef:
145 continue
146 column = schema_model.Column(
147 id=f"#{htm_index_column}",
148 name=htm_index_column,
149 datatype=felis.datamodel.DataType.long,
150 nullable=False,
151 value=None,
152 description="Pixelization index column.",
153 table=tableDef,
154 )
155 tableDef.columns.append(column)
156
157 # Adjust index if needed
158 if table == ApdbTables.DiaObject and self._dia_object_index == "pix_id_iov":
159 tableDef.primary_key.insert(0, column)
160
161 if table is ApdbTables.DiaObjectLast:
162 # use it as a leading PK column
163 tableDef.primary_key.insert(0, column)
164 else:
165 # make a regular index
166 name = f"IDX_{tableDef.name}_{htm_index_column}"
167 index = schema_model.Index(id=f"#{name}", name=name, columns=[column])
168 tableDef.indexes.append(index)
169
170 # generate schema for all tables, must be called last
171 apdb_tables = self._make_apdb_tables()
172 extra_tables = self._make_extra_tables(apdb_tables)
173
174 converter = ModelToSql(metadata=self._metadata, prefix=self._prefix)
175 id_to_table = converter.make_tables(itertools.chain(apdb_tables.values(), extra_tables.values()))
176
177 self._apdb_tables = {
178 apdb_enum: id_to_table[table_model.id] for apdb_enum, table_model in apdb_tables.items()
179 }
180 self._extra_tables = {
181 extra_enum: id_to_table[table_model.id] for extra_enum, table_model in extra_tables.items()
182 }
183
184 self._has_replica_chunks: bool | None = None
185 self._metadata_check: bool | None = None
186

Member Function Documentation

◆ _check_replica_chunks()

bool lsst.dax.apdb.sql.apdbSqlSchema.ApdbSqlSchema._check_replica_chunks ( self)
protected
Check whether database has tables for tracking insert IDs.

Definition at line 323 of file apdbSqlSchema.py.

323 def _check_replica_chunks(self) -> bool:
324 """Check whether database has tables for tracking insert IDs."""
325 inspector = sqlalchemy.inspect(self._engine)
326 db_tables = set(inspector.get_table_names(schema=self._metadata.schema))
327 return ExtraTables.ApdbReplicaChunks.table_name(self._prefix) in db_tables
328
daf::base::PropertySet * set
Definition fits.cc:931

◆ _make_apdb_tables()

Mapping[ApdbTables, schema_model.Table] lsst.dax.apdb.sql.apdbSqlSchema.ApdbSqlSchema._make_apdb_tables ( self,
str mysql_engine = "InnoDB" )
protected
Generate schema for regular tables.

Parameters
----------
mysql_engine : `str`, optional
    MySQL engine type to use for new tables.

Definition at line 329 of file apdbSqlSchema.py.

329 def _make_apdb_tables(self, mysql_engine: str = "InnoDB") -> Mapping[ApdbTables, schema_model.Table]:
330 """Generate schema for regular tables.
331
332 Parameters
333 ----------
334 mysql_engine : `str`, optional
335 MySQL engine type to use for new tables.
336 """
337 tables = {}
338 for table_enum in ApdbTables:
339 if table_enum is ApdbTables.DiaObjectLast and self._dia_object_index != "last_object_table":
340 continue
341 if table_enum is ApdbTables.metadata and table_enum not in self.tableSchemas:
342 # Schema does not define metadata.
343 continue
344 table = self.tableSchemas[table_enum]
345 tables[table_enum] = table
346
347 return tables
348

◆ _make_extra_tables()

Mapping[ExtraTables, schema_model.Table] lsst.dax.apdb.sql.apdbSqlSchema.ApdbSqlSchema._make_extra_tables ( self,
Mapping[ApdbTables, schema_model.Table] apdb_tables )
protected
Generate schema for insert ID tables.

Definition at line 349 of file apdbSqlSchema.py.

351 ) -> Mapping[ExtraTables, schema_model.Table]:
352 """Generate schema for insert ID tables."""
353 if not self._enable_replica:
354 return {}
355
356 tables = {}
357 column_defs: list[schema_model.Column] = [
358 schema_model.Column(
359 name="apdb_replica_chunk",
360 id="#ApdbReplicaChunks.apdb_replica_chunk",
361 datatype=felis.datamodel.DataType.long,
362 ),
363 schema_model.Column(
364 name="last_update_time",
365 id="#ApdbReplicaChunks.last_update_time",
366 datatype=felis.datamodel.DataType.timestamp,
367 nullable=False,
368 ),
369 schema_model.Column(
370 name="unique_id",
371 id="#ApdbReplicaChunks.unique_id",
372 datatype=schema_model.ExtraDataTypes.UUID,
373 nullable=False,
374 ),
375 ]
376 parent_table = schema_model.Table(
377 name=ExtraTables.ApdbReplicaChunks.table_name(self._prefix),
378 id="#ApdbReplicaChunks",
379 columns=column_defs,
380 primary_key=[column_defs[0]],
381 constraints=[],
382 indexes=[],
383 )
384 tables[ExtraTables.ApdbReplicaChunks] = parent_table
385
386 for table_enum, apdb_enum in ExtraTables.replica_chunk_tables().items():
387 apdb_table = apdb_tables[apdb_enum]
388 table_name = table_enum.table_name(self._prefix)
389
390 columns = self._replicaChunkColumns(table_enum, apdb_enum)
391 column_map = {column.name: column for column in columns}
392 # PK is the same as for original table
393 pk_columns = [column_map[column.name] for column in apdb_table.primary_key]
394
395 indices = self._replicaChunkIndices(table_enum, column_map)
396 constraints = self._replicaChunkConstraints(table_enum, apdb_table, parent_table, column_map)
397 table = schema_model.Table(
398 name=table_name,
399 id=f"#{table_name}",
400 columns=columns,
401 primary_key=pk_columns,
402 indexes=indices,
403 constraints=constraints,
404 )
405 tables[table_enum] = table
406
407 return tables
408
std::vector< SchemaItem< Flag > > * items

◆ _replicaChunkColumns()

list[schema_model.Column] lsst.dax.apdb.sql.apdbSqlSchema.ApdbSqlSchema._replicaChunkColumns ( self,
ExtraTables table_enum,
ApdbTables apdb_enum )
protected
Return list of columns for replica chunks tables.

Definition at line 409 of file apdbSqlSchema.py.

411 ) -> list[schema_model.Column]:
412 """Return list of columns for replica chunks tables."""
413 table_name = table_enum.table_name()
414 column_defs: list[schema_model.Column] = [
415 schema_model.Column(
416 name="apdb_replica_chunk",
417 id=f"#{table_name}.apdb_replica_chunk",
418 datatype=felis.datamodel.DataType.long,
419 nullable=False,
420 )
421 ]
422 if table_enum in ExtraTables.replica_chunk_tables():
423 table_model = self.tableSchemas[apdb_enum]
424 column_defs += [column.clone() for column in table_model.primary_key]
425 else:
426 assert False, "Above branches have to cover all enum values"
427 return column_defs
428

◆ _replicaChunkConstraints()

list[schema_model.Constraint] lsst.dax.apdb.sql.apdbSqlSchema.ApdbSqlSchema._replicaChunkConstraints ( self,
ExtraTables table_enum,
schema_model.Table apdb_table,
schema_model.Table parent_table,
Mapping[str, schema_model.Column] column_map )
protected
Return set of constraints for replica chunk table.

Definition at line 443 of file apdbSqlSchema.py.

449 ) -> list[schema_model.Constraint]:
450 """Return set of constraints for replica chunk table."""
451 constraints: list[schema_model.Constraint] = []
452 replica_chunk_tables = ExtraTables.replica_chunk_tables()
453 if table_enum in replica_chunk_tables:
454 # Foreign key to original table
455 name = f"{table_enum.table_name()}_fk_{apdb_table.name}"
456 other_columns = apdb_table.primary_key
457 this_columns = [column_map[column.name] for column in apdb_table.primary_key]
458 constraints.append(
459 schema_model.ForeignKeyConstraint(
460 name=name,
461 id=f"#{name}",
462 columns=this_columns,
463 referenced_columns=other_columns,
464 onupdate="CASCADE",
465 ondelete="CASCADE",
466 )
467 )
468
469 # Foreign key to parent chunk ID table
470 name = f"{table_enum.table_name()}_fk_{parent_table.name}"
471 other_columns = parent_table.primary_key
472 this_columns = [column_map[column.name] for column in parent_table.primary_key]
473 constraints.append(
474 schema_model.ForeignKeyConstraint(
475 name=name,
476 id=f"#{name}",
477 columns=this_columns,
478 referenced_columns=other_columns,
479 onupdate="CASCADE",
480 ondelete="CASCADE",
481 )
482 )
483 return constraints

◆ _replicaChunkIndices()

list[schema_model.Index] lsst.dax.apdb.sql.apdbSqlSchema.ApdbSqlSchema._replicaChunkIndices ( self,
ExtraTables table_enum,
Mapping[str, schema_model.Column] column_map )
protected
Return set of indices for replica chunk table.

Definition at line 429 of file apdbSqlSchema.py.

433 ) -> list[schema_model.Index]:
434 """Return set of indices for replica chunk table."""
435 index_defs: list[schema_model.Index] = []
436 if table_enum in ExtraTables.replica_chunk_tables():
437 # Non-unique index on replica chunk column.
438 name = self._prefix + table_enum.name + "_apdb_replica_chunk_idx"
439 column = column_map["apdb_replica_chunk"]
440 index_defs.append(schema_model.Index(name=name, id=f"#{name}", columns=[column]))
441 return index_defs
442

◆ empty()

bool lsst.dax.apdb.sql.apdbSqlSchema.ApdbSqlSchema.empty ( self)
Return True if database schema is empty.

Returns
-------
empty : `bool`
    `True` if none of the required APDB tables exist in the database,
    `False` if all required tables exist.

Raises
------
InconsistentSchemaError
    Raised when some of the required tables exist but not all.

Definition at line 187 of file apdbSqlSchema.py.

187 def empty(self) -> bool:
188 """Return True if database schema is empty.
189
190 Returns
191 -------
192 empty : `bool`
193 `True` if none of the required APDB tables exist in the database,
194 `False` if all required tables exist.
195
196 Raises
197 ------
198 InconsistentSchemaError
199 Raised when some of the required tables exist but not all.
200 """
201 inspector = sqlalchemy.inspect(self._engine)
202 table_names = set(inspector.get_table_names(self._metadata.schema))
203
204 existing_tables = []
205 missing_tables = []
206 for table_enum in self._apdb_tables:
207 table_name = table_enum.table_name(self._prefix)
208 if table_name in table_names:
209 existing_tables.append(table_name)
210 else:
211 missing_tables.append(table_name)
212
213 if not missing_tables:
214 return False
215 elif not existing_tables:
216 return True
217 else:
218 raise InconsistentSchemaError(
219 f"Only some required APDB tables exist: {existing_tables}, missing tables: {missing_tables}"
220 )
221

◆ get_apdb_columns()

list[sqlalchemy.schema.Column] lsst.dax.apdb.sql.apdbSqlSchema.ApdbSqlSchema.get_apdb_columns ( self,
ApdbTables | ExtraTables table_enum )
Return list of columns defined for a table in APDB schema.

Returned list excludes columns that are implementation-specific, e.g.
``pixelId`` column is not include in the returned list.

Parameters
----------
table_enum : `ApdbTables` or `ExtraTables`
    Type of table.

Returns
-------
table : `list` [`sqlalchemy.schema.Column`]
    Table instance.

Raises
------
ValueError
    Raised if ``table_enum`` is not valid for this database.

Definition at line 289 of file apdbSqlSchema.py.

289 def get_apdb_columns(self, table_enum: ApdbTables | ExtraTables) -> list[sqlalchemy.schema.Column]:
290 """Return list of columns defined for a table in APDB schema.
291
292 Returned list excludes columns that are implementation-specific, e.g.
293 ``pixelId`` column is not include in the returned list.
294
295 Parameters
296 ----------
297 table_enum : `ApdbTables` or `ExtraTables`
298 Type of table.
299
300 Returns
301 -------
302 table : `list` [`sqlalchemy.schema.Column`]
303 Table instance.
304
305 Raises
306 ------
307 ValueError
308 Raised if ``table_enum`` is not valid for this database.
309 """
310 table = self.get_table(table_enum)
311 exclude_columns = set()
312 if table_enum in self.pixel_id_tables:
313 exclude_columns.add(self._htm_index_column)
314 return [column for column in table.columns if column.name not in exclude_columns]
315

◆ get_table()

sqlalchemy.schema.Table lsst.dax.apdb.sql.apdbSqlSchema.ApdbSqlSchema.get_table ( self,
ApdbTables | ExtraTables table_enum )
Return SQLAlchemy table instance for a specified table type/enum.

Parameters
----------
table_enum : `ApdbTables` or `ExtraTables`
    Type of table to return.

Returns
-------
table : `sqlalchemy.schema.Table`
    Table instance.

Raises
------
ValueError
    Raised if ``table_enum`` is not valid for this database.

Definition at line 251 of file apdbSqlSchema.py.

251 def get_table(self, table_enum: ApdbTables | ExtraTables) -> sqlalchemy.schema.Table:
252 """Return SQLAlchemy table instance for a specified table type/enum.
253
254 Parameters
255 ----------
256 table_enum : `ApdbTables` or `ExtraTables`
257 Type of table to return.
258
259 Returns
260 -------
261 table : `sqlalchemy.schema.Table`
262 Table instance.
263
264 Raises
265 ------
266 ValueError
267 Raised if ``table_enum`` is not valid for this database.
268 """
269 try:
270 if isinstance(table_enum, ApdbTables):
271 if table_enum is ApdbTables.metadata:
272 # There may be cases when schema is configured with the
273 # metadata table but database is still missing it. Check
274 # that table actually exists in the database. Note that
275 # this may interact with `makeSchema`.
276 if self._metadata_check is None:
277 inspector = sqlalchemy.inspect(self._engine)
278 table_name = table_enum.table_name(self._prefix)
279 self._metadata_check = inspector.has_table(table_name, schema=self._metadata.schema)
280 if not self._metadata_check:
281 # this will be caught below
282 raise LookupError("metadata table is missing")
283 return self._apdb_tables[table_enum]
284 else:
285 return self._extra_tables[table_enum]
286 except LookupError:
287 raise ValueError(f"Table type {table_enum} does not exist in the schema") from None
288

◆ has_replica_chunks()

bool lsst.dax.apdb.sql.apdbSqlSchema.ApdbSqlSchema.has_replica_chunks ( self)
Whether insert ID tables are to be used (`bool`).

Definition at line 317 of file apdbSqlSchema.py.

317 def has_replica_chunks(self) -> bool:
318 """Whether insert ID tables are to be used (`bool`)."""
319 if self._has_replica_chunks is None:
320 self._has_replica_chunks = self._enable_replica and self._check_replica_chunks()
321 return self._has_replica_chunks
322

◆ makeSchema()

None lsst.dax.apdb.sql.apdbSqlSchema.ApdbSqlSchema.makeSchema ( self,
bool drop = False )
Create or re-create all tables.

Parameters
----------
drop : `bool`, optional
    If True then drop tables before creating new ones.

Definition at line 222 of file apdbSqlSchema.py.

222 def makeSchema(self, drop: bool = False) -> None:
223 """Create or re-create all tables.
224
225 Parameters
226 ----------
227 drop : `bool`, optional
228 If True then drop tables before creating new ones.
229 """
230 # Create namespace if it does not exist yet, for now this only makes
231 # sense for postgres.
232 if self._metadata.schema:
233 dialect = self._engine.dialect
234 quoted_schema = dialect.preparer(dialect).quote_schema(self._metadata.schema)
235 create_schema = sqlalchemy.schema.DDL(
236 "CREATE SCHEMA IF NOT EXISTS %(schema)s", context={"schema": quoted_schema}
237 ).execute_if(dialect="postgresql")
238 sqlalchemy.event.listen(self._metadata, "before_create", create_schema)
239
240 # create all tables (optionally drop first)
241 if drop:
242 _LOG.info("dropping all tables")
243 self._metadata.drop_all(self._engine)
244 _LOG.info("creating all tables")
245 self._metadata.create_all(self._engine)
246
247 # Reset possibly cached value.
248 self._has_replica_chunks = None
249 self._metadata_check = None
250

Member Data Documentation

◆ _apdb_tables

lsst.dax.apdb.sql.apdbSqlSchema.ApdbSqlSchema._apdb_tables
protected

Definition at line 177 of file apdbSqlSchema.py.

◆ _dia_object_index

lsst.dax.apdb.sql.apdbSqlSchema.ApdbSqlSchema._dia_object_index
protected

Definition at line 134 of file apdbSqlSchema.py.

◆ _enable_replica

lsst.dax.apdb.sql.apdbSqlSchema.ApdbSqlSchema._enable_replica
protected

Definition at line 137 of file apdbSqlSchema.py.

◆ _engine

lsst.dax.apdb.sql.apdbSqlSchema.ApdbSqlSchema._engine
protected

Definition at line 133 of file apdbSqlSchema.py.

◆ _extra_tables

lsst.dax.apdb.sql.apdbSqlSchema.ApdbSqlSchema._extra_tables
protected

Definition at line 180 of file apdbSqlSchema.py.

◆ _has_replica_chunks

lsst.dax.apdb.sql.apdbSqlSchema.ApdbSqlSchema._has_replica_chunks
protected

Definition at line 248 of file apdbSqlSchema.py.

◆ _htm_index_column

lsst.dax.apdb.sql.apdbSqlSchema.ApdbSqlSchema._htm_index_column
protected

Definition at line 135 of file apdbSqlSchema.py.

◆ _metadata

lsst.dax.apdb.sql.apdbSqlSchema.ApdbSqlSchema._metadata
protected

Definition at line 139 of file apdbSqlSchema.py.

◆ _metadata_check

lsst.dax.apdb.sql.apdbSqlSchema.ApdbSqlSchema._metadata_check
protected

Definition at line 249 of file apdbSqlSchema.py.

◆ _prefix

lsst.dax.apdb.sql.apdbSqlSchema.ApdbSqlSchema._prefix
protected

Definition at line 136 of file apdbSqlSchema.py.

◆ pixel_id_tables

tuple lsst.dax.apdb.sql.apdbSqlSchema.ApdbSqlSchema.pixel_id_tables = (ApdbTables.DiaObject, ApdbTables.DiaObjectLast, ApdbTables.DiaSource)
static

Definition at line 117 of file apdbSqlSchema.py.


The documentation for this class was generated from the following file: