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
Hide 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--
* 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
* Copyright (c) 1994, Regents of the University of California
*
*
*
*
* IDENTIFICATION
* 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
* DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the
* The "DefineFoo" routines take the parse tree and pick out the
* appropriate arguments/flags, passing the results to the
* appropriate arguments/flags, passing the results to the
* corresponding "FooDefine" routines (in src/catalog) that do
* 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
* NOTES
* These things must be defined and committed in the following order:
* These things must be defined and committed in the following order:
*
"defin
e function":
*
"creat
e function":
*
input/output, recv/send procedures
*
input/output, recv/send procedures
*
"defin
e type":
*
"creat
e type":
*
type
*
type
*
"defin
e operator":
*
"creat
e operator":
*
operators
*
operators
*
*
*
Most of the parse-tree manipulation routines are defined in
*
Most of the parse-tree manipulation routines are defined in
*
commands/manip.c.
*
commands/manip.c.
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -33,298 +36,358 @@
...
@@ -33,298 +36,358 @@
#include <ctype.h>
#include <ctype.h>
#include <math.h>
#include <math.h>
#include "postgres.h"
#include <postgres.h>
#include "access/heapam.h"
#include <access/heapam.h>
#include "access/htup.h"
#include <access/htup.h>
#include "utils/tqual.h"
#include <utils/tqual.h>
#include "catalog/catname.h"
#include <catalog/catname.h>
#include "catalog/pg_aggregate.h"
#include <catalog/pg_aggregate.h>
#include "catalog/pg_proc.h"
#include <catalog/pg_operator.h>
#include "catalog/pg_type.h"
#include <catalog/pg_proc.h>
#include "catalog/pg_operator.h"
#include <catalog/pg_type.h>
#include "utils/syscache.h"
#include <catalog/pg_user.h>
/* superuser() uses this */
#include "nodes/pg_list.h"
#include <utils/syscache.h>
#include "nodes/parsenodes.h"
#include <nodes/pg_list.h>
#include "fmgr.h"
/* for fmgr */
#include <nodes/parsenodes.h>
#include <fmgr.h>
/* for fmgr */
#include "utils/builtins.h"
/* prototype for textin() */
#include <utils/builtins.h>
/* prototype for textin() */
#include "utils/elog.h"
#include "utils/palloc.h"
#include <utils/elog.h>
#include "commands/defrem.h"
#include <utils/palloc.h>
#include "optimizer/xfunc.h"
#include <commands/defrem.h>
#include "tcop/dest.h"
#include <optimizer/xfunc.h>
#include <tcop/dest.h>
static
char
*
defGetString
(
DefElem
*
def
);
static
char
*
defGetString
(
DefElem
*
def
);
static
int
defGetTypeLength
(
DefElem
*
def
);
static
int
defGetTypeLength
(
DefElem
*
def
);
#define DEFAULT_TYPDELIM ','
#define DEFAULT_TYPDELIM ','
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
;
}
/*
* DefineFunction --
* Registers a new function.
*
*/
void
void
DefineFunction
(
ProcedureStmt
*
stmt
,
CommandDest
dest
)
case_translate_language_name
(
const
char
*
input
,
char
*
output
)
{
{
/*-------------------------------------------------------------------------
List
*
parameters
=
stmt
->
withClause
;
Translate the input language name to lower case, except if it's C,
char
*
proname
=
stmt
->
funcname
;
translate to upper case.
char
*
probin_str
;
--------------------------------------------------------------------------*/
char
*
prosrc_str
;
int
i
;
char
*
prorettype
;
char
*
languageName
;
for
(
i
=
0
;
i
<
NAMEDATALEN
&&
input
[
i
]
!=
'\0'
;
++
i
)
bool
canCache
=
FALSE
;
output
[
i
]
=
tolower
(
input
[
i
]);
List
*
argList
;
int32
byte_pct
=
100
,
perbyte_cpu
,
percall_cpu
,
outin_ratio
=
100
;
output
[
i
]
=
'\0'
;
bool
returnsSet
;
int
i
;
if
(
strcmp
(
output
,
"c"
)
==
0
)
output
[
0
]
=
'C'
;
}
/* ----------------
* figure out the language and convert it to lowercase.
* ----------------
*/
void
languageName
=
stmt
->
language
;
compute_return_type
(
const
Node
*
returnType
,
for
(
i
=
0
;
i
<
NAMEDATALEN
&&
languageName
[
i
];
++
i
)
{
char
**
prorettype_p
,
bool
*
returnsSet_p
)
{
languageName
[
i
]
=
tolower
(
languageName
[
i
]);
/*---------------------------------------------------------------------------
}
Examine the "returns" clause returnType of the CREATE FUNCTION statement
and return information about it as **prorettype_p and **returnsSet.
/* ----------------
----------------------------------------------------------------------------*/
* handle "returntype = X". The function could return a singleton
if
(
nodeTag
(
returnType
)
==
T_TypeName
)
{
* value or a set of values. Figure out which.
/* a set of values */
* ----------------
TypeName
*
setType
=
(
TypeName
*
)
returnType
;
*/
*
prorettype_p
=
setType
->
name
,
if
(
nodeTag
(
stmt
->
returnType
)
==
T_TypeName
)
{
*
returnsSet_p
=
true
;
TypeName
*
setType
=
(
TypeName
*
)
stmt
->
returnType
;
/* a set of values */
prorettype
=
setType
->
name
,
returnsSet
=
true
;
}
else
{
}
else
{
/* singleton */
/* singleton */
prorettype
=
strVal
(
stmt
->
returnType
);
*
prorettype_p
=
strVal
(
returnType
);
returnsSet
=
false
;
*
returnsSet_p
=
false
;
}
}
}
/* Next attributes are only defined for C functions */
if
(
strcmp
(
languageName
,
"c"
)
==
0
||
void
strcmp
(
languageName
,
"internal"
)
==
0
)
{
compute_full_attributes
(
const
List
*
parameters
,
int32
*
byte_pct_p
,
List
*
pl
;
int32
*
perbyte_cpu_p
,
int32
*
percall_cpu_p
,
int32
*
outin_ratio_p
,
bool
*
canCache_p
)
{
/* the defaults */
/*--------------------------------------------------------------------------
byte_pct
=
BYTE_PCT
;
Interpret the parameters *parameters and return their contents as
perbyte_cpu
=
PERBYTE_CPU
;
*byte_pct_p, etc.
percall_cpu
=
PERCALL_CPU
;
outin_ratio
=
OUTIN_RATIO
;
These are the full parameters of a C or internal function.
---------------------------------------------------------------------------*/
foreach
(
pl
,
parameters
)
{
List
*
pl
;
int
count
;
char
*
ptr
;
/* the defaults */
ParamString
*
param
=
(
ParamString
*
)
lfirst
(
pl
);
*
byte_pct_p
=
BYTE_PCT
;
*
perbyte_cpu_p
=
PERBYTE_CPU
;
if
(
!
strcasecmp
(
param
->
name
,
"isacachable"
))
{
*
percall_cpu_p
=
PERCALL_CPU
;
/* ----------------
*
outin_ratio_p
=
OUTIN_RATIO
;
* handle "[ iscachable ]": figure out if Postquel functions
* are cacheable automagically?
foreach
(
pl
,
(
List
*
)
parameters
)
{
* ----------------
int
count
;
*/
char
*
ptr
;
canCache
=
TRUE
;
ParamString
*
param
=
(
ParamString
*
)
lfirst
(
pl
);
}
else
if
(
!
strcasecmp
(
param
->
name
,
"trusted"
))
{
/*
if
(
strcasecmp
(
param
->
name
,
"iscachable"
)
==
0
)
{
* we don't have untrusted functions any more. The 4.2
*
canCache_p
=
true
;
* implementation is lousy anyway so I took it out.
}
else
if
(
strcasecmp
(
param
->
name
,
"trusted"
)
==
0
)
{
* -ay 10/94
/*
*/
* we don't have untrusted functions any more. The 4.2
elog
(
WARN
,
"untrusted function has been decommissioned."
);
* implementation is lousy anyway so I took it out.
}
else
if
(
!
strcasecmp
(
param
->
name
,
"byte_pct"
))
{
* -ay 10/94
/*
*/
** handle expensive function parameters
elog
(
WARN
,
"untrusted function has been decommissioned."
);
*/
}
else
if
(
strcasecmp
(
param
->
name
,
"byte_pct"
)
==
0
)
{
byte_pct
=
atoi
(
param
->
val
);
/*
}
else
if
(
!
strcasecmp
(
param
->
name
,
"perbyte_cpu"
))
{
** handle expensive function parameters
if
(
!
sscanf
(
param
->
val
,
"%d"
,
&
perbyte_cpu
))
{
*/
for
(
count
=
0
,
ptr
=
param
->
val
;
*
ptr
!=
'\0'
;
ptr
++
)
{
*
byte_pct_p
=
atoi
(
param
->
val
);
if
(
*
ptr
==
'!'
)
{
}
else
if
(
strcasecmp
(
param
->
name
,
"perbyte_cpu"
)
==
0
)
{
count
++
;
if
(
sscanf
(
param
->
val
,
"%d"
,
perbyte_cpu_p
)
==
0
)
{
}
for
(
count
=
0
,
ptr
=
param
->
val
;
*
ptr
!=
'\0'
;
ptr
++
)
}
if
(
*
ptr
==
'!'
)
count
++
;
perbyte_cpu
=
(
int
)
pow
(
10
.
0
,
(
double
)
count
);
}
}
*
perbyte_cpu_p
=
(
int
)
pow
(
10
.
0
,
(
double
)
count
);
}
else
if
(
!
strcasecmp
(
param
->
name
,
"percall_cpu"
))
{
}
else
if
(
strcasecmp
(
param
->
name
,
"percall_cpu"
)
==
0
)
{
if
(
!
sscanf
(
param
->
val
,
"%d"
,
&
percall_cpu
))
{
if
(
sscanf
(
param
->
val
,
"%d"
,
percall_cpu_p
)
==
0
)
{
for
(
count
=
0
,
ptr
=
param
->
val
;
*
ptr
!=
'\0'
;
ptr
++
)
{
for
(
count
=
0
,
ptr
=
param
->
val
;
*
ptr
!=
'\0'
;
ptr
++
)
if
(
*
ptr
==
'!'
)
{
if
(
*
ptr
==
'!'
)
count
++
;
count
++
;
*
percall_cpu_p
=
(
int
)
pow
(
10
.
0
,
(
double
)
count
);
}
}
}
}
else
if
(
strcasecmp
(
param
->
name
,
"outin_ratio"
)
==
0
)
{
percall_cpu
=
(
int
)
pow
(
10
.
0
,
(
double
)
count
);
*
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
;
}
else
{
elog
(
WARN
,
"DefineFunction: language '%s' is not supported"
,
languageName
);
}
}
}
/* ----------------
* handle "[ arg is (...) ]"
* XXX fix optional arg handling below
* ----------------
void
*/
interpret_AS_clause
(
const
char
languageName
[],
const
char
as
[],
argList
=
stmt
->
defArgs
;
char
**
prosrc_str_p
,
char
**
probin_str_p
)
{
if
(
strcmp
(
languageName
,
"
c
"
)
==
0
||
if
(
strcmp
(
languageName
,
"
C
"
)
==
0
||
strcmp
(
languageName
,
"internal"
)
==
0
)
{
strcmp
(
languageName
,
"internal"
)
==
0
)
{
prosrc_str
=
"-"
;
*
prosrc_str_p
=
"-"
;
probin_str
=
stmt
->
as
;
*
probin_str_p
=
(
char
*
)
as
;
}
else
{
}
else
{
prosrc_str
=
stmt
->
as
;
*
prosrc_str_p
=
(
char
*
)
as
;
probin_str
=
"-"
;
*
probin_str_p
=
"-"
;
}
}
}
/* C is stored uppercase in pg_language */
if
(
!
strcmp
(
languageName
,
"c"
))
{
languageName
[
0
]
=
'C'
;
/*
* 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"
*/
/* 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. */
case_translate_language_name
(
stmt
->
language
,
languageName
);
compute_return_type
(
stmt
->
returnType
,
&
prorettype
,
&
returnsSet
);
if
(
strcmp
(
languageName
,
"C"
)
==
0
||
strcmp
(
languageName
,
"internal"
)
==
0
)
{
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
{
elog
(
WARN
,
"Unrecognized language specified in a CREATE FUNCTION: "
"'%s'. Recognized languages are sql, C, and internal."
,
languageName
);
}
}
/* ----------------
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
,
ProcedureCreate
(
proname
,
"Only users with Postgres superuser privilege are permitted "
returnsSet
,
"to create a function "
prorettype
,
"in the '%s' language. Others may use the 'sql' language."
,
languageName
,
languageName
);
prosrc_str
,
/* converted to text later */
/* Above does not return. */
probin_str
,
/* converted to text later */
else
{
canCache
,
/* And now that we have all the parameters, and know we're permitted
TRUE
,
to do so, go ahead and create the function.
byte_pct
,
*/
perbyte_cpu
,
ProcedureCreate
(
stmt
->
funcname
,
percall_cpu
,
returnsSet
,
outin_ratio
,
prorettype
,
argList
,
languageName
,
dest
);
prosrc_str
,
/* converted to text later */
probin_str
,
/* converted to text later */
canCache
,
true
,
/* (obsolete "trusted") */
byte_pct
,
perbyte_cpu
,
percall_cpu
,
outin_ratio
,
stmt
->
defArgs
,
dest
);
}
}
}
/* --------------------------------
/* --------------------------------
* DefineOperator--
* DefineOperator--
*
*
*
this function extracts all the information from the
*
this function extracts all the information from the
*
parameter list generated by the parser and then has
*
parameter list generated by the parser and then has
*
OperatorCreate() do all the actual work.
*
OperatorCreate() do all the actual work.
*
*
* 'parameters' is a list of DefElem
* 'parameters' is a list of DefElem
* --------------------------------
* --------------------------------
*/
*/
void
void
DefineOperator
(
char
*
oprName
,
DefineOperator
(
char
*
oprName
,
List
*
parameters
)
List
*
parameters
)
{
{
uint16
precedence
=
0
;
/* operator precedence */
uint16
precedence
=
0
;
/* operator precedence */
bool
canHash
=
false
;
/* operator hashes */
bool
canHash
=
false
;
/* operator hashes */
bool
isLeftAssociative
=
true
;
/* operator is left associative */
bool
isLeftAssociative
=
true
;
/* operator is left associative */
char
*
functionName
=
NULL
;
/* function for operator */
char
*
functionName
=
NULL
;
/* function for operator */
char
*
typeName1
=
NULL
;
/* first type name */
char
*
typeName1
=
NULL
;
/* first type name */
char
*
typeName2
=
NULL
;
/* second type name */
char
*
typeName2
=
NULL
;
/* second type name */
char
*
commutatorName
=
NULL
;
/* optional commutator operator name */
char
*
commutatorName
=
NULL
;
/* optional commutator operator name */
char
*
negatorName
=
NULL
;
/* optional negator operator name */
char
*
negatorName
=
NULL
;
/* optional negator operator name */
char
*
restrictionName
=
NULL
;
/* optional restrict. sel. procedure */
char
*
restrictionName
=
NULL
;
/* optional restrict. sel. procedure */
char
*
joinName
=
NULL
;
/* optional join sel. procedure name */
char
*
joinName
=
NULL
;
/* optional join sel. procedure name */
char
*
sortName1
=
NULL
;
/* optional first sort operator */
char
*
sortName1
=
NULL
;
/* optional first sort operator */
char
*
sortName2
=
NULL
;
/* optional second sort operator */
char
*
sortName2
=
NULL
;
/* optional second sort operator */
List
*
pl
;
List
*
pl
;
/*
/*
* loop over the definition list and extract the information we need.
* loop over the definition list and extract the information we need.
*/
*/
foreach
(
pl
,
parameters
)
{
foreach
(
pl
,
parameters
)
{
DefElem
*
defel
=
(
DefElem
*
)
lfirst
(
pl
);
DefElem
*
defel
=
(
DefElem
*
)
lfirst
(
pl
);
if
(
!
strcasecmp
(
defel
->
defname
,
"leftarg"
))
{
if
(
!
strcasecmp
(
defel
->
defname
,
"leftarg"
))
{
/* see gram.y, must be setof */
/* see gram.y, must be setof */
if
(
nodeTag
(
defel
->
arg
)
==
T_TypeName
)
if
(
nodeTag
(
defel
->
arg
)
==
T_TypeName
)
elog
(
WARN
,
"setof type not implemented for leftarg"
);
elog
(
WARN
,
"setof type not implemented for leftarg"
);
if
(
nodeTag
(
defel
->
arg
)
==
T_String
)
{
if
(
nodeTag
(
defel
->
arg
)
==
T_String
)
{
typeName1
=
defGetString
(
defel
);
typeName1
=
defGetString
(
defel
);
}
else
{
}
else
{
elog
(
WARN
,
"type for leftarg is malformed."
);
elog
(
WARN
,
"type for leftarg is malformed."
);
}
}
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"rightarg"
))
{
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"rightarg"
))
{
/* see gram.y, must be setof */
/* see gram.y, must be setof */
if
(
nodeTag
(
defel
->
arg
)
==
T_TypeName
)
if
(
nodeTag
(
defel
->
arg
)
==
T_TypeName
)
elog
(
WARN
,
"setof type not implemented for rightarg"
);
elog
(
WARN
,
"setof type not implemented for rightarg"
);
if
(
nodeTag
(
defel
->
arg
)
==
T_String
)
{
if
(
nodeTag
(
defel
->
arg
)
==
T_String
)
{
typeName2
=
defGetString
(
defel
);
typeName2
=
defGetString
(
defel
);
}
else
{
}
else
{
elog
(
WARN
,
"type for rightarg is malformed."
);
elog
(
WARN
,
"type for rightarg is malformed."
);
}
}
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"procedure"
))
{
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"procedure"
))
{
functionName
=
defGetString
(
defel
);
functionName
=
defGetString
(
defel
);
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"precedence"
))
{
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"precedence"
))
{
/* NOT IMPLEMENTED (never worked in v4.2) */
/* NOT IMPLEMENTED (never worked in v4.2) */
elog
(
NOTICE
,
"CREATE OPERATOR: precedence not implemented"
);
elog
(
NOTICE
,
"CREATE OPERATOR: precedence not implemented"
);
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"associativity"
))
{
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"associativity"
))
{
/* NOT IMPLEMENTED (never worked in v4.2) */
/* NOT IMPLEMENTED (never worked in v4.2) */
elog
(
NOTICE
,
"CREATE OPERATOR: associativity not implemented"
);
elog
(
NOTICE
,
"CREATE OPERATOR: associativity not implemented"
);
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"commutator"
))
{
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"commutator"
))
{
commutatorName
=
defGetString
(
defel
);
commutatorName
=
defGetString
(
defel
);
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"negator"
))
{
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"negator"
))
{
negatorName
=
defGetString
(
defel
);
negatorName
=
defGetString
(
defel
);
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"restrict"
))
{
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"restrict"
))
{
restrictionName
=
defGetString
(
defel
);
restrictionName
=
defGetString
(
defel
);
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"join"
))
{
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"join"
))
{
joinName
=
defGetString
(
defel
);
joinName
=
defGetString
(
defel
);
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"hashes"
))
{
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"hashes"
))
{
canHash
=
TRUE
;
canHash
=
TRUE
;
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"sort1"
))
{
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"sort1"
))
{
/* ----------------
/* ----------------
* XXX ( ... [ , sort1 = oprname ] [ , sort2 = oprname ] ... )
* XXX ( ... [ , sort1 = oprname ] [ , sort2 = oprname ] ... )
* XXX is undocumented in the reference manual source as of
* XXX is undocumented in the reference manual source as of
* 89/8/22.
* 89/8/22.
* ----------------
* ----------------
*/
*/
sortName1
=
defGetString
(
defel
);
sortName1
=
defGetString
(
defel
);
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"sort2"
))
{
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"sort2"
))
{
sortName2
=
defGetString
(
defel
);
sortName2
=
defGetString
(
defel
);
}
else
{
}
else
{
elog
(
NOTICE
,
"DefineOperator: attribute
\"
%s
\"
not recognized"
,
elog
(
NOTICE
,
"DefineOperator: attribute
\"
%s
\"
not recognized"
,
defel
->
defname
);
defel
->
defname
);
}
}
}
}
/*
/*
* make sure we have our required definitions
* make sure we have our required definitions
*/
*/
if
(
functionName
==
NULL
)
{
if
(
functionName
==
NULL
)
{
elog
(
WARN
,
"Define:
\"
procedure
\"
unspecified"
);
elog
(
WARN
,
"Define:
\"
procedure
\"
unspecified"
);
}
}
/* ----------------
/* ----------------
*
now have OperatorCreate do all the work..
*
now have OperatorCreate do all the work..
* ----------------
* ----------------
*/
*/
OperatorCreate
(
oprName
,
/* operator name */
OperatorCreate
(
oprName
,
/* operator name */
typeName1
,
/* first type name */
typeName1
,
/* first type name */
typeName2
,
/* second type name */
typeName2
,
/* second type name */
functionName
,
/* function for operator */
functionName
,
/* function for operator */
precedence
,
/* operator precedence */
precedence
,
/* operator precedence */
isLeftAssociative
,
/* operator is left associative */
isLeftAssociative
,
/* operator is left associative */
commutatorName
,
/* optional commutator operator name */
commutatorName
,
/* optional commutator operator name */
negatorName
,
/* optional negator operator name */
negatorName
,
/* optional negator operator name */
restrictionName
,
/* optional restrict. sel. procedure */
restrictionName
,
/* optional restrict. sel. procedure */
joinName
,
/* optional join sel. procedure name */
joinName
,
/* optional join sel. procedure name */
canHash
,
/* operator hashes */
canHash
,
/* operator hashes */
sortName1
,
/* optional first sort operator */
sortName1
,
/* optional first sort operator */
sortName2
);
/* optional second sort operator */
sortName2
);
/* optional second sort operator */
}
}
...
@@ -347,170 +410,170 @@ DefineAggregate(char *aggName, List *parameters)
...
@@ -347,170 +410,170 @@ DefineAggregate(char *aggName, List *parameters)
List
*
pl
;
List
*
pl
;
foreach
(
pl
,
parameters
)
{
foreach
(
pl
,
parameters
)
{
DefElem
*
defel
=
(
DefElem
*
)
lfirst
(
pl
);
DefElem
*
defel
=
(
DefElem
*
)
lfirst
(
pl
);
/*
/*
* sfunc1
* sfunc1
*/
*/
if
(
!
strcasecmp
(
defel
->
defname
,
"sfunc1"
))
{
if
(
!
strcasecmp
(
defel
->
defname
,
"sfunc1"
))
{
stepfunc1Name
=
defGetString
(
defel
);
stepfunc1Name
=
defGetString
(
defel
);
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"basetype"
))
{
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"basetype"
))
{
baseType
=
defGetString
(
defel
);
baseType
=
defGetString
(
defel
);
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"stype1"
))
{
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"stype1"
))
{
stepfunc1Type
=
defGetString
(
defel
);
stepfunc1Type
=
defGetString
(
defel
);
/*
/*
* sfunc2
* sfunc2
*/
*/
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"sfunc2"
))
{
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"sfunc2"
))
{
stepfunc2Name
=
defGetString
(
defel
);
stepfunc2Name
=
defGetString
(
defel
);
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"stype2"
))
{
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"stype2"
))
{
stepfunc2Type
=
defGetString
(
defel
);
stepfunc2Type
=
defGetString
(
defel
);
/*
/*
* final
* final
*/
*/
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"finalfunc"
))
{
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"finalfunc"
))
{
finalfuncName
=
defGetString
(
defel
);
finalfuncName
=
defGetString
(
defel
);
/*
/*
* initial conditions
* initial conditions
*/
*/
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"initcond1"
))
{
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"initcond1"
))
{
init1
=
defGetString
(
defel
);
init1
=
defGetString
(
defel
);
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"initcond2"
))
{
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"initcond2"
))
{
init2
=
defGetString
(
defel
);
init2
=
defGetString
(
defel
);
}
else
{
}
else
{
elog
(
NOTICE
,
"DefineAggregate: attribute
\"
%s
\"
not recognized"
,
elog
(
NOTICE
,
"DefineAggregate: attribute
\"
%s
\"
not recognized"
,
defel
->
defname
);
defel
->
defname
);
}
}
}
}
/*
/*
* make sure we have our required definitions
* make sure we have our required definitions
*/
*/
if
(
baseType
==
NULL
)
if
(
baseType
==
NULL
)
elog
(
WARN
,
"Define:
\"
basetype
\"
unspecified"
);
elog
(
WARN
,
"Define:
\"
basetype
\"
unspecified"
);
if
(
stepfunc1Name
!=
NULL
)
{
if
(
stepfunc1Name
!=
NULL
)
{
if
(
stepfunc1Type
==
NULL
)
if
(
stepfunc1Type
==
NULL
)
elog
(
WARN
,
"Define:
\"
stype1
\"
unspecified"
);
elog
(
WARN
,
"Define:
\"
stype1
\"
unspecified"
);
}
}
if
(
stepfunc2Name
!=
NULL
)
{
if
(
stepfunc2Name
!=
NULL
)
{
if
(
stepfunc2Type
==
NULL
)
if
(
stepfunc2Type
==
NULL
)
elog
(
WARN
,
"Define:
\"
stype2
\"
unspecified"
);
elog
(
WARN
,
"Define:
\"
stype2
\"
unspecified"
);
}
}
/*
/*
* Most of the argument-checking is done inside of AggregateCreate
* Most of the argument-checking is done inside of AggregateCreate
*/
*/
AggregateCreate
(
aggName
,
/* aggregate name */
AggregateCreate
(
aggName
,
/* aggregate name */
stepfunc1Name
,
/* first step function name */
stepfunc1Name
,
/* first step function name */
stepfunc2Name
,
/* second step function name */
stepfunc2Name
,
/* second step function name */
finalfuncName
,
/* final function name */
finalfuncName
,
/* final function name */
baseType
,
/* type of object being aggregated */
baseType
,
/* type of object being aggregated */
stepfunc1Type
,
/* return type of first function */
stepfunc1Type
,
/* return type of first function */
stepfunc2Type
,
/* return type of second function */
stepfunc2Type
,
/* return type of second function */
init1
,
/* first initial condition */
init1
,
/* first initial condition */
init2
);
/* second initial condition */
init2
);
/* second initial condition */
/* XXX free palloc'd memory */
/* XXX free palloc'd memory */
}
}
/*
/*
* DefineType --
* DefineType --
*
Registers a new type.
*
Registers a new type.
*
*
*/
*/
void
void
DefineType
(
char
*
typeName
,
List
*
parameters
)
DefineType
(
char
*
typeName
,
List
*
parameters
)
{
{
int16
internalLength
=
0
;
/* int2 */
int16
internalLength
=
0
;
/* int2 */
int16
externalLength
=
0
;
/* int2 */
int16
externalLength
=
0
;
/* int2 */
char
*
elemName
=
NULL
;
char
*
elemName
=
NULL
;
char
*
inputName
=
NULL
;
char
*
inputName
=
NULL
;
char
*
outputName
=
NULL
;
char
*
outputName
=
NULL
;
char
*
sendName
=
NULL
;
char
*
sendName
=
NULL
;
char
*
receiveName
=
NULL
;
char
*
receiveName
=
NULL
;
char
*
defaultValue
=
NULL
;
/* Datum */
char
*
defaultValue
=
NULL
;
/* Datum */
bool
byValue
=
false
;
bool
byValue
=
false
;
char
delimiter
=
DEFAULT_TYPDELIM
;
char
delimiter
=
DEFAULT_TYPDELIM
;
char
*
shadow_type
;
char
*
shadow_type
;
List
*
pl
;
List
*
pl
;
char
alignment
=
'i'
;
/* default alignment */
char
alignment
=
'i'
;
/* default alignment */
/*
/*
* Type names can only be 15 characters long, so that the shadow type
* Type names can only be 15 characters long, so that the shadow type
* can be created using the 16th character as necessary.
* can be created using the 16th character as necessary.
*/
*/
if
(
strlen
(
typeName
)
>=
(
NAMEDATALEN
-
1
))
{
if
(
strlen
(
typeName
)
>=
(
NAMEDATALEN
-
1
))
{
elog
(
WARN
,
"DefineType: type names must be %d characters or less"
,
elog
(
WARN
,
"DefineType: type names must be %d characters or less"
,
NAMEDATALEN
-
1
);
NAMEDATALEN
-
1
);
}
}
foreach
(
pl
,
parameters
)
{
foreach
(
pl
,
parameters
)
{
DefElem
*
defel
=
(
DefElem
*
)
lfirst
(
pl
);
DefElem
*
defel
=
(
DefElem
*
)
lfirst
(
pl
);
if
(
!
strcasecmp
(
defel
->
defname
,
"internallength"
))
{
if
(
!
strcasecmp
(
defel
->
defname
,
"internallength"
))
{
internalLength
=
defGetTypeLength
(
defel
);
internalLength
=
defGetTypeLength
(
defel
);
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"externallength"
))
{
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"externallength"
))
{
externalLength
=
defGetTypeLength
(
defel
);
externalLength
=
defGetTypeLength
(
defel
);
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"input"
))
{
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"input"
))
{
inputName
=
defGetString
(
defel
);
inputName
=
defGetString
(
defel
);
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"output"
))
{
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"output"
))
{
outputName
=
defGetString
(
defel
);
outputName
=
defGetString
(
defel
);
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"send"
))
{
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"send"
))
{
sendName
=
defGetString
(
defel
);
sendName
=
defGetString
(
defel
);
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"delimiter"
))
{
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"delimiter"
))
{
char
*
p
=
defGetString
(
defel
);
char
*
p
=
defGetString
(
defel
);
delimiter
=
p
[
0
];
delimiter
=
p
[
0
];
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"receive"
))
{
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"receive"
))
{
receiveName
=
defGetString
(
defel
);
receiveName
=
defGetString
(
defel
);
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"element"
))
{
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"element"
))
{
elemName
=
defGetString
(
defel
);
elemName
=
defGetString
(
defel
);
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"default"
))
{
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"default"
))
{
defaultValue
=
defGetString
(
defel
);
defaultValue
=
defGetString
(
defel
);
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"passedbyvalue"
))
{
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"passedbyvalue"
))
{
byValue
=
true
;
byValue
=
true
;
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"alignment"
))
{
}
else
if
(
!
strcasecmp
(
defel
->
defname
,
"alignment"
))
{
char
*
a
=
defGetString
(
defel
);
char
*
a
=
defGetString
(
defel
);
if
(
!
strcasecmp
(
a
,
"double"
))
{
if
(
!
strcasecmp
(
a
,
"double"
))
{
alignment
=
'd'
;
alignment
=
'd'
;
}
else
if
(
!
strcasecmp
(
a
,
"int"
))
{
}
else
if
(
!
strcasecmp
(
a
,
"int"
))
{
alignment
=
'i'
;
alignment
=
'i'
;
}
else
{
}
else
{
elog
(
WARN
,
"DefineType:
\"
%s
\"
alignment not recognized"
,
elog
(
WARN
,
"DefineType:
\"
%s
\"
alignment not recognized"
,
a
);
a
);
}
}
}
else
{
}
else
{
elog
(
NOTICE
,
"DefineType: attribute
\"
%s
\"
not recognized"
,
elog
(
NOTICE
,
"DefineType: attribute
\"
%s
\"
not recognized"
,
defel
->
defname
);
defel
->
defname
);
}
}
}
}
/*
/*
* make sure we have our required definitions
* make sure we have our required definitions
*/
*/
if
(
inputName
==
NULL
)
if
(
inputName
==
NULL
)
elog
(
WARN
,
"Define:
\"
input
\"
unspecified"
);
elog
(
WARN
,
"Define:
\"
input
\"
unspecified"
);
if
(
outputName
==
NULL
)
if
(
outputName
==
NULL
)
elog
(
WARN
,
"Define:
\"
output
\"
unspecified"
);
elog
(
WARN
,
"Define:
\"
output
\"
unspecified"
);
/* ----------------
/* ----------------
*
now have TypeCreate do all the real work.
*
now have TypeCreate do all the real work.
* ----------------
* ----------------
*/
*/
(
void
)
TypeCreate
(
typeName
,
/* type name */
(
void
)
TypeCreate
(
typeName
,
/* type name */
InvalidOid
,
/* relation oid (n/a here) */
InvalidOid
,
/* relation oid (n/a here) */
internalLength
,
/* internal size */
internalLength
,
/* internal size */
externalLength
,
/* external size */
externalLength
,
/* external size */
'b'
,
/* type-type (base type) */
'b'
,
/* type-type (base type) */
delimiter
,
/* array element delimiter */
delimiter
,
/* array element delimiter */
inputName
,
/* input procedure */
inputName
,
/* input procedure */
outputName
,
/* output procedure */
outputName
,
/* output procedure */
sendName
,
/* send procedure */
sendName
,
/* send procedure */
receiveName
,
/* receive procedure */
receiveName
,
/* receive procedure */
elemName
,
/* element type name */
elemName
,
/* element type name */
defaultValue
,
/* default type value */
defaultValue
,
/* default type value */
byValue
,
/* passed by value */
byValue
,
/* passed by value */
alignment
);
alignment
);
/* ----------------
/* ----------------
* When we create a true type (as opposed to a complex type)
* When we create a true type (as opposed to a complex type)
...
@@ -519,20 +582,20 @@ DefineType(char *typeName, List *parameters)
...
@@ -519,20 +582,20 @@ DefineType(char *typeName, List *parameters)
*/
*/
shadow_type
=
makeArrayTypeName
(
typeName
);
shadow_type
=
makeArrayTypeName
(
typeName
);
(
void
)
TypeCreate
(
shadow_type
,
/* type name */
(
void
)
TypeCreate
(
shadow_type
,
/* type name */
InvalidOid
,
/* relation oid (n/a here) */
InvalidOid
,
/* relation oid (n/a here) */
-
1
,
/* internal size */
-
1
,
/* internal size */
-
1
,
/* external size */
-
1
,
/* external size */
'b'
,
/* type-type (base type) */
'b'
,
/* type-type (base type) */
DEFAULT_TYPDELIM
,
/* array element delimiter */
DEFAULT_TYPDELIM
,
/* array element delimiter */
"array_in"
,
/* input procedure */
"array_in"
,
/* input procedure */
"array_out"
,
/* output procedure */
"array_out"
,
/* output procedure */
"array_out"
,
/* send procedure */
"array_out"
,
/* send procedure */
"array_in"
,
/* receive procedure */
"array_in"
,
/* receive procedure */
typeName
,
/* element type name */
typeName
,
/* element type name */
defaultValue
,
/* default type value */
defaultValue
,
/* default type value */
false
,
/* never passed by value */
false
,
/* never passed by value */
alignment
);
alignment
);
pfree
(
shadow_type
);
pfree
(
shadow_type
);
}
}
...
@@ -541,7 +604,7 @@ static char *
...
@@ -541,7 +604,7 @@ static char *
defGetString
(
DefElem
*
def
)
defGetString
(
DefElem
*
def
)
{
{
if
(
nodeTag
(
def
->
arg
)
!=
T_String
)
if
(
nodeTag
(
def
->
arg
)
!=
T_String
)
elog
(
WARN
,
"Define:
\"
%s
\"
= what?"
,
def
->
defname
);
elog
(
WARN
,
"Define:
\"
%s
\"
= what?"
,
def
->
defname
);
return
(
strVal
(
def
->
arg
));
return
(
strVal
(
def
->
arg
));
}
}
...
@@ -549,10 +612,10 @@ static int
...
@@ -549,10 +612,10 @@ static int
defGetTypeLength
(
DefElem
*
def
)
defGetTypeLength
(
DefElem
*
def
)
{
{
if
(
nodeTag
(
def
->
arg
)
==
T_Integer
)
if
(
nodeTag
(
def
->
arg
)
==
T_Integer
)
return
(
intVal
(
def
->
arg
));
return
(
intVal
(
def
->
arg
));
else
if
(
nodeTag
(
def
->
arg
)
==
T_String
&&
else
if
(
nodeTag
(
def
->
arg
)
==
T_String
&&
!
strcasecmp
(
strVal
(
def
->
arg
),
"variable"
))
!
strcasecmp
(
strVal
(
def
->
arg
),
"variable"
))
return
-
1
;
/* variable length */
return
-
1
;
/* variable length */
elog
(
WARN
,
"Define:
\"
%s
\"
= what?"
,
def
->
defname
);
elog
(
WARN
,
"Define:
\"
%s
\"
= what?"
,
def
->
defname
);
return
-
1
;
return
-
1
;
...
...
src/backend/tcop/utility.c
View file @
33417507
...
@@ -9,7 +9,7 @@
...
@@ -9,7 +9,7 @@
*
*
*
*
* IDENTIFICATION
* 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,
...
@@ -367,7 +367,7 @@ ProcessUtility(Node *parsetree,
}
}
break
;
break
;
case
T_ViewStmt
:
/* VIEW */
case
T_ViewStmt
:
/*
CREATE
VIEW */
{
{
ViewStmt
*
stmt
=
(
ViewStmt
*
)
parsetree
;
ViewStmt
*
stmt
=
(
ViewStmt
*
)
parsetree
;
...
@@ -377,13 +377,13 @@ ProcessUtility(Node *parsetree,
...
@@ -377,13 +377,13 @@ ProcessUtility(Node *parsetree,
}
}
break
;
break
;
case
T_ProcedureStmt
:
/* FUNCTION */
case
T_ProcedureStmt
:
/*
CREATE
FUNCTION */
commandTag
=
"CREATE"
;
commandTag
=
"CREATE"
;
CHECK_IF_ABORTED
();
CHECK_IF_ABORTED
();
Defin
eFunction
((
ProcedureStmt
*
)
parsetree
,
dest
);
/* everything */
Creat
eFunction
((
ProcedureStmt
*
)
parsetree
,
dest
);
/* everything */
break
;
break
;
case
T_IndexStmt
:
case
T_IndexStmt
:
/* CREATE INDEX */
{
{
IndexStmt
*
stmt
=
(
IndexStmt
*
)
parsetree
;
IndexStmt
*
stmt
=
(
IndexStmt
*
)
parsetree
;
...
@@ -400,7 +400,7 @@ ProcessUtility(Node *parsetree,
...
@@ -400,7 +400,7 @@ ProcessUtility(Node *parsetree,
}
}
break
;
break
;
case
T_RuleStmt
:
case
T_RuleStmt
:
/* CREATE RULE */
{
{
RuleStmt
*
stmt
=
(
RuleStmt
*
)
parsetree
;
RuleStmt
*
stmt
=
(
RuleStmt
*
)
parsetree
;
#ifndef NO_SECURITY
#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