Skip to content

Commit

Permalink
feature: use database triggers to add records on Hardware insert (#1026)
Browse files Browse the repository at this point in the history
* refactor: add database triggers to insert records into all hardware tables

* refactor: remove code calling for inserts to hardware tables

* test: use data directory file to create test database; only data in test

* ci: force push tags so 'latest' always gets pushed

* refactor: update table models to add node to tree on Hardware insert

* test: update table model tests

* style: update stub files

* ci: update open PR workflow token
  • Loading branch information
weibullguy authored Mar 10, 2022
1 parent 6d4bc77 commit f7cbb7c
Show file tree
Hide file tree
Showing 36 changed files with 2,420 additions and 2,467 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/on-pr-close.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,4 @@ jobs:
git config --global user.email "${{ steps.import_gpg.outputs.email }}"
git config --global user.name "${{ steps.import_gpg.outputs.name }}"
git tag -s -a -m"v${{ steps.nextversion.outputs.next_version }}" v${{steps.nextversion.outputs.next_version }}
git push --tags
git push --tags -f
102 changes: 102 additions & 0 deletions data/postgres_program_db.sql
Original file line number Diff line number Diff line change
Expand Up @@ -1321,6 +1321,83 @@ END;
$function$
;

CREATE OR REPLACE FUNCTION public.insertdesignelectricrecord()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
BEGIN
IF NEW.fld_part = 1 THEN
INSERT INTO ramstk_design_electric(fld_revision_id,fld_hardware_id)
VALUES(NEW.fld_revision_id, NEW.fld_hardware_id);
END IF;

RETURN NEW;

END;
$function$
;

CREATE OR REPLACE FUNCTION public.insertdesignmechanicrecord()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
BEGIN
IF NEW.fld_part = 1 THEN
INSERT INTO ramstk_design_mechanic(fld_revision_id,fld_hardware_id)
VALUES(NEW.fld_revision_id, NEW.fld_hardware_id);
END IF;

RETURN NEW;

END;
$function$
;

CREATE OR REPLACE FUNCTION public.insertmilhdbk217frecord()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
BEGIN
IF NEW.fld_part = 1 THEN
INSERT INTO ramstk_mil_hdbk_f(fld_revision_id,fld_hardware_id)
VALUES(NEW.fld_revision_id, NEW.fld_hardware_id);
END IF;

RETURN NEW;

END;
$function$
;

CREATE OR REPLACE FUNCTION public.insertnswcrecord()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
BEGIN
IF NEW.fld_part = 1 THEN
INSERT INTO ramstk_nswc(fld_revision_id,fld_hardware_id)
VALUES(NEW.fld_revision_id, NEW.fld_hardware_id);
END IF;

RETURN NEW;

END;
$function$
;

CREATE OR REPLACE FUNCTION public.insertreliabilityrecord()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
BEGIN
INSERT INTO ramstk_reliability(fld_revision_id,fld_hardware_id)
VALUES(NEW.fld_revision_id, NEW.fld_hardware_id);
RETURN NEW;

END;
$function$
;

-- Create triggers
create trigger insertallocationrecord after
insert
Expand All @@ -1331,3 +1408,28 @@ create trigger insertsimilaritemrecord after
insert
on
public.ramstk_hardware for each row execute procedure insertsimilaritemrecord();

create trigger insertdesignelectricrecord after
insert
on
public.ramstk_hardware for each row execute procedure insertdesignelectricrecord();

create trigger insertdesignmechanicrecord after
insert
on
public.ramstk_hardware for each row execute procedure insertdesignmechanicrecord();

create trigger insertmilhdbk217frecord after
insert
on
public.ramstk_hardware for each row execute procedure insertmilhdbk217frecord();

create trigger insertnswcrecord after
insert
on
public.ramstk_hardware for each row execute procedure insertnswcrecord();

create trigger insertreliabilityrecord after
insert
on
public.ramstk_hardware for each row execute procedure insertreliabilityrecord();
34 changes: 34 additions & 0 deletions src/ramstk/models/dbtables/programdb_allocation_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from typing import Any, Dict, Tuple, Type, Union

# Third Party Imports
import treelib
from pubsub import pub

# RAMSTK Package Imports
Expand Down Expand Up @@ -93,6 +94,10 @@ def __init__(self, **kwargs: Dict[str, Union[float, int, str]]) -> None:
self.do_calculate_allocation_goals,
"request_calculate_allocation_goals",
)
pub.subscribe(
self._on_insert_hardware,
"succeed_insert_hardware",
)

def do_get_new_record( # pylint: disable=method-hidden
self, attributes: Dict[str, Union[date, float, int, str]]
Expand Down Expand Up @@ -348,3 +353,32 @@ def _do_calculate_foo_cumulative_weight(self, node_id: int) -> int:
)

