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

Commit720adc8

Browse files
author
Sofia Kopikova
committed
replace UNKNOWNOID to TEXTOID
1 parentdbc3c83 commit720adc8

File tree

7 files changed

+220
-19
lines changed

7 files changed

+220
-19
lines changed

‎expected/pg_variables.out

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -773,8 +773,8 @@ CLOSE r1_cur;
773773
COMMIT; -- warning
774774
RESET client_min_messages;
775775
-- Clean memory after unsuccessful creation of a variable
776-
SELECT pgv_insert('vars4', 'r1', row('str1', 'str1')); -- fail
777-
ERROR: could not identify a hash function for typeunknown
776+
SELECT pgv_insert('vars4', 'r1', row (('str1'::text, 'str1'::text))); -- fail
777+
ERROR: could not identify a hash function for typerecord
778778
SELECT package FROM pgv_stats() WHERE package = 'vars4';
779779
package
780780
---------
@@ -954,28 +954,32 @@ SELECT pgv_select('vars', 'r1');
954954
(1,str1,str2)
955955
(1 row)
956956

957-
SELECT pgv_insert('vars', 'r2', row(1, 'str1'));
957+
SELECT pgv_insert('vars', 'r2', row(1, 'str1')); -- ok, UNKNOWNOID of 'str1' converts to TEXTOID
958+
pgv_insert
959+
------------
960+
961+
(1 row)
962+
963+
SELECT pgv_insert('vars', 'r2', foo) FROM foo; -- ok
958964
pgv_insert
959965
------------
960966

961967
(1 row)
962968

963-
SELECT pgv_insert('vars', 'r2', foo) FROM foo;
964-
ERROR: new record attribute type for attribute number 2 differs from variable "r2" structure.
965-
HINT: You may need explicit type casts.
966969
SELECT pgv_select('vars', 'r2');
967970
pgv_select
968971
------------
969972
(1,str1)
970-
(1 row)
973+
(0,str00)
974+
(2 rows)
971975

972976
SELECT pgv_insert('vars', 'r3', row(1, 'str1'::text));
973977
pgv_insert
974978
------------
975979

976980
(1 row)
977981

978-
SELECT pgv_insert('vars', 'r3', foo) FROM foo;
982+
SELECT pgv_insert('vars', 'r3', foo) FROM foo; -- ok, no conversions
979983
pgv_insert
980984
------------
981985

@@ -988,3 +992,37 @@ SELECT pgv_select('vars', 'r3');
988992
(0,str00)
989993
(2 rows)
990994

995+
SELECT pgv_insert('vars', 'r4', row(1, 2::int));
996+
pgv_insert
997+
------------
998+
999+
(1 row)
1000+
1001+
SELECT pgv_insert('vars', 'r4', row(0, 'str1')); -- fail, UNKNOWNOID of 'str1' can't be converted to int
1002+
ERROR: new record attribute type for attribute number 2 differs from variable "r4" structure.
1003+
HINT: You may need explicit type casts.
1004+
SELECT pgv_select('vars', 'r4');
1005+
pgv_select
1006+
------------
1007+
(1,2)
1008+
(1 row)
1009+
1010+
SELECT pgv_insert('vars', 'r5', foo) FROM foo; -- types: int, text
1011+
pgv_insert
1012+
------------
1013+
1014+
(1 row)
1015+
1016+
SELECT pgv_insert('vars', 'r5', row(1, 'str1')); -- ok, UNKNOWNOID of 'str1' converts to TEXTOID
1017+
pgv_insert
1018+
------------
1019+
1020+
(1 row)
1021+
1022+
SELECT pgv_select('vars', 'r5');
1023+
pgv_select
1024+
------------
1025+
(1,str1)
1026+
(0,str00)
1027+
(2 rows)
1028+

‎expected/pg_variables_trans.out

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1858,8 +1858,8 @@ SELECT pgv_insert('package', 'errs',row(1), true);
18581858
(1 row)
18591859

18601860
-- Variable should not exists in case when error occurs during creation
1861-
SELECT pgv_insert('vars4', 'r1', row('str1', 'str1'));
1862-
ERROR: could not identify a hash function for typeunknown
1861+
SELECT pgv_insert('vars4', 'r1', row (('str1'::text, 'str1'::text)));
1862+
ERROR: could not identify a hash function for typerecord
18631863
SELECT pgv_select('vars4', 'r1', 0);
18641864
ERROR: unrecognized package "vars4"
18651865
-- If variable created and removed in same transaction level,

‎pg_variables.c

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,10 @@ do { \
114114
} while(0)
115115
#endif/* PG_VERSION_NUM */
116116

117+
/* User controlled GUCs */
118+
boolconvert_unknownoid_guc;
119+
boolconvert_unknownoid;
120+
117121
staticHTAB*packagesHash=NULL;
118122
staticMemoryContextModuleContext=NULL;
119123

@@ -701,6 +705,14 @@ variable_insert(PG_FUNCTION_ARGS)
701705
/*
702706
* This is the first record for the var_name. Initialize record.
703707
*/
708+
/* Convert UNKNOWNOID to TEXTOID if needed
709+
* tupdesc may be changed
710+
*/
711+
if (convert_unknownoid)
712+
{
713+
coerce_unknown_first_record(&tupdesc,&rec);
714+
}
715+
704716
init_record(record,tupdesc,variable);
705717
variable->is_deleted= false;
706718
}
@@ -709,8 +721,11 @@ variable_insert(PG_FUNCTION_ARGS)
709721
/*
710722
* We need to check attributes of the new row if this is a transient
711723
* record type or if last record has different id.
724+
* Also we convert UNKNOWNOID to TEXTOID if needed.
725+
* tupdesc may be changed
712726
*/
713-
check_attributes(variable,tupdesc);
727+
check_attributes(variable,&rec,tupdesc);
728+
714729
}
715730

716731
insert_record(variable,rec);
@@ -791,7 +806,11 @@ variable_update(PG_FUNCTION_ARGS)
791806
tupTypmod=HeapTupleHeaderGetTypMod(rec);
792807

793808
tupdesc=lookup_rowtype_tupdesc(tupType,tupTypmod);
794-
check_attributes(variable,tupdesc);
809+
/*
810+
* Convert UNKNOWNOID to TEXTOID if needed
811+
* tupdesc may be changed
812+
*/
813+
check_attributes(variable,&rec,tupdesc);
795814
ReleaseTupleDesc(tupdesc);
796815

797816
res=update_record(variable,rec);
@@ -2622,6 +2641,17 @@ freeStatsLists(void)
26222641
void
26232642
_PG_init(void)
26242643
{
2644+
DefineCustomBoolVariable("pg_variables.convert_unknownoid",
2645+
"Use \'TEXT\' format for all values of \'UNKNOWNOID\', default is true.",
2646+
NULL,
2647+
&convert_unknownoid,
2648+
true,
2649+
PGC_USERSET,
2650+
0,/* FLAGS??? */
2651+
NULL,
2652+
NULL,
2653+
NULL);
2654+
26252655
RegisterXactCallback(pgvTransCallback,NULL);
26262656
RegisterSubXactCallback(pgvSubTransCallback,NULL);
26272657

‎pg_variables.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include"access/tupdesc.h"
1717
#include"datatype/timestamp.h"
1818
#include"utils/date.h"
19+
#include"utils/guc.h"
1920
#include"utils/hsearch.h"
2021
#include"utils/numeric.h"
2122
#include"utils/jsonb.h"
@@ -155,8 +156,12 @@ typedef struct ChangesStackNode
155156
MemoryContextctx;
156157
}ChangesStackNode;
157158

159+
/* pg_variables.c */
160+
externboolconvert_unknownoid;
161+
158162
externvoidinit_record(RecordVar*record,TupleDesctupdesc,Variable*variable);
159-
externvoidcheck_attributes(Variable*variable,TupleDesctupdesc);
163+
externvoidcheck_attributes(Variable*variable,HeapTupleHeader*rec,TupleDesctupdesc);
164+
externvoidcoerce_unknown_first_record(TupleDesc*tupdesc,HeapTupleHeader*rec);
160165
externvoidcheck_record_key(Variable*variable,Oidtypid);
161166

162167
externvoidinsert_record(Variable*variable,HeapTupleHeadertupleHeader);

‎pg_variables_record.c

Lines changed: 121 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,11 @@
2525

2626
#include"catalog/pg_collation.h"
2727
#include"catalog/pg_type.h"
28+
#include"parser/parse_type.h"
2829
#include"utils/builtins.h"
2930
#include"utils/datum.h"
31+
#include"utils/lsyscache.h"
32+
#include"utils/syscache.h"
3033
#include"utils/memutils.h"
3134
#include"utils/typcache.h"
3235

