Skip to content

Bugfix/issue 32 - fix error on insert from table #36

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Dec 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 62 additions & 3 deletions expected/pg_variables.out
Original file line number Diff line number Diff line change
Expand Up @@ -563,11 +563,13 @@ ERROR: variable "j1" requires "jsonb" value
SELECT pgv_insert('vars3', 'r1', tab) FROM tab;
ERROR: there is a record in the variable "r1" with same key
SELECT pgv_insert('vars3', 'r1', row(1, 'str1', 'str2'));
ERROR: new record structure differs from variable "r1" structure
ERROR: new record structure have 3 attributes, but variable "r1" structure have 2.
SELECT pgv_insert('vars3', 'r1', row(1, 1));
ERROR: new record structure differs from variable "r1" structure
ERROR: new record attribute type for attribute number 2 differs from variable "r1" structure.
HINT: You may need explicit type casts.
SELECT pgv_insert('vars3', 'r1', row('str1', 'str1'));
ERROR: new record structure differs from variable "r1" structure
ERROR: new record attribute type for attribute number 1 differs from variable "r1" structure.
HINT: You may need explicit type casts.
SELECT pgv_select('vars3', 'r1', ARRAY[[1,2]]); -- fail
ERROR: searching for elements in multidimensional arrays is not supported
-- Test variables caching
Expand Down Expand Up @@ -929,3 +931,60 @@ SELECT * FROM pgv_list() order by package, name;
---------+------+------------------
(0 rows)

-- Check insert of record with various amount of fields
CREATE TEMP TABLE foo(id int, t text);
INSERT INTO foo VALUES (0, 'str00');
SELECT pgv_insert('vars', 'r1', row(1, 'str1'::text, 'str2'::text));
pgv_insert
------------

(1 row)

SELECT pgv_select('vars', 'r1');
pgv_select
---------------
(1,str1,str2)
(1 row)

SELECT pgv_insert('vars', 'r1', foo) FROM foo;
ERROR: new record structure have 2 attributes, but variable "r1" structure have 3.
SELECT pgv_select('vars', 'r1');
pgv_select
---------------
(1,str1,str2)
(1 row)

SELECT pgv_insert('vars', 'r2', row(1, 'str1'));
pgv_insert
------------

(1 row)

SELECT pgv_insert('vars', 'r2', foo) FROM foo;
ERROR: new record attribute type for attribute number 2 differs from variable "r2" structure.
HINT: You may need explicit type casts.
SELECT pgv_select('vars', 'r2');
pgv_select
------------
(1,str1)
(1 row)

SELECT pgv_insert('vars', 'r3', row(1, 'str1'::text));
pgv_insert
------------

(1 row)

SELECT pgv_insert('vars', 'r3', foo) FROM foo;
pgv_insert
------------

(1 row)

SELECT pgv_select('vars', 'r3');
pgv_select
------------
(1,str1)
(0,str00)
(2 rows)

56 changes: 56 additions & 0 deletions expected/pg_variables_trans.out
Original file line number Diff line number Diff line change
Expand Up @@ -3773,3 +3773,59 @@ SELECT pgv_free();

(1 row)

---
--- Test case for issue #32 [PGPRO-4456]
---
CREATE TEMP TABLE tab (id int, t varchar);
INSERT INTO tab VALUES (0, 'str00');
SELECT pgv_insert('vars', 'r1', row(1, 'str1', 'str2'));
pgv_insert
------------

(1 row)

SELECT pgv_insert('vars', 'a', tab) FROM tab;
pgv_insert
------------

(1 row)

SELECT pgv_insert('vars', 'r1', tab) FROM tab;
ERROR: new record structure have 2 attributes, but variable "r1" structure have 3.
SELECT pgv_select('vars', 'r1');
pgv_select
---------------
(1,str1,str2)
(1 row)

SELECT pgv_insert('vars', 'r2', row(1, 'str1'::varchar));
pgv_insert
------------

(1 row)

SELECT pgv_insert('vars', 'b', tab) FROM tab;
pgv_insert
------------

(1 row)

SELECT pgv_insert('vars', 'r2', tab) FROM tab;
pgv_insert
------------

(1 row)

SELECT pgv_select('vars', 'r2');
pgv_select
------------
(1,str1)
(0,str00)
(2 rows)

SELECT pgv_free();
pgv_free
----------

(1 row)

40 changes: 10 additions & 30 deletions pg_variables.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,6 @@ static MemoryContext ModuleContext = NULL;
static Package *LastPackage = NULL;
/* Recent variable */
static Variable *LastVariable = NULL;
/* Recent row type id */
static Oid LastTypeId = InvalidOid;

/* Saved hook values for recall */
static ExecutorEnd_hook_type prev_ExecutorEnd = NULL;
Expand Down Expand Up @@ -696,35 +694,25 @@ variable_insert(PG_FUNCTION_ARGS)
tupTypmod = HeapTupleHeaderGetTypMod(rec);

record = &(GetActualValue(variable).record);
if (!record->tupdesc)
tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);

