@@ -31,7 +31,7 @@ def _check_support(stix_id):
3131 raise DataSourceError (f"Reading { stix_type } objects is not supported." )
3232
3333
34- def _tables_for (stix_class , metadata ):
34+ def _tables_for (stix_class , metadata , db_backend ):
3535 """
3636 Get the core and type-specific tables for the given class
3737
@@ -42,17 +42,24 @@ def _tables_for(stix_class, metadata):
4242 """
4343 # Info about the type-specific table
4444 type_table_name = table_name_for (stix_class )
45- type_schema_name = schema_for (stix_class )
46- type_table = metadata .tables [f"{ type_schema_name } .{ type_table_name } " ]
45+ type_schema_name = db_backend .schema_for (stix_class )
46+ canon_type_table_name = canonicalize_table_name (type_table_name , type_schema_name )
47+
48+ type_table = metadata .tables [canon_type_table_name ]
4749
4850 # Some fixed info about core tables
49- if type_schema_name == "sco" :
50- core_table_name = "common.core_sco"
51+ if stix2 .utils .is_sco (stix_class ._type , stix2 .DEFAULT_VERSION ):
52+ canon_core_table_name = canonicalize_table_name (
53+ "core_sco" , db_backend .schema_for_core ()
54+ )
55+
5156 else :
5257 # for SROs and SMOs too?
53- core_table_name = "common.core_sdo"
58+ canon_core_table_name = canonicalize_table_name (
59+ "core_sdo" , db_backend .schema_for_core ()
60+ )
5461
55- core_table = metadata .tables [core_table_name ]
62+ core_table = metadata .tables [canon_core_table_name ]
5663
5764 return core_table , type_table
5865
@@ -138,18 +145,30 @@ def _read_hashes(fk_id, hashes_table, conn):
138145 return hashes
139146
140147
141- def _read_external_references (stix_id , metadata , conn ):
148+ def _read_external_references (stix_id , metadata , conn , db_backend ):
142149 """
143150 Read external references from some fixed tables in the common schema.
144151
145152 :param stix_id: A STIX ID used to filter table rows
146153 :param metadata: SQLAlchemy Metadata object containing all the table
147154 information
148155 :param conn: An SQLAlchemy DB connection
156+ :param db_backend: A backend object with information about how data is
157+ stored in the database
149158 :return: The external references, as a list of dicts
150159 """
151- ext_refs_table = metadata .tables ["common.external_references" ]
152- ext_refs_hashes_table = metadata .tables ["common.external_references_hashes" ]
160+ ext_refs_table = metadata .tables [
161+ canonicalize_table_name (
162+ "external_references" ,
163+ db_backend .schema_for_core ()
164+ )
165+ ]
166+ ext_refs_hashes_table = metadata .tables [
167+ canonicalize_table_name (
168+ "external_references_hashes" ,
169+ db_backend .schema_for_core ()
170+ )
171+ ]
153172 ext_refs = []
154173
155174 ext_refs_columns = (col for col in ext_refs_table .c if col .key != "id" )
@@ -169,43 +188,44 @@ def _read_external_references(stix_id, metadata, conn):
169188 return ext_refs
170189
171190
172- def _read_object_marking_refs (stix_id , stix_type_class , metadata , conn ):
191+ def _read_object_marking_refs (stix_id , common_table_kind , metadata , conn , db_backend ):
173192 """
174193 Read object marking refs from one of a couple special tables in the common
175194 schema.
176195
177196 :param stix_id: A STIX ID, used to filter table rows
178- :param stix_type_class: STIXTypeClass enum value , used to determine whether
197+ :param common_table_kind: "sco" or "sdo" , used to determine whether
179198 to read the table for SDOs or SCOs
180199 :param metadata: SQLAlchemy Metadata object containing all the table
181200 information
182201 :param conn: An SQLAlchemy DB connection
202+ :param db_backend: A backend object with information about how data is
203+ stored in the database
183204 :return: The references as a list of strings
184205 """
185206
186- marking_table_name = "object_marking_refs_"
187- if stix_type_class is stix2 .utils .STIXTypeClass .SCO :
188- marking_table_name += "sco"
189- else :
190- marking_table_name += "sdo"
207+ marking_table_name = canonicalize_table_name (
208+ "object_marking_refs_" + common_table_kind ,
209+ db_backend .schema_for_core ()
210+ )
191211
192212 # The SCO/SDO object_marking_refs tables are mostly identical; they just
193213 # have different foreign key constraints (to different core tables).
194- marking_table = metadata .tables ["common." + marking_table_name ]
214+ marking_table = metadata .tables [marking_table_name ]
195215
196216 stmt = sa .select (marking_table .c .ref_id ).where (marking_table .c .id == stix_id )
197217 refs = conn .scalars (stmt ).all ()
198218
199219 return refs
200220
201221
202- def _read_granular_markings (stix_id , stix_type_class , metadata , conn , db_backend ):
222+ def _read_granular_markings (stix_id , common_table_kind , metadata , conn , db_backend ):
203223 """
204224 Read granular markings from one of a couple special tables in the common
205225 schema.
206226
207227 :param stix_id: A STIX ID, used to filter table rows
208- :param stix_type_class: STIXTypeClass enum value , used to determine whether
228+ :param common_table_kind: "sco" or "sdo" , used to determine whether
209229 to read the table for SDOs or SCOs
210230 :param metadata: SQLAlchemy Metadata object containing all the table
211231 information
@@ -215,13 +235,11 @@ def _read_granular_markings(stix_id, stix_type_class, metadata, conn, db_backend
215235 :return: Granular markings as a list of dicts
216236 """
217237
218- marking_table_name = "granular_marking_"
219- if stix_type_class is stix2 .utils .STIXTypeClass .SCO :
220- marking_table_name += "sco"
221- else :
222- marking_table_name += "sdo"
223-
224- marking_table = metadata .tables ["common." + marking_table_name ]
238+ marking_table_name = canonicalize_table_name (
239+ "granular_marking_" + common_table_kind ,
240+ db_backend .schema_for_core ()
241+ )
242+ marking_table = metadata .tables [marking_table_name ]
225243
226244 if db_backend .array_allowed ():
227245 # arrays allowed: everything combined in the same table
@@ -334,7 +352,7 @@ def _read_dictionary_property(
334352 stmt = sa .select (
335353 dict_table .c .name , list_table .c .value
336354 ).select_from (dict_table ).join (
337- list_table , list_table .c .id == dict_table .c . values
355+ list_table , list_table .c .id == dict_table .c [ " values" ]
338356 ).where (
339357 dict_table .c .id == stix_id
340358 )
@@ -610,7 +628,7 @@ def _read_complex_property_value(
610628
611629def _read_complex_top_level_property_value (
612630 stix_id ,
613- stix_type_class ,
631+ common_table_kind ,
614632 prop_name ,
615633 prop_instance ,
616634 type_table ,
@@ -624,8 +642,8 @@ def _read_complex_top_level_property_value(
624642 reading top-level common properties, which use special fixed tables.
625643
626644 :param stix_id: STIX ID of an object to read
627- :param stix_type_class: The kind of object (SCO, SDO, etc). Which DB
628- tables to read can depend on this .
645+ :param common_table_kind: Used to find auxiliary common tables, e.g. those
646+ for object markings, granular markings, etc. Either "sco" or "sdo" .
629647 :param prop_name: The name of the property to read
630648 :param prop_instance: A Property (subclass) instance with property
631649 config information
@@ -641,20 +659,26 @@ def _read_complex_top_level_property_value(
641659
642660 # Common properties: these use a fixed set of tables for all STIX objects
643661 if prop_name == "external_references" :
644- prop_value = _read_external_references (stix_id , metadata , conn )
662+ prop_value = _read_external_references (
663+ stix_id ,
664+ metadata ,
665+ conn ,
666+ db_backend
667+ )
645668
646669 elif prop_name == "object_marking_refs" :
647670 prop_value = _read_object_marking_refs (
648671 stix_id ,
649- stix_type_class ,
672+ common_table_kind ,
650673 metadata ,
651674 conn ,
675+ db_backend ,
652676 )
653677
654678 elif prop_name == "granular_markings" :
655679 prop_value = _read_granular_markings (
656680 stix_id ,
657- stix_type_class ,
681+ common_table_kind ,
658682 metadata ,
659683 conn ,
660684 db_backend ,
@@ -663,7 +687,10 @@ def _read_complex_top_level_property_value(
663687 # Will apply when array columns are unsupported/disallowed by the backend
664688 elif prop_name == "labels" :
665689 label_table = metadata .tables [
666- f"common.core_{ stix_type_class .name .lower ()} _labels"
690+ canonicalize_table_name (
691+ f"core_{ common_table_kind } _labels" ,
692+ db_backend .schema_for_core ()
693+ )
667694 ]
668695 prop_value = _read_simple_array (stix_id , "label" , label_table , conn )
669696
@@ -702,16 +729,10 @@ def read_object(stix_id, metadata, conn, db_backend):
702729 stix_type = stix2 .utils .get_type_from_id (stix_id )
703730 raise DataSourceError ("Can't find registered class for type: " + stix_type )
704731
705- core_table , type_table = _tables_for (stix_class , metadata )
706-
707- if type_table .schema == "common" :
708- # Applies to extension-definition SMO, whose data is stored in the
709- # common schema; it does not get its own. This type class is used to
710- # determine which common tables to use; its markings are
711- # in the *_sdo tables.
712- stix_type_class = stix2 .utils .STIXTypeClass .SDO
713- else :
714- stix_type_class = stix2 .utils .to_enum (type_table .schema , stix2 .utils .STIXTypeClass )
732+ core_table , type_table = _tables_for (stix_class , metadata , db_backend )
733+ # Used to find auxiliary common tables, e.g. those for object markings,
734+ # granular markings, etc.
735+ common_table_kind = core_table .name [- 3 :]
715736
716737 simple_props = _read_simple_properties (stix_id , core_table , type_table , conn )
717738 if simple_props is None :
@@ -725,7 +746,7 @@ def read_object(stix_id, metadata, conn, db_backend):
725746 if prop_name not in obj_dict :
726747 prop_value = _read_complex_top_level_property_value (
727748 stix_id ,
728- stix_type_class ,
749+ common_table_kind ,
729750 prop_name ,
730751 prop_instance ,
731752 type_table ,
@@ -737,5 +758,10 @@ def read_object(stix_id, metadata, conn, db_backend):
737758 if prop_value is not None :
738759 obj_dict [prop_name ] = prop_value
739760
740- stix_obj = stix_class (** obj_dict , allow_custom = True )
761+ stix_obj = stix2 .parse (
762+ obj_dict ,
763+ allow_custom = True ,
764+ version = stix2 .DEFAULT_VERSION
765+ )
766+
741767 return stix_obj
0 commit comments