return _cum_weight

def _on_insert_hardware(self, tree: treelib.Tree) -> None:
"""Add new node to the Allocation tree for the newly added Hardware.
Allocation records are added by triggers in the database when a new Hardware
item is added. This method simply adds a new node to the Allocation tree
with a blank record.
:param tree: the Hardware tree with the new node.
:return: None
:rtype: None
"""
for _node in tree.all_nodes()[1:]:
if (
not self.tree.contains(_node.identifier)
and not _node.data["hardware"].part
):
_attributes = {
"revision_id": _node.data["hardware"].revision_id,
"hardware_id": _node.data["hardware"].hardware_id,
"parent_id": _node.data["hardware"].parent_id,
}
_record = self.do_get_new_record(_attributes)
self.tree.create_node(
tag=self._tag,
identifier=_node.data["hardware"].hardware_id,
parent=_node.data["hardware"].parent_id,
data={self._tag: _record},
)
4 changes: 4 additions & 0 deletions src/ramstk/models/dbtables/programdb_allocation_table.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
from datetime import date
from typing import Dict, List, Tuple, Type, Union

# Third Party Imports
import treelib

# RAMSTK Package Imports
from ramstk.analyses import allocation as allocation

Expand Down Expand Up @@ -33,3 +36,4 @@ class RAMSTKAllocationTable(RAMSTKBaseTable):
def do_calculate_foo_allocation(self, node_id: int) -> None: ...
def _do_calculate_agree_total_elements(self, node_id: int) -> Tuple[int, int]: ...
def _do_calculate_foo_cumulative_weight(self, node_id: int) -> int: ...
def _on_insert_hardware(self, tree: treelib.Tree) -> None: ...
40 changes: 39 additions & 1 deletion src/ramstk/models/dbtables/programdb_design_electric_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
from datetime import date
from typing import Dict, Type, Union

# Third Party Imports
import treelib
from pubsub import pub

# RAMSTK Local Imports
from ..dbrecords import RAMSTKDesignElectricRecord
from .basetable import RAMSTKBaseTable
Expand Down Expand Up @@ -61,6 +65,10 @@ def __init__(self, **kwargs: Dict[str, Union[float, int, str]]) -> None:
self.pkey = "hardware_id"

# Subscribe to PyPubSub messages.
pub.subscribe(
self._on_insert_hardware,
"succeed_insert_hardware",
)

