Skip to content

SQL - Business logic

In this example we create user defined functions implementing business logic. If you haven't done already, please read the Simple staging example first for a basic explanation of concepts used in the template and config. The functions implemented in this example are used in the SSIS DataVault example.

Model

In this example we will be generating the business logic (business rules) defined in the DWH model.

Template

We create a template for each type of business rule. The example model contains two types of rules: a derived field and a lookup.

DeriveRule_owner.udf_BR_DeriveRule_name.sql

The derived field template creates a function with the appropriate signature based on the parameters and attributes defined in the model. For the implementation the business rule child element expression is referenced.

Note

When a model attribute is accessed an underscore is used as accessor (for example Parameter_name) a child element is accessed using the dollar sign (for example DeriveRule$expression). The accessors can be configured in the config.

-- @XGenComment(This is the function template for all derive rules in the DWH)
CREATE FUNCTION [DeriveRule_owner].[udf_BR_DeriveRule_name] (
  -- @XGenTextSection(name="Parameter" suffix=",")
  @Parameter_name Parameter_fulldatatype
)
RETURNS TABLE
RETURN
  SELECT
    -- @XGenTextSection(name="Attribute" suffix=",")
    [Rule].[Attribute_name]
  FROM DeriveRule$expression AS [Rule]
GO

LookupRule_owner.udf_BR_LookupRule_name.sql

In the model a lookup business rule has a mapped source entity. With the information in the model an implementation can be generated that performs a lookup query on the mapped source entity.

-- @XGenComment(This is the function template for all lookup rules in the DWH)
CREATE FUNCTION [LookupRule_owner].[udf_BR_LookupRule_name] (
  -- @XGenTextSection(name="Parameter" suffix=",")
  @Parameter_name Parameter_fulldatatype
)
RETURNS TABLE
RETURN
  WITH [Source_CTE] (
    -- @XGenTextSection(name="Parameter")
    [Parameter_name],
    -- @XGenTextSection(name="Attribute" suffix=",")
    [Attribute_name]
  ) AS (
    SELECT
      -- @XGenTextSection(name="MappedParameter")
      MappedParameter_expression AS [MappedParameter_targetAttributeName],
      -- @XGenTextSection(name="MappedAttribute" suffix=",")
      MappedAttribute_expression AS [MappedAttribute_targetAttributeName]
    -- @XGenTextSection(name="MappableObjectMapping")
    FROM MappableObjectMapping_mappedObjectJoiner
  )
  SELECT
    -- @XGenTextSection(name="Attribute" suffix=",")
    [Attribute_name]
  FROM [Source_CTE]
  WHERE
    -- @XGenTextSection(name="Parameter" prefix="AND ")
    [Parameter_name] = @Parameter_name
;
GO

Documentation

For documentation on templates, please see Template.

Config

Each type of business rule requires it's specific configuration, for this example we therefore have two configs.

Config for derived field

<?xml version="1.0" encoding="UTF-8"?>
<XGenConfig>
  <Model/>
  <TextTemplate rootSectionName="DeriveRule">
    <FileFormat currentAccessor="_" childAccessor="$" singleLineCommentPrefix="--" annotationPrefix="@XGen" annotationArgsPrefix="(" annotationArgsSuffix=")" />
    <Output type="output_per_element" />
  </TextTemplate>
  <Binding>
        <SectionModelBinding section="DeriveRule" modelXPath="/modeldefinition/system/mappableObjects/businessRule[@stereotype='derive']" placeholderName="DeriveRule">
            <SectionModelBinding section="Parameter" modelXPath="attributes/parameter" placeholderName="Parameter" />
            <SectionModelBinding section="Attribute" modelXPath="attributes/attribute" placeholderName="Attribute" />
        </SectionModelBinding>
  </Binding>
</XGenConfig>

Config for lookup rule

<?xml version="1.0" encoding="UTF-8"?>
<XGenConfig>
  <Model/>
  <TextTemplate rootSectionName="LookupRule">
    <FileFormat currentAccessor="_" childAccessor="$" singleLineCommentPrefix="--" annotationPrefix="@XGen" annotationArgsPrefix="(" annotationArgsSuffix=")" />
    <Output type="output_per_element" />
  </TextTemplate>
  <Binding>
        <SectionModelBinding section="LookupRule" modelXPath="/modeldefinition/system/mappableObjects/businessRule[@stereotype='lookup']" placeholderName="LookupRule">
            <SectionModelBinding section="Parameter" modelXPath="attributes/parameter" placeholderName="Parameter" />
            <SectionModelBinding section="Attribute" modelXPath="attributes/attribute" placeholderName="Attribute" />
            <SectionModelBinding section="MappableObjectMapping" modelXPath="mappableObjectMappings/mappableObjectMapping" placeholderName="MappableObjectMapping" />
            <SectionModelBinding section="MappedParameter" modelXPath="mappableObjectMappings/mappableObjectMapping/attributeMappings/attributeMapping[@targetAttributeStereotype='parameter']" placeholderName="MappedParameter" />
            <SectionModelBinding section="MappedAttribute" modelXPath="mappableObjectMappings/mappableObjectMapping/attributeMappings/attributeMapping[@targetAttributeStereotype='attribute']" placeholderName="MappedAttribute" />
        </SectionModelBinding>
  </Binding>
</XGenConfig>

Documentation

For documentation on the configuration, please see Config.

Output

When running CrossGenerate the output using the given Model, Templates and Configs will be as follows:

BusinessRule.udf_BR_Derive_Customer_FullName.sql

CREATE FUNCTION [BusinessRule].[udf_BR_Derive_Customer_FullName] (
  @FirstName varchar(50),
  @LastName varchar(100)
)
RETURNS TABLE
RETURN
  SELECT
    [Rule].[FullName]
  FROM (SELECT @FirstName + ' ' + @LastName AS [FullName]) AS [Rule]
GO

BusinessRule.udf_BR_Lookup_Country.sql

CREATE FUNCTION [BusinessRule].[udf_BR_Lookup_Country] (
  @Country_Code varchar(3)
)
RETURNS TABLE
RETURN
  WITH [Source_CTE] (
    [Country_Code],
    [Country_Description],
    [Country_Continent]
  ) AS (
    SELECT
      Reference_Country.Country_Code AS [Country_Code],
      Reference_Country.Country_Description AS [Country_Description],
      Reference_Country.Country_Continent AS [Country_Continent]
    FROM [$(DWH_Staging_Reference)].[dbo].[Country] AS [Reference_Country]
  )
  SELECT
    [Country_Description],
    [Country_Continent]
  FROM [Source_CTE]
  WHERE
        [Country_Code] = @Country_Code
;
GO

Attachments

The entire DataVault example, including SQL and SSIS templates, can be found in the SSIS DataVault example.