* get_relation_keys * Return a list of relation keys */
| 4139 | * Return a list of relation keys |
| 4140 | */ |
| 4141 | List * |
| 4142 | get_relation_keys(Oid relid) |
| 4143 | { |
| 4144 | List *keys = NIL; |
| 4145 | |
| 4146 | // lookup unique constraints for relation from the catalog table |
| 4147 | ScanKeyData skey[1]; |
| 4148 | |
| 4149 | Relation rel = table_open(ConstraintRelationId, AccessShareLock); |
| 4150 | SysScanDesc scan; |
| 4151 | HeapTuple htup; |
| 4152 | |
| 4153 | ScanKeyInit(&skey[0], Anum_pg_constraint_conrelid, BTEqualStrategyNumber, F_OIDEQ, relid); |
| 4154 | scan = systable_beginscan(rel, ConstraintRelidTypidNameIndexId, true, |
| 4155 | NULL, 1, skey); |
| 4156 | |
| 4157 | while (HeapTupleIsValid(htup = systable_getnext(scan))) |
| 4158 | { |
| 4159 | Form_pg_constraint contuple = (Form_pg_constraint) GETSTRUCT(htup); |
| 4160 | |
| 4161 | // skip non-unique constraints |
| 4162 | if (CONSTRAINT_UNIQUE != contuple->contype && |
| 4163 | CONSTRAINT_PRIMARY != contuple->contype) |
| 4164 | { |
| 4165 | continue; |
| 4166 | } |
| 4167 | |
| 4168 | // skip the constraint if deferrable |
| 4169 | if (contuple->condeferrable) |
| 4170 | { |
| 4171 | continue; |
| 4172 | } |
| 4173 | |
| 4174 | // store key set in an array |
| 4175 | List *key = NIL; |
| 4176 | |
| 4177 | bool null = false; |
| 4178 | Datum dat = |
| 4179 | heap_getattr(htup, Anum_pg_constraint_conkey, RelationGetDescr(rel), &null); |
| 4180 | |
| 4181 | Datum *dats = NULL; |
| 4182 | int numKeys = 0; |
| 4183 | |
| 4184 | // extract key elements |
| 4185 | deconstruct_array(DatumGetArrayTypeP(dat), INT2OID, 2, true, 's', &dats, NULL, &numKeys); |
| 4186 | |
| 4187 | for (int i = 0; i < numKeys; i++) |
| 4188 | { |
| 4189 | int16 key_elem = DatumGetInt16(dats[i]); |
| 4190 | key = lappend_int(key, key_elem); |
| 4191 | } |
| 4192 | |
| 4193 | keys = lappend(keys, key); |
| 4194 | } |
| 4195 | |
| 4196 | systable_endscan(scan); |
| 4197 | table_close(rel, AccessShareLock); |
| 4198 |
no test coverage detected