def do_get_new_record( # pylint: disable=method-hidden
self, attributes: Dict[str, Union[date, float, int, str]]
Expand All @@ -73,6 +81,36 @@ def do_get_new_record( # pylint: disable=method-hidden
"""
_new_record = self._record()
_new_record.revision_id = attributes["revision_id"]
_new_record.hardware_id = self.last_id + 1
_new_record.hardware_id = attributes["hardware_id"]

return _new_record

def _on_insert_hardware(self, tree: treelib.Tree) -> None:
"""Add new node to the Design Electric tree for the newly added Hardware.
Design Electric records are added by triggers in the database when a new
Hardware item is added. This method simply adds a new node to the Design
Electric tree with a blank record.
:param tree: the Hardware tree with the new node.
:return: None
:rtype: None
"""
for _node in tree.all_nodes()[1:]:
if not self.tree.contains(_node.identifier) and _node.data["hardware"].part:
_attributes = {
"revision_id": _node.data["hardware"].revision_id,
"hardware_id": _node.data["hardware"].hardware_id,
}
_record = self.do_get_new_record(_attributes)
self.tree.create_node(
tag=self._tag,
identifier=_node.data["hardware"].hardware_id,
parent=0,
data={self._tag: _record},
)

pub.sendMessage(
f"succeed_insert_{self._tag}",
tree=self.tree,
)
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
from datetime import date
from typing import Dict, List, Type, Union

# Third Party Imports
import treelib

# RAMSTK Local Imports
from ..dbrecords import RAMSTKDesignElectricRecord as RAMSTKDesignElectricRecord
from .basetable import RAMSTKBaseTable as RAMSTKBaseTable
Expand All @@ -18,3 +21,4 @@ class RAMSTKDesignElectricTable(RAMSTKBaseTable):
def do_get_new_record(
self, attributes: Dict[str, Union[date, float, int, str]]
) -> RAMSTKDesignElectricRecord: ...
def _on_insert_hardware(self, tree: treelib.Tree) -> None: ...
40 changes: 39 additions & 1 deletion src/ramstk/models/dbtables/programdb_design_mechanic_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
from datetime import date
from typing import Dict, Type, Union

# Third Party Imports
import treelib
from pubsub import pub

# RAMSTK Local Imports
from ..dbrecords import RAMSTKDesignMechanicRecord
from .basetable import RAMSTKBaseTable
Expand Down Expand Up @@ -60,6 +64,10 @@ def __init__(self, **kwargs: Dict[str, Union[float, int, str]]) -> None:
self.pkey = "hardware_id"

# Subscribe to PyPubSub messages.
pub.subscribe(
self._on_insert_hardware,
"succeed_insert_hardware",
)

def do_get_new_record( # pylint: disable=method-hidden
self, attributes: Dict[str, Union[date, float, int, str]]
Expand All @@ -72,6 +80,36 @@ def do_get_new_record( # pylint: disable=method-hidden
"""
_new_record = self._record()
_new_record.revision_id = attributes["revision_id"]
_new_record.hardware_id = self.last_id + 1
_new_record.hardware_id = attributes["hardware_id"]

return _new_record

def _on_insert_hardware(self, tree: treelib.Tree) -> None:
"""Add new node to the Design Mechanic tree for the newly added Hardware.
Design Mechanic records are added by triggers in the database when a new
Hardware item is added. This method simply adds a new node to the Design
Mechanic tree with a blank record.
:param tree: the Hardware tree with the new node.
:return: None
:rtype: None
"""
for _node in tree.all_nodes()[1:]:
if not self.tree.contains(_node.identifier) and _node.data["hardware"].part:
_attributes = {
"revision_id": _node.data["hardware"].revision_id,
"hardware_id": _node.data["hardware"].hardware_id,
}
_record = self.do_get_new_record(_attributes)
self.tree.create_node(
tag=self._tag,
identifier=_node.data["hardware"].hardware_id,
parent=0,
data={self._tag: _record},
)

pub.sendMessage(
f"succeed_insert_{self._tag}",
tree=self.tree,
)
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
from datetime import date
from typing import Dict, List, Type, Union

# Third Party Imports
import treelib

# RAMSTK Local Imports
from ..dbrecords import RAMSTKDesignMechanicRecord as RAMSTKDesignMechanicRecord
from .basetable import RAMSTKBaseTable as RAMSTKBaseTable
Expand All @@ -18,3 +21,4 @@ class RAMSTKDesignMechanicTable(RAMSTKBaseTable):
def do_get_new_record(
self, attributes: Dict[str, Union[date, float, int, str]]
) -> RAMSTKDesignMechanicRecord: ...
def _on_insert_hardware(self, tree: treelib.Tree) -> None: ...
40 changes: 39 additions & 1 deletion src/ramstk/models/dbtables/programdb_milhdbk217f_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
from datetime import date
from typing import Dict, Type, Union

# Third Party Imports
import treelib
from pubsub import pub

# RAMSTK Local Imports
from ..dbrecords import RAMSTKMilHdbk217FRecord
from .basetable import RAMSTKBaseTable
Expand Down Expand Up @@ -60,6 +64,10 @@ def __init__(self, **kwargs: Dict[str, Union[float, int, str]]) -> None:
self.pkey = "hardware_id"

# Subscribe to PyPubSub messages.
pub.subscribe(
self._on_insert_hardware,
"succeed_insert_hardware",
)

def do_get_new_record( # pylint: disable=method-hidden
self, attributes: Dict[str, Union[date, float, int, str]]
Expand All @@ -72,6 +80,36 @@ def do_get_new_record( # pylint: disable=method-hidden
"""
_new_record = self._record()
_new_record.revision_id = attributes["revision_id"]
_new_record.hardware_id = self.last_id + 1
_new_record.hardware_id = attributes["hardware_id"]

return _new_record

def _on_insert_hardware(self, tree: treelib.Tree) -> None:
"""Add new node to the MIL-HDBK-217F tree for the newly added Hardware.
MIL-HDBK-217F records are added by triggers in the database when a new
Hardware item is added. This method simply adds a new node to the MIL-HDBK-217F
tree with a blank record.
:param tree: the Hardware tree with the new node.
:return: None
:rtype: None
"""
for _node in tree.all_nodes()[1:]:
if not self.tree.contains(_node.identifier) and _node.data["hardware"].part:
_attributes = {
"revision_id": _node.data["hardware"].revision_id,
"hardware_id": _node.data["hardware"].hardware_id,
}
_record = self.do_get_new_record(_attributes)
self.tree.create_node(
tag=self._tag,
identifier=_node.data["hardware"].hardware_id,
parent=0,
data={self._tag: _record},
)

pub.sendMessage(
f"succeed_insert_{self._tag}",
tree=self.tree,
)
Loading

0 comments on commit f7cbb7c

Please sign in to comment.