feat!: to the moon

This commit is contained in:
2025-05-14 12:15:45 +00:00
parent bcb8afbbf4
commit e9ba38f4eb
2 changed files with 27 additions and 122 deletions

View File

@@ -318,14 +318,13 @@
"host sameuser all ::1/128 scram-sha-256" "host sameuser all ::1/128 scram-sha-256"
]; ];
initialScript = pkgs.writeText "init-sql-script" '' initialScript = pkgs.writeText "init-sql-script" ''
SET log_min_messages TO DEBUG1;
ALTER DATABASE postgres SET log_min_messages TO DEBUG1;
CREATE EXTENSION "hemar"; CREATE EXTENSION "hemar";
-- SELECT hemar.parse('{% zalupa %}'); -- SELECT hemar.parse('{% zalupa %}');
-- SELECT hemar.parse('{% zalupa %}'); SELECT hemar.render('{"a": "b"}'::JSONB, 'a {% a %}');
-- SELECT hemar.parse('zalupa {% her %} davalka')::JSON; SELECT hemar.render('{"a": ["b", "c"]}'::JSONB, 'a {% for i in a do text %}');
-- SELECT hemar.parse('zalupa {% her %} davalka')::JSON;
-- SELECT hemar.parse('zalupa {% her %} davalka')::JSON;
-- SELECT hemar.parse('zalupa {% her %} davalka')::JSON;
''; '';
}; };

View File

