Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit66a4bad

Browse files
committed
Convert ExecComputeStoredGenerated to use tuple slots
This code was still using the old style of forming a heap tuple ratherthan using tuple slots. This would be less efficient if a non-heapaccess method was used. And using tuple slots is actually quite a bitfaster when using heap as well.Also add some test cases for generated columns with null values andwith varlena values. This lack of coverage was discovered whileworking on this patch.Discussion:https://www.postgresql.org/message-id/flat/20190331025744.ugbsyks7czfcoksd%40alap3.anarazel.de
1 parent03de518 commit66a4bad

File tree

3 files changed

+52
-22
lines changed

3 files changed

+52
-22
lines changed

‎src/backend/executor/nodeModifyTable.c

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
#include"storage/bufmgr.h"
5454
#include"storage/lmgr.h"
5555
#include"utils/builtins.h"
56+
#include"utils/datum.h"
5657
#include"utils/memutils.h"
5758
#include"utils/rel.h"
5859

@@ -254,9 +255,6 @@ ExecComputeStoredGenerated(EState *estate, TupleTableSlot *slot)
254255
MemoryContextoldContext;
255256
Datum*values;
256257
bool*nulls;
257-
bool*replaces;
258-
HeapTupleoldtuple,newtuple;
259-
boolshould_free;
260258

261259
Assert(tupdesc->constr&&tupdesc->constr->has_generated_stored);
262260

@@ -294,11 +292,15 @@ ExecComputeStoredGenerated(EState *estate, TupleTableSlot *slot)
294292

295293
values=palloc(sizeof(*values)*natts);
296294
nulls=palloc(sizeof(*nulls)*natts);
297-
replaces=palloc0(sizeof(*replaces)*natts);
295+
296+
slot_getallattrs(slot);
297+
memcpy(nulls,slot->tts_isnull,sizeof(*nulls)*natts);
298298

299299
for (inti=0;i<natts;i++)
300300
{
301-
if (TupleDescAttr(tupdesc,i)->attgenerated==ATTRIBUTE_GENERATED_STORED)
301+
Form_pg_attributeattr=TupleDescAttr(tupdesc,i);
302+
303+
if (attr->attgenerated==ATTRIBUTE_GENERATED_STORED)
302304
{
303305
ExprContext*econtext;
304306
Datumval;
@@ -311,20 +313,19 @@ ExecComputeStoredGenerated(EState *estate, TupleTableSlot *slot)
311313

312314
values[i]=val;
313315
nulls[i]=isnull;
314-
replaces[i]= true;
316+
}
317+
else
318+
{
319+
if (!nulls[i])
320+
values[i]=datumCopy(slot->tts_values[i],attr->attbyval,attr->attlen);
315321
}
316322
}
317323

318-
oldtuple=ExecFetchSlotHeapTuple(slot, true,&should_free);
319-
newtuple=heap_modify_tuple(oldtuple,tupdesc,values,nulls,replaces);
320-
/*
321-
* The tuple will be freed by way of the memory context - the slot might
322-
* only be cleared after the context is reset, and we'd thus potentially
323-
* double free.
324-
*/
325-
ExecForceStoreHeapTuple(newtuple,slot, false);
326-
if (should_free)
327-
heap_freetuple(oldtuple);
324+
ExecClearTuple(slot);
325+
memcpy(slot->tts_values,values,sizeof(*values)*natts);
326+
memcpy(slot->tts_isnull,nulls,sizeof(*nulls)*natts);
327+
ExecStoreVirtualTuple(slot);
328+
ExecMaterializeSlot(slot);
328329

329330
MemoryContextSwitchTo(oldContext);
330331
}

‎src/test/regress/expected/generated.out

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -226,15 +226,16 @@ NOTICE: merging multiple inherited definitions of column "b"
226226
ERROR: inherited column "b" has a generation conflict
227227
DROP TABLE gtesty;
228228
-- test stored update
229-
CREATE TABLE gtest3 (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 3) STORED);
230-
INSERT INTO gtest3 (a) VALUES (1), (2), (3);
229+
CREATE TABLE gtest3 (a int, b int GENERATED ALWAYS AS (a * 3) STORED);
230+
INSERT INTO gtest3 (a) VALUES (1), (2), (3), (NULL);
231231
SELECT * FROM gtest3 ORDER BY a;
232232
a | b
233233
---+---
234234
1 | 3
235235
2 | 6
236236
3 | 9
237-
(3 rows)
237+
|
238+
(4 rows)
238239

239240
UPDATE gtest3 SET a = 22 WHERE a = 2;
240241
SELECT * FROM gtest3 ORDER BY a;
@@ -243,7 +244,29 @@ SELECT * FROM gtest3 ORDER BY a;
243244
1 | 3
244245
3 | 9
245246
22 | 66
246-
(3 rows)
247+
|
248+
(4 rows)
249+
250+
CREATE TABLE gtest3a (a text, b text GENERATED ALWAYS AS (a || '+' || a) STORED);
251+
INSERT INTO gtest3a (a) VALUES ('a'), ('b'), ('c'), (NULL);
252+
SELECT * FROM gtest3a ORDER BY a;
253+
a | b
254+
---+-----
255+
a | a+a
256+
b | b+b
257+
c | c+c
258+
|
259+
(4 rows)
260+
261+
UPDATE gtest3a SET a = 'bb' WHERE a = 'b';
262+
SELECT * FROM gtest3a ORDER BY a;
263+
a | b
264+
----+-------
265+
a | a+a
266+
bb | bb+bb
267+
c | c+c
268+
|
269+
(4 rows)
247270

248271
-- COPY
249272
TRUNCATE gtest1;

‎src/test/regress/sql/generated.sql

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,12 +95,18 @@ CREATE TABLE gtest1_2 () INHERITS (gtest1, gtesty); -- error
9595
DROPTABLE gtesty;
9696

9797
-- test stored update
98-
CREATETABLEgtest3 (aintPRIMARY KEY, bint GENERATED ALWAYSAS (a*3) STORED);
99-
INSERT INTO gtest3 (a)VALUES (1), (2), (3);
98+
CREATETABLEgtest3 (aint, bint GENERATED ALWAYSAS (a*3) STORED);
99+
INSERT INTO gtest3 (a)VALUES (1), (2), (3), (NULL);
100100
SELECT*FROM gtest3ORDER BY a;
101101
UPDATE gtest3SET a=22WHERE a=2;
102102
SELECT*FROM gtest3ORDER BY a;
103103

104+
CREATETABLEgtest3a (atext, btext GENERATED ALWAYSAS (a||'+'|| a) STORED);
105+
INSERT INTO gtest3a (a)VALUES ('a'), ('b'), ('c'), (NULL);
106+
SELECT*FROM gtest3aORDER BY a;
107+
UPDATE gtest3aSET a='bb'WHERE a='b';
108+
SELECT*FROM gtest3aORDER BY a;
109+
104110
-- COPY
105111
TRUNCATE gtest1;
106112
INSERT INTO gtest1 (a)VALUES (1), (2);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp