Chapter 2: The Building Blocks
Goal: Deconstruct the magic. Understand the core components of a Daana project and how they work together.
Prerequisites: You should have completed Chapter 1: Jump Start.
The "Why" Behind the "Wow"
In Chapter 1, you ran a few commands and got a fully merged, time-traveling data warehouse. It felt like magic, but it's actually engineering.
Let's break down the three pillars of Daana:
- The Model (What)
- The Mapping (Where)
- The Workflow (How)
1. The Model (What)
The Model is your "Commercial Representation". It describes your business reality, independent of source systems.
entities:
- id: "CUSTOMER"
attributes:
- id: "CUSTOMER_NAME"
type: "STRING"- Entities: The nouns of your business (Customer, Order, Product).
- Attributes: The adjectives (Name, Price, City).
- Relationships: The verbs (Customer places Order).
Key Concept: Models are declarative. You don't tell Daana "create a table with varchar(255)". You say "I have a Customer Name", and Daana figures out the optimal storage for your database platform.
2. The Mapping (Where)
The Mapping connects your clean Model to your messy Source Data.
entity_id: CUSTOMER
mapping_groups:
- tables:
- table: stage.customers
attributes:
- id: CUSTOMER_NAME
transformation_expression: CONCAT(first_name, ' ', last_name)- Transformation Expression: Where you write SQL logic to clean data before it enters your warehouse.
- Mapping Groups: How you tell Daana "these 2 tables all describe the same Entity" (like we did with customers + customer_addresses).
3. The Workflow (How)
The Workflow orchestrates the execution.
workflow:
model:
file: "model.yaml"
mappings:
- "mappings/customer-mapping.yaml"
connection: "dev"It ties the abstract Model and Mappings to a concrete environment (Connection Profile). This allows you to deploy the same logic to Dev, Staging, and Production just by changing the profile.
The Lifecycle: Check -> Deploy -> Execute
You ran these commands in Chapter 1. Here is what they actually do:
1. Check (daana-cli check)
Input: Your YAML files (human-readable). Action: Validates syntax, checks references, and ensures your model and mappings are correct. Think of this as "compiling code" - catching errors before runtime.
2. Deploy (daana-cli deploy)
Input: Your workflow file.
Output: Physical tables and views in your Data Warehouse.
Action: This is where CREATE TABLE and CREATE VIEW statements happen. It creates the infrastructure and prepares your workflow for execution.
3. Execute (daana-cli execute)
Action: Moves the actual data. It runs the INSERT / MERGE / SELECT statements generated by the deploy step.
Try It Yourself
Now let's experiment to see how Daana validates your work.
Exercise 1: Break the Model (and See Daana Catch It)
Introduce an intentional error:
-
Open
model.yamland changeCUSTOMERtoCUSTOMERZ(just in the entity id):Before:
entities: - id: "CUSTOMER"After:
entities: - id: "CUSTOMERZ" -
Run validation:
daana-cli check workflowNote: You may see "Connection Profile Warnings" about hardcoded passwords. This is expected in the tutorial setup - in production you would use environment variables.
-
You'll see an error like:
✘ Errors: Undefined Entity Reference: • model.yaml: Relationship 'IS_PLACED_BY' references undefined entity 'CUSTOMER' Mapping Model Validation: • customer-mapping.yaml: Entity 'CUSTOMER' not found in model
Why this matters: Daana catches reference errors before you touch the database. No more "deploy and pray".
Fix it back to CUSTOMER before continuing.
Exercise 2: Remove an Attribute from the Model
-
In
model.yaml, comment out the entireCUSTOMER_STATUSattribute block:# - id: "CUSTOMER_STATUS" # name: "CUSTOMER_STATUS" # definition: "Account status (Active, Inactive, Suspended)" # type: "STRING" # effective_timestamp: true -
Run validation:
daana-cli check workflow -
Observe the error - the mapping references an attribute that no longer exists in the model.
This demonstrates the tight connection between Model and Mapping. They must stay in sync.
Fix it by uncommenting the attribute before continuing.
Exercise 3: See What's in the Database
Curious what Daana actually created? Explore the generated tables:
docker exec -it daana-customerdb psql -U dev -d customerdb -c "\dt daana_dw.*"Output:
List of relations
Schema | Name | Type | Owner
----------+------------------+-------+-------
daana_dw | customer_desc | table | dev
daana_dw | customer_focal | table | dev
daana_dw | customer_idfr | table | dev
daana_dw | order_customer_x | table | dev
daana_dw | order_desc | table | dev
daana_dw | order_focal | table | dev
daana_dw | order_idfr | table | dev
(7 rows)See the structure of the customer table:
docker exec -it daana-customerdb psql -U dev -d customerdb -c "\d daana_dw.customer_focal"Output:
Table "daana_dw.customer_focal"
Column | Type | Collation | Nullable | Default
--------------+--------------------------------+-----------+----------+----------------
customer_key | character varying(256) | | not null |
inst_key | bigint | | not null |
inst_row_key | bigint | | |
popln_tmstp | timestamp(6) without time zone | | not null | LOCALTIMESTAMP
Indexes:
"pk_daana_dw_customer_focal" UNIQUE, btree (customer_key)Notice how Daana translated your abstract model into concrete database objects.
Learn more: See Understanding Daana Output for details on the
_focal,_desc,_idfr, and_xtables.
Summary
- Models define the destination.
- Mappings define the path from source.
- Workflows define the execution context.
Now that you understand the pieces, let's learn how to design better Models.