@@ -38,16 +38,25 @@ static bool is_jsonb_container_valid(JsonbContainer *container);
static bool static bool
is_jsonb_container_valid(JsonbContainer *container) is_jsonb_container_valid(JsonbContainer *container)
{ {
/* Basic sanity check: non-NULL pointer */ PG_TRY();
{
container->header;
container->children;
}
PG_CATCH();
{
elog(ERROR, "Invalid JSONB container");
return false;
}
PG_END_TRY();
if (container == NULL) if (container == NULL)
return false; return false;
/* Check that container has a valid header size (at least 4 bytes) */
uint32 header = *(uint32 *)container; uint32 header = *(uint32 *)container;
if (header == 0) /* Simplistic check for corrupted/empty header */ if (header == 0)
return false; return false;
/* This is a simplified check. In a real implementation, we'd do more validation. */
return true; return true;
} }
@@ -826,7 +835,6 @@ template_render(MemoryContext context, TemplateNode *node, Datum jsonb_context,
case TEMPLATE_NODE_SECTION: case TEMPLATE_NODE_SECTION:
case TEMPLATE_NODE_EXECUTE: case TEMPLATE_NODE_EXECUTE:
case TEMPLATE_NODE_INCLUDE: case TEMPLATE_NODE_INCLUDE:
/* Use nested PG_TRY/PG_CATCH blocks for each node type for better error handling */
PG_TRY(); PG_TRY();
{ {
if (current->type == TEMPLATE_NODE_INTERPOLATE) if (current->type == TEMPLATE_NODE_INTERPOLATE)
@@ -1256,7 +1264,6 @@ get_jsonb_path_value(Datum jsonb_context, const char *path, bool *found)
return NULL; return NULL;
} }
/* Use PG_TRY/PG_CATCH to handle any errors during extraction */
PG_TRY(); PG_TRY();
{ {
/* Handle simple top-level key */ /* Handle simple top-level key */
@@ -1339,7 +1346,6 @@ get_jsonb_path_value(Datum jsonb_context, const char *path, bool *found)
else else
{ {
/* Handle nested paths using a JSON path expression */ /* Handle nested paths using a JSON path expression */
/* This is a simplified implementation */
elog(DEBUG1, "Complex path not fully supported: %s", path); elog(DEBUG1, "Complex path not fully supported: %s", path);
result = pstrdup("[Complex Path]"); result = pstrdup("[Complex Path]");
*found = true; *found = true;
@@ -1403,7 +1409,7 @@ get_jsonb_array(Datum jsonb_context, const char *path, bool *found)
if (jbv_result) if (jbv_result)
{ {
elog(DEBUG1, "Found value for key %s (type=%d)", path, jbv_result->type); elog(DEBUG1, "Found value for key %s (type=%d) value=%s", path, jbv_result->type, jbv_result->val.string.val);
if (jbv_result->type == jbvBinary) if (jbv_result->type == jbvBinary)
{ {
@@ -1411,12 +1417,13 @@ get_jsonb_array(Datum jsonb_context, const char *path, bool *found)
elog(DEBUG1, "Binary value found, trying to examine structure"); elog(DEBUG1, "Binary value found, trying to examine structure");
/* Validate the binary container before iterating */ /* Validate the binary container before iterating */
if (!is_jsonb_container_valid((JsonbContainer *)&jbv_result->val.binary)) if (!is_jsonb_container_valid(jbv_result->val.binary.data))
{ {
elog(WARNING, "Invalid binary JSONB container for key: %s", path); elog(WARNING, "Invalid binary JSONB container for key: %s", path);
return result; return result;
} }
elog(DEBUG1, "Trying to initialize the iterator...");
/* Try to initialize the iterator */ /* Try to initialize the iterator */
PG_TRY(); PG_TRY();
{ {
@@ -1429,7 +1436,7 @@ get_jsonb_array(Datum jsonb_context, const char *path, bool *found)
/* Initialize the iterator with careful error handling */ /* Initialize the iterator with careful error handling */
elog(DEBUG1, "Initializing iterator for binary container"); elog(DEBUG1, "Initializing iterator for binary container");
it = JsonbIteratorInit((JsonbContainer *)&jbv_result->val.binary); it = JsonbIteratorInit(jbv_result->val.binary.data);
elog(DEBUG1, "Iterator initialized successfully"); elog(DEBUG1, "Iterator initialized successfully");
elog(DEBUG1, "Getting first token"); elog(DEBUG1, "Getting first token");
@@ -1484,111 +1491,10 @@ get_jsonb_array(Datum jsonb_context, const char *path, bool *found)
} }
PG_END_TRY(); PG_END_TRY();
} }
else else {
{ elog(DEBUG1, "Complex path not fully supported: %s", path);
/* Handle nested paths */ result = pstrdup("[Complex Path]");
/* This is a simplified implementation */
char *current_path = pstrdup(path);
char *token_str;
char *saveptr;
JsonbValue *current_jbv;
/* Use PG_TRY/PG_CATCH to handle any errors during iteration */
PG_TRY();
{
token_str = strtok_r(current_path, ".", &saveptr);
while (token_str != NULL)
{
key.type = jbvString;
key.val.string.val = token_str;
key.val.string.len = strlen(token_str);
current_jbv = findJsonbValueFromContainer(&jb->root, JB_FOBJECT, &key);
if (!current_jbv)
{
elog(DEBUG1, "Path segment %s not found in nested path %s", token_str, path);
pfree(current_path);
return result;
}
token_str = strtok_r(NULL, ".", &saveptr);
/* If there are more path segments, current value must be an object */
if (token_str != NULL)
{
if (current_jbv->type != jbvBinary)
{
elog(DEBUG1, "Path segment %s is not a binary JSONB object in nested path %s", token_str, path);
pfree(current_path);
return result;
}
/* Validate the binary container before using it */
if (!is_jsonb_container_valid((JsonbContainer *)&current_jbv->val.binary))
{
elog(WARNING, "Invalid binary JSONB container for path segment: %s", token_str);
pfree(current_path);
return result;
}
jb = (Jsonb *) DatumGetPointer(JsonbValueToJsonb(current_jbv));
/* Validate the new container */
if (!jb || !is_jsonb_container_valid(&jb->root))
{
elog(WARNING, "Invalid JSONB container after path segment: %s", token_str);
pfree(current_path);
return result;
}
}
else
{
/* Check if the final value is an array */
if (current_jbv->type == jbvBinary)
{
/* Validate the binary container before iterating */
if (!is_jsonb_container_valid((JsonbContainer *)&current_jbv->val.binary))
{
elog(WARNING, "Invalid binary JSONB container for nested path: %s", path);
pfree(current_path);
return result;
}
it = JsonbIteratorInit((JsonbContainer *)&current_jbv->val.binary);
token = JsonbIteratorNext(&it, &v, false);
if (token == WJB_BEGIN_ARRAY)
{
*found = true; *found = true;
result = PointerGetDatum(JsonbValueToJsonb(current_jbv));
elog(DEBUG1, "Found array at nested path %s", path);
debug_jsonb_value(result, "Array");
}
else
{
elog(DEBUG1, "Nested path %s exists but is not an array (token type: %d)", path, token);
}
}
else
{
elog(DEBUG1, "Nested path %s exists but is not binary JSONB (type: %d)", path, current_jbv->type);
}
}
}
}
PG_CATCH();
{
elog(WARNING, "Exception while processing nested array at path %s", path);
if (current_path)
pfree(current_path);
FlushErrorState();
return result;
}
PG_END_TRY();
if (current_path)
pfree(current_path);
} }
return result; return result;