|
1 | 1 | /*-------------------------------------------------------------------------
|
2 | 2 | *
|
3 | 3 | * lsyscache.c
|
4 |
| - *Routines to access information withinsystemcaches |
| 4 | + *Convenience routines for common queries in thesystemcatalog cache. |
5 | 5 | *
|
6 | 6 | * Copyright (c) 1994, Regents of the University of California
|
7 | 7 | *
|
8 |
| - * |
9 | 8 | * 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 $ |
11 | 10 | *
|
12 | 11 | * NOTES
|
13 | 12 | * Eventually, the index information should go through here, too.
|
14 | 13 | *-------------------------------------------------------------------------
|
15 | 14 | */
|
16 | 15 | #include"postgres.h"
|
17 | 16 |
|
18 |
| - |
19 | 17 | #include"catalog/pg_operator.h"
|
20 | 18 | #include"catalog/pg_type.h"
|
21 | 19 | #include"utils/lsyscache.h"
|
@@ -166,6 +164,77 @@ get_atttypmod(Oid relid, AttrNumber attnum)
|
166 | 164 | return-1;
|
167 | 165 | }
|
168 | 166 |
|
| 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(Oidrelid,AttrNumberattnum,doublemin_estimate) |
| 181 | +{ |
| 182 | +HeapTupleatp; |
| 183 | +doubledisbursion; |
| 184 | +int32ntuples; |
| 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 | +returnmin_estimate; |
| 196 | +} |
| 197 | + |
| 198 | +disbursion= ((Form_pg_attribute)GETSTRUCT(atp))->attdisbursion; |
| 199 | +if (disbursion>0.0) |
| 200 | +returndisbursion;/* 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 | +returnmin_estimate; |
| 215 | +} |
| 216 | + |
| 217 | +ntuples= ((Form_pg_class)GETSTRUCT(atp))->reltuples; |
| 218 | + |
| 219 | +if (ntuples==0) |
| 220 | +returnmin_estimate;/* no data available */ |
| 221 | + |
| 222 | +if (disbursion<0.0)/* VACUUM thinks there are no duplicates */ |
| 223 | +return1.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 | +returndisbursion; |
| 236 | +} |
| 237 | + |
169 | 238 | /*---------- INDEX CACHE ---------- */
|
170 | 239 |
|
171 | 240 | /*watch this space...
|
@@ -504,15 +573,110 @@ get_typalign(Oid typid)
|
504 | 573 | /*
|
505 | 574 | * get_typdefault -
|
506 | 575 | *
|
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. |
509 | 581 | */
|
510 |
| -structvarlena* |
| 582 | +Datum |
511 | 583 | get_typdefault(Oidtypid)
|
512 | 584 | {
|
513 |
| -structvarlena*typdefault= (structvarlena*)TypeDefaultRetrieve(typid); |
| 585 | +structvarlena*typDefault; |
| 586 | +int32dataSize; |
| 587 | +HeapTupletypeTuple; |
| 588 | +Form_pg_typetype; |
| 589 | +int32typLen; |
| 590 | +booltypByVal; |
| 591 | +DatumreturnValue; |
| 592 | + |
| 593 | +/* |
| 594 | + * First, see if there is a non-null typdefault field (usually there isn't) |
| 595 | + */ |
| 596 | +typDefault= (structvarlena*) |
| 597 | +SearchSysCacheGetAttribute(TYPOID, |
| 598 | +Anum_pg_type_typdefault, |
| 599 | +ObjectIdGetDatum(typid), |
| 600 | +0,0,0); |
| 601 | + |
| 602 | +if (typDefault==NULL) |
| 603 | +returnPointerGetDatum(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 | +int8i8; |
| 628 | +int16i16; |
| 629 | +int32i32=0; |
| 630 | + |
| 631 | +if (dataSize==typLen) |
| 632 | +{ |
| 633 | +switch (typLen) |
| 634 | +{ |
| 635 | +casesizeof(int8): |
| 636 | +memcpy((char*)&i8,VARDATA(typDefault),sizeof(int8)); |
| 637 | +i32=i8; |
| 638 | +break; |
| 639 | +casesizeof(int16): |
| 640 | +memcpy((char*)&i16,VARDATA(typDefault),sizeof(int16)); |
| 641 | +i32=i16; |
| 642 | +break; |
| 643 | +casesizeof(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 | +elseif (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 | +} |
514 | 678 |
|
515 |
| -returntypdefault; |
| 679 | +returnreturnValue; |
516 | 680 | }
|
517 | 681 |
|
518 | 682 | /*
|
|