Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
33417507
Commit
33417507
authored
Oct 31, 1996
by
Bryan Henderson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Require superuser privilege to create C function.
parent
b13f5c25
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
463 additions
and
400 deletions
+463
-400
src/backend/commands/define.c
src/backend/commands/define.c
+457
-394
src/backend/tcop/utility.c
src/backend/tcop/utility.c
+6
-6
No files found.
src/backend/commands/define.c
View file @
33417507
/*-------------------------------------------------------------------------
*
* define.c--
* POSTGRES "define" utility code.
*
* These routines execute some of the CREATE statements. In an earlier
* version of Postgres, these were "define" statements.
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.
2 1996/10/23 07:40:01 scrappy
Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.
3 1996/10/31 09:07:41 bryanh
Exp $
*
* DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the
* appropriate arguments/flags, passing the results to the
* corresponding "FooDefine" routines (in src/catalog) that do
* the actual catalog-munging.
* the actual catalog-munging. These routines also verify permission
* of the user to execute the command.
*
* NOTES
* These things must be defined and committed in the following order:
*
"defin
e function":
*
"creat
e function":
* input/output, recv/send procedures
*
"defin
e type":
*
"creat
e type":
* type
*
"defin
e operator":
*
"creat
e operator":
* operators
*
* Most of the parse-tree manipulation routines are defined in
...
...
@@ -33,186 +36,246 @@
#include <ctype.h>
#include <math.h>
#include "postgres.h"
#include "access/heapam.h"
#include "access/htup.h"
#include "utils/tqual.h"
#include "catalog/catname.h"
#include "catalog/pg_aggregate.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "catalog/pg_operator.h"
#include "utils/syscache.h"
#include "nodes/pg_list.h"
#include "nodes/parsenodes.h"
#include "fmgr.h"
/* for fmgr */
#include "utils/builtins.h"
/* prototype for textin() */
#include "utils/elog.h"
#include "utils/palloc.h"
#include "commands/defrem.h"
#include "optimizer/xfunc.h"
#include "tcop/dest.h"
#include <postgres.h>
#include <access/heapam.h>
#include <access/htup.h>
#include <utils/tqual.h>
#include <catalog/catname.h>
#include <catalog/pg_aggregate.h>
#include <catalog/pg_operator.h>
#include <catalog/pg_proc.h>
#include <catalog/pg_type.h>
#include <catalog/pg_user.h>
/* superuser() uses this */
#include <utils/syscache.h>
#include <nodes/pg_list.h>
#include <nodes/parsenodes.h>
#include <fmgr.h>
/* for fmgr */
#include <utils/builtins.h>
/* prototype for textin() */
#include <utils/elog.h>
#include <utils/palloc.h>
#include <commands/defrem.h>
#include <optimizer/xfunc.h>
#include <tcop/dest.h>
static
char
*
defGetString
(
DefElem
*
def
);
static
int
defGetTypeLength
(
DefElem
*
def
);
#define DEFAULT_TYPDELIM ','
/*
* DefineFunction --
* Registers a new function.
*
*/
bool
superuser
(
void
)
{
/*--------------------------------------------------------------------------
The Postgres user running this command has Postgres superuser
privileges.
--------------------------------------------------------------------------*/
HeapTuple
utup
;
char
*
userName
;
userName
=
GetPgUserName
();
utup
=
SearchSysCacheTuple
(
USENAME
,
PointerGetDatum
(
userName
),
0
,
0
,
0
);
Assert
(
utup
!=
NULL
);
return
((
Form_pg_user
)
GETSTRUCT
(
utup
))
->
usesuper
;
}
void
DefineFunction
(
ProcedureStmt
*
stmt
,
CommandDest
dest
)
{
List
*
parameters
=
stmt
->
withClause
;
char
*
proname
=
stmt
->
funcname
;
char
*
probin_str
;
char
*
prosrc_str
;
char
*
prorettype
;
char
*
languageName
;
bool
canCache
=
FALSE
;
List
*
argList
;
int32
byte_pct
=
100
,
perbyte_cpu
,
percall_cpu
,
outin_ratio
=
100
;
bool
returnsSet
;
case_translate_language_name
(
const
char
*
input
,
char
*
output
)
{
/*-------------------------------------------------------------------------
Translate the input language name to lower case, except if it's C,
translate to upper case.
--------------------------------------------------------------------------*/
int
i
;
/* ----------------
* figure out the language and convert it to lowercase.
* ----------------
*/
languageName
=
stmt
->
language
;
for
(
i
=
0
;
i
<
NAMEDATALEN
&&
languageName
[
i
];
++
i
)
{
languageName
[
i
]
=
tolower
(
languageName
[
i
]);
}
for
(
i
=
0
;
i
<
NAMEDATALEN
&&
input
[
i
]
!=
'\0'
;
++
i
)
output
[
i
]
=
tolower
(
input
[
i
]);
/* ----------------
* handle "returntype = X". The function could return a singleton
* value or a set of values. Figure out which.
* ----------------
*/
if
(
nodeTag
(
stmt
->
returnType
)
==
T_TypeName
)
{
TypeName
*
setType
=
(
TypeName
*
)
stmt
->
returnType
;
output
[
i
]
=
'\0'
;
if
(
strcmp
(
output
,
"c"
)
==
0
)
output
[
0
]
=
'C'
;
}
void
compute_return_type
(
const
Node
*
returnType
,
char
**
prorettype_p
,
bool
*
returnsSet_p
)
{
/*---------------------------------------------------------------------------
Examine the "returns" clause returnType of the CREATE FUNCTION statement
and return information about it as **prorettype_p and **returnsSet.
----------------------------------------------------------------------------*/
if
(
nodeTag
(
returnType
)
==
T_TypeName
)
{
/* a set of values */
prorettype
=
setType
->
name
,
returnsSet
=
true
;
TypeName
*
setType
=
(
TypeName
*
)
returnType
;
*
prorettype_p
=
setType
->
name
,
*
returnsSet_p
=
true
;
}
else
{
/* singleton */
prorettype
=
strVal
(
stmt
->
returnType
);
returnsSet
=
false
;
*
prorettype_p
=
strVal
(
returnType
);
*
returnsSet_p
=
false
;
}
}
/* Next attributes are only defined for C functions */
if
(
strcmp
(
languageName
,
"c"
)
==
0
||
strcmp
(
languageName
,
"internal"
)
==
0
)
{
void
compute_full_attributes
(
const
List
*
parameters
,
int32
*
byte_pct_p
,
int32
*
perbyte_cpu_p
,
int32
*
percall_cpu_p
,
int32
*
outin_ratio_p
,
bool
*
canCache_p
)
{
/*--------------------------------------------------------------------------
Interpret the parameters *parameters and return their contents as
*byte_pct_p, etc.
These are the full parameters of a C or internal function.
---------------------------------------------------------------------------*/
List
*
pl
;
/* the defaults */
byte_pct
=
BYTE_PCT
;
perbyte_cpu
=
PERBYTE_CPU
;
percall_cpu
=
PERCALL_CPU
;
outin_ratio
=
OUTIN_RATIO
;
*
byte_pct_p
=
BYTE_PCT
;
*
perbyte_cpu_p
=
PERBYTE_CPU
;
*
percall_cpu_p
=
PERCALL_CPU
;
*
outin_ratio_p
=
OUTIN_RATIO
;
foreach
(
pl
,
parameters
)
{
foreach
(
pl
,
(
List
*
)
parameters
)
{
int
count
;
char
*
ptr
;
ParamString
*
param
=
(
ParamString
*
)
lfirst
(
pl
);
if
(
!
strcasecmp
(
param
->
name
,
"isacachable"
))
{
/* ----------------
* handle "[ iscachable ]": figure out if Postquel functions
* are cacheable automagically?
* ----------------
*/
canCache
=
TRUE
;
}
else
if
(
!
strcasecmp
(
param
->
name
,
"trusted"
))
{
if
(
strcasecmp
(
param
->
name
,
"iscachable"
)
==
0
)
{
*
canCache_p
=
true
;
}
else
if
(
strcasecmp
(
param
->
name
,
"trusted"
)
==
0
)
{
/*
* we don't have untrusted functions any more. The 4.2
* implementation is lousy anyway so I took it out.
* -ay 10/94
*/
elog
(
WARN
,
"untrusted function has been decommissioned."
);
}
else
if
(
!
strcasecmp
(
param
->
name
,
"byte_pct"
)
)
{
}
else
if
(
strcasecmp
(
param
->
name
,
"byte_pct"
)
==
0
)
{
/*
** handle expensive function parameters
*/
byte_pct
=
atoi
(
param
->
val
);
}
else
if
(
!
strcasecmp
(
param
->
name
,
"perbyte_cpu"
))
{
if
(
!
sscanf
(
param
->
val
,
"%d"
,
&
perbyte_cpu
))
{
for
(
count
=
0
,
ptr
=
param
->
val
;
*
ptr
!=
'\0'
;
ptr
++
)
{
if
(
*
ptr
==
'!'
)
{
count
++
;
}
}
perbyte_cpu
=
(
int
)
pow
(
10
.
0
,
(
double
)
count
);
}
}
else
if
(
!
strcasecmp
(
param
->
name
,
"percall_cpu"
))
{
if
(
!
sscanf
(
param
->
val
,
"%d"
,
&
percall_cpu
))
{
for
(
count
=
0
,
ptr
=
param
->
val
;
*
ptr
!=
'\0'
;
ptr
++
)
{
if
(
*
ptr
==
'!'
)
{
count
++
;
*
byte_pct_p
=
atoi
(
param
->
val
);
}
else
if
(
strcasecmp
(
param
->
name
,
"perbyte_cpu"
)
==
0
)
{
if
(
sscanf
(
param
->
val
,
"%d"
,
perbyte_cpu_p
)
==
0
)
{
for
(
count
=
0
,
ptr
=
param
->
val
;
*
ptr
!=
'\0'
;
ptr
++
)
if
(
*
ptr
==
'!'
)
count
++
;
}
*
perbyte_cpu_p
=
(
int
)
pow
(
10
.
0
,
(
double
)
count
);
}
else
if
(
strcasecmp
(
param
->
name
,
"percall_cpu"
)
==
0
)
{
if
(
sscanf
(
param
->
val
,
"%d"
,
percall_cpu_p
)
==
0
)
{
for
(
count
=
0
,
ptr
=
param
->
val
;
*
ptr
!=
'\0'
;
ptr
++
)
if
(
*
ptr
==
'!'
)
count
++
;
*
percall_cpu_p
=
(
int
)
pow
(
10
.
0
,
(
double
)
count
);
}
percall_cpu
=
(
int
)
pow
(
10
.
0
,
(
double
)
count
);
}
else
if
(
strcasecmp
(
param
->
name
,
"outin_ratio"
)
==
0
)
{
*
outin_ratio_p
=
atoi
(
param
->
val
);
}
}
else
if
(
!
strcasecmp
(
param
->
name
,
"outin_ratio"
))
{
outin_ratio
=
atoi
(
param
->
val
);
}
}
}
else
if
(
!
strcmp
(
languageName
,
"sql"
))
{
/* query optimizer groks sql, these are meaningless */
perbyte_cpu
=
percall_cpu
=
0
;
}
void
interpret_AS_clause
(
const
char
languageName
[],
const
char
as
[],
char
**
prosrc_str_p
,
char
**
probin_str_p
)
{
if
(
strcmp
(
languageName
,
"C"
)
==
0
||
strcmp
(
languageName
,
"internal"
)
==
0
)
{
*
prosrc_str_p
=
"-"
;
*
probin_str_p
=
(
char
*
)
as
;
}
else
{
elog
(
WARN
,
"DefineFunction: language '%s' is not supported"
,
languageName
)
;
*
prosrc_str_p
=
(
char
*
)
as
;
*
probin_str_p
=
"-"
;
}
}
/* ----------------
* handle "[ arg is (...) ]"
* XXX fix optional arg handling below
* ----------------
/*
* CreateFunction --
* Execute a CREATE FUNCTION utility statement.
*
*/
void
CreateFunction
(
ProcedureStmt
*
stmt
,
CommandDest
dest
)
{
char
*
probin_str
;
/* pathname of executable file that executes this function, if any */
char
*
prosrc_str
;
/* SQL that executes this function, if any */
char
*
prorettype
;
/* Type of return value (or member of set of values) from function */
char
languageName
[
NAMEDATALEN
+
1
];
/* name of language of function, with case adjusted:
"C", "internal", or "SQL"
*/
argList
=
stmt
->
defArgs
;
/* The following are attributes of the function, as expressed in the
CREATE FUNCTION statement, where applicable.
*/
int32
byte_pct
,
perbyte_cpu
,
percall_cpu
,
outin_ratio
;
bool
canCache
;
bool
returnsSet
;
/* The function returns a set of values, as opposed to a singleton. */
if
(
strcmp
(
languageName
,
"c"
)
==
0
||
case_translate_language_name
(
stmt
->
language
,
languageName
);
compute_return_type
(
stmt
->
returnType
,
&
prorettype
,
&
returnsSet
);
if
(
strcmp
(
languageName
,
"C"
)
==
0
||
strcmp
(
languageName
,
"internal"
)
==
0
)
{
prosrc_str
=
"-"
;
probin_str
=
stmt
->
as
;
compute_full_attributes
(
stmt
->
withClause
,
&
byte_pct
,
&
perbyte_cpu
,
&
percall_cpu
,
&
outin_ratio
,
&
canCache
);
}
else
if
(
strcmp
(
languageName
,
"sql"
)
==
0
)
{
/* query optimizer groks sql, these are meaningless */
perbyte_cpu
=
percall_cpu
=
0
;
byte_pct
=
outin_ratio
=
100
;
canCache
=
false
;
}
else
{
prosrc_str
=
stmt
->
as
;
probin_str
=
"-"
;
elog
(
WARN
,
"Unrecognized language specified in a CREATE FUNCTION: "
"'%s'. Recognized languages are sql, C, and internal."
,
languageName
);
}
/* C is stored uppercase in pg_language */
if
(
!
strcmp
(
languageName
,
"c"
))
{
languageName
[
0
]
=
'C'
;
}
interpret_AS_clause
(
languageName
,
stmt
->
as
,
&
prosrc_str
,
&
probin_str
);
/* ----------------
* now have ProcedureDefine do all the work..
* ----------------
if
(
strcmp
(
languageName
,
"sql"
)
!=
0
&&
!
superuser
())
elog
(
WARN
,
"Only users with Postgres superuser privilege are permitted "
"to create a function "
"in the '%s' language. Others may use the 'sql' language."
,
languageName
);
/* Above does not return. */
else
{
/* And now that we have all the parameters, and know we're permitted
to do so, go ahead and create the function.
*/
ProcedureCreate
(
pro
name
,
ProcedureCreate
(
stmt
->
func
name
,
returnsSet
,
prorettype
,
languageName
,
prosrc_str
,
/* converted to text later */
probin_str
,
/* converted to text later */
canCache
,
TRUE
,
true
,
/* (obsolete "trusted") */
byte_pct
,
perbyte_cpu
,
percall_cpu
,
outin_ratio
,
argList
,
stmt
->
defArgs
,
dest
);
}
}
/* --------------------------------
* DefineOperator--
*
...
...
src/backend/tcop/utility.c
View file @
33417507
...
...
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.
2 1996/08/24 20:49:03 scrappy
Exp $
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.
3 1996/10/31 09:08:10 bryanh
Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -367,7 +367,7 @@ ProcessUtility(Node *parsetree,
}
break
;
case
T_ViewStmt
:
/* VIEW */
case
T_ViewStmt
:
/*
CREATE
VIEW */
{
ViewStmt
*
stmt
=
(
ViewStmt
*
)
parsetree
;
...
...
@@ -377,13 +377,13 @@ ProcessUtility(Node *parsetree,
}
break
;
case
T_ProcedureStmt
:
/* FUNCTION */
case
T_ProcedureStmt
:
/*
CREATE
FUNCTION */
commandTag
=
"CREATE"
;
CHECK_IF_ABORTED
();
Defin
eFunction
((
ProcedureStmt
*
)
parsetree
,
dest
);
/* everything */
Creat
eFunction
((
ProcedureStmt
*
)
parsetree
,
dest
);
/* everything */
break
;
case
T_IndexStmt
:
case
T_IndexStmt
:
/* CREATE INDEX */
{
IndexStmt
*
stmt
=
(
IndexStmt
*
)
parsetree
;
...
...
@@ -400,7 +400,7 @@ ProcessUtility(Node *parsetree,
}
break
;
case
T_RuleStmt
:
case
T_RuleStmt
:
/* CREATE RULE */
{
RuleStmt
*
stmt
=
(
RuleStmt
*
)
parsetree
;
#ifndef NO_SECURITY
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment