blob: 56b6697be2fefcb4fd67eaaf628d3b37685751ae [file] [log] [blame]
JvD_Ericsson0cf610f2024-07-24 16:34:11 +01001PG SQL Schema Generator
2#######################
3
4*PG SQL Schema Generator* provides the capability of generating a PostgreSQL schema from the YANG models. This schema
5in turn is used in TE&IV for validating, ingesting and exposing the topology.
6
7Algorithm
8*********
9
10Overview
11========
12
13The *PG SQL Schema Generator* necessitates the execution of multiple processes, each designed to fulfill distinct tasks
14ensuring the thorough completion of their designated tasks for the complete schema generation flow. The various stages
15involved in the schema generation are:
16
17- :ref:`Model information retrieval <Model Information Retrieval>`
18- :ref:`DB schema generation <PG SQL Schema Generation>`
19
20The logic behind each stage is explained below.
21
22Prerequisite
23============
24
25The main input for schema generation is the YANG modules. In order to start the process, we need to configure the path
26which contains all the YANG modules that should be considered for DB schema generation.
27
28The configuration is done in application.yaml as follows:
29
30.. code-block:: yaml
31
32 yang-model:
33 source: classpath:generate-defaults
34
35Model Information Retrieval
36===========================
37
38The models are used for identifying the entities & relationships information. For schema generation we need
39the following information:
40
41- modules
42- entities
43- relationships
44
45The logic for retrieving the above information is explained below.
46
47Modules
48-------
49
50Modules are identified with the help of the YANG parser.
51
52Refer YangParser.java "src/main/java/org/oran/smo/teiv/pgsqlgenerator/YangParser.java" for implementation.
53
54A module is constructed with the following details:
55
56- name: name of the module.
57- namespace: namespace of the module.
58- domain: domain of the module. Identified with the help of the statement 'domain' from the module 'o-ran-smo-teiv-common-yang-extensions'
59- revision: module revision.
60- content: content of the module.
61- ownerAppId: set to 'BUILT_IN_MODULE' for all modules.
62- status: set to 'IN_USAGE' for all modules.
63- availableListElements: set to all the list elements defined in the module. Identified with the help of the statement with 'list' as the yang DOM element name.
64- availableEntities: Initially constructed as empty list. This will be populated later with all the entities defined in the module.
65- availableRelations: set to the list of all relationship names defined in the module. Identified with the help of the statement name 'or-teiv-yext:biDirectionalTopologyRelationship'
66- includedModules: set to the list of all the imported modules in the domain.
67
68Entity Types
69------------
70
71Entity types are identified from the yang.
72
73An entity type is constructed with the following details:
74
75- entityName: name of the entity.
76- moduleReferenceName: module to which the entity belongs. Identified by checking which of the identified modules has:
77
78 - the same namespace as the entity, and
79 - the availableListElements contains the entity name
80
81- consumerData: sourceIds, classifiers and decorators.
82- attributes: attributes for the entity. Retrieval of attribute information is detailed in the next section.
83
84Attributes
85^^^^^^^^^^
86
87For every identified entity, we also retrieve the attributes belonging to it. An attribute is constructed with the
88following information:
89
90- name: name of the attribute
91- dataType: dataType of the attribute. The datatype from the model is mapped to the corresponding DB datatype as shown in the below table:
92
93 +-----------------------+----------------+
94 | Model Attribute Types | Database Types |
95 +=======================+================+
96 | STRING | TEXT |
97 +-----------------------+----------------+
98 | COMPLEX_REF | jsonb |
99 +-----------------------+----------------+
100 | DOUBLE | DECIMAL |
101 +-----------------------+----------------+
102 | LONG | BIGINT |
103 +-----------------------+----------------+
104 | ENUM_REF | TEXT |
105 +-----------------------+----------------+
106 | MO_REF | TEXT |
107 +-----------------------+----------------+
108 | INTEGER | INTEGER |
109 +-----------------------+----------------+
110 | GEO_LOCATION | GEOGRAPHY |
111 +-----------------------+----------------+
112
113 **Note:** ID model attribute type is mapped to TEXT datatype as part of this algorithm.
114
115- constraints: list of constraints applicable for the attribute.
116- defaultValue: default value of the attribute.
117- indexTypes: indexes applicable for the attribute. Refer :ref:`Indexing Support <Indexing Support>` for more details on index.
118
119Relationship Types
120------------------
121
122Relationship types information is retrieved from the model. The model doesn't support retrieval of relationships
123directly, hence we get them by finding the outgoing associations for the identified entities.
124
125A relationship type is constructed with the following information:
126
127- name: name of the relationship
128- aSideAssociationName: name of the aSide association.
129- aSideMOType: aSide entity type.
130- aSideModule: module to which aSide entity type belongs.
131- aSideMinCardinality: minimum cardinality of the aSide.
132- aSideMaxCardinality: maximum cardinality of the aSide.
133- bSideAssociationName: name of the bSide association.
134- bSideMOType: bSide entity type.
135- bSideModule: module to which bSide entity type belongs.
136- bSideMinCardinality: minimum cardinality of the bSide.
137- bSideMaxCardinality: maximum cardinality of the bSide.
138- associationKind: association kind. eg, 'BI_DIRECTIONAL'.
139- connectSameEntity: whether the relationship connects the same entity type.
140- relationshipDataLocation: type of the table used for storing the relationship instances. Can be one of the following:
141
142 - A_SIDE
143 - B_SIDE
144 - RELATION
145
146 +--------------------------------------------------+----------------------------+
147 | Case | Relationship instance info |
148 +==================================================+============================+
149 | 1:1 | aSide |
150 +--------------------------------------------------+----------------------------+
151 | 1:N / N:1 | N-side |
152 +--------------------------------------------------+----------------------------+
153 | N:M | relation table |
154 +--------------------------------------------------+----------------------------+
155 | Relations connecting same Entity Types | relation table |
156 | 1 : 1 (or) 1 : n (or) m : n | |
157 +--------------------------------------------------+----------------------------+
158
159- moduleReferenceName: module to which the relationship belongs. The relationship module is identified by identifying the module that contains the relationship name in the availableRelations list.
160- consumerData: sourceIds, classifiers, decorators.
161
162Indexing Support
163----------------
164
165**Note:** This feature is currently **NOT** supported
166
167Indexing is supported for the identified column's based on the column's data type.
168
169Currently, we support indexing on JSONB columns.
170
171- GIN Index: used for columns storing object, eg, decorators.
172- GIN TRIGRAM Index: used for columns storing list of entries, eg, classifiers, sourceIds.
173
174PG SQL Schema Generation
175========================
176
177Data schema
178-----------
179
180The information gathered from the model is then used to generate the TE&IV data schema
181by creating tables from entities and relationships which is needed for persisting data,
182this is performed in numerous steps.
183
184Firstly, the data schema is prepared for use this is done by checking if a baseline data schema
185file already exists. If it does not exist or if it's a green field installation,
186it copies a skeleton data schema file to the new data schema file location.
187Otherwise, if the baseline data schema file exists, it copies it to the new data schema file location.
188
189Once the data schema is prepared the entities and relationships retrieved from the model need to be converted
190into structured tables suitable for database storage. It starts by analyzing the relationships
191between entities to determine the appropriate tables for storing relationship data,
192considering various connection types such as one-to-one, one-to-many, many-to-one and many-to-many.
193
194Next, it iterates over the entities generating the tables and columns based on their attributes.
195For each entity, it creates a table with columns representing its attributes and columns to accommodate
196associated relationships, ensuring adequate capturing of the relationships between entities.
197In the case where there is many-to-many relationships or relationships between same entity type
198these relationships are granted their own tables.
199
200For every entity and relationship identified from the model, we add additional columns to store **sourceIds**,
201**classifiers** and **decorators** information. This hard coding is necessary as sourceIds, classifiers and decorators
202are not transformed as part of the yang model as it is for now considered consumer data.
203
204+-----------------------------------------+-------+---------------+-------------------------------------------------------------------------------------------+
205| Column name | Type | Default | Description |
206| | | | |
207| | | Value | |
208+=========================================+=======+===============+===========================================================================================+
209| CD_sourceIds | jsonb | [] | Stores sourceIds for entities in entities table and relationships in relationship tables. |
210+-----------------------------------------+-------+---------------+-------------------------------------------------------------------------------------------+
211| REL_CD_sourceIds_<RELATIONSHIP_NAME> | jsonb | [] | Stores sourceIds for relationship inside an entity table. |
212+-----------------------------------------+-------+---------------+-------------------------------------------------------------------------------------------+
213| CD_classifiers | jsonb | [] | Stores classifiers for entities in entities table. |
214+-----------------------------------------+-------+---------------+-------------------------------------------------------------------------------------------+
215| REL_CD_classifiers_<RELATIONSHIP_NAME> | jsonb | [] | Stores classifiers for relationship inside an entity table. |
216+-----------------------------------------+-------+---------------+-------------------------------------------------------------------------------------------+
217| CD_decorators | jsonb | {} | Stores decorator for entities in entities table. |
218+-----------------------------------------+-------+---------------+-------------------------------------------------------------------------------------------+
219| REL_CD_decorators_<RELATIONSHIP_NAME> | jsonb | {} | Stores decorator for relationship inside an entity table. |
220+-----------------------------------------+-------+---------------+-------------------------------------------------------------------------------------------+
221
222When it comes to data integrity, constraints are applied to the columns. These constraints include the following:
223
224- **Primary keys:** Used to uniquely identify each record.
225- **Foreign keys:** Used for establishing relationships between tables.
226- **Uniqueness:** Used to ensure data population and prevent duplicated data.
227
228After this, tables are retrieved from the baseline schema by extracting and parsing the data. This is done by identifying various statements such as table creation, column definitions, constraints, indexes and default values from the retrieved schema file. From this it generates a comprehensive list of tables along with their respective columns and constraints.
229
230A comparison then happens between the tables from the baseline schema and the model service by performing the following actions:
231
232- Identify differences between the tables
233- Check table / column consistency
234- Verify default values and label any discrepancies
235- Verify any changes in the index
236
237The differences from this operation are then used for schema generation by generating PG SQL statements to modify/create database schema based on the identified differences between the models. It first analyzes the differences and then generates appropriate SQL statements for alterations or creations of tables and columns.
238
239These statements cater for the following scenarios:
240
241- Adding new tables / columns
242- Constraint definition such as UNIQUE or NOT NULL
243- Default value handling
244- Existing attributes modification
245- Index definition
246
247Finally, the generated schema is written into the prepared SQL file.
248
249Model Schema
250------------
251
252Following this procedure, it then proceeds to produce the TE&IV model schema by crafting SQL entries for diverse tables associated with the model, which in turn is used for dynamically loading data in schema service at start up for modules, entities and relationships.
253
254These SQL entries include:
255
256**execution_status:** This table helps in storing the execution status of the schema. This will be used in the kubernetes init containers to confirm the successful execution of the schema.
257
258+---------------+--------------------------+--------------------------------+
259| Column name | Type | Description |
260+===============+==========================+================================+
261| schema | VARCHAR(127) PRIMARY KEY | Name of the schema |
262+---------------+--------------------------+--------------------------------+
263| status | VARCHAR(127) | Status of the schema execution |
264+---------------+--------------------------+--------------------------------+
265
266**hash_info:** Postgres sets a limit of 63 characters for names of the columns, tables and constraints. Characters after the 63rd character are truncated. Names that are longer than 63 characters are hashed using SHA-1 hashing algorithm and used. _hash_info_ tables holds the name, hashedValue and the type of the entry.
267
268Sample entries:
269
270- **Hashed**: UNIQUE_GNBCUUPFunction_REL_ID_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION, UNIQUE_BDB349CDF0C4055902881ECCB71F460AE1DD323E, CONSTRAINT
271- **Un-hashed**: NRSectorCarrier, NRSectorCarrier, TABLE
272
273+---------------+--------------------------+-----------------------------------------------------------+
274| Column name | Type | Description |
275+===============+==========================+===========================================================+
276| name | TEXT PRIMARY KEY | Table / column / constraint name |
277+---------------+--------------------------+-----------------------------------------------------------+
278| hashedValue | VARCHAR(63) NOT NULL | | Hashed version of name column value if over 63 |
279| | | | character otherwise same un-hashed value |
280+---------------+--------------------------+-----------------------------------------------------------+
281| type | VARCHAR(511) | | The type of information associated i.e. Table, column |
282| | | | or constraint |
283+---------------+--------------------------+-----------------------------------------------------------+
284
285**module_reference:** For the module reference related module names from provided entities retrieved from the model service are extracted and stored which will be used for execution to module_reference table.
286
287+-----------------+-----------------------+------------------------------------------------+
288| Column name | Type | Description |
289+=================+=======================+================================================+
290| name | TEXT PRIMARY KEY | The module name |
291+-----------------+-----------------------+------------------------------------------------+
292| namespace | TEXT | The namespace the module is located |
293+-----------------+-----------------------+------------------------------------------------+
294| domain | TEXT | The domain the module is a part of |
295+-----------------+-----------------------+------------------------------------------------+
296| includedModules | jsonb | | aSideMO's and bSideMO's module reference |
297| | | | name stored within the Module |
298+-----------------+-----------------------+------------------------------------------------+
299| revision | TEXT NOT NULL | The revision date of the file |
300+-----------------+-----------------------+------------------------------------------------+
301| content | TEXT NOT NULL | | The base64 encoded format of the |
302| | | | corresponding schema. |
303+-----------------+-----------------------+------------------------------------------------+
304| ownerAppId | VARCHAR(511) NOT NULL | The identity of the owner App. |
305+-----------------+-----------------------+------------------------------------------------+
306| status | VARCHAR(127) NOT NULL | | Current status of the module reference to |
307| | | | track during the pod's life cycle. Needed |
308| | | | to avoid data loss / corruption. |
309+-----------------+-----------------------+------------------------------------------------+
310
311**decorators:** There will be the ability for Administrators to decorate topology entities and relationships. We will be storing the schemas for the decorators in this table.
312
313+------------------------------------------+--------------------------+-----------------------------------+
314| Column name | Type | Description |
315+==========================================+==========================+===================================+
316| name | VARCHAR(511) PRIMARY KEY | The key of the decorator. |
317+------------------------------------------+--------------------------+-----------------------------------+
318| dataType | VARCHAR(511) | | The data type of the decorator, |
319| | | | needed for parsing. |
320+------------------------------------------+--------------------------+-----------------------------------+
321| moduleReferenceName | VARCHAR(511) | | References the corresponding |
322| | | | module reference the decorator |
323| | | | belongs to. |
324+------------------------------------------+--------------------------+-----------------------------------+
325| | FOREIGN KEY ("moduleReferenceName") | FOREIGN KEY | Foreign key constraint |
326| | REFERENCES ties_model.module_reference | | |
327| | ("name") ON DELETE CASCADE | | |
328+------------------------------------------+--------------------------+-----------------------------------+
329
330**classifier:** There will be the ability for client applications to apply user-defined keywords/tags (classifiers) to topology entities and relationships. We will be storing the schemas for the classifiers in this table.
331
332+------------------------------------------+--------------------------+-----------------------------------------+
333| Column name | Type | Description |
334+==========================================+==========================+=========================================+
335| name | VARCHAR(511) PRIMARY KEY | The actual classifier. |
336+------------------------------------------+--------------------------+-----------------------------------------+
337| moduleReferenceName | VARCHAR(511) | | References the corresponding module |
338| | | | reference the classifier belongs to. |
339+------------------------------------------+--------------------------+-----------------------------------------+
340| | FOREIGN KEY ("moduleReferenceName") | FOREIGN KEY | Foreign key constraint |
341| | REFERENCES ties_model.module_reference | | |
342| | ("name") ON DELETE CASCADE | | |
343+------------------------------------------+--------------------------+-----------------------------------------+
344
345**entity_info:** For the entity info generation SQL entries are created and stored which will be used for execution to populate entity_info table.
346
347+------------------------------------------+------------------+-----------------------------------------+
348| Column name | Type | Description |
349+==========================================+==================+=========================================+
350| name | TEXT NOT NULL | The entity type name |
351+------------------------------------------+------------------+-----------------------------------------+
352| moduleReferenceName | TEXT NOT NULL | A reference to an associated module |
353+------------------------------------------+------------------+-----------------------------------------+
354| | FOREIGN KEY ("moduleReferenceName") | FOREIGN KEY | Foreign key constraint |
355| | REFERENCES ties_model.module_reference | | |
356| | ("name") ON DELETE CASCADE | | |
357+------------------------------------------+------------------+-----------------------------------------+
358
359**relationship_info:** When it comes to relationship info generation module reference names are assigned to relationships. For each relationship the max cardinality is taken and then sorted depending on the connection type:
360
361+------------------------------------------+------------------+-------------------------------------------------------------------+
362| Column name | Type | Description |
363+==========================================+==================+===================================================================+
364| name | TEXT PRIMARY KEY | The name of the relationship |
365+------------------------------------------+------------------+-------------------------------------------------------------------+
366| aSideAssociationName | TEXT NOT NULL | The association name for the A-side of the relationship |
367+------------------------------------------+------------------+-------------------------------------------------------------------+
368| aSideMOType | TEXT NOT NULL | The type of the managed object on the A-side of the relationship |
369+------------------------------------------+------------------+-------------------------------------------------------------------+
370| aSideModule | TEXT NOT NULL | The aSide module name |
371+------------------------------------------+------------------+-------------------------------------------------------------------+
372| aSideMinCardinality | BIGINT NOT NULL | The minimum cardinality of the A-side of the relationship |
373+------------------------------------------+------------------+-------------------------------------------------------------------+
374| aSideMaxCardinality | BIGINT NOT NULL | The maximum cardinality of the A-side of the relationship |
375+------------------------------------------+------------------+-------------------------------------------------------------------+
376| bSideAssociationName | TEXT NOT NULL | The association name for the B-side of the relationship |
377+------------------------------------------+------------------+-------------------------------------------------------------------+
378| bSideMOType | TEXT NOT NULL | The type of the managed object on the B-side of the relationship |
379+------------------------------------------+------------------+-------------------------------------------------------------------+
380| bSideModule | TEXT NOT NULL | The bSide module name |
381+------------------------------------------+------------------+-------------------------------------------------------------------+
382| bSideMinCardinality | BIGINT NOT NULL | The minimum cardinality of the B-side of the relationship |
383+------------------------------------------+------------------+-------------------------------------------------------------------+
384| bSideMaxCardinality | BIGINT NOT NULL | The maximum cardinality of the B-side of the relationship |
385+------------------------------------------+------------------+-------------------------------------------------------------------+
386| associationKind | TEXT NOT NULL | The kind of association between entities |
387+------------------------------------------+------------------+-------------------------------------------------------------------+
388| relationshipDataLocation | TEXT NOT NULL | Indicates where associated relationship data is stored |
389+------------------------------------------+------------------+-------------------------------------------------------------------+
390| connectSameEntity | BOOLEAN NOT NULL | Indicates whether the relationship connects the same entity |
391+------------------------------------------+------------------+-------------------------------------------------------------------+
392| moduleReferenceName | TEXT PRIMARY KEY | The name of the module reference associated with the relationship |
393+------------------------------------------+------------------+-------------------------------------------------------------------+
394| | FOREIGN KEY ("aSideModule") REFERENCES | FOREIGN KEY | Foreign key constraint |
395| | ties_model.module_reference ("name") | | |
396| | ON DELETE CASCADE | | |
397+------------------------------------------+------------------+-------------------------------------------------------------------+
398| | FOREIGN KEY ("bSideModule") REFERENCES | FOREIGN KEY | Foreign key constraint |
399| | ties_model.module_reference ("name") | | |
400| | ON DELETE CASCADE | | | |
401+------------------------------------------+------------------+-------------------------------------------------------------------+
402| | FOREIGN KEY ("moduleReferenceName") |FOREIGN KEY | Foreign key constraint |
403| | REFERENCES | | |
404| | ties_model.module_reference ("name") | | |
405| | ON DELETE CASCADE | | |
406+------------------------------------------+------------------+-------------------------------------------------------------------+
407
408Along with this, it ensures that the structure for the model schema SQL file starts with the correct structure by importing the baseline schema information.
409
410Finally, these generated entries and structure are then used to modify the model SQL file.
411
412Skeleton Data and Model SQL Files
413=================================
414
415- 00_init-oran-smo-teiv-data.sql "src/main/resources/scripts/00_init-oran-smo-teiv-data.sql"
416
417 Proprietary PG SQL Function
418
419 Create constant if it doesn't exist
420
421 .. code-block:: sql
422
423 CREATE OR REPLACE FUNCTION ties_data.create_constraint_if_not_exists (
424 t_name TEXT, c_name TEXT, constraint_sql TEXT
425 )
426 RETURNS void AS
427 BEGIN
428 IF NOT EXISTS (SELECT constraint_name FROM information_schema.table_constraints
429 WHERE table_name = t_name AND constraint_name = c_name) THEN
430 EXECUTE constraint_sql;
431 END IF;
432 END;
433
434 Example:
435
436 .. code-block:: sql
437
438 SELECT ties_data.create_constraint_if_not_exists(
439 'CloudNativeApplication',
440 'PK_CloudNativeApplication_id',
441 'ALTER TABLE ties_data."CloudNativeApplication" ADD CONSTRAINT "PK_CloudNativeApplication_id" PRIMARY KEY ("id");'
442 );
443
444- "01_init-oran-smo-teiv-model.sql "src/main/resources/scripts/01_init-oran-smo-teiv-model.sql"
445
446Unsupported Non-Backward Compatible(NBC) Model Changes
447======================================================
448
449The following NBC model changes are unsupported due to their actions resulting in issues for upgrade scenarios.
450
451+-------------------------------------------------------+
452| Change |
453+=======================================================+
454| Delete attributes / entities / relationships |
455+-------------------------------------------------------+
456| Modify constraints on the attributes / relationships |
457+-------------------------------------------------------+
458| Change datatype of the attributes |
459+-------------------------------------------------------+
460| Rename attributes / relationships / entities |
461+-------------------------------------------------------+
462| Change aSide / bSide associated with a relationship |
463+-------------------------------------------------------+
464| Change cardinality of aSide / bSide in a relationship |
465+-------------------------------------------------------+
466
467There are checks in place to identify any NBC model change from above. These checks will compare the extracted data from baseline schema with data from model service to identify NBC model changes.
468
469NBC checks:
470
471- Verify deletion or modification to any attribute / entities / relationships and their properties.
472- Validate constraints on attributes / relationships.
473- Identify change to aSide / bSide managed object associated with a relationship.
474- Verify cardinality constraints to aSide/bSide of a relationship.
475
476If there is a requirement to update schema with NBC changes, in such case green field installation must be turned on. Green field installation enables the PG SQL Schema generator service to construct a new schema from scratch rather than updating on top of existing baseline schema.
477
478Please refer to BackwardCompatibilityChecker.java "src/main/java/org/oran/smo/teiv/pgsqlgenerator/schema/BackwardCompatibilityChecker.java" for more info.
479
480Local Use
481=========
482
483Copy YANG models into the generate-defaults "src/main/resources/generate-defaults" directory. Once done, perform the schema generation process by running the Spring Boot application within the pgsql-schema-generator directory using *mvn spring-boot:run*. The command will also run the Spring Boot tests and output the results.
484
485To run the test suite:
486
487- In your terminal, navigate into the pgsql-schema-generator directory and run 'mvn clean install'
488- In your terminal, navigate into the pgsql-schema-generator directory and run 'mvn -Dtest=<Test Name> test'