@@ -172,14 +175,118 @@ init_record(RecordVar *record, TupleDesc tupdesc, Variable *variable)
172175
MemoryContextSwitchTo(oldcxt);
173176
}
174177

178+
/* Check if any attributes of type UNKNOWNOID are in given tupdesc */
179+
staticint
180+
is_unknownoid_in_tupdesc(TupleDesctupdesc)
181+
{
182+
inti=0;
183+
for (i=0;i<tupdesc->natts;i++)
184+
{
185+
Form_pg_attributeattr=GetTupleDescAttr(tupdesc,i);
186+
187+
if (attr->atttypid==UNKNOWNOID)
188+
return true;
189+
190+
}
191+
return false;
192+
}
193+
194+
/* Replace all attributes of type UNKNOWNOID to TEXTOID in given tupdesc */
195+
staticvoid
196+
coerce_unknown_rewrite_tupdesc(TupleDescold_tupdesc,TupleDesc*return_tupdesc)
197+
{
198+
inti;
199+
200+
(*return_tupdesc)=CreateTupleDescCopy(old_tupdesc);
201+
202+
for (i=0;i<old_tupdesc->natts;i++)
203+
{
204+
Form_pg_attributeattr=GetTupleDescAttr(old_tupdesc,i);
205+
206+
if (attr->atttypid==UNKNOWNOID)
207+
{
208+
FormData_pg_attributenew_attr=*attr;
209+
210+
new_attr.atttypid=TEXTOID;
211+
new_attr.attlen=-1;
212+
new_attr.atttypmod=-1;
213+
memcpy(TupleDescAttr((*return_tupdesc),i),&new_attr,sizeof(FormData_pg_attribute));
214+
}
215+
}
216+
}
217+
218+
/*
219+
* Deform tuple with old_tupdesc, coerce values of type UNKNOWNOID to TEXTOID, form tuple with new_tupdesc.
220+
* new_tupdesc must have the same attributes as old_tupdesc except such of types UNKNOWNOID -- they must be of TEXTOID type
221+
*/
222+
staticvoid
223+
reconstruct_tuple(TupleDescold_tupdesc,TupleDescnew_tupdesc,HeapTupleHeader*rec)
224+
{
225+
HeapTupleDatatuple;
226+
HeapTuplenewtup;
227+
Datum*values= (Datum*)palloc(old_tupdesc->natts*sizeof(Datum));
228+
bool*isnull= (bool*)palloc(old_tupdesc->natts*sizeof(bool));
229+
OidbaseTypeId=UNKNOWNOID;
230+
int32baseTypeMod=-1;
231+
int32inputTypeMod=-1;
232+
TypebaseType=NULL;
233+
inti;
234+
235+
baseTypeId=getBaseTypeAndTypmod(TEXTOID,&baseTypeMod);
236+
baseType=typeidType(baseTypeId);
237+
/* Build a temporary HeapTuple control structure */
238+
tuple.t_len=HeapTupleHeaderGetDatumLength(*rec);
239+
tuple.t_data=*rec;
240+
heap_deform_tuple(&tuple,old_tupdesc,values,isnull);
241+
242+
for (i=0;i<old_tupdesc->natts;i++)
243+
{
244+
Form_pg_attributeattr=GetTupleDescAttr(old_tupdesc,i);
245+
246+
if (attr->atttypid==UNKNOWNOID)
247+
{
248+
values[i]=stringTypeDatum(baseType,
249+
DatumGetCString(values[i]),
250+
inputTypeMod);
251+
}
252+
}
253+
254+
newtup=heap_form_tuple(new_tupdesc,values,isnull);
255+
(*rec)=newtup->t_data;
256+
pfree(isnull);
257+
pfree(values);
258+
ReleaseSysCache(baseType);
259+
}
260+
261+
/*
262+
* Used in pg_variables.c insert_record for coercing types in first record in variable.
263+
* If there are UNKNOWNOIDs in tupdesc, rewrites it and reconstructs tuple with new tupdesc.
264+
* Replaces given tupdesc with the new one.
265+
*/
266+
void
267+
coerce_unknown_first_record(TupleDesc*tupdesc,HeapTupleHeader*rec)
268+
{
269+
TupleDescnew_tupdesc=NULL;
270+
271+
if (!is_unknownoid_in_tupdesc(*tupdesc))
272+
return;
273+
274+
coerce_unknown_rewrite_tupdesc(*tupdesc,&new_tupdesc);
275+
reconstruct_tuple(*tupdesc,new_tupdesc,rec);
276+
277+
ReleaseTupleDesc(*tupdesc);
278+
(*tupdesc)=new_tupdesc;
279+
}
280+
175281
/*
176282
* New record structure should be the same as the first record.
177283
*/
178284
void
179-
check_attributes(Variable*variable,TupleDesctupdesc)
285+
check_attributes(Variable*variable,HeapTupleHeader*rec,TupleDesctupdesc)
180286
{
181287
inti;
182288
RecordVar*record;
289+
boolunknowns= false;
183290

184291
Assert(variable->typid==RECORDOID);
185292

@@ -198,6 +305,16 @@ check_attributes(Variable *variable, TupleDesc tupdesc)
198305
Form_pg_attributeattr1=GetTupleDescAttr(record->tupdesc,i),
199306
attr2=GetTupleDescAttr(tupdesc,i);
200307

308+
/*
309+
* For the sake of convenience, we consider all the unknown types are to be
310+
* a text type.
311+
*/
312+
if (convert_unknownoid&& (attr1->atttypid==TEXTOID)&& (attr2->atttypid==UNKNOWNOID))
313+
{
314+
unknowns= true;
315+
continue;
316+
}
317+
201318
if ((attr1->atttypid!=attr2->atttypid)
202319
|| (attr1->attndims!=attr2->attndims)
203320
|| (attr1->atttypmod!=attr2->atttypmod))
@@ -208,6 +325,9 @@ check_attributes(Variable *variable, TupleDesc tupdesc)
208325
i+1,GetName(variable)),
209326
errhint("You may need explicit type casts.")));
210327
}
328+
329+
if (unknowns)
330+
reconstruct_tuple(tupdesc,record->tupdesc,rec);
211331
}
212332