if (!record->tupdesc || variable->is_deleted)
{
/*
* This is the first record for the var_name. Initialize record.
*/
tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
init_record(record, tupdesc, variable);
variable->is_deleted = false;
}
else if (LastTypeId == RECORDOID || !OidIsValid(LastTypeId) ||
LastTypeId != tupType)
else
{
/*
* We need to check attributes of the new row if this is a transient
* record type or if last record has different id.
*/
tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
if (variable->is_deleted)
{
init_record(record, tupdesc, variable);
variable->is_deleted = false;
}
else
{
check_attributes(variable, tupdesc);
}
check_attributes(variable, tupdesc);
}

LastTypeId = tupType;

insert_record(variable, rec);

/* Release resources */
Expand All @@ -749,6 +737,7 @@ variable_update(PG_FUNCTION_ARGS)
bool res;
Oid tupType;
int32 tupTypmod;
TupleDesc tupdesc = NULL;

/* Checks */
CHECK_ARGS_FOR_NULL();
Expand Down Expand Up @@ -801,17 +790,9 @@ variable_update(PG_FUNCTION_ARGS)
tupType = HeapTupleHeaderGetTypeId(rec);
tupTypmod = HeapTupleHeaderGetTypMod(rec);

if (LastTypeId == RECORDOID || !OidIsValid(LastTypeId) ||
LastTypeId != tupType)
{
TupleDesc tupdesc = NULL;

tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
check_attributes(variable, tupdesc);
ReleaseTupleDesc(tupdesc);
}

LastTypeId = tupType;
tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
check_attributes(variable, tupdesc);
ReleaseTupleDesc(tupdesc);

res = update_record(variable, rec);

Expand Down Expand Up @@ -1337,7 +1318,6 @@ resetVariablesCache(void)
/* Remove package and variable from cache */
LastPackage = NULL;
LastVariable = NULL;
LastTypeId = InvalidOid;
}

/*
Expand Down
11 changes: 7 additions & 4 deletions pg_variables_record.c
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,9 @@ check_attributes(Variable *variable, TupleDesc tupdesc)
if (record->tupdesc->natts != tupdesc->natts)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("new record structure differs from variable \"%s\" "
"structure", GetName(variable))));
errmsg("new record structure have %d attributes, but variable "
"\"%s\" structure have %d.",
tupdesc->natts, GetName(variable), record->tupdesc->natts)));

/* Second, check columns type. */
for (i = 0; i < tupdesc->natts; i++)
Expand All @@ -202,8 +203,10 @@ check_attributes(Variable *variable, TupleDesc tupdesc)
|| (attr1->atttypmod != attr2->atttypmod))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("new record structure differs from variable \"%s\" "
"structure", GetName(variable))));
errmsg("new record attribute type for attribute number %d "
"differs from variable \"%s\" structure.",
i + 1, GetName(variable)),
errhint("You may need explicit type casts.")));
}
}

Expand Down
16 changes: 16 additions & 0 deletions sql/pg_variables.sql
Original file line number Diff line number Diff line change
Expand Up @@ -259,3 +259,19 @@ SELECT pgv_free();
SELECT pgv_exists('vars');

SELECT * FROM pgv_list() order by package, name;
-- Check insert of record with various amount of fields
CREATE TEMP TABLE foo(id int, t text);
INSERT INTO foo VALUES (0, 'str00');

SELECT pgv_insert('vars', 'r1', row(1, 'str1'::text, 'str2'::text));
SELECT pgv_select('vars', 'r1');
SELECT pgv_insert('vars', 'r1', foo) FROM foo;
SELECT pgv_select('vars', 'r1');

SELECT pgv_insert('vars', 'r2', row(1, 'str1'));
SELECT pgv_insert('vars', 'r2', foo) FROM foo;
SELECT pgv_select('vars', 'r2');

SELECT pgv_insert('vars', 'r3', row(1, 'str1'::text));
SELECT pgv_insert('vars', 'r3', foo) FROM foo;
SELECT pgv_select('vars', 'r3');
18 changes: 18 additions & 0 deletions sql/pg_variables_trans.sql
Original file line number Diff line number Diff line change
Expand Up @@ -1145,3 +1145,21 @@ COMMIT;

DROP VIEW pgv_stats_view;
SELECT pgv_free();

---
--- Test case for issue #32 [PGPRO-4456]
---
CREATE TEMP TABLE tab (id int, t varchar);
INSERT INTO tab VALUES (0, 'str00');

SELECT pgv_insert('vars', 'r1', row(1, 'str1', 'str2'));
SELECT pgv_insert('vars', 'a', tab) FROM tab;
SELECT pgv_insert('vars', 'r1', tab) FROM tab;
SELECT pgv_select('vars', 'r1');

SELECT pgv_insert('vars', 'r2', row(1, 'str1'::varchar));
SELECT pgv_insert('vars', 'b', tab) FROM tab;
SELECT pgv_insert('vars', 'r2', tab) FROM tab;
SELECT pgv_select('vars', 'r2');

SELECT pgv_free();