diff --git a/package/c/hemar/hemar.c b/package/c/hemar/hemar.c
index 7183394..104b8ea 100755
--- a/package/c/hemar/hemar.c
+++ b/package/c/hemar/hemar.c
@@ -1547,9 +1547,13 @@ render_template(TemplateNode *node, Jsonb *define, StringInfo result, MemoryCont
/* Get the include data from the context */
JsonbValue *include_data = jsonb_get_by_path_internal(define, include_path, context);
- elog(DEBUG1, "Include data: %s", JsonbToCString(NULL, &JsonbValueToJsonb(include_data)->root, VARSIZE_ANY_EXHDR(JsonbValueToJsonb(include_data))));
+ if (!include_data)
+ {
+ elog(WARNING, "Include data not found");
+ break;
+ }
- if (include_data != NULL && include_data->type == jbvBinary)
+ if (include_data->type == jbvBinary)
{
JsonbIterator *it = JsonbIteratorInit((JsonbContainer *)include_data->val.binary.data);
JsonbIteratorToken token;
diff --git a/package/c/hemar/test/test_render_all.sql b/package/c/hemar/test/test_render_all.sql
index 8282ea6..d590999 100755
--- a/package/c/hemar/test/test_render_all.sql
+++ b/package/c/hemar/test/test_render_all.sql
@@ -1,219 +1,231 @@
--- Test all template tags together
-DO $$
-DECLARE
- total_tests INT := 0;
- passed_tests INT := 0;
- test_result TEXT;
- expected TEXT;
- passed BOOLEAN;
-BEGIN
- -- Test 1: Complex template with all tag types
- total_tests := total_tests + 1;
- test_result := hemar.render(
- '{
- "page": {
- "title": "My Page",
- "sections": [
- {
- "id": "section1",
- "title": "Section 1",
- "items": [
- {
- "id": "item1",
- "status": "active",
- "content": "Item 1 Content",
- "template": "item_template"
- },
- {
- "id": "item2",
- "status": "inactive",
- "content": "Item 2 Content",
- "template": "item_template"
- }
- ]
- }
- ]
- },
- "include": {
- "meta_tags": {
- "content": ""
- },
- "header": {
- "template": "Welcome to {{ page.title }}!",
- "context": {
- "page": {
- "title": "My Page"
- }
- }
- },
- "item_template": {
- "template": "Status: {{ status }}, Content: {{ content }}"
- },
- "footer": {
- "content": ""
- }
- }
- }'::jsonb,
- $template$
-
-
- {{ page.title }}
- {{ include meta_tags }}
-
-
-
-
- {{ for section in page.sections }}
-
- {{ section.title }}
- {{ for item in section.items }}
-
- {{ include item.template }}
- {{ exec
- DECLARE
- v_status TEXT;
- BEGIN
- v_status := context->'item'->>'status';
- RETURN CASE
- WHEN v_status = 'active' THEN ' (Active Item)'
- ELSE ' (Inactive Item)'
- END;
- END;
- }}
-
- {{ end }}
-
- {{ end }}
-
-
-
-$template$
- );
-
- expected := '
-
-
- My Page
-
-
-
-
-
-
- Section 1
-
- Status: active, Content: Item 1 Content (Active Item)
-
-
- Status: inactive, Content: Item 2 Content (Inactive Item)
-
-
-
-
-
-';
-
- passed := test_result = expected;
- passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
- IF passed THEN
- RAISE NOTICE 'Test %: Complex template with all tag types: PASSED', total_tests;
- ELSE
- RAISE WARNING 'Test %: Complex template with all tag types: FAILED. Expected "%", got "%"',
- total_tests, expected, test_result;
- END IF;
-
- -- Test 2: Template with nested includes and shared context
- total_tests := total_tests + 1;
- test_result := hemar.render(
- '{
- "user": {
- "name": "John",
- "role": "admin"
- },
- "include": {
- "user_info": {
- "template": "User: {{ user.name }} ({{ user.role }})"
- },
- "permissions": {
- "template": "{{ include user_info }} - Permissions: {{ for perm in user.permissions }}{{ perm }} {{ end }}",
- "context": {
- "user": {
- "name": "John",
- "role": "admin",
- "permissions": ["read", "write", "delete"]
- }
- }
- }
- }
- }'::jsonb,
- $template${{ include permissions }}$template$
- );
-
- expected := 'User: John (admin) - Permissions: read write delete ';
-
- passed := test_result = expected;
- passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
- IF passed THEN
- RAISE NOTICE 'Test %: Template with nested includes and shared context: PASSED', total_tests;
- ELSE
- RAISE WARNING 'Test %: Template with nested includes and shared context: FAILED. Expected "%", got "%"',
- total_tests, expected, test_result;
- END IF;
-
- -- Test 3: Template with execute tag using context from section
- total_tests := total_tests + 1;
- test_result := hemar.render(
- '{
- "items": [
- {"id": 1, "value": 100},
- {"id": 2, "value": 200},
- {"id": 3, "value": 300}
- ]
- }'::jsonb,
- $template$Items:
-{{ for item in items }}
- Item {{ item.id }}: {{ exec
- DECLARE
- v_value INT;
- BEGIN
- v_value := (context->>'value')::int;
- RETURN v_value * 2;
- END;
- }}
-{{ end }}$template$
- );
-
- expected := 'Items:
- Item 1: 200
- Item 2: 400
- Item 3: 600
-';
-
- passed := test_result = expected;
- passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
- IF passed THEN
- RAISE NOTICE 'Test %: Template with execute tag using context from section: PASSED', total_tests;
- ELSE
- RAISE WARNING 'Test %: Template with execute tag using context from section: FAILED. Expected "%", got "%"',
- total_tests, expected, test_result;
- END IF;
-
- -- Print summary
- IF passed_tests = total_tests THEN
- RAISE NOTICE '------------------------------------';
- RAISE NOTICE 'SUMMARY: % of % combined template tests passed (100%%)',
- passed_tests, total_tests;
- RAISE NOTICE '------------------------------------';
- ELSE
- RAISE WARNING '------------------------------------';
- RAISE WARNING 'SUMMARY: % of % combined template tests passed (%)',
- passed_tests,
- total_tests,
- round((passed_tests::numeric / total_tests::numeric) * 100, 2) || '%';
- RAISE WARNING '------------------------------------';
- END IF;
-
- IF passed_tests != total_tests THEN
- RAISE EXCEPTION 'Tests failed: % of % combined template tests did not pass', (total_tests - passed_tests), total_tests;
- END IF;
+-- Test all template tags together
+DO $$
+DECLARE
+ total_tests INT := 0;
+ passed_tests INT := 0;
+ test_result TEXT;
+ expected TEXT;
+ passed BOOLEAN;
+BEGIN
+ -- Test 1: Complex template with all tag types
+ total_tests := total_tests + 1;
+ BEGIN
+ test_result := hemar.render(
+ '{
+ "page": {
+ "title": "My Page",
+ "sections": [
+ {
+ "id": "section1",
+ "title": "Section 1",
+ "items": [
+ {
+ "id": "item1",
+ "status": "active",
+ "content": "Item 1 Content",
+ "template": "item_template"
+ },
+ {
+ "id": "item2",
+ "status": "inactive",
+ "content": "Item 2 Content",
+ "template": "item_template"
+ }
+ ]
+ }
+ ]
+ },
+ "include": {
+ "meta_tags": {
+ "content": ""
+ },
+ "header": {
+ "template": "Welcome to {{ page.title }}!",
+ "context": {
+ "page": {
+ "title": "My Page"
+ }
+ }
+ },
+ "item_template": {
+ "template": "Status: {{ status }}, Content: {{ content }}"
+ },
+ "footer": {
+ "content": ""
+ }
+ }
+ }'::jsonb,
+ $template$
+
+
+ {{ page.title }}
+ {{ include meta_tags }}
+
+
+
+
+ {{ for section in page.sections }}
+
+ {{ section.title }}
+ {{ for item in section.items }}
+
+ {{ include item.template }}
+ {{ exec
+ DECLARE
+ v_status TEXT;
+ BEGIN
+ v_status := context->'item'->>'status';
+ RETURN CASE
+ WHEN v_status = 'active' THEN ' (Active Item)'
+ ELSE ' (Inactive Item)'
+ END;
+ END;
+ }}
+
+ {{ end }}
+
+ {{ end }}
+
+
+
+$template$
+ );
+
+ expected := '
+
+
+ My Page
+
+
+
+
+
+
+ Section 1
+
+ Status: active, Content: Item 1 Content (Active Item)
+
+
+ Status: inactive, Content: Item 2 Content (Inactive Item)
+
+
+
+
+
+';
+
+ passed := test_result = expected;
+ passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
+ IF passed THEN
+ RAISE NOTICE 'Test %: Complex template with all tag types: PASSED', total_tests;
+ ELSE
+ RAISE WARNING 'Test %: Complex template with all tag types: FAILED. Expected "%", got "%"',
+ total_tests, expected, test_result;
+ END IF;
+ EXCEPTION WHEN OTHERS THEN
+ RAISE WARNING 'Test % failed: Error: %', total_tests, SQLERRM;
+ END;
+
+ -- Test 2: Template with nested includes and shared context
+ total_tests := total_tests + 1;
+ BEGIN
+ test_result := hemar.render(
+ '{
+ "user": {
+ "name": "John",
+ "role": "admin"
+ },
+ "include": {
+ "user_info": {
+ "template": "User: {{ user.name }} ({{ user.role }})"
+ },
+ "permissions": {
+ "template": "{{ include user_info }} - Permissions: {{ for perm in user.permissions }}{{ perm }} {{ end }}",
+ "context": {
+ "user": {
+ "name": "John",
+ "role": "admin",
+ "permissions": ["read", "write", "delete"]
+ }
+ }
+ }
+ }
+ }'::jsonb,
+ $template${{ include permissions }}$template$
+ );
+
+ expected := 'User: John (admin) - Permissions: read write delete ';
+
+ passed := test_result = expected;
+ passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
+ IF passed THEN
+ RAISE NOTICE 'Test %: Template with nested includes and shared context: PASSED', total_tests;
+ ELSE
+ RAISE WARNING 'Test %: Template with nested includes and shared context: FAILED. Expected "%", got "%"',
+ total_tests, expected, test_result;
+ END IF;
+ EXCEPTION WHEN OTHERS THEN
+ RAISE WARNING 'Test % failed: Error: %', total_tests, SQLERRM;
+ END;
+
+ -- Test 3: Template with execute tag using context from section
+ total_tests := total_tests + 1;
+ BEGIN
+ test_result := hemar.render(
+ '{
+ "items": [
+ {"id": 1, "value": 100},
+ {"id": 2, "value": 200},
+ {"id": 3, "value": 300}
+ ]
+ }'::jsonb,
+ $template$Items:
+{{ for item in items }}
+ Item {{ item.id }}: {{ exec
+ DECLARE
+ v_value INT;
+ BEGIN
+ v_value := (context->>'value')::int;
+ RETURN v_value * 2;
+ END;
+ }}
+{{ end }}$template$
+ );
+
+ expected := 'Items:
+ Item 1: 200
+ Item 2: 400
+ Item 3: 600
+';
+
+ passed := test_result = expected;
+ passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
+ IF passed THEN
+ RAISE NOTICE 'Test %: Template with execute tag using context from section: PASSED', total_tests;
+ ELSE
+ RAISE WARNING 'Test %: Template with execute tag using context from section: FAILED. Expected "%", got "%"',
+ total_tests, expected, test_result;
+ END IF;
+ EXCEPTION WHEN OTHERS THEN
+ RAISE WARNING 'Test % failed: Error: %', total_tests, SQLERRM;
+ END;
+
+ -- Print summary
+ IF passed_tests = total_tests THEN
+ RAISE NOTICE '------------------------------------';
+ RAISE NOTICE 'SUMMARY: % of % combined template tests passed (100%%)',
+ passed_tests, total_tests;
+ RAISE NOTICE '------------------------------------';
+ ELSE
+ RAISE WARNING '------------------------------------';
+ RAISE WARNING 'SUMMARY: % of % combined template tests passed (%)',
+ passed_tests,
+ total_tests,
+ round((passed_tests::numeric / total_tests::numeric) * 100, 2) || '%';
+ RAISE WARNING '------------------------------------';
+ END IF;
+
+ IF passed_tests != total_tests THEN
+ RAISE EXCEPTION 'Tests failed: % of % combined template tests did not pass', (total_tests - passed_tests), total_tests;
+ END IF;
END $$;
\ No newline at end of file
diff --git a/package/c/hemar/test/test_render_include.sql b/package/c/hemar/test/test_render_include.sql
index 2a63bdd..c4a8d99 100755
--- a/package/c/hemar/test/test_render_include.sql
+++ b/package/c/hemar/test/test_render_include.sql
@@ -177,6 +177,44 @@ BEGIN
RAISE WARNING 'Test % failed: Should have raised an error for invalid include data', total_tests;
END;
+ -- Test 8: Error handling - unexisting include object
+ total_tests := total_tests + 1;
+ BEGIN
+ result := hemar.render(
+ '{}'::jsonb,
+ '{{ include invalid_template }}'
+ );
+
+ IF result = '' THEN
+ RAISE NOTICE 'Test % passed: Error handling for unexisting include object works correctly', total_tests;
+ passed_tests := passed_tests + 1;
+ ELSE
+ RAISE WARNING 'Test % failed: Expected "", got "%"', total_tests, result;
+ END IF;
+ EXCEPTION WHEN OTHERS THEN
+ RAISE WARNING 'Test % failed: Should have raised an error for unexisting include object', total_tests;
+ END;
+
+ -- Test 9: Error handling - unexisting include data
+ total_tests := total_tests + 1;
+ BEGIN
+ result := hemar.render(
+ '{
+ "include": { }
+ }'::jsonb,
+ '{{ include invalid_template }}'
+ );
+
+ IF result = '' THEN
+ RAISE NOTICE 'Test % passed: Error handling for unexisting include data works correctly', total_tests;
+ passed_tests := passed_tests + 1;
+ ELSE
+ RAISE WARNING 'Test % failed: Expected "", got "%"', total_tests, result;
+ END IF;
+ EXCEPTION WHEN OTHERS THEN
+ RAISE WARNING 'Test % failed: Should have raised an error for unexisting include data', total_tests;
+ END;
+
IF passed_tests = total_tests THEN
RAISE NOTICE '------------------------------------';
RAISE NOTICE 'SUMMARY: % of % template include tests passed (100%%)',