/* * ProcessRoleGUC -- * We now process pg_authid.rolconfig separately from InitializeSessionUserId, * since it's too early to access toast table before initializing all * relcaches in phase3. */ static void ProcessRoleGUC(void) { cqContext *pcqCtx; Oid roleId; HeapTuple roleTup; Datum datum; bool isnull; /* This should have been set by now */ roleId = GetUserId(); Assert(OidIsValid(roleId)); pcqCtx = caql_beginscan( NULL, cql("SELECT * FROM pg_authid " " WHERE oid = :1", ObjectIdGetDatum(roleId))); roleTup = caql_getnext(pcqCtx); if (!HeapTupleIsValid(roleTup)) ereport(FATAL, (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION), errmsg("role %u does not exist", roleId), errSendAlert(false))); /* * Set up user-specific configuration variables. This is a good place to * do it so we don't have to read pg_authid twice during session startup. */ datum = caql_getattr(pcqCtx, Anum_pg_authid_rolconfig, &isnull); if (!isnull) { ArrayType *a = DatumGetArrayTypeP(datum); /* * We process all the options at SUSET level. We assume that the * right to insert an option into pg_authid was checked when it was * inserted. */ ProcessGUCArray(a, PGC_SUSET, PGC_S_USER, GUC_ACTION_SET); } caql_endscan(pcqCtx); }
/* * get_func_result_name * * If the function has exactly one output parameter, and that parameter * is named, return the name (as a palloc'd string). Else return NULL. * * This is used to determine the default output column name for functions * returning scalar types. */ char * get_func_result_name(Oid functionId) { char *result; HeapTuple procTuple; Datum proargmodes; Datum proargnames; bool isnull; ArrayType *arr; int numargs; char *argmodes; Datum *argnames; int numoutargs; int nargnames; int i; cqContext *pcqCtx; /* First fetch the function's pg_proc row */ pcqCtx = caql_beginscan( NULL, cql("SELECT * FROM pg_proc " " WHERE oid = :1 ", ObjectIdGetDatum(functionId))); procTuple = caql_getnext(pcqCtx); if (!HeapTupleIsValid(procTuple)) elog(ERROR, "cache lookup failed for function %u", functionId); /* If there are no named OUT parameters, return NULL */ if (heap_attisnull(procTuple, Anum_pg_proc_proargmodes) || heap_attisnull(procTuple, Anum_pg_proc_proargnames)) result = NULL; else { /* Get the data out of the tuple */ proargmodes = caql_getattr(pcqCtx, Anum_pg_proc_proargmodes, &isnull); Assert(!isnull); proargnames = caql_getattr(pcqCtx, Anum_pg_proc_proargnames, &isnull); Assert(!isnull); /* * We expect the arrays to be 1-D arrays of the right types; verify * that. For the char array, we don't need to use deconstruct_array() * since the array data is just going to look like a C array of * values. */ arr = DatumGetArrayTypeP(proargmodes); /* ensure not toasted */ numargs = ARR_DIMS(arr)[0]; if (ARR_NDIM(arr) != 1 || numargs < 0 || ARR_HASNULL(arr) || ARR_ELEMTYPE(arr) != CHAROID) elog(ERROR, "proargmodes is not a 1-D char array"); argmodes = (char *) ARR_DATA_PTR(arr); arr = DatumGetArrayTypeP(proargnames); /* ensure not toasted */ if (ARR_NDIM(arr) != 1 || ARR_DIMS(arr)[0] != numargs || ARR_HASNULL(arr) || ARR_ELEMTYPE(arr) != TEXTOID) elog(ERROR, "proargnames is not a 1-D text array"); deconstruct_array(arr, TEXTOID, -1, false, 'i', &argnames, NULL, &nargnames); Assert(nargnames == numargs); /* scan for output argument(s) */ result = NULL; numoutargs = 0; for (i = 0; i < numargs; i++) { if (argmodes[i] == PROARGMODE_IN || argmodes[i] == PROARGMODE_VARIADIC) continue; Assert(argmodes[i] == PROARGMODE_OUT || argmodes[i] == PROARGMODE_INOUT || argmodes[i] == PROARGMODE_TABLE); if (++numoutargs > 1) { /* multiple out args, so forget it */ result = NULL; break; } result = DatumGetCString(DirectFunctionCall1(textout, argnames[i])); if (result == NULL || result[0] == '\0') { /* Parameter is not named, so forget it */ result = NULL; break; } } } caql_endscan(pcqCtx); return result; }
Datum caql_insert_to_in_memory_pg_namespace(PG_FUNCTION_ARGS) { Oid nspid = PG_GETARG_OID(0); char *nspname = text_to_cstring(PG_GETARG_TEXT_P(1)); Oid nspdboid = PG_GETARG_OID(2); HeapTuple tuple; Datum values[Natts_pg_namespace]; bool nulls[Natts_pg_namespace]; /* initialize nulls and values */ for (int i = 0; i < Natts_pg_namespace; i++) { nulls[i] = true; values[i] = (Datum) 0; } NameData name; namestrcpy(&name, nspname); values[Anum_pg_namespace_nspname - 1] = NameGetDatum(&name); values[Anum_pg_namespace_nspdboid - 1] = ObjectIdGetDatum(nspdboid); nulls[Anum_pg_namespace_nspname - 1] = false; nulls[Anum_pg_namespace_nspdboid - 1] = false; cqContext *pcqCtx = caql_beginscan( NULL, cql("INSERT INTO pg_namespace", NULL)); HeapTuple tup = caql_form_tuple(pcqCtx, values, nulls); HeapTupleSetOid(tup, nspid); caql_insert_inmem(pcqCtx, tup); caql_endscan(pcqCtx); StringInfoData buf; initStringInfo(&buf); appendStringInfo(&buf, "inserted tuple to pg_namespace (oid %d, nspname %s, nspdboid %d)", nspid, nspname, nspdboid); pcqCtx = caql_beginscan( NULL, cql("SELECT * FROM pg_namespace " "WHERE nspname = :1", CStringGetDatum((char *) nspname))); while (HeapTupleIsValid(tuple = caql_getnext(pcqCtx))) { Oid thisoid = HeapTupleGetOid(tuple); bool isNull; Datum data = caql_getattr(pcqCtx, Anum_pg_namespace_nspdboid, &isNull); Oid namespacedboid = DatumGetObjectId(data); data = caql_getattr(pcqCtx, Anum_pg_namespace_nspname, &isNull); char *namespacename = DatumGetCString(data); appendStringInfo(&buf, "\nresult tuple: (oid %d, nspname %s, nspdboid %d)", thisoid, namespacename, namespacedboid); } caql_endscan(pcqCtx); PG_RETURN_TEXT_P(cstring_to_text(buf.data)); }