|
8 | 8 | *
|
9 | 9 | *
|
10 | 10 | * IDENTIFICATION
|
11 |
| - * $PostgreSQL: pgsql/src/backend/catalog/pg_constraint.c,v 1.54 2010/08/05 15:25:35 rhaas Exp $ |
| 11 | + * $PostgreSQL: pgsql/src/backend/catalog/pg_constraint.c,v 1.55 2010/08/07 02:44:06 tgl Exp $ |
12 | 12 | *
|
13 | 13 | *-------------------------------------------------------------------------
|
14 | 14 | */
|
@@ -783,3 +783,112 @@ get_constraint_oid(Oid relid, const char *conname, bool missing_ok)
|
783 | 783 |
|
784 | 784 | returnconOid;
|
785 | 785 | }
|
| 786 | + |
| 787 | +/* |
| 788 | + * Determine whether a relation can be proven functionally dependent on |
| 789 | + * a set of grouping columns. If so, return TRUE and add the pg_constraint |
| 790 | + * OIDs of the constraints needed for the proof to the *constraintDeps list. |
| 791 | + * |
| 792 | + * grouping_columns is a list of grouping expressions, in which columns of |
| 793 | + * the rel of interest are Vars with the indicated varno/varlevelsup. |
| 794 | + * |
| 795 | + * Currently we only check to see if the rel has a primary key that is a |
| 796 | + * subset of the grouping_columns. We could also use plain unique constraints |
| 797 | + * if all their columns are known not null, but there's a problem: we need |
| 798 | + * to be able to represent the not-null-ness as part of the constraints added |
| 799 | + * to *constraintDeps. FIXME whenever not-null constraints get represented |
| 800 | + * in pg_constraint. |
| 801 | + */ |
| 802 | +bool |
| 803 | +check_functional_grouping(Oidrelid, |
| 804 | +Indexvarno,Indexvarlevelsup, |
| 805 | +List*grouping_columns, |
| 806 | +List**constraintDeps) |
| 807 | +{ |
| 808 | +boolresult= false; |
| 809 | +Relationpg_constraint; |
| 810 | +HeapTupletuple; |
| 811 | +SysScanDescscan; |
| 812 | +ScanKeyDataskey[1]; |
| 813 | + |
| 814 | +/* Scan pg_constraint for constraints of the target rel */ |
| 815 | +pg_constraint=heap_open(ConstraintRelationId,AccessShareLock); |
| 816 | + |
| 817 | +ScanKeyInit(&skey[0], |
| 818 | +Anum_pg_constraint_conrelid, |
| 819 | +BTEqualStrategyNumber,F_OIDEQ, |
| 820 | +ObjectIdGetDatum(relid)); |
| 821 | + |
| 822 | +scan=systable_beginscan(pg_constraint,ConstraintRelidIndexId, true, |
| 823 | +SnapshotNow,1,skey); |
| 824 | + |
| 825 | +while (HeapTupleIsValid(tuple=systable_getnext(scan))) |
| 826 | +{ |
| 827 | +Form_pg_constraintcon= (Form_pg_constraint)GETSTRUCT(tuple); |
| 828 | +Datumadatum; |
| 829 | +boolisNull; |
| 830 | +ArrayType*arr; |
| 831 | +int16*attnums; |
| 832 | +intnumkeys; |
| 833 | +inti; |
| 834 | +boolfound_col; |
| 835 | + |
| 836 | +/* Only PK constraints are of interest for now, see comment above */ |
| 837 | +if (con->contype!=CONSTRAINT_PRIMARY) |
| 838 | +continue; |
| 839 | + |
| 840 | +/* Extract the conkey array, ie, attnums of PK's columns */ |
| 841 | +adatum=heap_getattr(tuple,Anum_pg_constraint_conkey, |
| 842 | +RelationGetDescr(pg_constraint),&isNull); |
| 843 | +if (isNull) |
| 844 | +elog(ERROR,"null conkey for constraint %u", |
| 845 | +HeapTupleGetOid(tuple)); |
| 846 | +arr=DatumGetArrayTypeP(adatum);/* ensure not toasted */ |
| 847 | +numkeys=ARR_DIMS(arr)[0]; |
| 848 | +if (ARR_NDIM(arr)!=1|| |
| 849 | +numkeys<0|| |
| 850 | +ARR_HASNULL(arr)|| |
| 851 | +ARR_ELEMTYPE(arr)!=INT2OID) |
| 852 | +elog(ERROR,"conkey is not a 1-D smallint array"); |
| 853 | +attnums= (int16*)ARR_DATA_PTR(arr); |
| 854 | + |
| 855 | +found_col= false; |
| 856 | +for (i=0;i<numkeys;i++) |
| 857 | +{ |
| 858 | +AttrNumberattnum=attnums[i]; |
| 859 | +ListCell*gl; |
| 860 | + |
| 861 | +found_col= false; |
| 862 | +foreach(gl,grouping_columns) |
| 863 | +{ |
| 864 | +Var*gvar= (Var*)lfirst(gl); |
| 865 | + |
| 866 | +if (IsA(gvar,Var)&& |
| 867 | +gvar->varno==varno&& |
| 868 | +gvar->varlevelsup==varlevelsup&& |
| 869 | +gvar->varattno==attnum) |
| 870 | +{ |
| 871 | +found_col= true; |
| 872 | +break; |
| 873 | +} |
| 874 | +} |
| 875 | +if (!found_col) |
| 876 | +break; |
| 877 | +} |
| 878 | + |
| 879 | +if (found_col) |
| 880 | +{ |
| 881 | +/* The PK is a subset of grouping_columns, so we win */ |
| 882 | +*constraintDeps=lappend_oid(*constraintDeps, |
| 883 | +HeapTupleGetOid(tuple)); |
| 884 | +result= true; |
| 885 | +break; |
| 886 | +} |
| 887 | +} |
| 888 | + |
| 889 | +systable_endscan(scan); |
| 890 | + |
| 891 | +heap_close(pg_constraint,AccessShareLock); |
| 892 | + |
| 893 | +returnresult; |
| 894 | +} |