diff options
Diffstat (limited to 'src/backend/commands/define.c')
-rw-r--r-- | src/backend/commands/define.c | 1113 |
1 files changed, 628 insertions, 485 deletions
diff --git a/src/backend/commands/define.c b/src/backend/commands/define.c index 800d85a48b8..fb1df213cec 100644 --- a/src/backend/commands/define.c +++ b/src/backend/commands/define.c @@ -2,33 +2,33 @@ * * define.c-- * - * These routines execute some of the CREATE statements. In an earlier - * version of Postgres, these were "define" statements. + * 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.13 1997/08/12 22:52:23 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.14 1997/09/07 04:40:46 momjian 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. These routines also verify permission - * of the user to execute the command. + * 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. These routines also verify permission + * of the user to execute the command. * * NOTES - * These things must be defined and committed in the following order: - * "create function": - * input/output, recv/send procedures - * "create type": - * type - * "create operator": - * operators + * These things must be defined and committed in the following order: + * "create function": + * input/output, recv/send procedures + * "create type": + * type + * "create operator": + * operators * - * Most of the parse-tree manipulation routines are defined in - * commands/manip.c. + * Most of the parse-tree manipulation routines are defined in + * commands/manip.c. * *------------------------------------------------------------------------- */ @@ -46,209 +46,259 @@ #include <catalog/pg_proc.h> #include <catalog/pg_type.h> #include <utils/syscache.h> -#include <fmgr.h> /* for fmgr */ -#include <utils/builtins.h> /* prototype for textin() */ +#include <fmgr.h> /* for fmgr */ +#include <utils/builtins.h> /* prototype for textin() */ #include <commands/defrem.h> #include <optimizer/xfunc.h> #include <tcop/dest.h> #include <catalog/pg_user.h> -static char *defGetString(DefElem *def); -static int defGetTypeLength(DefElem *def); +static char *defGetString(DefElem * def); +static int defGetTypeLength(DefElem * def); -#define DEFAULT_TYPDELIM ',' +#define DEFAULT_TYPDELIM ',' static void -case_translate_language_name(const char *input, char *output) { +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. + translate to upper case. --------------------------------------------------------------------------*/ - int i; + int i; - for (i = 0; i < NAMEDATALEN && input[i] != '\0'; ++i) - output[i] = tolower(input[i]); + for (i = 0; i < NAMEDATALEN && input[i] != '\0'; ++i) + output[i] = tolower(input[i]); - output[i] = '\0'; + output[i] = '\0'; - if (strcmp(output, "c") == 0) output[0] = 'C'; -} + if (strcmp(output, "c") == 0) + output[0] = 'C'; +} static void -compute_return_type(const Node *returnType, - char **prorettype_p, bool *returnsSet_p) { +compute_return_type(const Node * returnType, + char **prorettype_p, bool * returnsSet_p) +{ /*--------------------------------------------------------------------------- - Examine the "returns" clause returnType of the CREATE FUNCTION statement + 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 */ - TypeName *setType = (TypeName *)returnType; - *prorettype_p = setType->name; - *returnsSet_p = true; - }else { - /* singleton */ - *prorettype_p = strVal(returnType); - *returnsSet_p = false; - } + if (nodeTag(returnType) == T_TypeName) + { + /* a set of values */ + TypeName *setType = (TypeName *) returnType; + + *prorettype_p = setType->name; + *returnsSet_p = true; + } + else + { + /* singleton */ + *prorettype_p = strVal(returnType); + *returnsSet_p = false; + } } - -static 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) { + +static 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_p = BYTE_PCT; - *perbyte_cpu_p = PERBYTE_CPU; - *percall_cpu_p = PERCALL_CPU; - *outin_ratio_p = OUTIN_RATIO; - - foreach(pl, (List *)parameters) { - ParamString *param = (ParamString*)lfirst(pl); - - 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") == 0) { - /* - ** handle expensive function parameters - */ - *byte_pct_p = atoi(param->val); - } else if (strcasecmp(param->name, "perbyte_cpu") == 0) { - if (sscanf(param->val, "%d", perbyte_cpu_p) == 0) { - int count; - char *ptr; - 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) { - int count; - char *ptr; - for (count = 0, ptr = param->val; *ptr != '\0'; ptr++) - if (*ptr == '!') count++; - *percall_cpu_p = (int) pow(10.0, (double) count); - } - } else if (strcasecmp(param->name, "outin_ratio") == 0) { - *outin_ratio_p = atoi(param->val); - } - } + List *pl; + + /* the defaults */ + *byte_pct_p = BYTE_PCT; + *perbyte_cpu_p = PERBYTE_CPU; + *percall_cpu_p = PERCALL_CPU; + *outin_ratio_p = OUTIN_RATIO; + + foreach(pl, (List *) parameters) + { + ParamString *param = (ParamString *) lfirst(pl); + + 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") == 0) + { + + /* + * * handle expensive function parameters + */ + *byte_pct_p = atoi(param->val); + } + else if (strcasecmp(param->name, "perbyte_cpu") == 0) + { + if (sscanf(param->val, "%d", perbyte_cpu_p) == 0) + { + int count; + char *ptr; + + 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) + { + int count; + char *ptr; + + for (count = 0, ptr = param->val; *ptr != '\0'; ptr++) + if (*ptr == '!') + count++; + *percall_cpu_p = (int) pow(10.0, (double) count); + } + } + else if (strcasecmp(param->name, "outin_ratio") == 0) + { + *outin_ratio_p = atoi(param->val); + } + } } static 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 { - *prosrc_str_p = (char *)as; - *probin_str_p = "-"; - } + 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 + { + *prosrc_str_p = (char *) as; + *probin_str_p = "-"; + } } /* * CreateFunction -- - * Execute a CREATE FUNCTION utility statement. + * Execute a CREATE FUNCTION utility statement. * */ void -CreateFunction(ProcedureStmt *stmt, CommandDest dest) +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]; - /* 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); - - 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(stmt->funcname, - returnsSet, - prorettype, - languageName, - 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); - } + 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]; + + /* + * 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); + + 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(stmt->funcname, + returnsSet, + prorettype, + languageName, + 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); + } } @@ -256,344 +306,437 @@ CreateFunction(ProcedureStmt *stmt, CommandDest dest) /* -------------------------------- * DefineOperator-- * - * this function extracts all the information from the - * parameter list generated by the parser and then has - * OperatorCreate() do all the actual work. + * this function extracts all the information from the + * parameter list generated by the parser and then has + * OperatorCreate() do all the actual work. * * 'parameters' is a list of DefElem * -------------------------------- */ void -DefineOperator(char *oprName, - List *parameters) +DefineOperator(char *oprName, + List * parameters) { - uint16 precedence=0; /* operator precedence */ - bool canHash=false; /* operator hashes */ - bool isLeftAssociative=true; /* operator is left associative */ - char *functionName=NULL; /* function for operator */ - char *typeName1=NULL; /* first type name */ - char *typeName2=NULL; /* second type name */ - char *commutatorName=NULL; /* optional commutator operator name */ - char *negatorName=NULL; /* optional negator operator name */ - char *restrictionName=NULL; /* optional restrict. sel. procedure */ - char *joinName=NULL; /* optional join sel. procedure name */ - char *sortName1=NULL; /* optional first sort operator */ - char *sortName2=NULL; /* optional second sort operator */ - List *pl; - - /* - * loop over the definition list and extract the information we need. - */ - foreach (pl, parameters) { - DefElem *defel = (DefElem *)lfirst(pl); - - if (!strcasecmp(defel->defname, "leftarg")) { - /* see gram.y, must be setof */ - if (nodeTag(defel->arg)==T_TypeName) - elog(WARN, "setof type not implemented for leftarg"); - - if (nodeTag(defel->arg)==T_String) { - typeName1 = defGetString(defel); - }else { - elog(WARN, "type for leftarg is malformed."); - } - } else if (!strcasecmp(defel->defname, "rightarg")) { - /* see gram.y, must be setof */ - if (nodeTag(defel->arg)==T_TypeName) - elog(WARN, "setof type not implemented for rightarg"); - - if (nodeTag(defel->arg)==T_String) { - typeName2 = defGetString(defel); - }else { - elog(WARN, "type for rightarg is malformed."); - } - } else if (!strcasecmp(defel->defname, "procedure")) { - functionName = defGetString(defel); - } else if (!strcasecmp(defel->defname, "precedence")) { - /* NOT IMPLEMENTED (never worked in v4.2) */ - elog(NOTICE, "CREATE OPERATOR: precedence not implemented"); - } else if (!strcasecmp(defel->defname, "associativity")) { - /* NOT IMPLEMENTED (never worked in v4.2) */ - elog(NOTICE, "CREATE OPERATOR: associativity not implemented"); - } else if (!strcasecmp(defel->defname, "commutator")) { - commutatorName = defGetString(defel); - } else if (!strcasecmp(defel->defname, "negator")) { - negatorName = defGetString(defel); - } else if (!strcasecmp(defel->defname, "restrict")) { - restrictionName = defGetString(defel); - } else if (!strcasecmp(defel->defname, "join")) { - joinName = defGetString(defel); - } else if (!strcasecmp(defel->defname, "hashes")) { - canHash = TRUE; - } else if (!strcasecmp(defel->defname, "sort1")) { - /* ---------------- - * XXX ( ... [ , sort1 = oprname ] [ , sort2 = oprname ] ... ) - * XXX is undocumented in the reference manual source as of - * 89/8/22. - * ---------------- - */ - sortName1 = defGetString(defel); - } else if (!strcasecmp(defel->defname, "sort2")) { - sortName2 = defGetString(defel); - } else { - elog(NOTICE, "DefineOperator: attribute \"%s\" not recognized", - defel->defname); - } - } - - /* - * make sure we have our required definitions - */ - if (functionName==NULL) { - elog(WARN, "Define: \"procedure\" unspecified"); - } - - /* ---------------- - * now have OperatorCreate do all the work.. - * ---------------- - */ - OperatorCreate(oprName, /* operator name */ - typeName1, /* first type name */ - typeName2, /* second type name */ - functionName, /* function for operator */ - precedence, /* operator precedence */ - isLeftAssociative, /* operator is left associative */ - commutatorName, /* optional commutator operator name */ - negatorName, /* optional negator operator name */ - restrictionName, /* optional restrict. sel. procedure */ - joinName, /* optional join sel. procedure name */ - canHash, /* operator hashes */ - sortName1, /* optional first sort operator */ - sortName2); /* optional second sort operator */ - + uint16 precedence = 0; /* operator precedence */ + bool canHash = false; /* operator hashes */ + bool isLeftAssociative = true; /* operator is left + * associative */ + char *functionName = NULL; /* function for operator */ + char *typeName1 = NULL; /* first type name */ + char *typeName2 = NULL; /* second type name */ + char *commutatorName = NULL; /* optional commutator + * operator name */ + char *negatorName = NULL; /* optional negator operator name */ + char *restrictionName = NULL; /* optional restrict. sel. + * procedure */ + char *joinName = NULL; /* optional join sel. procedure + * name */ + char *sortName1 = NULL; /* optional first sort operator */ + char *sortName2 = NULL; /* optional second sort operator */ + List *pl; + + /* + * loop over the definition list and extract the information we need. + */ + foreach(pl, parameters) + { + DefElem *defel = (DefElem *) lfirst(pl); + + if (!strcasecmp(defel->defname, "leftarg")) + { + /* see gram.y, must be setof */ + if (nodeTag(defel->arg) == T_TypeName) + elog(WARN, "setof type not implemented for leftarg"); + + if (nodeTag(defel->arg) == T_String) + { + typeName1 = defGetString(defel); + } + else + { + elog(WARN, "type for leftarg is malformed."); + } + } + else if (!strcasecmp(defel->defname, "rightarg")) + { + /* see gram.y, must be setof */ + if (nodeTag(defel->arg) == T_TypeName) + elog(WARN, "setof type not implemented for rightarg"); + + if (nodeTag(defel->arg) == T_String) + { + typeName2 = defGetString(defel); + } + else + { + elog(WARN, "type for rightarg is malformed."); + } + } + else if (!strcasecmp(defel->defname, "procedure")) + { + functionName = defGetString(defel); + } + else if (!strcasecmp(defel->defname, "precedence")) + { + /* NOT IMPLEMENTED (never worked in v4.2) */ + elog(NOTICE, "CREATE OPERATOR: precedence not implemented"); + } + else if (!strcasecmp(defel->defname, "associativity")) + { + /* NOT IMPLEMENTED (never worked in v4.2) */ + elog(NOTICE, "CREATE OPERATOR: associativity not implemented"); + } + else if (!strcasecmp(defel->defname, "commutator")) + { + commutatorName = defGetString(defel); + } + else if (!strcasecmp(defel->defname, "negator")) + { + negatorName = defGetString(defel); + } + else if (!strcasecmp(defel->defname, "restrict")) + { + restrictionName = defGetString(defel); + } + else if (!strcasecmp(defel->defname, "join")) + { + joinName = defGetString(defel); + } + else if (!strcasecmp(defel->defname, "hashes")) + { + canHash = TRUE; + } + else if (!strcasecmp(defel->defname, "sort1")) + { + /* ---------------- + * XXX ( ... [ , sort1 = oprname ] [ , sort2 = oprname ] ... ) + * XXX is undocumented in the reference manual source as of + * 89/8/22. + * ---------------- + */ + sortName1 = defGetString(defel); + } + else if (!strcasecmp(defel->defname, "sort2")) + { + sortName2 = defGetString(defel); + } + else + { + elog(NOTICE, "DefineOperator: attribute \"%s\" not recognized", + defel->defname); + } + } + + /* + * make sure we have our required definitions + */ + if (functionName == NULL) + { + elog(WARN, "Define: \"procedure\" unspecified"); + } + + /* ---------------- + * now have OperatorCreate do all the work.. + * ---------------- + */ + OperatorCreate(oprName, /* operator name */ + typeName1, /* first type name */ + typeName2, /* second type name */ + functionName,/* function for operator */ + precedence, /* operator precedence */ + isLeftAssociative, /* operator is left associative */ + commutatorName, /* optional commutator operator + * name */ + negatorName, /* optional negator operator name */ + restrictionName, /* optional restrict. sel. + * procedure */ + joinName, /* optional join sel. procedure name */ + canHash, /* operator hashes */ + sortName1, /* optional first sort operator */ + sortName2); /* optional second sort operator */ + } /* ------------------- - * DefineAggregate + * DefineAggregate * ------------------ */ void -DefineAggregate(char *aggName, List *parameters) +DefineAggregate(char *aggName, List * parameters) { - char *stepfunc1Name = NULL; - char *stepfunc2Name = NULL; - char *finalfuncName = NULL; - char *baseType = NULL; - char *stepfunc1Type = NULL; - char *stepfunc2Type = NULL; - char *init1 = NULL; - char *init2 = NULL; - List *pl; - - foreach (pl, parameters) { - DefElem *defel = (DefElem *)lfirst(pl); - - /* - * sfunc1 - */ - if (!strcasecmp(defel->defname, "sfunc1")) { - stepfunc1Name = defGetString(defel); - } else if (!strcasecmp(defel->defname, "basetype")) { - baseType = defGetString(defel); - } else if (!strcasecmp(defel->defname, "stype1")) { - stepfunc1Type = defGetString(defel); - - /* - * sfunc2 - */ - } else if (!strcasecmp(defel->defname, "sfunc2")) { - stepfunc2Name = defGetString(defel); - } else if (!strcasecmp(defel->defname, "stype2")) { - stepfunc2Type = defGetString(defel); - /* - * final - */ - } else if (!strcasecmp(defel->defname, "finalfunc")) { - finalfuncName = defGetString(defel); - /* - * initial conditions - */ - } else if (!strcasecmp(defel->defname, "initcond1")) { - init1 = defGetString(defel); - } else if (!strcasecmp(defel->defname, "initcond2")) { - init2 = defGetString(defel); - } else { - elog(NOTICE, "DefineAggregate: attribute \"%s\" not recognized", - defel->defname); - } - } - - /* - * make sure we have our required definitions - */ - if (baseType==NULL) - elog(WARN, "Define: \"basetype\" unspecified"); - if (stepfunc1Name!=NULL) { - if (stepfunc1Type==NULL) - elog(WARN, "Define: \"stype1\" unspecified"); - } - if (stepfunc2Name!=NULL) { - if (stepfunc2Type==NULL) - elog(WARN, "Define: \"stype2\" unspecified"); - } - - /* - * Most of the argument-checking is done inside of AggregateCreate - */ - AggregateCreate(aggName, /* aggregate name */ - stepfunc1Name, /* first step function name */ - stepfunc2Name, /* second step function name */ - finalfuncName, /* final function name */ - baseType, /* type of object being aggregated */ - stepfunc1Type, /* return type of first function */ - stepfunc2Type, /* return type of second function */ - init1, /* first initial condition */ - init2); /* second initial condition */ - - /* XXX free palloc'd memory */ + char *stepfunc1Name = NULL; + char *stepfunc2Name = NULL; + char *finalfuncName = NULL; + char *baseType = NULL; + char *stepfunc1Type = NULL; + char *stepfunc2Type = NULL; + char *init1 = NULL; + char *init2 = NULL; + List *pl; + + foreach(pl, parameters) + { + DefElem *defel = (DefElem *) lfirst(pl); + + /* + * sfunc1 + */ + if (!strcasecmp(defel->defname, "sfunc1")) + { + stepfunc1Name = defGetString(defel); + } + else if (!strcasecmp(defel->defname, "basetype")) + { + baseType = defGetString(defel); + } + else if (!strcasecmp(defel->defname, "stype1")) + { + stepfunc1Type = defGetString(defel); + + /* + * sfunc2 + */ + } + else if (!strcasecmp(defel->defname, "sfunc2")) + { + stepfunc2Name = defGetString(defel); + } + else if (!strcasecmp(defel->defname, "stype2")) + { + stepfunc2Type = defGetString(defel); + + /* + * final + */ + } + else if (!strcasecmp(defel->defname, "finalfunc")) + { + finalfuncName = defGetString(defel); + + /* + * initial conditions + */ + } + else if (!strcasecmp(defel->defname, "initcond1")) + { + init1 = defGetString(defel); + } + else if (!strcasecmp(defel->defname, "initcond2")) + { + init2 = defGetString(defel); + } + else + { + elog(NOTICE, "DefineAggregate: attribute \"%s\" not recognized", + defel->defname); + } + } + + /* + * make sure we have our required definitions + */ + if (baseType == NULL) + elog(WARN, "Define: \"basetype\" unspecified"); + if (stepfunc1Name != NULL) + { + if (stepfunc1Type == NULL) + elog(WARN, "Define: \"stype1\" unspecified"); + } + if (stepfunc2Name != NULL) + { + if (stepfunc2Type == NULL) + elog(WARN, "Define: \"stype2\" unspecified"); + } + + /* + * Most of the argument-checking is done inside of AggregateCreate + */ + AggregateCreate(aggName, /* aggregate name */ + stepfunc1Name, /* first step function name */ + stepfunc2Name, /* second step function name */ + finalfuncName, /* final function name */ + baseType, /* type of object being aggregated */ + stepfunc1Type, /* return type of first function */ + stepfunc2Type, /* return type of second function */ + init1, /* first initial condition */ + init2); /* second initial condition */ + + /* XXX free palloc'd memory */ } /* * DefineType -- - * Registers a new type. + * Registers a new type. * */ void -DefineType(char *typeName, List *parameters) +DefineType(char *typeName, List * parameters) { - int16 internalLength= 0; /* int2 */ - int16 externalLength= 0; /* int2 */ - char *elemName = NULL; - char *inputName = NULL; - char *outputName = NULL; - char *sendName = NULL; - char *receiveName = NULL; - char *defaultValue = NULL; /* Datum */ - bool byValue = false; - char delimiter = DEFAULT_TYPDELIM; - char *shadow_type; - List *pl; - char alignment = 'i'; /* default alignment */ - - /* - * Type names can only be 15 characters long, so that the shadow type - * can be created using the 16th character as necessary. - */ - if (strlen(typeName) >= (NAMEDATALEN - 1)) { - elog(WARN, "DefineType: type names must be %d characters or less", - NAMEDATALEN - 1); - } - - foreach(pl, parameters) { - DefElem *defel = (DefElem*)lfirst(pl); - - if (!strcasecmp(defel->defname, "internallength")) { - internalLength = defGetTypeLength(defel); - }else if (!strcasecmp(defel->defname, "externallength")) { - externalLength = defGetTypeLength(defel); - }else if (!strcasecmp(defel->defname, "input")) { - inputName = defGetString(defel); - }else if (!strcasecmp(defel->defname, "output")) { - outputName = defGetString(defel); - }else if (!strcasecmp(defel->defname, "send")) { - sendName = defGetString(defel); - }else if (!strcasecmp(defel->defname, "delimiter")) { - char *p = defGetString(defel); - delimiter = p[0]; - }else if (!strcasecmp(defel->defname, "receive")) { - receiveName = defGetString(defel); - }else if (!strcasecmp(defel->defname, "element")) { - elemName = defGetString(defel); - }else if (!strcasecmp(defel->defname, "default")) { - defaultValue = defGetString(defel); - }else if (!strcasecmp(defel->defname, "passedbyvalue")) { - byValue = true; - }else if (!strcasecmp(defel->defname, "alignment")) { - char *a = defGetString(defel); - if (!strcasecmp(a, "double")) { - alignment = 'd'; - } else if (!strcasecmp(a, "int")) { - alignment = 'i'; - } else { - elog(WARN, "DefineType: \"%s\" alignment not recognized", - a); - } - }else { - elog(NOTICE, "DefineType: attribute \"%s\" not recognized", - defel->defname); - } - } - - /* - * make sure we have our required definitions - */ - if (inputName==NULL) - elog(WARN, "Define: \"input\" unspecified"); - if (outputName==NULL) - elog(WARN, "Define: \"output\" unspecified"); - - /* ---------------- - * now have TypeCreate do all the real work. - * ---------------- - */ - TypeCreate(typeName, /* type name */ - InvalidOid, /* relation oid (n/a here) */ - internalLength, /* internal size */ - externalLength, /* external size */ - 'b', /* type-type (base type) */ - delimiter, /* array element delimiter */ - inputName, /* input procedure */ - outputName, /* output procedure */ - sendName, /* send procedure */ - receiveName, /* receive procedure */ - elemName, /* element type name */ - defaultValue, /* default type value */ - byValue, /* passed by value */ - alignment); - - /* ---------------- - * When we create a true type (as opposed to a complex type) - * we need to have an shadow array entry for it in pg_type as well. - * ---------------- - */ - shadow_type = makeArrayTypeName(typeName); - - TypeCreate(shadow_type, /* type name */ - InvalidOid, /* relation oid (n/a here) */ - -1, /* internal size */ - -1, /* external size */ - 'b', /* type-type (base type) */ - DEFAULT_TYPDELIM, /* array element delimiter */ - "array_in", /* input procedure */ - "array_out", /* output procedure */ - "array_out", /* send procedure */ - "array_in", /* receive procedure */ - typeName, /* element type name */ - defaultValue, /* default type value */ - false, /* never passed by value */ - alignment); - - pfree(shadow_type); + int16 internalLength = 0; /* int2 */ + int16 externalLength = 0; /* int2 */ + char *elemName = NULL; + char *inputName = NULL; + char *outputName = NULL; + char *sendName = NULL; + char *receiveName = NULL; + char *defaultValue = NULL; /* Datum */ + bool byValue = false; + char delimiter = DEFAULT_TYPDELIM; + char *shadow_type; + List *pl; + char alignment = 'i'; /* default alignment */ + + /* + * Type names can only be 15 characters long, so that the shadow type + * can be created using the 16th character as necessary. + */ + if (strlen(typeName) >= (NAMEDATALEN - 1)) + { + elog(WARN, "DefineType: type names must be %d characters or less", + NAMEDATALEN - 1); + } + + foreach(pl, parameters) + { + DefElem *defel = (DefElem *) lfirst(pl); + + if (!strcasecmp(defel->defname, "internallength")) + { + internalLength = defGetTypeLength(defel); + } + else if (!strcasecmp(defel->defname, "externallength")) + { + externalLength = defGetTypeLength(defel); + } + else if (!strcasecmp(defel->defname, "input")) + { + inputName = defGetString(defel); + } + else if (!strcasecmp(defel->defname, "output")) + { + outputName = defGetString(defel); + } + else if (!strcasecmp(defel->defname, "send")) + { + sendName = defGetString(defel); + } + else if (!strcasecmp(defel->defname, "delimiter")) + { + char *p = defGetString(defel); + + delimiter = p[0]; + } + else if (!strcasecmp(defel->defname, "receive")) + { + receiveName = defGetString(defel); + } + else if (!strcasecmp(defel->defname, "element")) + { + elemName = defGetString(defel); + } + else if (!strcasecmp(defel->defname, "default")) + { + defaultValue = defGetString(defel); + } + else if (!strcasecmp(defel->defname, "passedbyvalue")) + { + byValue = true; + } + else if (!strcasecmp(defel->defname, "alignment")) + { + char *a = defGetString(defel); + + if (!strcasecmp(a, "double")) + { + alignment = 'd'; + } + else if (!strcasecmp(a, "int")) + { + alignment = 'i'; + } + else + { + elog(WARN, "DefineType: \"%s\" alignment not recognized", + a); + } + } + else + { + elog(NOTICE, "DefineType: attribute \"%s\" not recognized", + defel->defname); + } + } + + /* + * make sure we have our required definitions + */ + if (inputName == NULL) + elog(WARN, "Define: \"input\" unspecified"); + if (outputName == NULL) + elog(WARN, "Define: \"output\" unspecified"); + + /* ---------------- + * now have TypeCreate do all the real work. + * ---------------- + */ + TypeCreate(typeName, /* type name */ + InvalidOid, /* relation oid (n/a here) */ + internalLength, /* internal size */ + externalLength, /* external size */ + 'b', /* type-type (base type) */ + delimiter, /* array element delimiter */ + inputName, /* input procedure */ + outputName, /* output procedure */ + sendName, /* send procedure */ + receiveName, /* receive procedure */ + elemName, /* element type name */ + defaultValue, /* default type value */ + byValue, /* passed by value */ + alignment); + + /* ---------------- + * When we create a true type (as opposed to a complex type) + * we need to have an shadow array entry for it in pg_type as well. + * ---------------- + */ + shadow_type = makeArrayTypeName(typeName); + + TypeCreate(shadow_type, /* type name */ + InvalidOid, /* relation oid (n/a here) */ + -1, /* internal size */ + -1, /* external size */ + 'b', /* type-type (base type) */ + DEFAULT_TYPDELIM,/* array element delimiter */ + "array_in", /* input procedure */ + "array_out", /* output procedure */ + "array_out", /* send procedure */ + "array_in", /* receive procedure */ + typeName, /* element type name */ + defaultValue, /* default type value */ + false, /* never passed by value */ + alignment); + + pfree(shadow_type); } -static char * -defGetString(DefElem *def) +static char * +defGetString(DefElem * def) { - if (nodeTag(def->arg)!=T_String) - elog(WARN, "Define: \"%s\" = what?", def->defname); - return (strVal(def->arg)); + if (nodeTag(def->arg) != T_String) + elog(WARN, "Define: \"%s\" = what?", def->defname); + return (strVal(def->arg)); } -static int -defGetTypeLength(DefElem *def) +static int +defGetTypeLength(DefElem * def) { - if (nodeTag(def->arg)==T_Integer) - return (intVal(def->arg)); - else if (nodeTag(def->arg)==T_String && - !strcasecmp(strVal(def->arg),"variable")) - return -1; /* variable length */ - - elog(WARN, "Define: \"%s\" = what?", def->defname); - return -1; + if (nodeTag(def->arg) == T_Integer) + return (intVal(def->arg)); + else if (nodeTag(def->arg) == T_String && + !strcasecmp(strVal(def->arg), "variable")) + return -1; /* variable length */ + + elog(WARN, "Define: \"%s\" = what?", def->defname); + return -1; } |