/*
* Show oid, filenode, name, schema and tablespace for each of the
* given objects in the current database.
*/
void
sql_exec_searchtables(PGconn *conn, struct options * opts)
{
char *todo;
char *qualifiers,
*ptr;
char *comma_oids,
*comma_filenodes,
*comma_tables;
bool written = false;
char *addfields = ",c.oid AS \"Oid\", nspname AS \"Schema\", spcname as \"Tablespace\" ";
/* get tables qualifiers, whether names, filenodes, or OIDs */
comma_oids = get_comma_elts(opts->oids);
comma_tables = get_comma_elts(opts->tables);
comma_filenodes = get_comma_elts(opts->filenodes);
/* 80 extra chars for SQL expression */
qualifiers = (char *) pg_malloc(strlen(comma_oids) + strlen(comma_tables) +
strlen(comma_filenodes) + 80);
ptr = qualifiers;
if (opts->oids->num > 0)
{
ptr += sprintf(ptr, "c.oid IN (%s)", comma_oids);
written = true;
}
if (opts->filenodes->num > 0)
{
if (written)
ptr += sprintf(ptr, " OR ");
ptr += sprintf(ptr, "pg_catalog.pg_relation_filenode(c.oid) IN (%s)", comma_filenodes);
written = true;
}
if (opts->tables->num > 0)
{
if (written)
ptr += sprintf(ptr, " OR ");
sprintf(ptr, "c.relname ~~ ANY (ARRAY[%s])", comma_tables);
}
free(comma_oids);
free(comma_tables);
free(comma_filenodes);
/* now build the query */
todo = psprintf(
"SELECT pg_catalog.pg_relation_filenode(c.oid) as \"Filenode\", relname as \"Table Name\" %s\n"
"FROM pg_catalog.pg_class c \n"
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace \n"
" LEFT JOIN pg_catalog.pg_database d ON d.datname = pg_catalog.current_database(),\n"
" pg_catalog.pg_tablespace t \n"
"WHERE relkind IN ('r', 'm', 'i', 'S', 't') AND \n"
" t.oid = CASE\n"
" WHEN reltablespace <> 0 THEN reltablespace\n"
" ELSE dattablespace\n"
" END AND \n"
" (%s) \n"
"ORDER BY relname\n",
opts->extended ? addfields : "",
qualifiers);
free(qualifiers);
sql_exec(conn, todo, opts->quiet);
}
开发者ID:adam8157,项目名称:gpdb,代码行数:69,代码来源:oid2name.c
示例3: pg_tablespace_databases
Datum
pg_tablespace_databases(PG_FUNCTION_ARGS)
{
FuncCallContext *funcctx;
struct dirent *de;
ts_db_fctx *fctx;
if (SRF_IS_FIRSTCALL())
{
MemoryContext oldcontext;
Oid tablespaceOid = PG_GETARG_OID(0);
funcctx = SRF_FIRSTCALL_INIT();
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
fctx = palloc(sizeof(ts_db_fctx));
if (tablespaceOid == GLOBALTABLESPACE_OID)
{
fctx->dirdesc = NULL;
ereport(WARNING,
(errmsg("global tablespace never has databases")));
}
else
{
if (tablespaceOid == DEFAULTTABLESPACE_OID)
fctx->location = psprintf("base");
else
fctx->location = psprintf("pg_tblspc/%u/%s", tablespaceOid,
TABLESPACE_VERSION_DIRECTORY);
fctx->dirdesc = AllocateDir(fctx->location);
if (!fctx->dirdesc)
{
/* the only expected error is ENOENT */
if (errno != ENOENT)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not open directory \"%s\": %m",
fctx->location)));
ereport(WARNING,
(errmsg("%u is not a tablespace OID", tablespaceOid)));
}
}
funcctx->user_fctx = fctx;
MemoryContextSwitchTo(oldcontext);
}
funcctx = SRF_PERCALL_SETUP();
fctx = (ts_db_fctx *) funcctx->user_fctx;
if (!fctx->dirdesc) /* not a tablespace */
SRF_RETURN_DONE(funcctx);
while ((de = ReadDir(fctx->dirdesc, fctx->location)) != NULL)
{
Oid datOid = atooid(de->d_name);
char *subdir;
bool isempty;
/* this test skips . and .., but is awfully weak */
if (!datOid)
continue;
/* if database subdir is empty, don't report tablespace as used */
subdir = psprintf("%s/%s", fctx->location, de->d_name);
isempty = directory_is_empty(subdir);
pfree(subdir);
if (isempty)
continue; /* indeed, nothing in it */
SRF_RETURN_NEXT(funcctx, ObjectIdGetDatum(datOid));
}
FreeDir(fctx->dirdesc);
SRF_RETURN_DONE(funcctx);
}
/*
* pg_be_scram_init
*
* Initialize a new SCRAM authentication exchange status tracker. This
* needs to be called before doing any exchange. It will be filled later
* after the beginning of the exchange with verifier data.
*
* 'selected_mech' identifies the SASL mechanism that the client selected.
* It should be one of the mechanisms that we support, as returned by
* pg_be_scram_get_mechanisms().
*
* 'shadow_pass' is the role's password verifier, from pg_authid.rolpassword.
* The username was provided by the client in the startup message, and is
* available in port->user_name. If 'shadow_pass' is NULL, we still perform
* an authentication exchange, but it will fail, as if an incorrect password
* was given.
*/
void *
pg_be_scram_init(Port *port,
const char *selected_mech,
const char *shadow_pass)
{
scram_state *state;
bool got_verifier;
state = (scram_state *) palloc0(sizeof(scram_state));
state->port = port;
state->state = SCRAM_AUTH_INIT;
/*
* Parse the selected mechanism.
*
* Note that if we don't support channel binding, either because the SSL
* implementation doesn't support it or we're not using SSL at all, we
* would not have advertised the PLUS variant in the first place. If the
* client nevertheless tries to select it, it's a protocol violation like
* selecting any other SASL mechanism we don't support.
*/
#ifdef HAVE_BE_TLS_GET_CERTIFICATE_HASH
if (strcmp(selected_mech, SCRAM_SHA_256_PLUS_NAME) == 0 && port->ssl_in_use)
state->channel_binding_in_use = true;
else
#endif
if (strcmp(selected_mech, SCRAM_SHA_256_NAME) == 0)
state->channel_binding_in_use = false;
else
ereport(ERROR,
(errcode(ERRCODE_PROTOCOL_VIOLATION),
errmsg("client selected an invalid SASL authentication mechanism")));
/*
* Parse the stored password verifier.
*/
if (shadow_pass)
{
int password_type = get_password_type(shadow_pass);
if (password_type == PASSWORD_TYPE_SCRAM_SHA_256)
{
if (parse_scram_verifier(shadow_pass, &state->iterations, &state->salt,
state->StoredKey, state->ServerKey))
got_verifier = true;
else
{
/*
* The password looked like a SCRAM verifier, but could not be
* parsed.
*/
ereport(LOG,
(errmsg("invalid SCRAM verifier for user \"%s\"",
state->port->user_name)));
got_verifier = false;
}
}
else
{
/*
* The user doesn't have SCRAM verifier. (You cannot do SCRAM
* authentication with an MD5 hash.)
*/
state->logdetail = psprintf(_("User \"%s\" does not have a valid SCRAM verifier."),
state->port->user_name);
got_verifier = false;
}
}
else
{
/*
* The caller requested us to perform a dummy authentication. This is
* considered normal, since the caller requested it, so don't set log
* detail.
*/
got_verifier = false;
}
/*
* If the user did not have a valid SCRAM verifier, we still go through
* the motions with a mock one, and fail as if the client supplied an
* incorrect password. This is to avoid revealing information to an
* attacker.
//.........这里部分代码省略.........
/*
* Actually do a base backup for the specified tablespaces.
*
* This is split out mainly to avoid complaints about "variable might be
* clobbered by longjmp" from stupider versions of gcc.
*/
static void
perform_base_backup(basebackup_options *opt, DIR *tblspcdir)
{
XLogRecPtr startptr;
TimeLineID starttli;
XLogRecPtr endptr;
TimeLineID endtli;
char *labelfile;
int datadirpathlen;
datadirpathlen = strlen(DataDir);
backup_started_in_recovery = RecoveryInProgress();
startptr = do_pg_start_backup(opt->label, opt->fastcheckpoint, &starttli,
&labelfile);
/*
* Once do_pg_start_backup has been called, ensure that any failure causes
* us to abort the backup so we don't "leak" a backup counter. For this reason,
* *all* functionality between do_pg_start_backup() and do_pg_stop_backup()
* should be inside the error cleanup block!
*/
PG_ENSURE_ERROR_CLEANUP(base_backup_cleanup, (Datum) 0);
{
List *tablespaces = NIL;
ListCell *lc;
struct dirent *de;
tablespaceinfo *ti;
SendXlogRecPtrResult(startptr, starttli);
/*
* Calculate the relative path of temporary statistics directory in order
* to skip the files which are located in that directory later.
*/
if (is_absolute_path(pgstat_stat_directory) &&
strncmp(pgstat_stat_directory, DataDir, datadirpathlen) == 0)
statrelpath = psprintf("./%s", pgstat_stat_directory + datadirpathlen + 1);
else if (strncmp(pgstat_stat_directory, "./", 2) != 0)
statrelpath = psprintf("./%s", pgstat_stat_directory);
else
statrelpath = pgstat_stat_directory;
/* Collect information about all tablespaces */
while ((de = ReadDir(tblspcdir, "pg_tblspc")) != NULL)
{
char fullpath[MAXPGPATH];
char linkpath[MAXPGPATH];
char *relpath = NULL;
int rllen;
/* Skip special stuff */
if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
continue;
snprintf(fullpath, sizeof(fullpath), "pg_tblspc/%s", de->d_name);
#if defined(HAVE_READLINK) || defined(WIN32)
rllen = readlink(fullpath, linkpath, sizeof(linkpath));
if (rllen < 0)
{
ereport(WARNING,
(errmsg("could not read symbolic link \"%s\": %m",
fullpath)));
continue;
}
else if (rllen >= sizeof(linkpath))
{
ereport(WARNING,
(errmsg("symbolic link \"%s\" target is too long",
fullpath)));
continue;
}
linkpath[rllen] = '\0';
/*
* Relpath holds the relative path of the tablespace directory
* when it's located within PGDATA, or NULL if it's located
* elsewhere.
*/
if (rllen > datadirpathlen &&
strncmp(linkpath, DataDir, datadirpathlen) == 0 &&
IS_DIR_SEP(linkpath[datadirpathlen]))
relpath = linkpath + datadirpathlen + 1;
ti = palloc(sizeof(tablespaceinfo));
ti->oid = pstrdup(de->d_name);
ti->path = pstrdup(linkpath);
ti->rpath = relpath ? pstrdup(relpath) : NULL;
ti->size = opt->progress ? sendTablespace(fullpath, true) : -1;
tablespaces = lappend(tablespaces, ti);
#else
//.........这里部分代码省略.........
/* Get authority (host:port) for the PXF server URL */
char *
get_authority(void)
{
return psprintf("%s:%d", get_pxf_host(), get_pxf_port());
}
开发者ID:adam8157,项目名称:gpdb,代码行数:6,代码来源:pxfutils.c
示例12: bt_metap
/* ------------------------------------------------
* bt_metap()
*
* Get a btree's meta-page information
*
* Usage: SELECT * FROM bt_metap('t1_pkey')
* ------------------------------------------------
*/
Datum
bt_metap(PG_FUNCTION_ARGS)
{
text *relname = PG_GETARG_TEXT_PP(0);
Datum result;
Relation rel;
RangeVar *relrv;
BTMetaPageData *metad;
TupleDesc tupleDesc;
int j;
char *values[6];
Buffer buffer;
Page page;
HeapTuple tuple;
if (!superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
(errmsg("must be superuser to use pageinspect functions"))));
relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname));
rel = relation_openrv(relrv, AccessShareLock);
if (!IS_INDEX(rel) || !IS_BTREE(rel))
elog(ERROR, "relation \"%s\" is not a btree index",
RelationGetRelationName(rel));
/*
* Reject attempts to read non-local temporary relations; we would be
* likely to get wrong data since we have no visibility into the owning
* session's local buffers.
*/
if (RELATION_IS_OTHER_TEMP(rel))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot access temporary tables of other sessions")));
buffer = ReadBuffer(rel, 0);
LockBuffer(buffer, BUFFER_LOCK_SHARE);
page = BufferGetPage(buffer);
metad = BTPageGetMeta(page);
/* Build a tuple descriptor for our result type */
if (get_call_result_type(fcinfo, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE)
elog(ERROR, "return type must be a row type");
j = 0;
values[j++] = psprintf("%d", metad->btm_magic);
values[j++] = psprintf("%d", metad->btm_version);
values[j++] = psprintf("%d", metad->btm_root);
values[j++] = psprintf("%d", metad->btm_level);
values[j++] = psprintf("%d", metad->btm_fastroot);
values[j++] = psprintf("%d", metad->btm_fastlevel);
tuple = BuildTupleFromCStrings(TupleDescGetAttInMetadata(tupleDesc),
values);
result = HeapTupleGetDatum(tuple);
UnlockReleaseBuffer(buffer);
relation_close(rel, AccessShareLock);
PG_RETURN_DATUM(result);
}
/*
* build_function_result_tupdesc_d
*
* Build a RECORD function's tupledesc from the pg_proc proallargtypes,
* proargmodes, and proargnames arrays. This is split out for the
* convenience of ProcedureCreate, which needs to be able to compute the
* tupledesc before actually creating the function.
*
* Returns NULL if there are not at least two OUT or INOUT arguments.
*/
TupleDesc
build_function_result_tupdesc_d(Datum proallargtypes,
Datum proargmodes,
Datum proargnames)
{
TupleDesc desc;
ArrayType *arr;
int numargs;
Oid *argtypes;
char *argmodes;
Datum *argnames = NULL;
Oid *outargtypes;
char **outargnames;
int numoutargs;
int nargnames;
int i;
/* Can't have output args if columns are null */
if (proallargtypes == PointerGetDatum(NULL) ||
proargmodes == PointerGetDatum(NULL))
return NULL;
/*
* We expect the arrays to be 1-D arrays of the right types; verify that.
* For the OID and char arrays, 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(proallargtypes); /* ensure not toasted */
numargs = ARR_DIMS(arr)[0];
if (ARR_NDIM(arr) != 1 ||
numargs < 0 ||
ARR_HASNULL(arr) ||
ARR_ELEMTYPE(arr) != OIDOID)
elog(ERROR, "proallargtypes is not a 1-D Oid array");
argtypes = (Oid *) ARR_DATA_PTR(arr);
arr = DatumGetArrayTypeP(proargmodes); /* ensure not toasted */
if (ARR_NDIM(arr) != 1 ||
ARR_DIMS(arr)[0] != numargs ||
ARR_HASNULL(arr) ||
ARR_ELEMTYPE(arr) != CHAROID)
elog(ERROR, "proargmodes is not a 1-D char array");
argmodes = (char *) ARR_DATA_PTR(arr);
if (proargnames != PointerGetDatum(NULL))
{
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);
}
/* zero elements probably shouldn't happen, but handle it gracefully */
if (numargs <= 0)
return NULL;
/* extract output-argument types and names */
outargtypes = (Oid *) palloc(numargs * sizeof(Oid));
outargnames = (char **) palloc(numargs * sizeof(char *));
numoutargs = 0;
for (i = 0; i < numargs; i++)
{
char *pname;
if (argmodes[i] == PROARGMODE_IN ||
argmodes[i] == PROARGMODE_VARIADIC)
continue;
Assert(argmodes[i] == PROARGMODE_OUT ||
argmodes[i] == PROARGMODE_INOUT ||
argmodes[i] == PROARGMODE_TABLE);
outargtypes[numoutargs] = argtypes[i];
if (argnames)
pname = TextDatumGetCString(argnames[i]);
else
pname = NULL;
if (pname == NULL || pname[0] == '\0')
{
/* Parameter is not named, so gin up a column name */
pname = psprintf("column%d", numoutargs + 1);
}
outargnames[numoutargs] = pname;
numoutargs++;
}
/*
* If there is no output argument, or only one, the function does not
* return tuples.
//.........这里部分代码省略.........
/*
* create_tablespace_directories
*
* Attempt to create filesystem infrastructure linking $PGDATA/pg_tblspc/
* to the specified directory
*/
static void
create_tablespace_directories(const char *location, const Oid tablespaceoid)
{
char *linkloc;
char *location_with_version_dir;
linkloc = psprintf("pg_tblspc/%u", tablespaceoid);
location_with_version_dir = psprintf("%s/%s", location,
TABLESPACE_VERSION_DIRECTORY);
/*
* Attempt to coerce target directory to safe permissions. If this fails,
* it doesn't exist or has the wrong owner.
*/
if (chmod(location, S_IRWXU) != 0)
{
if (errno == ENOENT)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FILE),
errmsg("directory \"%s\" does not exist", location),
InRecovery ? errhint("Create this directory for the tablespace before "
"restarting the server.") : 0));
else
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not set permissions on directory \"%s\": %m",
location)));
}
if (InRecovery)
{
struct stat st;
/*
* Our theory for replaying a CREATE is to forcibly drop the target
* subdirectory if present, and then recreate it. This may be more
* work than needed, but it is simple to implement.
*/
if (stat(location_with_version_dir, &st) == 0 && S_ISDIR(st.st_mode))
{
if (!rmtree(location_with_version_dir, true))
/* If this failed, mkdir() below is going to error. */
ereport(WARNING,
(errmsg("some useless files may be left behind in old database directory \"%s\"",
location_with_version_dir)));
}
}
/*
* The creation of the version directory prevents more than one tablespace
* in a single location.
*/
if (mkdir(location_with_version_dir, S_IRWXU) < 0)
{
if (errno == EEXIST)
ereport(ERROR,
(errcode(ERRCODE_OBJECT_IN_USE),
errmsg("directory \"%s\" already in use as a tablespace",
location_with_version_dir)));
else
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not create directory \"%s\": %m",
location_with_version_dir)));
}
/* Remove old symlink in recovery, in case it points to the wrong place */
if (InRecovery)
{
if (unlink(linkloc) < 0 && errno != ENOENT)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not remove symbolic link \"%s\": %m",
linkloc)));
}
/*
* Create the symlink under PGDATA
*/
if (symlink(location, linkloc) < 0)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not create symbolic link \"%s\": %m",
linkloc)));
pfree(linkloc);
pfree(location_with_version_dir);
}
请发表评论