213333
/*

‎sql/pg_variables.sql

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ COMMIT; -- warning
222222
RESET client_min_messages;
223223

224224
-- Clean memory after unsuccessful creation of a variable
225-
SELECT pgv_insert('vars4','r1', row('str1','str1'));-- fail
225+
SELECT pgv_insert('vars4','r1', row (('str1'::text,'str1'::text)));-- fail
226226
SELECT packageFROM pgv_stats()WHERE package='vars4';
227227

228228
-- Remove package if it is empty
@@ -268,10 +268,18 @@ SELECT pgv_select('vars', 'r1');
268268
SELECT pgv_insert('vars','r1', foo)FROM foo;
269269
SELECT pgv_select('vars','r1');
270270

271-
SELECT pgv_insert('vars','r2', row(1,'str1'));
272-
SELECT pgv_insert('vars','r2', foo)FROM foo;
271+
SELECT pgv_insert('vars','r2', row(1,'str1'));-- ok, UNKNOWNOID of 'str1' converts to TEXTOID
272+
SELECT pgv_insert('vars','r2', foo)FROM foo;-- ok
273273
SELECT pgv_select('vars','r2');
274274

275275
SELECT pgv_insert('vars','r3', row(1,'str1'::text));
276-
SELECT pgv_insert('vars','r3', foo)FROM foo;
276+
SELECT pgv_insert('vars','r3', foo)FROM foo;-- ok, no conversions
277277
SELECT pgv_select('vars','r3');
278+
279+
SELECT pgv_insert('vars','r4', row(1,2::int));
280+
SELECT pgv_insert('vars','r4', row(0,'str1'));-- fail, UNKNOWNOID of 'str1' can't be converted to int
281+
SELECT pgv_select('vars','r4');
282+
283+
SELECT pgv_insert('vars','r5', foo)FROM foo;-- types: int, text
284+
SELECT pgv_insert('vars','r5', row(1,'str1'));-- ok, UNKNOWNOID of 'str1' converts to TEXTOID
285+
SELECT pgv_select('vars','r5');

‎sql/pg_variables_trans.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,7 @@ FROM generate_series(1,5) AS gs(n) WHERE 1.0/(n-3)<>0;
470470
SELECT pgv_insert('package','errs',row(1), true);
471471

472472
-- Variable should not exists in case when error occurs during creation
473-
SELECT pgv_insert('vars4','r1', row('str1','str1'));
473+
SELECT pgv_insert('vars4','r1', row (('str1'::text,'str1'::text)));
474474
SELECT pgv_select('vars4','r1',0);
475475

476476
-- If variable created and removed in same transaction level,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp