Skip to content

Commit 5af4b04

Browse files
committed
Move get_attdisbursion to lsyscache. Clean up get_typdefault.
1 parent e905482 commit 5af4b04

File tree

5 files changed

+187
-131
lines changed

5 files changed

+187
-131
lines changed

src/backend/optimizer/prep/preptlist.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.28 1999/08/09 00:51:26 tgl Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.29 1999/08/09 03:13:31 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -297,12 +297,12 @@ new_relation_targetlist(Oid relid, Index rt_index, NodeTag node_type)
297297
{
298298
case T_Const: /* INSERT command */
299299
{
300-
struct varlena *typedefault = get_typdefault(atttype);
300+
Datum typedefault = get_typdefault(atttype);
301301
int typlen;
302302
Const *temp_const;
303303
TargetEntry *temp_tle;
304304

305-
if (typedefault == NULL)
305+
if (typedefault == PointerGetDatum(NULL))
306306
typlen = 0;
307307
else
308308
{
@@ -319,9 +319,8 @@ new_relation_targetlist(Oid relid, Index rt_index, NodeTag node_type)
319319

320320
temp_const = makeConst(atttype,
321321
typlen,
322-
(Datum) typedefault,
323-
(typedefault == NULL),
324-
/* XXX ? */
322+
typedefault,
323+
(typedefault == PointerGetDatum(NULL)),
325324
false,
326325
false, /* not a set */
327326
false);

src/backend/utils/cache/lsyscache.c

Lines changed: 173 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,19 @@
11
/*-------------------------------------------------------------------------
22
*
33
* lsyscache.c
4-
* Routines to access information within system caches
4+
* Convenience routines for common queries in the system catalog cache.
55
*
66
* Copyright (c) 1994, Regents of the University of California
77
*
8-
*
98
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.31 1999/07/17 20:18:01 momjian Exp $
9+
* $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.32 1999/08/09 03:13:30 tgl Exp $
1110
*
1211
* NOTES
1312
* Eventually, the index information should go through here, too.
1413
*-------------------------------------------------------------------------
1514
*/
1615
#include "postgres.h"
1716

18-
1917
#include "catalog/pg_operator.h"
2018
#include "catalog/pg_type.h"
2119
#include "utils/lsyscache.h"
@@ -166,6 +164,77 @@ get_atttypmod(Oid relid, AttrNumber attnum)
166164
return -1;
167165
}
168166

167+
/*
168+
* get_attdisbursion
169+
*
170+
* Retrieve the disbursion statistic for an attribute,
171+
* or produce an estimate if no info is available.
172+
*
173+
* min_estimate is the minimum estimate to return if insufficient data
174+
* is available to produce a reliable value. This value may vary
175+
* depending on context. (For example, when deciding whether it is
176+
* safe to use a hashjoin, we want to be more conservative than when
177+
* estimating the number of tuples produced by an equijoin.)
178+
*/
179+
double
180+
get_attdisbursion(Oid relid, AttrNumber attnum, double min_estimate)
181+
{
182+
HeapTuple atp;
183+
double disbursion;
184+
int32 ntuples;
185+
186+
atp = SearchSysCacheTuple(ATTNUM,
187+
ObjectIdGetDatum(relid),
188+
Int16GetDatum(attnum),
189+
0, 0);
190+
if (!HeapTupleIsValid(atp))
191+
{
192+
/* this should not happen */
193+
elog(ERROR, "get_attdisbursion: no attribute tuple %u %d",
194+
relid, attnum);
195+
return min_estimate;
196+
}
197+
198+
disbursion = ((Form_pg_attribute) GETSTRUCT(atp))->attdisbursion;
199+
if (disbursion > 0.0)
200+
return disbursion; /* we have a specific estimate */
201+
202+
/*
203+
* Disbursion is either 0 (no data available) or -1 (disbursion
204+
* is 1/numtuples). Either way, we need the relation size.
205+
*/
206+
207+
atp = SearchSysCacheTuple(RELOID,
208+
ObjectIdGetDatum(relid),
209+
0, 0, 0);
210+
if (!HeapTupleIsValid(atp))
211+
{
212+
/* this should not happen */
213+
elog(ERROR, "get_attdisbursion: no relation tuple %u", relid);
214+
return min_estimate;
215+
}
216+
217+
ntuples = ((Form_pg_class) GETSTRUCT(atp))->reltuples;
218+
219+
if (ntuples == 0)
220+
return min_estimate; /* no data available */
221+
222+
if (disbursion < 0.0) /* VACUUM thinks there are no duplicates */
223+
return 1.0 / (double) ntuples;
224+
225+
/*
226+
* VACUUM ANALYZE has not been run for this table.
227+
* Produce an estimate = 1/numtuples. This may produce
228+
* unreasonably small estimates for large tables, so limit
229+
* the estimate to no less than min_estimate.
230+
*/
231+
disbursion = 1.0 / (double) ntuples;
232+
if (disbursion < min_estimate)
233+
disbursion = min_estimate;
234+
235+
return disbursion;
236+
}
237+
169238
/* ---------- INDEX CACHE ---------- */
170239

171240
/* watch this space...
@@ -504,15 +573,110 @@ get_typalign(Oid typid)
504573
/*
505574
* get_typdefault -
506575
*
507-
* Given the type OID, return the default value of the ADT.
508-
*
576+
* Given a type OID, return the typdefault field associated with that
577+
* type, or Datum(NULL) if there is no typdefault. (This implies
578+
* that pass-by-value types can't have a default value that has
579+
* a representation of zero. Not worth fixing now.)
580+
* The result points to palloc'd storage for non-pass-by-value types.
509581
*/
510-
struct varlena *
582+
Datum
511583
get_typdefault(Oid typid)
512584
{
513-
struct varlena *typdefault = (struct varlena *) TypeDefaultRetrieve(typid);
585+
struct varlena *typDefault;
586+
int32 dataSize;
587+
HeapTuple typeTuple;
588+
Form_pg_type type;
589+
int32 typLen;
590+
bool typByVal;
591+
Datum returnValue;
592+
593+
/*
594+
* First, see if there is a non-null typdefault field (usually there isn't)
595+
*/
596+
typDefault = (struct varlena *)
597+
SearchSysCacheGetAttribute(TYPOID,
598+
Anum_pg_type_typdefault,
599+
ObjectIdGetDatum(typid),
600+
0, 0, 0);
601+
602+
if (typDefault == NULL)
603+
return PointerGetDatum(NULL);
604+
605+
dataSize = VARSIZE(typDefault) - VARHDRSZ;
606+
607+
/*
608+
* Need the type's length and byVal fields.
609+
*
610+
* XXX silly to repeat the syscache search that SearchSysCacheGetAttribute
611+
* just did --- but at present this path isn't taken often enough to
612+
* make it worth fixing.
613+
*/
614+
typeTuple = SearchSysCacheTuple(TYPOID,
615+
ObjectIdGetDatum(typid),
616+
0, 0, 0);
617+
618+
if (!HeapTupleIsValid(typeTuple))
619+
elog(ERROR, "get_typdefault: failed to lookup type %u", typid);
620+
621+
type = (Form_pg_type) GETSTRUCT(typeTuple);
622+
typLen = type->typlen;
623+
typByVal = type->typbyval;
624+
625+
if (typByVal)
626+
{
627+
int8 i8;
628+
int16 i16;
629+
int32 i32 = 0;
630+
631+
if (dataSize == typLen)
632+
{
633+
switch (typLen)
634+
{
635+
case sizeof(int8):
636+
memcpy((char *) &i8, VARDATA(typDefault), sizeof(int8));
637+
i32 = i8;
638+
break;
639+
case sizeof(int16):
640+
memcpy((char *) &i16, VARDATA(typDefault), sizeof(int16));
641+
i32 = i16;
642+
break;
643+
case sizeof(int32):
644+
memcpy((char *) &i32, VARDATA(typDefault), sizeof(int32));
645+
break;
646+
}
647+
returnValue = Int32GetDatum(i32);
648+
}
649+
else
650+
returnValue = PointerGetDatum(NULL);
651+
}
652+
else if (typLen < 0)
653+
{
654+
/* variable-size type */
655+
if (dataSize < 0)
656+
returnValue = PointerGetDatum(NULL);
657+
else
658+
{
659+
returnValue = PointerGetDatum(palloc(VARSIZE(typDefault)));
660+
memcpy((char *) DatumGetPointer(returnValue),
661+
(char *) typDefault,
662+
(int) VARSIZE(typDefault));
663+
}
664+
}
665+
else
666+
{
667+
/* fixed-size pass-by-ref type */
668+
if (dataSize != typLen)
669+
returnValue = PointerGetDatum(NULL);
670+
else
671+
{
672+
returnValue = PointerGetDatum(palloc(dataSize));
673+
memcpy((char *) DatumGetPointer(returnValue),
674+
VARDATA(typDefault),
675+
(int) dataSize);
676+
}
677+
}
514678

515-
return typdefault;
679+
return returnValue;
516680
}
517681

518682
/*

src/backend/utils/cache/syscache.c

Lines changed: 1 addition & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.33 1999/07/20 17:14:06 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.34 1999/08/09 03:13:30 tgl Exp $
1111
*
1212
* NOTES
1313
* These routines allow the parser/planner/executor to perform
@@ -631,112 +631,3 @@ SearchSysCacheGetAttribute(int cacheId,
631631
heap_close(relation);
632632
return returnValue;
633633
}
634-
635-
/*
636-
* TypeDefaultRetrieve
637-
*
638-
* Given a type OID, return the typdefault field associated with that
639-
* type. The result is a Datum, and points to palloc'd storage for
640-
* non-pass-by-value types.
641-
*
642-
* [identical to get_typdefault, expecting a (struct varlena *) as ret val.
643-
* some day, either of the functions should be removed -ay 10/94]
644-
*/
645-
void *
646-
TypeDefaultRetrieve(Oid typId)
647-
{
648-
struct varlena *typDefault;
649-
int32 dataSize;
650-
HeapTuple typeTuple;
651-
Form_pg_type type;
652-
int32 typByVal,
653-
typLen;
654-
void *returnValue;
655-
656-
/*
657-
* First, see if there is a non-null typdefault field (usually there isn't)
658-
*/
659-
typDefault = (struct varlena *)
660-
SearchSysCacheGetAttribute(TYPOID,
661-
Anum_pg_type_typdefault,
662-
ObjectIdGetDatum(typId),
663-
0, 0, 0);
664-
665-
if (typDefault == NULL)
666-
{
667-
#ifdef CACHEDEBUG
668-
elog(DEBUG, "TypeDefaultRetrieve: No extractable typdefault in %s(%d)",
669-
cacheinfo[TYPOID].name, TYPOID);
670-
#endif /* defined(CACHEDEBUG) */
671-
return NULL;
672-
}
673-
674-
dataSize = VARSIZE(typDefault) - VARHDRSZ;
675-
676-
/*
677-
* Need the type's length and byVal fields.
678-
*
679-
* XXX silly to repeat the syscache search that SearchSysCacheGetAttribute
680-
* just did --- but at present this path isn't taken often enough to
681-
* make it worth fixing.
682-
*/
683-
typeTuple = SearchSysCacheTuple(TYPOID,
684-
ObjectIdGetDatum(typId),
685-
0, 0, 0);
686-
687-
if (!HeapTupleIsValid(typeTuple))
688-
{
689-
/* should never get here, really... */
690-
#ifdef CACHEDEBUG
691-
elog(DEBUG, "TypeDefaultRetrieve: Lookup in %s(%d) failed",
692-
cacheinfo[TYPOID].name, TYPOID);
693-
#endif /* defined(CACHEDEBUG) */
694-
return NULL;
695-
}
696-
697-
type = (Form_pg_type) GETSTRUCT(typeTuple);
698-
typLen = type->typlen;
699-
typByVal = type->typbyval;
700-
701-
if (typByVal)
702-
{
703-
int8 i8;
704-
int16 i16;
705-
int32 i32 = 0;
706-
707-
if (dataSize == typLen)
708-
{
709-
switch (typLen)
710-
{
711-
case sizeof(int8):
712-
memcpy((char *) &i8, VARDATA(typDefault), sizeof(int8));
713-
i32 = i8;
714-
break;
715-
case sizeof(int16):
716-
memcpy((char *) &i16, VARDATA(typDefault), sizeof(int16));
717-
i32 = i16;
718-
break;
719-
case sizeof(int32):
720-
memcpy((char *) &i32, VARDATA(typDefault), sizeof(int32));
721-
break;
722-
}
723-
returnValue = (void *) i32;
724-
}
725-
else
726-
returnValue = NULL;
727-
}
728-
else
729-
{
730-
if ((typLen < 0 && dataSize < 0) || dataSize != typLen)
731-
returnValue = NULL;
732-
else
733-
{
734-
returnValue = (void *) palloc(VARSIZE(typDefault));
735-
memcpy((char *) returnValue,
736-
(char *) typDefault,
737-
(int) VARSIZE(typDefault));
738-
}
739-
}
740-
741-
return returnValue;
742-
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy