|
3 | 3 | * back to source text
|
4 | 4 | *
|
5 | 5 | * IDENTIFICATION
|
6 |
| - * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.173 2004/06/18 06:13:49 tgl Exp $ |
| 6 | + * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.174 2004/06/25 17:20:24 tgl Exp $ |
7 | 7 | *
|
8 | 8 | * This software is copyrighted by Jan Wieck - Hamburg.
|
9 | 9 | *
|
|
42 | 42 |
|
43 | 43 | #include "access/genam.h"
|
44 | 44 | #include "catalog/catname.h"
|
| 45 | +#include "catalog/dependency.h" |
45 | 46 | #include "catalog/heap.h"
|
46 | 47 | #include "catalog/index.h"
|
47 | 48 | #include "catalog/indexing.h"
|
48 | 49 | #include "catalog/namespace.h"
|
49 | 50 | #include "catalog/pg_cast.h"
|
50 | 51 | #include "catalog/pg_constraint.h"
|
| 52 | +#include "catalog/pg_depend.h" |
51 | 53 | #include "catalog/pg_index.h"
|
52 | 54 | #include "catalog/pg_opclass.h"
|
53 | 55 | #include "catalog/pg_operator.h"
|
@@ -1232,6 +1234,116 @@ pg_get_userbyid(PG_FUNCTION_ARGS)
|
1232 | 1234 | PG_RETURN_NAME(result);
|
1233 | 1235 | }
|
1234 | 1236 |
|
| 1237 | + |
| 1238 | +/* |
| 1239 | + * pg_get_serial_sequence |
| 1240 | + * Get the name of the sequence used by a serial column, |
| 1241 | + * formatted suitably for passing to setval, nextval or currval. |
| 1242 | + */ |
| 1243 | +Datum |
| 1244 | +pg_get_serial_sequence(PG_FUNCTION_ARGS) |
| 1245 | +{ |
| 1246 | + text *tablename = PG_GETARG_TEXT_P(0); |
| 1247 | + text *columnname = PG_GETARG_TEXT_P(1); |
| 1248 | + RangeVar *tablerv; |
| 1249 | + Oid tableOid; |
| 1250 | + char *column; |
| 1251 | + AttrNumber attnum; |
| 1252 | + Oid sequenceId = InvalidOid; |
| 1253 | + Relation depRel; |
| 1254 | + ScanKeyData key[3]; |
| 1255 | + SysScanDesc scan; |
| 1256 | + HeapTuple tup; |
| 1257 | + |
| 1258 | + /* Get the OID of the table */ |
| 1259 | + tablerv = makeRangeVarFromNameList(textToQualifiedNameList(tablename, |
| 1260 | + "pg_get_serial_sequence")); |
| 1261 | + tableOid = RangeVarGetRelid(tablerv, false); |
| 1262 | + |
| 1263 | + /* Get the number of the column */ |
| 1264 | + column = DatumGetCString(DirectFunctionCall1(textout, |
| 1265 | + PointerGetDatum(columnname))); |
| 1266 | + |
| 1267 | + attnum = get_attnum(tableOid, column); |
| 1268 | + if (attnum == InvalidAttrNumber) |
| 1269 | + ereport(ERROR, |
| 1270 | + (errcode(ERRCODE_UNDEFINED_COLUMN), |
| 1271 | + errmsg("column \"%s\" of relation \"%s\" does not exist", |
| 1272 | + column, tablerv->relname))); |
| 1273 | + |
| 1274 | + /* Search the dependency table for the dependent sequence */ |
| 1275 | + depRel = heap_openr(DependRelationName, AccessShareLock); |
| 1276 | + |
| 1277 | + ScanKeyInit(&key[0], |
| 1278 | + Anum_pg_depend_refclassid, |
| 1279 | + BTEqualStrategyNumber, F_OIDEQ, |
| 1280 | + ObjectIdGetDatum(RelOid_pg_class)); |
| 1281 | + ScanKeyInit(&key[1], |
| 1282 | + Anum_pg_depend_refobjid, |
| 1283 | + BTEqualStrategyNumber, F_OIDEQ, |
| 1284 | + ObjectIdGetDatum(tableOid)); |
| 1285 | + ScanKeyInit(&key[2], |
| 1286 | + Anum_pg_depend_refobjsubid, |
| 1287 | + BTEqualStrategyNumber, F_INT4EQ, |
| 1288 | + Int32GetDatum(attnum)); |
| 1289 | + |
| 1290 | + scan = systable_beginscan(depRel, DependReferenceIndex, true, |
| 1291 | + SnapshotNow, 3, key); |
| 1292 | + |
| 1293 | + while (HeapTupleIsValid(tup = systable_getnext(scan))) |
| 1294 | + { |
| 1295 | + Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup); |
| 1296 | + |
| 1297 | + /* |
| 1298 | + * We assume any internal dependency of a relation on a column |
| 1299 | + * must be what we are looking for. |
| 1300 | + */ |
| 1301 | + if (deprec->classid == RelOid_pg_class && |
| 1302 | + deprec->objsubid == 0 && |
| 1303 | + deprec->deptype == DEPENDENCY_INTERNAL) |
| 1304 | + { |
| 1305 | + sequenceId = deprec->objid; |
| 1306 | + break; |
| 1307 | + } |
| 1308 | + } |
| 1309 | + |
| 1310 | + systable_endscan(scan); |
| 1311 | + heap_close(depRel, AccessShareLock); |
| 1312 | + |
| 1313 | + if (OidIsValid(sequenceId)) |
| 1314 | + { |
| 1315 | + HeapTuple classtup; |
| 1316 | + Form_pg_class classtuple; |
| 1317 | + char *nspname; |
| 1318 | + char *result; |
| 1319 | + |
| 1320 | + /* Get the sequence's pg_class entry */ |
| 1321 | + classtup = SearchSysCache(RELOID, |
| 1322 | + ObjectIdGetDatum(sequenceId), |
| 1323 | + 0, 0, 0); |
| 1324 | + if (!HeapTupleIsValid(classtup)) |
| 1325 | + elog(ERROR, "cache lookup failed for relation %u", sequenceId); |
| 1326 | + classtuple = (Form_pg_class) GETSTRUCT(classtup); |
| 1327 | + |
| 1328 | + /* Get the namespace */ |
| 1329 | + nspname = get_namespace_name(classtuple->relnamespace); |
| 1330 | + if (!nspname) |
| 1331 | + elog(ERROR, "cache lookup failed for namespace %u", |
| 1332 | + classtuple->relnamespace); |
| 1333 | + |
| 1334 | + /* And construct the result string */ |
| 1335 | + result = quote_qualified_identifier(nspname, |
| 1336 | + NameStr(classtuple->relname)); |
| 1337 | + |
| 1338 | + ReleaseSysCache(classtup); |
| 1339 | + |
| 1340 | + PG_RETURN_TEXT_P(string_to_text(result)); |
| 1341 | + } |
| 1342 | + |
| 1343 | + PG_RETURN_NULL(); |
| 1344 | +} |
| 1345 | + |
| 1346 | + |
1235 | 1347 | /* ----------
|
1236 | 1348 | * deparse_expression - General utility for deparsing expressions
|
1237 | 1349 | *
|
|
0 commit comments