Fix bug in checking permissions on table being COPY'd.
This commit is contained in:
parent
d27c28fdc0
commit
fa608ad2a6
|
@ -9,7 +9,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.3 1996/10/31 09:08:10 bryanh Exp $
|
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.4 1996/11/02 02:03:13 bryanh Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -52,25 +52,25 @@
|
||||||
|
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* CHECK_IF_ABORTED() is used to avoid doing unnecessary
|
* CHECK_IF_ABORTED() is used to avoid doing unnecessary
|
||||||
* processing within an aborted transaction block.
|
* processing within an aborted transaction block.
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
#define CHECK_IF_ABORTED() \
|
#define CHECK_IF_ABORTED() \
|
||||||
if (IsAbortedTransactionBlockState()) { \
|
if (IsAbortedTransactionBlockState()) { \
|
||||||
elog(NOTICE, "(transaction aborted): %s", \
|
elog(NOTICE, "(transaction aborted): %s", \
|
||||||
"queries ignored until END"); \
|
"queries ignored until END"); \
|
||||||
commandTag = "*ABORT STATE*"; \
|
commandTag = "*ABORT STATE*"; \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* general utility function invoker
|
* general utility function invoker
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
ProcessUtility(Node *parsetree,
|
ProcessUtility(Node *parsetree,
|
||||||
CommandDest dest)
|
CommandDest dest)
|
||||||
{
|
{
|
||||||
char *commandTag = NULL;
|
char *commandTag = NULL;
|
||||||
char *relname;
|
char *relname;
|
||||||
|
@ -80,163 +80,139 @@ ProcessUtility(Node *parsetree,
|
||||||
userName = GetPgUserName();
|
userName = GetPgUserName();
|
||||||
|
|
||||||
switch (nodeTag(parsetree)) {
|
switch (nodeTag(parsetree)) {
|
||||||
/* ********************************
|
/* ********************************
|
||||||
* transactions
|
* transactions
|
||||||
* ********************************
|
* ********************************
|
||||||
*/
|
*/
|
||||||
case T_TransactionStmt:
|
case T_TransactionStmt:
|
||||||
{
|
{
|
||||||
TransactionStmt *stmt = (TransactionStmt *)parsetree;
|
TransactionStmt *stmt = (TransactionStmt *)parsetree;
|
||||||
switch (stmt->command) {
|
switch (stmt->command) {
|
||||||
case BEGIN_TRANS:
|
case BEGIN_TRANS:
|
||||||
commandTag = "BEGIN";
|
commandTag = "BEGIN";
|
||||||
CHECK_IF_ABORTED();
|
CHECK_IF_ABORTED();
|
||||||
BeginTransactionBlock();
|
BeginTransactionBlock();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case END_TRANS:
|
case END_TRANS:
|
||||||
commandTag = "END";
|
commandTag = "END";
|
||||||
EndTransactionBlock();
|
EndTransactionBlock();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ABORT_TRANS:
|
case ABORT_TRANS:
|
||||||
commandTag = "ABORT";
|
commandTag = "ABORT";
|
||||||
UserAbortTransactionBlock();
|
UserAbortTransactionBlock();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* ********************************
|
/* ********************************
|
||||||
* portal manipulation
|
* portal manipulation
|
||||||
* ********************************
|
* ********************************
|
||||||
*/
|
*/
|
||||||
case T_ClosePortalStmt:
|
case T_ClosePortalStmt:
|
||||||
{
|
{
|
||||||
ClosePortalStmt *stmt = (ClosePortalStmt *)parsetree;
|
ClosePortalStmt *stmt = (ClosePortalStmt *)parsetree;
|
||||||
|
|
||||||
commandTag = "CLOSE";
|
commandTag = "CLOSE";
|
||||||
CHECK_IF_ABORTED();
|
CHECK_IF_ABORTED();
|
||||||
|
|
||||||
PerformPortalClose(stmt->portalname, dest);
|
PerformPortalClose(stmt->portalname, dest);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_FetchStmt:
|
case T_FetchStmt:
|
||||||
{
|
{
|
||||||
FetchStmt *stmt = (FetchStmt *)parsetree;
|
FetchStmt *stmt = (FetchStmt *)parsetree;
|
||||||
char *portalName = stmt->portalname;
|
char *portalName = stmt->portalname;
|
||||||
bool forward;
|
bool forward;
|
||||||
int count;
|
int count;
|
||||||
|
|
||||||
commandTag = "FETCH";
|
commandTag = "FETCH";
|
||||||
CHECK_IF_ABORTED();
|
CHECK_IF_ABORTED();
|
||||||
|
|
||||||
forward = (bool)(stmt->direction == FORWARD);
|
forward = (bool)(stmt->direction == FORWARD);
|
||||||
|
|
||||||
/* parser ensures that count is >= 0 and
|
/* parser ensures that count is >= 0 and
|
||||||
'fetch ALL' -> 0 */
|
'fetch ALL' -> 0 */
|
||||||
|
|
||||||
count = stmt->howMany;
|
count = stmt->howMany;
|
||||||
PerformPortalFetch(portalName, forward, count, commandTag, dest);
|
PerformPortalFetch(portalName, forward, count, commandTag, dest);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* ********************************
|
/* ********************************
|
||||||
* relation and attribute manipulation
|
* relation and attribute manipulation
|
||||||
* ********************************
|
* ********************************
|
||||||
*/
|
*/
|
||||||
case T_CreateStmt:
|
case T_CreateStmt:
|
||||||
commandTag = "CREATE";
|
commandTag = "CREATE";
|
||||||
CHECK_IF_ABORTED();
|
CHECK_IF_ABORTED();
|
||||||
|
|
||||||
DefineRelation((CreateStmt *)parsetree);
|
DefineRelation((CreateStmt *)parsetree);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_DestroyStmt:
|
case T_DestroyStmt:
|
||||||
{
|
{
|
||||||
DestroyStmt *stmt = (DestroyStmt *)parsetree;
|
DestroyStmt *stmt = (DestroyStmt *)parsetree;
|
||||||
List *arg;
|
List *arg;
|
||||||
List *args = stmt->relNames;
|
List *args = stmt->relNames;
|
||||||
|
|
||||||
commandTag = "DROP";
|
commandTag = "DROP";
|
||||||
CHECK_IF_ABORTED();
|
CHECK_IF_ABORTED();
|
||||||
|
|
||||||
foreach (arg, args) {
|
foreach (arg, args) {
|
||||||
relname = strVal(lfirst(arg));
|
relname = strVal(lfirst(arg));
|
||||||
if (IsSystemRelationName(relname))
|
if (IsSystemRelationName(relname))
|
||||||
elog(WARN, "class \"%-.*s\" is a system catalog",
|
elog(WARN, "class \"%-.*s\" is a system catalog",
|
||||||
NAMEDATALEN, relname);
|
NAMEDATALEN, relname);
|
||||||
#ifndef NO_SECURITY
|
#ifndef NO_SECURITY
|
||||||
if (!pg_ownercheck(userName, relname, RELNAME))
|
if (!pg_ownercheck(userName, relname, RELNAME))
|
||||||
elog(WARN, "you do not own class \"%-.*s\"",
|
elog(WARN, "you do not own class \"%-.*s\"",
|
||||||
NAMEDATALEN, relname);
|
NAMEDATALEN, relname);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
foreach (arg, args) {
|
foreach (arg, args) {
|
||||||
relname = strVal(lfirst(arg));
|
relname = strVal(lfirst(arg));
|
||||||
RemoveRelation(relname);
|
RemoveRelation(relname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_PurgeStmt:
|
case T_PurgeStmt:
|
||||||
{
|
{
|
||||||
PurgeStmt *stmt = (PurgeStmt *)parsetree;
|
PurgeStmt *stmt = (PurgeStmt *)parsetree;
|
||||||
|
|
||||||
commandTag = "PURGE";
|
commandTag = "PURGE";
|
||||||
CHECK_IF_ABORTED();
|
CHECK_IF_ABORTED();
|
||||||
|
|
||||||
RelationPurge(stmt->relname,
|
RelationPurge(stmt->relname,
|
||||||
stmt->beforeDate, /* absolute time string */
|
stmt->beforeDate, /* absolute time string */
|
||||||
stmt->afterDate); /* relative time string */
|
stmt->afterDate); /* relative time string */
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_CopyStmt:
|
case T_CopyStmt:
|
||||||
{
|
{
|
||||||
CopyStmt *stmt = (CopyStmt *)parsetree;
|
CopyStmt *stmt = (CopyStmt *)parsetree;
|
||||||
char *filename;
|
|
||||||
char *delim;
|
|
||||||
bool isBinary;
|
|
||||||
bool isOids;
|
|
||||||
bool isFrom;
|
|
||||||
bool pipe = false;
|
|
||||||
|
|
||||||
commandTag = "COPY";
|
commandTag = "COPY";
|
||||||
CHECK_IF_ABORTED();
|
CHECK_IF_ABORTED();
|
||||||
|
|
||||||
relname = stmt->relname;
|
|
||||||
isBinary = stmt->binary;
|
|
||||||
isOids = stmt->oids;
|
|
||||||
|
|
||||||
isFrom = (bool)(stmt->direction == FROM);
|
|
||||||
filename = stmt->filename;
|
|
||||||
delim = stmt->delimiter;
|
|
||||||
|
|
||||||
#ifndef NO_SECURITY
|
|
||||||
if (isFrom) {
|
|
||||||
if (!pg_aclcheck(relname, userName, ACL_RD))
|
|
||||||
elog(WARN, "%s %s", relname, ACL_NO_PRIV_WARNING);
|
|
||||||
} else {
|
|
||||||
if (!pg_aclcheck(relname, userName, ACL_WR))
|
|
||||||
elog(WARN, "%s %s", relname, ACL_NO_PRIV_WARNING);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Free up file descriptors - going to do a read... */
|
/* Free up file descriptors - going to do a read... */
|
||||||
|
|
||||||
closeOneVfd();
|
closeOneVfd();
|
||||||
|
|
||||||
/*
|
DoCopy(stmt->relname,
|
||||||
* use stdin/stdout if filename is null.
|
stmt->binary,
|
||||||
*/
|
stmt->oids,
|
||||||
if (filename == NULL)
|
(bool)(stmt->direction == FROM),
|
||||||
pipe = true;
|
(bool)(stmt->filename == NULL),
|
||||||
|
/* null filename means copy to/from stdout/stdin,
|
||||||
if (pipe && IsUnderPostmaster) dest = CopyEnd;
|
rather than to/from a file.
|
||||||
|
*/
|
||||||
DoCopy(relname, isBinary, isOids, isFrom, pipe, filename, delim);
|
stmt->filename,
|
||||||
|
stmt->delimiter);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue