Mostly Harmless: Welcoming our C++ friends - Mailing list pgsql-hackers
From | Kurt Harriman |
---|---|
Subject | Mostly Harmless: Welcoming our C++ friends |
Date | |
Msg-id | 4938E5ED.60102@acm.org Whole thread Raw |
Responses |
Re: Mostly Harmless: Welcoming our C++ friends
Re: Mostly Harmless: Welcoming our C++ friends Re: Mostly Harmless: c++reserved - patch 1 of 4 Re: Mostly Harmless: c++bookends - patch 2 of 4 Re: Mostly Harmless: c++configure - patch 3 of 4 Re: Mostly Harmless: c++exception - patch 4 of 4 Re: Mostly Harmless: Welcoming our C++ friends |
List | pgsql-hackers |
Hi, Sometimes people would like to call C++ code in the PostgreSQL backend environment... for example, in user-defined functions, triggers, access methods. And there is sometimes a need for C++ code to call back into PostgreSQL's C functions, such as the SPI interface. Many useful software packages and libraries are written in C++. The attached series of 4 patches is meant to provide a minimal level of support for C++ aficionados to easily compile and link with the PostgreSQL backend. No new interfaces or wrappers are provided. The goal is merely to make the backend a friendlier place for developing extensions involving C++, with minimal impact on the existing C code. The proposed change is divided into 4 patches with the hope that each will be simple and easy to review. They can be reviewed and discussed independently, and I hope some or all may be judged benign enough to be taken up into 8.5 or earlier. The patches are described in more detail below. They are: 1. c++reserved -- changes a few field and parameter names which happened to be C++ reserved words 2. c++bookends -- adds C linkage declarations to a few header files 3. c++configure -- adds C++ support to 'configure', 'make', and 'pg_config'. A new configure option --enable-cplusplus links the C++ runtime library in to the postgres backend. 4. c++exception -- converts unhandled C++ exceptions to PostgreSQL elog(FATAL) errors Regards, ... kurt These patches are based on CVS head in which the latest commit was user: petere date: Thu Dec 04 17:51:28 2008 +0000 summary: Default values for function arguments 1. c++reserved User-defined functions and extensions may need to access backend data structures such as parse trees. A few of the relevant header files contain field or parameter names which happen to be C++ reserved words. This makes them unusable from C++ because the compiler chokes on the reserved word. It has been suggested that the C++ user could surround these #includes with #defines to substitute innocuous words for the reserved words; but that would be unbearably kludgy, error prone and unmaintainable. A polite host does not demand such things of a guest. Fortunately, there are not many instances which are likely to be encountered by our C++ guests, and these can easily be changed. In memnodes.h, parsenodes.h, and primnodes.h, this patch changes the following field names: typename => typeName typeid => typeOid using => usingClause delete => delete_context Also, the patch changes a few parameter names in function prototypes in makefuncs.h, parse_type.h, and builtins.h: typename => typeName typeid => typeOid namespace => qualifier There's no need to ask PostgreSQL developers to remember to avoid C++ reserved words, because C++ users who are affected by such occurrences can be asked to submit a corrective patch. 2. c++bookends C++ code can call C functions and share global variables with C, provided those declarations are surrounded by "bookends": extern "C" { ... }; Header files can be made bilingual, to declare interfaces which look the same to both C and C++ callers. This is done by placing C++ bookends within the header file, guarded by #ifdefs #ifdef __cplusplus extern "C" { #endif ... #ifdef __cplusplus }; /* extern "C" */ #endif This way the C++ caller can just #include the header file without worrying whether the interface is implemented in C or C++. Usually, extension modules written in C++ will put bookends around all of their PostgreSQL #includes. However, "postgres.h" usually stands alone as the first #include, followed by some system #includes, and then the rest of the PostgreSQL #includes. It is much nicer if a C++ file has just one pair of bookends around its main block of PostgreSQL #includes. This patch gives postgres.h its own internal bookends, making it bilingual, so that its #include can continue to stand alone at the head of each file. Just a few additional header files are mentioned in the PostgreSQL Reference Manual for add-on developers to use: fmgr.h, funcapi.h, and spi.h. This patch adds bookends within those three files for the benefit of beginners writing very simple extensions in C++. Documentation and learning are simplified because C example code can be compiled as C or C++ without change. 3. c++configure This patch adds C++ support to the PostgreSQL build system. After you have applied the patch, cd to the top of the source tree (to the directory containing the file 'configure.in') and execute these two commands to regenerate the 'configure' script and some related files: autoconf autoheader Much as it already does for the C compiler, the 'configure' script will try to find the C++ compiler and set up appropriate command line options. If 'configure' finds a C++ compiler, it will set up src/Makefile.global to define the following makefile variables: CXX = command for invoking C++ compiler CXXCPP = command for invoking C++ preprocessor CXXFLAGS = C++ compiler options GXX = 'yes' if the C++ compiler is gcc/g++ Implicit rules are defined so that gmake will automatically invoke the C++ compiler using the above variables given a source file name suffixed with '.cpp' or '.cc'. So, to add a file named marvin.cpp to the build, just add 'marvin.o' to the OBJS list in the Makefile. To C++-compile a file with '.c' suffix, the Makefile should list the .o file in both OBJS and CXXOBJS. The pg_config utility can be used to display the CXX and CXXFLAGS. Most C++ code typically uses some C++ features whose implementation makes use of the compiler's runtime library: exceptions, static constructors, new/delete, STL containers, stream I/O, etc. Specify the following 'configure' option to link the C++ runtime library into the postgres backend: --enable-cplusplus If --enable-cplusplus is specified, the makefile variable 'enable_cplusplus' will be set to 'yes', and pg_config.h will #define ENABLE_CPLUSPLUS. To ensure that the C++ runtime library is properly initialized, on some platforms it is necessary for the main() function to be compiled as C++. Therefore, if --enable-cplusplus is configured, src/backend/main/main.c will be compiled as C++. This is handled by the following lines in src/backend/main/Makefile: ifeq ($(enable_cplusplus),yes) CXXOBJS = main.o endif Fortunately, main.c can be compiled as either C or C++ with no difficulty after applying the c++reserved and c++bookends patches. To make main.c bilingual, all that was needed was a pair of bookends around its #includes. Limitations: - I haven't added support for profiling and code coverage for C++. Automatic dependency generation is supported, however. - This ought to work on platforms which use GCC, and maybe some others. The only one I have tested is x86_32 Linux with GCC 4.1.2. Hopefully some interested hackers will try it on platforms to which they have access, and post the results. 4. c++exception When C code calls C++ code, all C++ exceptions need to be caught and fully contained within the C++ code. Exceptions should never be thrown outward across the C/C++ frontier. If an exception is not caught within C++ code, and the search for a matching 'catch' bumps into a C stack frame, the result may be platform dependent. On my platform (Linux/GCC), if this happens in the postgres backend, the process terminates silently as if abort() had been called. With this patch, if --enable-cplusplus is configured, PostgresMain defines a handler to intercept any uncaught C++ exception and convert it to a conventional PostgreSQL error of FATAL severity. This allows the backend to clean up and report the error before terminating. diff -r bd5a52b2681a src/backend/access/common/tupdesc.c --- a/src/backend/access/common/tupdesc.c +++ b/src/backend/access/common/tupdesc.c @@ -532,10 +532,10 @@ attnum++; attname = entry->colname; - atttypid = typenameTypeId(NULL, entry->typename, &atttypmod); - attdim = list_length(entry->typename->arrayBounds); + atttypid = typenameTypeId(NULL, entry->typeName, &atttypmod); + attdim = list_length(entry->typeName->arrayBounds); - if (entry->typename->setof) + if (entry->typeName->setof) ereport(ERROR, (errcode(ERRCODE_INVALID_TABLE_DEFINITION), errmsg("column \"%s\" cannot be declared SETOF", diff -r bd5a52b2681a src/backend/commands/sequence.c --- a/src/backend/commands/sequence.c +++ b/src/backend/commands/sequence.c @@ -141,53 +141,53 @@ switch (i) { case SEQ_COL_NAME: - coldef->typename = makeTypeNameFromOid(NAMEOID, -1); + coldef->typeName = makeTypeNameFromOid(NAMEOID, -1); coldef->colname = "sequence_name"; namestrcpy(&name, seq->sequence->relname); value[i - 1] = NameGetDatum(&name); break; case SEQ_COL_LASTVAL: - coldef->typename = makeTypeNameFromOid(INT8OID, -1); + coldef->typeName = makeTypeNameFromOid(INT8OID, -1); coldef->colname = "last_value"; value[i - 1] = Int64GetDatumFast(new.last_value); break; case SEQ_COL_STARTVAL: - coldef->typename = makeTypeNameFromOid(INT8OID, -1); + coldef->typeName = makeTypeNameFromOid(INT8OID, -1); coldef->colname = "start_value"; value[i - 1] = Int64GetDatumFast(new.start_value); break; case SEQ_COL_INCBY: - coldef->typename = makeTypeNameFromOid(INT8OID, -1); + coldef->typeName = makeTypeNameFromOid(INT8OID, -1); coldef->colname = "increment_by"; value[i - 1] = Int64GetDatumFast(new.increment_by); break; case SEQ_COL_MAXVALUE: - coldef->typename = makeTypeNameFromOid(INT8OID, -1); + coldef->typeName = makeTypeNameFromOid(INT8OID, -1); coldef->colname = "max_value"; value[i - 1] = Int64GetDatumFast(new.max_value); break; case SEQ_COL_MINVALUE: - coldef->typename = makeTypeNameFromOid(INT8OID, -1); + coldef->typeName = makeTypeNameFromOid(INT8OID, -1); coldef->colname = "min_value"; value[i - 1] = Int64GetDatumFast(new.min_value); break; case SEQ_COL_CACHE: - coldef->typename = makeTypeNameFromOid(INT8OID, -1); + coldef->typeName = makeTypeNameFromOid(INT8OID, -1); coldef->colname = "cache_value"; value[i - 1] = Int64GetDatumFast(new.cache_value); break; case SEQ_COL_LOG: - coldef->typename = makeTypeNameFromOid(INT8OID, -1); + coldef->typeName = makeTypeNameFromOid(INT8OID, -1); coldef->colname = "log_cnt"; value[i - 1] = Int64GetDatum((int64) 1); break; case SEQ_COL_CYCLE: - coldef->typename = makeTypeNameFromOid(BOOLOID, -1); + coldef->typeName = makeTypeNameFromOid(BOOLOID, -1); coldef->colname = "is_cycled"; value[i - 1] = BoolGetDatum(new.is_cycled); break; case SEQ_COL_CALLED: - coldef->typename = makeTypeNameFromOid(BOOLOID, -1); + coldef->typeName = makeTypeNameFromOid(BOOLOID, -1); coldef->colname = "is_called"; value[i - 1] = BoolGetDatum(false); break; diff -r bd5a52b2681a src/backend/commands/tablecmds.c --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -303,7 +303,7 @@ bool recurse, bool recursing, AlterTableCmd *cmd); static void ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, - const char *colName, TypeName *typename); + const char *colName, TypeName *typeName); static void ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab); static void ATPostAlterTypeParse(char *cmd, List **wqueue); static void change_owner_recurse_to_sequences(Oid relationOid, @@ -1251,7 +1251,7 @@ (errmsg("merging multiple inherited definitions of column \"%s\"", attributeName))); def = (ColumnDef *) list_nth(inhSchema, exist_attno - 1); - defTypeId = typenameTypeId(NULL, def->typename, &deftypmod); + defTypeId = typenameTypeId(NULL, def->typeName, &deftypmod); if (defTypeId != attribute->atttypid || deftypmod != attribute->atttypmod) ereport(ERROR, @@ -1259,7 +1259,7 @@ errmsg("inherited column \"%s\" has a type conflict", attributeName), errdetail("%s versus %s", - TypeNameToString(def->typename), + TypeNameToString(def->typeName), format_type_be(attribute->atttypid)))); def->inhcount++; /* Merge of NOT NULL constraints = OR 'em together */ @@ -1274,7 +1274,7 @@ */ def = makeNode(ColumnDef); def->colname = pstrdup(attributeName); - def->typename = makeTypeNameFromOid(attribute->atttypid, + def->typeName = makeTypeNameFromOid(attribute->atttypid, attribute->atttypmod); def->inhcount = 1; def->is_local = false; @@ -1409,16 +1409,16 @@ (errmsg("merging column \"%s\" with inherited definition", attributeName))); def = (ColumnDef *) list_nth(inhSchema, exist_attno - 1); - defTypeId = typenameTypeId(NULL, def->typename, &deftypmod); - newTypeId = typenameTypeId(NULL, newdef->typename, &newtypmod); + defTypeId = typenameTypeId(NULL, def->typeName, &deftypmod); + newTypeId = typenameTypeId(NULL, newdef->typeName, &newtypmod); if (defTypeId != newTypeId || deftypmod != newtypmod) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("column \"%s\" has a type conflict", attributeName), errdetail("%s versus %s", - TypeNameToString(def->typename), - TypeNameToString(newdef->typename)))); + TypeNameToString(def->typeName), + TypeNameToString(newdef->typeName)))); /* Mark the column as locally defined */ def->is_local = true; /* Merge of NOT NULL constraints = OR 'em together */ @@ -3480,7 +3480,7 @@ int32 ctypmod; /* Okay if child matches by type */ - ctypeId = typenameTypeId(NULL, colDef->typename, &ctypmod); + ctypeId = typenameTypeId(NULL, colDef->typeName, &ctypmod); if (ctypeId != childatt->atttypid || ctypmod != childatt->atttypmod) ereport(ERROR, @@ -3535,7 +3535,7 @@ MaxHeapAttributeNumber))); i = minattnum + 1; - typeTuple = typenameType(NULL, colDef->typename, &typmod); + typeTuple = typenameType(NULL, colDef->typeName, &typmod); tform = (Form_pg_type) GETSTRUCT(typeTuple); typeOid = HeapTupleGetOid(typeTuple); @@ -3551,7 +3551,7 @@ attribute.atttypmod = typmod; attribute.attnum = i; attribute.attbyval = tform->typbyval; - attribute.attndims = list_length(colDef->typename->arrayBounds); + attribute.attndims = list_length(colDef->typeName->arrayBounds); attribute.attstorage = tform->typstorage; attribute.attalign = tform->typalign; attribute.attnotnull = colDef->is_not_null; @@ -5415,7 +5415,7 @@ AlterTableCmd *cmd) { char *colName = cmd->name; - TypeName *typename = (TypeName *) cmd->def; + TypeName *typeName = (TypeName *) cmd->def; HeapTuple tuple; Form_pg_attribute attTup; AttrNumber attnum; @@ -5450,7 +5450,7 @@ colName))); /* Look up the target type */ - targettype = typenameTypeId(NULL, typename, &targettypmod); + targettype = typenameTypeId(NULL, typeName, &targettypmod); /* make sure datatype is legal for a column */ CheckAttributeType(colName, targettype); @@ -5541,7 +5541,7 @@ static void ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, - const char *colName, TypeName *typename) + const char *colName, TypeName *typeName) { HeapTuple heapTup; Form_pg_attribute attTup; @@ -5578,7 +5578,7 @@ colName))); /* Look up the target type (should not fail, since prep found it) */ - typeTuple = typenameType(NULL, typename, &targettypmod); + typeTuple = typenameType(NULL, typeName, &targettypmod); tform = (Form_pg_type) GETSTRUCT(typeTuple); targettype = HeapTupleGetOid(typeTuple); @@ -5825,7 +5825,7 @@ */ attTup->atttypid = targettype; attTup->atttypmod = targettypmod; - attTup->attndims = list_length(typename->arrayBounds); + attTup->attndims = list_length(typeName->arrayBounds); attTup->attlen = tform->typlen; attTup->attbyval = tform->typbyval; attTup->attalign = tform->typalign; diff -r bd5a52b2681a src/backend/commands/typecmds.c --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -676,7 +676,7 @@ bool saw_default = false; bool typNotNull = false; bool nullDefined = false; - int32 typNDims = list_length(stmt->typename->arrayBounds); + int32 typNDims = list_length(stmt->typeName->arrayBounds); HeapTuple typeTup; List *schema = stmt->constraints; ListCell *listptr; @@ -716,7 +716,7 @@ /* * Look up the base type. */ - typeTup = typenameType(NULL, stmt->typename, &basetypeMod); + typeTup = typenameType(NULL, stmt->typeName, &basetypeMod); baseType = (Form_pg_type) GETSTRUCT(typeTup); basetypeoid = HeapTupleGetOid(typeTup); @@ -732,7 +732,7 @@ ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("\"%s\" is not a valid base type for a domain", - TypeNameToString(stmt->typename)))); + TypeNameToString(stmt->typeName)))); /* passed by value */ byValue = baseType->typbyval; @@ -1013,7 +1013,7 @@ Relation pg_type; /* Convert list of names to a name and namespace */ - enumNamespace = QualifiedNameGetCreationNamespace(stmt->typename, + enumNamespace = QualifiedNameGetCreationNamespace(stmt->typeName, &enumName); /* Check we have creation rights in target namespace */ diff -r bd5a52b2681a src/backend/commands/view.c --- a/src/backend/commands/view.c +++ b/src/backend/commands/view.c @@ -118,7 +118,7 @@ ColumnDef *def = makeNode(ColumnDef); def->colname = pstrdup(tle->resname); - def->typename = makeTypeNameFromOid(exprType((Node *) tle->expr), + def->typeName = makeTypeNameFromOid(exprType((Node *) tle->expr), exprTypmod((Node *) tle->expr)); def->inhcount = 0; def->is_local = true; diff -r bd5a52b2681a src/backend/nodes/copyfuncs.c --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -1491,7 +1491,7 @@ COPY_SCALAR_FIELD(isNatural); COPY_NODE_FIELD(larg); COPY_NODE_FIELD(rarg); - COPY_NODE_FIELD(using); + COPY_NODE_FIELD(usingClause); COPY_NODE_FIELD(quals); COPY_NODE_FIELD(alias); COPY_SCALAR_FIELD(rtindex); @@ -1915,7 +1915,7 @@ TypeName *newnode = makeNode(TypeName); COPY_NODE_FIELD(names); - COPY_SCALAR_FIELD(typeid); + COPY_SCALAR_FIELD(typeOid); COPY_SCALAR_FIELD(setof); COPY_SCALAR_FIELD(pct_type); COPY_NODE_FIELD(typmods); @@ -1969,7 +1969,7 @@ TypeCast *newnode = makeNode(TypeCast); COPY_NODE_FIELD(arg); - COPY_NODE_FIELD(typename); + COPY_NODE_FIELD(typeName); COPY_LOCATION_FIELD(location); return newnode; @@ -1995,7 +1995,7 @@ ColumnDef *newnode = makeNode(ColumnDef); COPY_STRING_FIELD(colname); - COPY_NODE_FIELD(typename); + COPY_NODE_FIELD(typeName); COPY_SCALAR_FIELD(inhcount); COPY_SCALAR_FIELD(is_local); COPY_SCALAR_FIELD(is_not_null); @@ -2052,7 +2052,7 @@ COPY_SCALAR_FIELD(xmloption); COPY_NODE_FIELD(expr); - COPY_NODE_FIELD(typename); + COPY_NODE_FIELD(typeName); COPY_LOCATION_FIELD(location); return newnode; @@ -2204,7 +2204,7 @@ AlterDomainStmt *newnode = makeNode(AlterDomainStmt); COPY_SCALAR_FIELD(subtype); - COPY_NODE_FIELD(typename); + COPY_NODE_FIELD(typeName); COPY_STRING_FIELD(name); COPY_NODE_FIELD(def); COPY_SCALAR_FIELD(behavior); @@ -2622,7 +2622,7 @@ { CreateEnumStmt *newnode = makeNode(CreateEnumStmt); - COPY_NODE_FIELD(typename); + COPY_NODE_FIELD(typeName); COPY_NODE_FIELD(vals); return newnode; @@ -2657,7 +2657,7 @@ CreateDomainStmt *newnode = makeNode(CreateDomainStmt); COPY_NODE_FIELD(domainname); - COPY_NODE_FIELD(typename); + COPY_NODE_FIELD(typeName); COPY_NODE_FIELD(constraints); return newnode; diff -r bd5a52b2681a src/backend/nodes/equalfuncs.c --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -688,7 +688,7 @@ COMPARE_SCALAR_FIELD(isNatural); COMPARE_NODE_FIELD(larg); COMPARE_NODE_FIELD(rarg); - COMPARE_NODE_FIELD(using); + COMPARE_NODE_FIELD(usingClause); COMPARE_NODE_FIELD(quals); COMPARE_NODE_FIELD(alias); COMPARE_SCALAR_FIELD(rtindex); @@ -957,7 +957,7 @@ _equalAlterDomainStmt(AlterDomainStmt *a, AlterDomainStmt *b) { COMPARE_SCALAR_FIELD(subtype); - COMPARE_NODE_FIELD(typename); + COMPARE_NODE_FIELD(typeName); COMPARE_STRING_FIELD(name); COMPARE_NODE_FIELD(def); COMPARE_SCALAR_FIELD(behavior); @@ -1311,7 +1311,7 @@ static bool _equalCreateEnumStmt(CreateEnumStmt *a, CreateEnumStmt *b) { - COMPARE_NODE_FIELD(typename); + COMPARE_NODE_FIELD(typeName); COMPARE_NODE_FIELD(vals); return true; @@ -1340,7 +1340,7 @@ _equalCreateDomainStmt(CreateDomainStmt *a, CreateDomainStmt *b) { COMPARE_NODE_FIELD(domainname); - COMPARE_NODE_FIELD(typename); + COMPARE_NODE_FIELD(typeName); COMPARE_NODE_FIELD(constraints); return true; @@ -1852,7 +1852,7 @@ _equalTypeName(TypeName *a, TypeName *b) { COMPARE_NODE_FIELD(names); - COMPARE_SCALAR_FIELD(typeid); + COMPARE_SCALAR_FIELD(typeOid); COMPARE_SCALAR_FIELD(setof); COMPARE_SCALAR_FIELD(pct_type); COMPARE_NODE_FIELD(typmods); @@ -1867,7 +1867,7 @@ _equalTypeCast(TypeCast *a, TypeCast *b) { COMPARE_NODE_FIELD(arg); - COMPARE_NODE_FIELD(typename); + COMPARE_NODE_FIELD(typeName); COMPARE_LOCATION_FIELD(location); return true; @@ -1920,7 +1920,7 @@ _equalColumnDef(ColumnDef *a, ColumnDef *b) { COMPARE_STRING_FIELD(colname); - COMPARE_NODE_FIELD(typename); + COMPARE_NODE_FIELD(typeName); COMPARE_SCALAR_FIELD(inhcount); COMPARE_SCALAR_FIELD(is_local); COMPARE_SCALAR_FIELD(is_not_null); @@ -2062,7 +2062,7 @@ { COMPARE_SCALAR_FIELD(xmloption); COMPARE_NODE_FIELD(expr); - COMPARE_NODE_FIELD(typename); + COMPARE_NODE_FIELD(typeName); COMPARE_LOCATION_FIELD(location); return true; diff -r bd5a52b2681a src/backend/nodes/makefuncs.c --- a/src/backend/nodes/makefuncs.c +++ b/src/backend/nodes/makefuncs.c @@ -316,11 +316,11 @@ * build a TypeName node to represent a type already known by OID/typmod. */ TypeName * -makeTypeNameFromOid(Oid typeid, int32 typmod) +makeTypeNameFromOid(Oid typeOid, int32 typmod) { TypeName *n = makeNode(TypeName); - n->typeid = typeid; + n->typeOid = typeOid; n->typemod = typmod; n->location = -1; return n; diff -r bd5a52b2681a src/backend/nodes/nodeFuncs.c --- a/src/backend/nodes/nodeFuncs.c +++ b/src/backend/nodes/nodeFuncs.c @@ -860,7 +860,7 @@ * so any of the components might be leftmost. */ loc = exprLocation(tc->arg); - loc = leftmostLoc(loc, tc->typename->location); + loc = leftmostLoc(loc, tc->typeName->location); loc = leftmostLoc(loc, tc->location); } break; @@ -2359,7 +2359,7 @@ if (walker(tc->arg, context)) return true; - if (walker(tc->typename, context)) + if (walker(tc->typeName, context)) return true; } break; @@ -2400,7 +2400,7 @@ { ColumnDef *coldef = (ColumnDef *) node; - if (walker(coldef->typename, context)) + if (walker(coldef->typeName, context)) return true; if (walker(coldef->raw_default, context)) return true; @@ -2415,7 +2415,7 @@ if (walker(xs->expr, context)) return true; - if (walker(xs->typename, context)) + if (walker(xs->typeName, context)) return true; } break; diff -r bd5a52b2681a src/backend/nodes/outfuncs.c --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -1207,7 +1207,7 @@ WRITE_BOOL_FIELD(isNatural); WRITE_NODE_FIELD(larg); WRITE_NODE_FIELD(rarg); - WRITE_NODE_FIELD(using); + WRITE_NODE_FIELD(usingClause); WRITE_NODE_FIELD(quals); WRITE_NODE_FIELD(alias); WRITE_INT_FIELD(rtindex); @@ -1772,7 +1772,7 @@ WRITE_ENUM_FIELD(xmloption, XmlOptionType); WRITE_NODE_FIELD(expr); - WRITE_NODE_FIELD(typename); + WRITE_NODE_FIELD(typeName); WRITE_LOCATION_FIELD(location); } @@ -1782,7 +1782,7 @@ WRITE_NODE_TYPE("COLUMNDEF"); WRITE_STRING_FIELD(colname); - WRITE_NODE_FIELD(typename); + WRITE_NODE_FIELD(typeName); WRITE_INT_FIELD(inhcount); WRITE_BOOL_FIELD(is_local); WRITE_BOOL_FIELD(is_not_null); @@ -1797,7 +1797,7 @@ WRITE_NODE_TYPE("TYPENAME"); WRITE_NODE_FIELD(names); - WRITE_OID_FIELD(typeid); + WRITE_OID_FIELD(typeOid); WRITE_BOOL_FIELD(setof); WRITE_BOOL_FIELD(pct_type); WRITE_NODE_FIELD(typmods); @@ -1812,7 +1812,7 @@ WRITE_NODE_TYPE("TYPECAST"); WRITE_NODE_FIELD(arg); - WRITE_NODE_FIELD(typename); + WRITE_NODE_FIELD(typeName); WRITE_LOCATION_FIELD(location); } diff -r bd5a52b2681a src/backend/nodes/readfuncs.c --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -984,7 +984,7 @@ READ_BOOL_FIELD(isNatural); READ_NODE_FIELD(larg); READ_NODE_FIELD(rarg); - READ_NODE_FIELD(using); + READ_NODE_FIELD(usingClause); READ_NODE_FIELD(quals); READ_NODE_FIELD(alias); READ_INT_FIELD(rtindex); diff -r bd5a52b2681a src/backend/parser/gram.y --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -2021,7 +2021,7 @@ { ColumnDef *n = makeNode(ColumnDef); n->colname = $1; - n->typename = $2; + n->typeName = $2; n->constraints = $3; n->is_local = true; $$ = (Node *)n; @@ -2468,7 +2468,7 @@ { ColumnDef *n = makeNode(ColumnDef); n->colname = $1; - n->typename = NULL; + n->typeName = NULL; n->inhcount = 0; n->is_local = true; n->is_not_null = false; @@ -3056,7 +3056,7 @@ | CREATE TYPE_P any_name AS ENUM_P '(' enum_val_list ')' { CreateEnumStmt *n = makeNode(CreateEnumStmt); - n->typename = $3; + n->typeName = $3; n->vals = $7; $$ = (Node *)n; } @@ -5622,7 +5622,7 @@ { CreateDomainStmt *n = makeNode(CreateDomainStmt); n->domainname = $3; - n->typename = $5; + n->typeName = $5; n->constraints = $6; $$ = (Node *)n; } @@ -5634,7 +5634,7 @@ { AlterDomainStmt *n = makeNode(AlterDomainStmt); n->subtype = 'T'; - n->typename = $3; + n->typeName = $3; n->def = $4; $$ = (Node *)n; } @@ -5643,7 +5643,7 @@ { AlterDomainStmt *n = makeNode(AlterDomainStmt); n->subtype = 'N'; - n->typename = $3; + n->typeName = $3; $$ = (Node *)n; } /* ALTER DOMAIN <domain> SET NOT NULL */ @@ -5651,7 +5651,7 @@ { AlterDomainStmt *n = makeNode(AlterDomainStmt); n->subtype = 'O'; - n->typename = $3; + n->typeName = $3; $$ = (Node *)n; } /* ALTER DOMAIN <domain> ADD CONSTRAINT ... */ @@ -5659,7 +5659,7 @@ { AlterDomainStmt *n = makeNode(AlterDomainStmt); n->subtype = 'C'; - n->typename = $3; + n->typeName = $3; n->def = $5; $$ = (Node *)n; } @@ -5668,7 +5668,7 @@ { AlterDomainStmt *n = makeNode(AlterDomainStmt); n->subtype = 'X'; - n->typename = $3; + n->typeName = $3; n->name = $6; n->behavior = $7; $$ = (Node *)n; @@ -6920,7 +6920,7 @@ n->isNatural = FALSE; n->larg = $1; n->rarg = $4; - n->using = NIL; + n->usingClause = NIL; n->quals = NULL; $$ = n; } @@ -6932,7 +6932,7 @@ n->larg = $1; n->rarg = $4; if ($5 != NULL && IsA($5, List)) - n->using = (List *) $5; /* USING clause */ + n->usingClause = (List *) $5; /* USING clause */ else n->quals = $5; /* ON clause */ $$ = n; @@ -6946,7 +6946,7 @@ n->larg = $1; n->rarg = $3; if ($4 != NULL && IsA($4, List)) - n->using = (List *) $4; /* USING clause */ + n->usingClause = (List *) $4; /* USING clause */ else n->quals = $4; /* ON clause */ $$ = n; @@ -6958,7 +6958,7 @@ n->isNatural = TRUE; n->larg = $1; n->rarg = $5; - n->using = NIL; /* figure out which columns later... */ + n->usingClause = NIL; /* figure out which columns later... */ n->quals = NULL; /* fill later */ $$ = n; } @@ -6970,7 +6970,7 @@ n->isNatural = TRUE; n->larg = $1; n->rarg = $4; - n->using = NIL; /* figure out which columns later... */ + n->usingClause = NIL; /* figure out which columns later... */ n->quals = NULL; /* fill later */ $$ = n; } @@ -7135,7 +7135,7 @@ { ColumnDef *n = makeNode(ColumnDef); n->colname = $1; - n->typename = $2; + n->typeName = $2; n->constraints = NIL; n->is_local = true; $$ = (Node *)n; @@ -8694,7 +8694,7 @@ XmlSerialize *n = makeNode(XmlSerialize); n->xmloption = $3; n->expr = $4; - n->typename = $6; + n->typeName = $6; n->location = @1; $$ = (Node *)n; } @@ -9906,7 +9906,7 @@ { TypeCast *n = makeNode(TypeCast); n->arg = arg; - n->typename = typename; + n->typeName = typename; n->location = location; return (Node *) n; } diff -r bd5a52b2681a src/backend/parser/parse_clause.c --- a/src/backend/parser/parse_clause.c +++ b/src/backend/parser/parse_clause.c @@ -772,7 +772,7 @@ ListCell *lx, *rx; - Assert(j->using == NIL); /* shouldn't have USING() too */ + Assert(j->usingClause == NIL); /* shouldn't have USING() too */ foreach(lx, l_colnames) { @@ -795,7 +795,7 @@ rlist = lappend(rlist, m_name); } - j->using = rlist; + j->usingClause = rlist; } /* @@ -804,14 +804,14 @@ res_colnames = NIL; res_colvars = NIL; - if (j->using) + if (j->usingClause) { /* * JOIN/USING (or NATURAL JOIN, as transformed above). Transform * the list into an explicit ON-condition, and generate a list of * merged result columns. */ - List *ucols = j->using; + List *ucols = j->usingClause; List *l_usingvars = NIL; List *r_usingvars = NIL; ListCell *ucol; diff -r bd5a52b2681a src/backend/parser/parse_expr.c --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -159,7 +159,7 @@ Oid elementType; int32 targetTypmod; - targetType = typenameTypeId(pstate, tc->typename, + targetType = typenameTypeId(pstate, tc->typeName, &targetTypmod); elementType = get_element_type(targetType); if (OidIsValid(elementType)) @@ -1770,7 +1770,7 @@ XMLOID, "XMLSERIALIZE")); - targetType = typenameTypeId(pstate, xs->typename, &targetTypmod); + targetType = typenameTypeId(pstate, xs->typeName, &targetTypmod); xexpr->xmloption = xs->xmloption; xexpr->location = xs->location; @@ -1994,7 +1994,7 @@ int32 targetTypmod; int location; - targetType = typenameTypeId(pstate, tc->typename, &targetTypmod); + targetType = typenameTypeId(pstate, tc->typeName, &targetTypmod); if (inputType == InvalidOid) return expr; /* do nothing if NULL input */ @@ -2006,7 +2006,7 @@ */ location = tc->location; if (location < 0) - location = tc->typename->location; + location = tc->typeName->location; result = coerce_to_target_type(pstate, expr, inputType, targetType, targetTypmod, diff -r bd5a52b2681a src/backend/parser/parse_relation.c --- a/src/backend/parser/parse_relation.c +++ b/src/backend/parser/parse_relation.c @@ -1067,13 +1067,13 @@ int32 attrtypmod; attrname = pstrdup(n->colname); - if (n->typename->setof) + if (n->typeName->setof) ereport(ERROR, (errcode(ERRCODE_INVALID_TABLE_DEFINITION), errmsg("column \"%s\" cannot be declared SETOF", attrname), - parser_errposition(pstate, n->typename->location))); - attrtype = typenameTypeId(pstate, n->typename, &attrtypmod); + parser_errposition(pstate, n->typeName->location))); + attrtype = typenameTypeId(pstate, n->typeName, &attrtypmod); eref->colnames = lappend(eref->colnames, makeString(attrname)); rte->funccoltypes = lappend_oid(rte->funccoltypes, attrtype); rte->funccoltypmods = lappend_int(rte->funccoltypmods, attrtypmod); diff -r bd5a52b2681a src/backend/parser/parse_target.c --- a/src/backend/parser/parse_target.c +++ b/src/backend/parser/parse_target.c @@ -1355,9 +1355,9 @@ name); if (strength <= 1) { - if (((TypeCast *) node)->typename != NULL) + if (((TypeCast *) node)->typeName != NULL) { - *name = strVal(llast(((TypeCast *) node)->typename->names)); + *name = strVal(llast(((TypeCast *) node)->typeName->names)); return 1; } } diff -r bd5a52b2681a src/backend/parser/parse_type.c --- a/src/backend/parser/parse_type.c +++ b/src/backend/parser/parse_type.c @@ -27,7 +27,7 @@ #include "utils/syscache.h" -static int32 typenameTypeMod(ParseState *pstate, const TypeName *typename, +static int32 typenameTypeMod(ParseState *pstate, const TypeName *typeName, Type typ); @@ -54,57 +54,57 @@ * pstate is only used for error location info, and may be NULL. */ Type -LookupTypeName(ParseState *pstate, const TypeName *typename, +LookupTypeName(ParseState *pstate, const TypeName *typeName, int32 *typmod_p) { Oid typoid; HeapTuple tup; int32 typmod; - if (typename->names == NIL) + if (typeName->names == NIL) { /* We have the OID already if it's an internally generated TypeName */ - typoid = typename->typeid; + typoid = typeName->typeOid; } - else if (typename->pct_type) + else if (typeName->pct_type) { /* Handle %TYPE reference to type of an existing field */ - RangeVar *rel = makeRangeVar(NULL, NULL, typename->location); + RangeVar *rel = makeRangeVar(NULL, NULL, typeName->location); char *field = NULL; Oid relid; AttrNumber attnum; /* deconstruct the name list */ - switch (list_length(typename->names)) + switch (list_length(typeName->names)) { case 1: ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("improper %%TYPE reference (too few dotted names): %s", - NameListToString(typename->names)), - parser_errposition(pstate, typename->location))); + NameListToString(typeName->names)), + parser_errposition(pstate, typeName->location))); break; case 2: - rel->relname = strVal(linitial(typename->names)); - field = strVal(lsecond(typename->names)); + rel->relname = strVal(linitial(typeName->names)); + field = strVal(lsecond(typeName->names)); break; case 3: - rel->schemaname = strVal(linitial(typename->names)); - rel->relname = strVal(lsecond(typename->names)); - field = strVal(lthird(typename->names)); + rel->schemaname = strVal(linitial(typeName->names)); + rel->relname = strVal(lsecond(typeName->names)); + field = strVal(lthird(typeName->names)); break; case 4: - rel->catalogname = strVal(linitial(typename->names)); - rel->schemaname = strVal(lsecond(typename->names)); - rel->relname = strVal(lthird(typename->names)); - field = strVal(lfourth(typename->names)); + rel->catalogname = strVal(linitial(typeName->names)); + rel->schemaname = strVal(lsecond(typeName->names)); + rel->relname = strVal(lthird(typeName->names)); + field = strVal(lfourth(typeName->names)); break; default: ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("improper %%TYPE reference (too many dotted names): %s", - NameListToString(typename->names)), - parser_errposition(pstate, typename->location))); + NameListToString(typeName->names)), + parser_errposition(pstate, typeName->location))); break; } @@ -116,16 +116,16 @@ (errcode(ERRCODE_UNDEFINED_COLUMN), errmsg("column \"%s\" of relation \"%s\" does not exist", field, rel->relname), - parser_errposition(pstate, typename->location))); + parser_errposition(pstate, typeName->location))); typoid = get_atttype(relid, attnum); /* this construct should never have an array indicator */ - Assert(typename->arrayBounds == NIL); + Assert(typeName->arrayBounds == NIL); /* emit nuisance notice (intentionally not errposition'd) */ ereport(NOTICE, (errmsg("type reference %s converted to %s", - TypeNameToString(typename), + TypeNameToString(typeName), format_type_be(typoid)))); } else @@ -135,7 +135,7 @@ char *typname; /* deconstruct the name list */ - DeconstructQualifiedName(typename->names, &schemaname, &typname); + DeconstructQualifiedName(typeName->names, &schemaname, &typname); if (schemaname) { @@ -155,7 +155,7 @@ } /* If an array reference, return the array type instead */ - if (typename->arrayBounds != NIL) + if (typeName->arrayBounds != NIL) typoid = get_array_type(typoid); } @@ -172,7 +172,7 @@ if (!HeapTupleIsValid(tup)) /* should not happen */ elog(ERROR, "cache lookup failed for type %u", typoid); - typmod = typenameTypeMod(pstate, typename, (Type) tup); + typmod = typenameTypeMod(pstate, typeName, (Type) tup); if (typmod_p) *typmod_p = typmod; @@ -188,23 +188,23 @@ * Callers of this can therefore assume the result is a fully valid type. */ Type -typenameType(ParseState *pstate, const TypeName *typename, int32 *typmod_p) +typenameType(ParseState *pstate, const TypeName *typeName, int32 *typmod_p) { Type tup; - tup = LookupTypeName(pstate, typename, typmod_p); + tup = LookupTypeName(pstate, typeName, typmod_p); if (tup == NULL) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("type \"%s\" does not exist", - TypeNameToString(typename)), - parser_errposition(pstate, typename->location))); + TypeNameToString(typeName)), + parser_errposition(pstate, typeName->location))); if (!((Form_pg_type) GETSTRUCT(tup))->typisdefined) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("type \"%s\" is only a shell", - TypeNameToString(typename)), - parser_errposition(pstate, typename->location))); + TypeNameToString(typeName)), + parser_errposition(pstate, typeName->location))); return tup; } @@ -215,12 +215,12 @@ * not the syscache entry. */ Oid -typenameTypeId(ParseState *pstate, const TypeName *typename, int32 *typmod_p) +typenameTypeId(ParseState *pstate, const TypeName *typeName, int32 *typmod_p) { Oid typoid; Type tup; - tup = typenameType(pstate, typename, typmod_p); + tup = typenameType(pstate, typeName, typmod_p); typoid = HeapTupleGetOid(tup); ReleaseSysCache(tup); @@ -239,7 +239,7 @@ * pstate is only used for error location info, and may be NULL. */ static int32 -typenameTypeMod(ParseState *pstate, const TypeName *typename, Type typ) +typenameTypeMod(ParseState *pstate, const TypeName *typeName, Type typ) { int32 result; Oid typmodin; @@ -250,8 +250,8 @@ ParseCallbackState pcbstate; /* Return prespecified typmod if no typmod expressions */ - if (typename->typmods == NIL) - return typename->typemod; + if (typeName->typmods == NIL) + return typeName->typemod; /* * Else, type had better accept typmods. We give a special error message @@ -262,8 +262,8 @@ ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("type modifier cannot be specified for shell type \"%s\"", - TypeNameToString(typename)), - parser_errposition(pstate, typename->location))); + TypeNameToString(typeName)), + parser_errposition(pstate, typeName->location))); typmodin = ((Form_pg_type) GETSTRUCT(typ))->typmodin; @@ -271,17 +271,17 @@ ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("type modifier is not allowed for type \"%s\"", - TypeNameToString(typename)), - parser_errposition(pstate, typename->location))); + TypeNameToString(typeName)), + parser_errposition(pstate, typeName->location))); /* * Convert the list of raw-grammar-output expressions to a cstring array. * Currently, we allow simple numeric constants, string literals, and * identifiers; possibly this list could be extended. */ - datums = (Datum *) palloc(list_length(typename->typmods) * sizeof(Datum)); + datums = (Datum *) palloc(list_length(typeName->typmods) * sizeof(Datum)); n = 0; - foreach(l, typename->typmods) + foreach(l, typeName->typmods) { Node *tm = (Node *) lfirst(l); char *cstr = NULL; @@ -314,7 +314,7 @@ ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("type modifiers must be simple constants or identifiers"), - parser_errposition(pstate, typename->location))); + parser_errposition(pstate, typeName->location))); datums[n++] = CStringGetDatum(cstr); } @@ -323,7 +323,7 @@ -2, false, 'c'); /* arrange to report location if type's typmodin function fails */ - setup_parser_errposition_callback(&pcbstate, pstate, typename->location); + setup_parser_errposition_callback(&pcbstate, pstate, typeName->location); result = DatumGetInt32(OidFunctionCall1(typmodin, PointerGetDatum(arrtypmod))); @@ -345,16 +345,16 @@ * it is mostly used for reporting lookup errors. */ static void -appendTypeNameToBuffer(const TypeName *typename, StringInfo string) +appendTypeNameToBuffer(const TypeName *typeName, StringInfo string) { - if (typename->names != NIL) + if (typeName->names != NIL) { /* Emit possibly-qualified name as-is */ ListCell *l; - foreach(l, typename->names) + foreach(l, typeName->names) { - if (l != list_head(typename->names)) + if (l != list_head(typeName->names)) appendStringInfoChar(string, '.'); appendStringInfoString(string, strVal(lfirst(l))); } @@ -362,17 +362,17 @@ else { /* Look up internally-specified type */ - appendStringInfoString(string, format_type_be(typename->typeid)); + appendStringInfoString(string, format_type_be(typeName->typeOid)); } /* * Add decoration as needed, but only for fields considered by * LookupTypeName */ - if (typename->pct_type) + if (typeName->pct_type) appendStringInfoString(string, "%TYPE"); - if (typename->arrayBounds != NIL) + if (typeName->arrayBounds != NIL) appendStringInfoString(string, "[]"); } @@ -384,12 +384,12 @@ * it is mostly used for reporting lookup errors. */ char * -TypeNameToString(const TypeName *typename) +TypeNameToString(const TypeName *typeName) { StringInfoData string; initStringInfo(&string); - appendTypeNameToBuffer(typename, &string); + appendTypeNameToBuffer(typeName, &string); return string.data; } @@ -406,12 +406,12 @@ initStringInfo(&string); foreach(l, typenames) { - TypeName *typename = (TypeName *) lfirst(l); + TypeName *typeName = (TypeName *) lfirst(l); - Assert(IsA(typename, TypeName)); + Assert(IsA(typeName, TypeName)); if (l != list_head(typenames)) appendStringInfoChar(&string, ','); - appendTypeNameToBuffer(typename, &string); + appendTypeNameToBuffer(typeName, &string); } return string.data; } @@ -574,7 +574,7 @@ SelectStmt *stmt; ResTarget *restarget; TypeCast *typecast; - TypeName *typename; + TypeName *typeName; ErrorContextCallback ptserrcontext; /* make sure we give useful error for empty input */ @@ -633,14 +633,14 @@ typecast->arg == NULL || !IsA(typecast->arg, A_Const)) goto fail; - typename = typecast->typename; - if (typename == NULL || - !IsA(typename, TypeName)) + typeName = typecast->typeName; + if (typeName == NULL || + !IsA(typeName, TypeName)) goto fail; - if (typename->setof) + if (typeName->setof) goto fail; - *type_id = typenameTypeId(NULL, typename, typmod_p); + *type_id = typenameTypeId(NULL, typeName, typmod_p); pfree(buf.data); diff -r bd5a52b2681a src/backend/parser/parse_utilcmd.c --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -266,24 +266,24 @@ /* Check for SERIAL pseudo-types */ is_serial = false; - if (list_length(column->typename->names) == 1 && - !column->typename->pct_type) + if (list_length(column->typeName->names) == 1 && + !column->typeName->pct_type) { - char *typname = strVal(linitial(column->typename->names)); + char *typname = strVal(linitial(column->typeName->names)); if (strcmp(typname, "serial") == 0 || strcmp(typname, "serial4") == 0) { is_serial = true; - column->typename->names = NIL; - column->typename->typeid = INT4OID; + column->typeName->names = NIL; + column->typeName->typeOid = INT4OID; } else if (strcmp(typname, "bigserial") == 0 || strcmp(typname, "serial8") == 0) { is_serial = true; - column->typename->names = NIL; - column->typename->typeid = INT8OID; + column->typeName->names = NIL; + column->typeName->typeOid = INT8OID; } /* @@ -291,7 +291,7 @@ * set typeid, LookupTypeName won't notice arrayBounds. We don't * need any special coding for serial(typmod) though. */ - if (is_serial && column->typename->arrayBounds != NIL) + if (is_serial && column->typeName->arrayBounds != NIL) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("array of serial is not implemented"))); @@ -382,7 +382,7 @@ snamenode->val.val.str = qstring; snamenode->location = -1; castnode = makeNode(TypeCast); - castnode->typename = SystemTypeName("regclass"); + castnode->typeName = SystemTypeName("regclass"); castnode->arg = (Node *) snamenode; castnode->location = -1; funccallnode = makeNode(FuncCall); @@ -622,7 +622,7 @@ */ def = makeNode(ColumnDef); def->colname = pstrdup(attributeName); - def->typename = makeTypeNameFromOid(attribute->atttypid, + def->typeName = makeTypeNameFromOid(attribute->atttypid, attribute->atttypmod); def->inhcount = 0; def->is_local = true; @@ -1962,7 +1962,7 @@ /* * All we really need to do here is verify that the type is valid. */ - Type ctype = typenameType(pstate, column->typename, NULL); + Type ctype = typenameType(pstate, column->typeName, NULL); ReleaseSysCache(ctype); } diff -r bd5a52b2681a src/backend/tcop/utility.c --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -602,23 +602,23 @@ * Recursively alter column default for table and, if * requested, for descendants */ - AlterDomainDefault(stmt->typename, + AlterDomainDefault(stmt->typeName, stmt->def); break; case 'N': /* ALTER DOMAIN DROP NOT NULL */ - AlterDomainNotNull(stmt->typename, + AlterDomainNotNull(stmt->typeName, false); break; case 'O': /* ALTER DOMAIN SET NOT NULL */ - AlterDomainNotNull(stmt->typename, + AlterDomainNotNull(stmt->typeName, true); break; case 'C': /* ADD CONSTRAINT */ - AlterDomainAddConstraint(stmt->typename, + AlterDomainAddConstraint(stmt->typeName, stmt->def); break; case 'X': /* DROP CONSTRAINT */ - AlterDomainDropConstraint(stmt->typename, + AlterDomainDropConstraint(stmt->typeName, stmt->name, stmt->behavior); break; diff -r bd5a52b2681a src/backend/utils/adt/ruleutils.c --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -5539,14 +5539,14 @@ if (!j->isNatural) { - if (j->using) + if (j->usingClause) { ListCell *col; appendStringInfo(buf, " USING ("); - foreach(col, j->using) - { - if (col != list_head(j->using)) + foreach(col, j->usingClause) + { + if (col != list_head(j->usingClause)) appendStringInfo(buf, ", "); appendStringInfoString(buf, quote_identifier(strVal(lfirst(col)))); @@ -5878,18 +5878,18 @@ /* * quote_qualified_identifier - Quote a possibly-qualified identifier * - * Return a name of the form namespace.ident, or just ident if namespace + * Return a name of the form qualifier.ident, or just ident if qualifier * is NULL, quoting each component if necessary. The result is palloc'd. */ char * -quote_qualified_identifier(const char *namespace, +quote_qualified_identifier(const char *qualifier, const char *ident) { StringInfoData buf; initStringInfo(&buf); - if (namespace) - appendStringInfo(&buf, "%s.", quote_identifier(namespace)); + if (qualifier) + appendStringInfo(&buf, "%s.", quote_identifier(qualifier)); appendStringInfoString(&buf, quote_identifier(ident)); return buf.data; } diff -r bd5a52b2681a src/backend/utils/misc/guc.c --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -5370,7 +5370,7 @@ { Node *arg = (Node *) lfirst(l); char *val; - TypeName *typename = NULL; + TypeName *typeName = NULL; A_Const *con; if (l != list_head(args)) @@ -5381,7 +5381,7 @@ TypeCast *tc = (TypeCast *) arg; arg = tc->arg; - typename = tc->typename; + typeName = tc->typeName; } if (!IsA(arg, A_Const)) @@ -5399,7 +5399,7 @@ break; case T_String: val = strVal(&con->val); - if (typename != NULL) + if (typeName != NULL) { /* * Must be a ConstInterval argument for TIME ZONE. Coerce @@ -5411,7 +5411,7 @@ Datum interval; char *intervalout; - typoid = typenameTypeId(NULL, typename, &typmod); + typoid = typenameTypeId(NULL, typeName, &typmod); Assert(typoid == INTERVALOID); interval = diff -r bd5a52b2681a src/backend/utils/mmgr/mcxt.c --- a/src/backend/utils/mmgr/mcxt.c +++ b/src/backend/utils/mmgr/mcxt.c @@ -193,7 +193,7 @@ } } } - (*context->methods->delete) (context); + (*context->methods->delete_context) (context); pfree(context); } diff -r bd5a52b2681a src/include/c.h --- a/src/include/c.h +++ b/src/include/c.h @@ -150,7 +150,7 @@ * dummyret is used to set return values in macros that use ?: to make * assignments. gcc wants these to be void, other compilers like char */ -#ifdef __GNUC__ /* GNU cc */ +#if defined(__GNUC__) && !defined(__cplusplus) /* GNU cc */ #define dummyret void #else #define dummyret char diff -r bd5a52b2681a src/include/nodes/makefuncs.h --- a/src/include/nodes/makefuncs.h +++ b/src/include/nodes/makefuncs.h @@ -60,7 +60,7 @@ extern TypeName *makeTypeName(char *typnam); extern TypeName *makeTypeNameFromNameList(List *names); -extern TypeName *makeTypeNameFromOid(Oid typeid, int32 typmod); +extern TypeName *makeTypeNameFromOid(Oid typeOid, int32 typmod); extern FuncExpr *makeFuncExpr(Oid funcid, Oid rettype, List *args, CoercionForm fformat); diff -r bd5a52b2681a src/include/nodes/memnodes.h --- a/src/include/nodes/memnodes.h +++ b/src/include/nodes/memnodes.h @@ -41,7 +41,7 @@ void *(*realloc) (MemoryContext context, void *pointer, Size size); void (*init) (MemoryContext context); void (*reset) (MemoryContext context); - void (*delete) (MemoryContext context); + void (*delete_context) (MemoryContext context); Size (*get_chunk_space) (MemoryContext context, void *pointer); bool (*is_empty) (MemoryContext context); void (*stats) (MemoryContext context, int level); diff -r bd5a52b2681a src/include/nodes/parsenodes.h --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -157,7 +157,7 @@ * * For TypeName structures generated internally, it is often easier to * specify the type by OID than by name. If "names" is NIL then the - * actual type OID is given by typeid, otherwise typeid is unused. + * actual type OID is given by typeOid, otherwise typeOid is unused. * Similarly, if "typmods" is NIL then the actual typmod is expected to * be prespecified in typemod, otherwise typemod is unused. * @@ -169,7 +169,7 @@ { NodeTag type; List *names; /* qualified name (list of Value strings) */ - Oid typeid; /* type identified by OID */ + Oid typeOid; /* type identified by OID */ bool setof; /* is a set? */ bool pct_type; /* %TYPE specified? */ List *typmods; /* type modifier expression(s) */ @@ -252,7 +252,7 @@ { NodeTag type; Node *arg; /* the expression being casted */ - TypeName *typename; /* the target type */ + TypeName *typeName; /* the target type */ int location; /* token location, or -1 if unknown */ } TypeCast; @@ -409,7 +409,7 @@ { NodeTag type; char *colname; /* name of column */ - TypeName *typename; /* type of column */ + TypeName *typeName; /* type of column */ int inhcount; /* number of times column is inherited */ bool is_local; /* column has local (non-inherited) def'n */ bool is_not_null; /* NOT NULL constraint specified? */ @@ -490,7 +490,7 @@ NodeTag type; XmlOptionType xmloption; /* DOCUMENT or CONTENT */ Node *expr; - TypeName *typename; + TypeName *typeName; int location; /* token location, or -1 if unknown */ } XmlSerialize; @@ -1059,7 +1059,7 @@ * X = drop constraint *------------ */ - List *typename; /* domain to work on */ + List *typeName; /* domain to work on */ char *name; /* column or constraint name to act on */ Node *def; /* definition of default or constraint */ DropBehavior behavior; /* RESTRICT or CASCADE for DROP cases */ @@ -1459,7 +1459,7 @@ { NodeTag type; List *domainname; /* qualified name (list of Value strings) */ - TypeName *typename; /* the base type */ + TypeName *typeName; /* the base type */ List *constraints; /* constraints (list of Constraint nodes) */ } CreateDomainStmt; @@ -1872,7 +1872,7 @@ typedef struct CreateEnumStmt { NodeTag type; - List *typename; /* qualified name (list of Value strings) */ + List *typeName; /* qualified name (list of Value strings) */ List *vals; /* enum values (list of Value strings) */ } CreateEnumStmt; diff -r bd5a52b2681a src/include/nodes/primnodes.h --- a/src/include/nodes/primnodes.h +++ b/src/include/nodes/primnodes.h @@ -1107,8 +1107,8 @@ /*---------- * JoinExpr - for SQL JOIN expressions * - * isNatural, using, and quals are interdependent. The user can write only - * one of NATURAL, USING(), or ON() (this is enforced by the grammar). + * isNatural, usingClause, and quals are interdependent. The user can write + * only one of NATURAL, USING(), or ON() (this is enforced by the grammar). * If he writes NATURAL then parse analysis generates the equivalent USING() * list, and from that fills in "quals" with the right equality comparisons. * If he writes USING() then "quals" is filled with equality comparisons. @@ -1132,7 +1132,7 @@ bool isNatural; /* Natural join? Will need to shape table */ Node *larg; /* left subtree */ Node *rarg; /* right subtree */ - List *using; /* USING clause, if any (list of String) */ + List *usingClause; /* USING clause, if any (list of String) */ Node *quals; /* qualifiers on join, if any */ Alias *alias; /* user-written alias clause, if any */ int rtindex; /* RT index assigned for join */ diff -r bd5a52b2681a src/include/parser/parse_type.h --- a/src/include/parser/parse_type.h +++ b/src/include/parser/parse_type.h @@ -19,14 +19,14 @@ typedef HeapTuple Type; -extern Type LookupTypeName(ParseState *pstate, const TypeName *typename, +extern Type LookupTypeName(ParseState *pstate, const TypeName *typeName, int32 *typmod_p); -extern Type typenameType(ParseState *pstate, const TypeName *typename, +extern Type typenameType(ParseState *pstate, const TypeName *typeName, int32 *typmod_p); -extern Oid typenameTypeId(ParseState *pstate, const TypeName *typename, +extern Oid typenameTypeId(ParseState *pstate, const TypeName *typeName, int32 *typmod_p); -extern char *TypeNameToString(const TypeName *typename); +extern char *TypeNameToString(const TypeName *typeName); extern char *TypeNameListToString(List *typenames); extern Type typeidType(Oid id); diff -r bd5a52b2681a src/include/utils/builtins.h --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -560,7 +560,7 @@ extern List *deparse_context_for_plan(Node *plan, Node *outer_plan, List *rtable, List *subplans); extern const char *quote_identifier(const char *ident); -extern char *quote_qualified_identifier(const char *namespace, +extern char *quote_qualified_identifier(const char *qualifier, const char *ident); /* tid.c */ diff -r 55d732d0fbcd src/include/executor/spi.h --- a/src/include/executor/spi.h +++ b/src/include/executor/spi.h @@ -18,6 +18,10 @@ * included postgres.h */ #include "postgres.h" + +#ifdef __cplusplus +extern "C" { +#endif /* * Most of these are not needed by this file, but may be used by @@ -156,4 +160,8 @@ extern void AtEOXact_SPI(bool isCommit); extern void AtEOSubXact_SPI(bool isCommit, SubTransactionId mySubid); +#ifdef __cplusplus +} /* extern "C" */ +#endif + #endif /* SPI_H */ diff -r 55d732d0fbcd src/include/fmgr.h --- a/src/include/fmgr.h +++ b/src/include/fmgr.h @@ -17,6 +17,10 @@ */ #ifndef FMGR_H #define FMGR_H + +#ifdef __cplusplus +extern "C" { +#endif /* We don't want to include primnodes.h here, so make a stub reference */ typedef struct Node *fmNodePtr; @@ -544,4 +548,8 @@ */ extern char *fmgr(Oid procedureId,...); +#ifdef __cplusplus +} /* extern "C" */ +#endif + #endif /* FMGR_H */ diff -r 55d732d0fbcd src/include/funcapi.h --- a/src/include/funcapi.h +++ b/src/include/funcapi.h @@ -16,11 +16,14 @@ #ifndef FUNCAPI_H #define FUNCAPI_H +#ifdef __cplusplus +extern "C" { +#endif + #include "fmgr.h" #include "access/tupdesc.h" #include "executor/executor.h" #include "executor/tuptable.h" - /*------------------------------------------------------------------------- * Support to ease writing Functions returning composite types @@ -299,4 +302,8 @@ PG_RETURN_NULL(); \ } while (0) +#ifdef __cplusplus +} /* extern "C" */ +#endif + #endif /* FUNCAPI_H */ diff -r 55d732d0fbcd src/include/postgres.h --- a/src/include/postgres.h +++ b/src/include/postgres.h @@ -44,7 +44,12 @@ #ifndef POSTGRES_H #define POSTGRES_H +#ifdef __cplusplus +extern "C" { +#endif + #include "c.h" + #include "utils/elog.h" #include "utils/palloc.h" @@ -693,4 +698,8 @@ const char *errorType, const char *fileName, int lineNumber); +#ifdef __cplusplus +} /* extern "C" */ +#endif + #endif /* POSTGRES_H */ diff -r 257c0be599ab config/c-compiler.m4 --- a/config/c-compiler.m4 +++ b/config/c-compiler.m4 @@ -103,6 +103,7 @@ # command-line option. If it does, add the string to CFLAGS. AC_DEFUN([PGAC_PROG_CC_CFLAGS_OPT], [AC_MSG_CHECKING([if $CC supports $1]) +AC_LANG_ASSERT([C]) pgac_save_CFLAGS=$CFLAGS CFLAGS="$pgac_save_CFLAGS $1" _AC_COMPILE_IFELSE([AC_LANG_PROGRAM()], @@ -110,6 +111,23 @@ [CFLAGS="$pgac_save_CFLAGS" AC_MSG_RESULT(no)]) ])# PGAC_PROG_CC_CFLAGS_OPT + + + +# PGAC_PROG_CXX_CXXFLAGS_OPT +# ----------------------- +# Given a string, check if the C++ compiler supports the string as a +# command-line option. If it does, add the string to CXXFLAGS. +AC_DEFUN([PGAC_PROG_CXX_CXXFLAGS_OPT], +[AC_MSG_CHECKING([if $CXX supports $1]) +AC_LANG_ASSERT([C++]) +pgac_save_CXXFLAGS=$CXXFLAGS +CXXFLAGS="$pgac_save_CXXFLAGS $1" +_AC_COMPILE_IFELSE([AC_LANG_PROGRAM()], + AC_MSG_RESULT(yes), + [CXXFLAGS="$pgac_save_CXXFLAGS" + AC_MSG_RESULT(no)]) +])# PGAC_PROG_CXX_CXXFLAGS_OPT diff -r 257c0be599ab configure.in --- a/configure.in +++ b/configure.in @@ -195,6 +195,14 @@ PGAC_ARG_BOOL(enable, debug, no, [build with debugging symbols (-g)]) AC_SUBST(enable_debug) + +# +# --enable-cplusplus links the postgres backend with the C++ runtime library +# +PGAC_ARG_BOOL(enable, cplusplus, no, [build with C++ runtime library], + [AC_DEFINE([ENABLE_CPLUSPLUS], 1, + [Define to 1 for mixed C/C++ build. (--enable-cplusplus)])]) +AC_SUBST(enable_cplusplus) # # --enable-profiling enables gcc profiling @@ -365,9 +373,9 @@ PGAC_ARG_REQ(with, CC, [CMD], [set compiler (deprecated)], [CC=$with_CC]) case $template in - aix) pgac_cc_list="gcc xlc";; - irix) pgac_cc_list="cc";; # no gcc - *) pgac_cc_list="gcc cc";; + aix) pgac_cc_list="gcc xlc"; pgac_cxx_list="g++ xlC";; + irix) pgac_cc_list="cc"; pgac_cxx_list="CC";; # no gcc + *) pgac_cc_list="gcc cc"; pgac_cxx_list="g++ CC";; esac AC_PROG_CC([$pgac_cc_list]) @@ -387,7 +395,15 @@ AC_SUBST(SUN_STUDIO_CC) +# +# C++ compiler +# +AC_PROG_CXX([$pgac_cxx_list]) +AC_PROG_CXXCPP +AC_SUBST(GXX) + unset CFLAGS +unset CXXFLAGS # # Read the template @@ -421,9 +437,8 @@ # ICC pretends to be GCC but it's lying; it doesn't support these options. if test "$GCC" = yes -a "$ICC" = no; then - CFLAGS="$CFLAGS -Wall -Wmissing-prototypes -Wpointer-arith" + CFLAGS="$CFLAGS -Wall -Wpointer-arith" # These work in some but not all gcc versions - PGAC_PROG_CC_CFLAGS_OPT([-Wdeclaration-after-statement]) PGAC_PROG_CC_CFLAGS_OPT([-Wendif-labels]) # Disable strict-aliasing rules; needed for gcc 3.3+ PGAC_PROG_CC_CFLAGS_OPT([-fno-strict-aliasing]) @@ -470,12 +485,53 @@ CPPFLAGS="$CPPFLAGS -I$srcdir/src/include/port/win32 -DEXEC_BACKEND" fi +# +# Initialize C++ flags from CFLAGS unless overridden in environment or template +# +if test "$ac_env_CXXFLAGS_set" = set; then + CXXFLAGS=$ac_env_CXXFLAGS_value +elif test "${CXXFLAGS+set}" = set; then + : # (keep what template set) +else + CXXFLAGS="$CFLAGS" +fi + +# Some CXXFLAGS are only valid for C++, not for C. Add them here. +if test "$GXX" = yes -a "$ICC" = no; then + AC_LANG_PUSH([C++]) + CXXFLAGS="$CXXFLAGS -Wabi" + PGAC_PROG_CXX_CXXFLAGS_OPT([-fno-enforce-eh-specs]) + PGAC_PROG_CXX_CXXFLAGS_OPT([-fno-threadsafe-statics]) + AC_LANG_POP([C++]) +fi + +# Some CFLAGS are only valid for C, not for C++. Add them here. +if test "$GCC" = yes -a "$ICC" = no; then + CFLAGS="$CFLAGS -Wmissing-prototypes" + # These work in some but not all gcc versions + PGAC_PROG_CC_CFLAGS_OPT([-Wdeclaration-after-statement]) +fi + + +# # Check if the compiler still works with the template settings +# AC_MSG_CHECKING([whether the C compiler still works]) AC_TRY_LINK([], [return 0;], [AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no) AC_MSG_ERROR([cannot proceed])]) + +if test "$enable_cplusplus" = yes; then + AC_LANG_PUSH([C++]) + AC_MSG_CHECKING([whether the C++ compiler still works]) + AC_TRY_LINK([class X {public: bool b; X(bool bb){this->b = bb;}};], + [X* x = new X(true);], + [AC_MSG_RESULT(yes)], + [AC_MSG_RESULT(no) + AC_MSG_ERROR([cannot proceed])]) + AC_LANG_POP([C++]) +fi # Defend against gcc -ffast-math if test "$GCC" = yes; then @@ -1765,6 +1821,7 @@ # Begin output steps AC_MSG_NOTICE([using CFLAGS=$CFLAGS]) +AC_MSG_NOTICE([using CXXFLAGS=$CXXFLAGS]) AC_MSG_NOTICE([using CPPFLAGS=$CPPFLAGS]) AC_MSG_NOTICE([using LDFLAGS=$LDFLAGS]) diff -r 257c0be599ab doc/src/sgml/installation.sgml --- a/doc/src/sgml/installation.sgml +++ b/doc/src/sgml/installation.sgml @@ -1261,6 +1261,17 @@ can be profiled. On backend exit, a subdirectory will be created that contains the <filename>gmon.out</> file for use in profiling. This option is for use only with GCC and when doing development work. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>--enable-cplusplus</option></term> + <listitem> + <para> + Compiles the <filename>postgres</> server with C++ runtime + library support. Specify this option only if you intend to use or + develop server extensions or modifications in the C++ language. </para> </listitem> </varlistentry> diff -r 257c0be599ab doc/src/sgml/ref/pg_config-ref.sgml --- a/doc/src/sgml/ref/pg_config-ref.sgml +++ b/doc/src/sgml/ref/pg_config-ref.sgml @@ -223,6 +223,27 @@ </varlistentry> <varlistentry> + <term><option>--cxx</option></> + <listitem> + <para> + Print the value of the <varname>CXX</varname> variable showing the C++ + compiler that was used for building C++ modules (if any) in the + <productname>PostgreSQL</> backend. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>--cxxflags</option></> + <listitem> + <para> + Print the value of the <varname>CXXFLAGS</varname> variable that was used for building + <productname>PostgreSQL</>. This shows C++ compiler switches. + </para> + </listitem> + </varlistentry> + + <varlistentry> <term><option>--ldflags</option></> <listitem> <para> diff -r 257c0be599ab src/Makefile.global.in --- a/src/Makefile.global.in +++ b/src/Makefile.global.in @@ -164,6 +164,7 @@ enable_debug = @enable_debug@ enable_dtrace = @enable_dtrace@ enable_coverage = @enable_coverage@ +enable_cplusplus = @enable_cplusplus@ enable_thread_safety = @enable_thread_safety@ python_includespec = @python_includespec@ @@ -214,6 +215,21 @@ GCC = @GCC@ SUN_STUDIO_CC = @SUN_STUDIO_CC@ CFLAGS = @CFLAGS@ + +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXFLAGS = @CXXFLAGS@ +GXX = @GXX@ + +# gmake predefines these and uses them in its predefined implicit rules. +# We include them here just in case someone uses a version of gmake which +# doesn't have them built in. These are as defined by gmake 3.81. +COMPILE.c ?= $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c +LINK.c ?= $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH) +COMPILE.cc ?= $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c +LINK.cc ?= $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH) +COMPILE.cpp ?= $(COMPILE.cc) +LINK.cpp ?= $(LINK.cc) # Kind-of compilers @@ -545,18 +561,25 @@ ifeq ($(autodepend), yes) -ifndef COMPILE.c -COMPILE.c = $(CC) $(CFLAGS) $(CPPFLAGS) -c -endif - DEPDIR = .deps +DEPMKDIR = @if test ! -d $(DEPDIR); then mkdir -p $(DEPDIR); fi ifeq ($(GCC), yes) # GCC allows us to create object and dependency file in one invocation. +DEPFLAGS = -MMD -MP -MF $(DEPDIR)/$(*F).Po + %.o : %.c - @if test ! -d $(DEPDIR); then mkdir -p $(DEPDIR); fi - $(COMPILE.c) -o $@ $< -MMD -MP -MF $(DEPDIR)/$(*F).Po + $(DEPMKDIR) + $(COMPILE.c) $(DEPFLAGS) -o $@ $< + +%.o : %.cc + $(DEPMKDIR) + $(COMPILE.cc) $(DEPFLAGS) -o $@ $< + +%.o: %.cpp + $(DEPMKDIR) + $(COMPILE.cpp) $(DEPFLAGS) -o $@ $< endif # GCC diff -r 257c0be599ab src/backend/Makefile --- a/src/backend/Makefile +++ b/src/backend/Makefile @@ -43,7 +43,12 @@ ifneq ($(PORTNAME), aix) postgres: $(OBJS) +ifeq ($(enable_cplusplus), yes) + # Link with C++ runtime support + $(CXX) $(CXXFLAGS) $(LDFLAGS) $(export_dynamic) $(call expand_subsys,$^) $(LIBS) -o $@ +else $(CC) $(CFLAGS) $(LDFLAGS) $(export_dynamic) $(call expand_subsys,$^) $(LIBS) -o $@ +endif endif endif @@ -111,7 +116,12 @@ # The postgres.o target is needed by the rule in Makefile.global that # creates the exports file when MAKE_EXPORTS = true. postgres.o: $(OBJS) +ifeq ($(enable_cplusplus), yes) + # Link with C++ runtime support + $(CXX) $(LDREL) $(LDFLAGS) $(call expand_subsys,$^) $(LIBS) -o $@ +else $(CC) $(LDREL) $(LDFLAGS) $(call expand_subsys,$^) $(LIBS) -o $@ +endif # The following targets are specified in make commands that appear in @@ -268,4 +278,9 @@ # are up to date. It saves the time of doing all the submakes. .PHONY: quick quick: $(OBJS) +ifeq ($(enable_cplusplus), yes) + # Link with C++ runtime support + $(CXX) $(CXXFLAGS) $(LDFLAGS) $(export_dynamic) $(call expand_subsys,$^) $(LIBS) -o postgres +else $(CC) $(CFLAGS) $(LDFLAGS) $(export_dynamic) $(call expand_subsys,$^) $(LIBS) -o postgres +endif diff -r 257c0be599ab src/backend/common.mk --- a/src/backend/common.mk +++ b/src/backend/common.mk @@ -6,7 +6,7 @@ # When including this file, set OBJS to the object files created in # this directory and SUBDIRS to subdirectories containing more things -# to build. +# to build. Set CXXOBJS to the subset of OBJS which are to be C++ compiled. ifdef PARTIAL_LINKING # old style: linking using SUBSYS.o @@ -36,6 +36,11 @@ # Parallel make trickery $(SUBDIROBJS): $(SUBDIRS:%=%-recursive) ; +# For .o files listed in CXXOBJS, use C++ compiler to make .o from .c +$(CXXOBJS) : %.o: %.c + $(DEPMKDIR) + $(COMPILE.cc) $(DEPFLAGS) -o $@ $< + .PHONY: $(SUBDIRS:%=%-recursive) $(SUBDIRS:%=%-recursive): $(MAKE) -C $(subst -recursive,,$@) all diff -r 257c0be599ab src/backend/main/Makefile --- a/src/backend/main/Makefile +++ b/src/backend/main/Makefile @@ -14,4 +14,11 @@ OBJS = main.o +# If "configure --enable-cplusplus" was specified, make list of modules +# which are to be compiled as C++. The main() function should be compiled as +# C++ to ensure proper initialization of the mixed C/C++ runtime environment. +ifeq ($(enable_cplusplus),yes) +CXXOBJS = main.o +endif + include $(top_srcdir)/src/backend/common.mk diff -r 257c0be599ab src/backend/main/main.c --- a/src/backend/main/main.c +++ b/src/backend/main/main.c @@ -34,6 +34,14 @@ #include <sys/param.h> #endif +#if defined(ENABLE_CPLUSPLUS) && !defined(__cplusplus) +#error --enable-cplusplus configure option specified; this file should be compiled as C++ +#endif + +#ifdef __cplusplus +extern "C" { +#endif + #include "bootstrap/bootstrap.h" #include "postmaster/postmaster.h" #include "tcop/tcopprot.h" @@ -42,6 +50,10 @@ #include "utils/ps_status.h" #ifdef WIN32 #include "libpq/pqsignal.h" +#endif + +#ifdef __cplusplus +} /* extern "C" */ #endif diff -r 257c0be599ab src/bin/pg_config/Makefile --- a/src/bin/pg_config/Makefile +++ b/src/bin/pg_config/Makefile @@ -24,6 +24,8 @@ override CPPFLAGS += -DVAL_CPPFLAGS="\"$(STD_CPPFLAGS)\"" override CPPFLAGS += -DVAL_CFLAGS="\"$(CFLAGS)\"" override CPPFLAGS += -DVAL_CFLAGS_SL="\"$(CFLAGS_SL)\"" +override CPPFLAGS += -DVAL_CXX="\"$(CXX)\"" +override CPPFLAGS += -DVAL_CXXFLAGS="\"$(CXXFLAGS)\"" override CPPFLAGS += -DVAL_LDFLAGS="\"$(STD_LDFLAGS)\"" override CPPFLAGS += -DVAL_LDFLAGS_SL="\"$(LDFLAGS_SL)\"" override CPPFLAGS += -DVAL_LIBS="\"$(LIBS)\"" diff -r 257c0be599ab src/bin/pg_config/pg_config.c --- a/src/bin/pg_config/pg_config.c +++ b/src/bin/pg_config/pg_config.c @@ -311,6 +311,38 @@ } static void +show_cxx(bool all) +{ +#ifdef VAL_CXX + if (all) + printf("CXX = "); + printf("%s\n", VAL_CXX); +#else + if (!all) + { + fprintf(stderr, _("not recorded\n")); + exit(1); + } +#endif +} + +static void +show_cxxflags(bool all) +{ +#ifdef VAL_CXXFLAGS + if (all) + printf("CXXFLAGS = "); + printf("%s\n", VAL_CXXFLAGS); +#else + if (!all) + { + fprintf(stderr, _("not recorded\n")); + exit(1); + } +#endif +} + +static void show_ldflags(bool all) { #ifdef VAL_LDFLAGS @@ -397,6 +429,8 @@ {"--cppflags", show_cppflags}, {"--cflags", show_cflags}, {"--cflags_sl", show_cflags_sl}, + {"--cxx", show_cxx}, + {"--cxxflags", show_cxxflags}, {"--ldflags", show_ldflags}, {"--ldflags_sl", show_ldflags_sl}, {"--libs", show_libs}, @@ -432,6 +466,8 @@ printf(_(" --cppflags show CPPFLAGS value used when PostgreSQL was built\n")); printf(_(" --cflags show CFLAGS value used when PostgreSQL was built\n")); printf(_(" --cflags_sl show CFLAGS_SL value used when PostgreSQL was built\n")); + printf(_(" --cxx show CXX value used when PostgreSQL was built\n")); + printf(_(" --cxxflags show CXXFLAGS value used when PostgreSQL was built\n")); printf(_(" --ldflags show LDFLAGS value used when PostgreSQL was built\n")); printf(_(" --ldflags_sl show LDFLAGS_SL value used when PostgreSQL was built\n")); printf(_(" --libs show LIBS value used when PostgreSQL was built\n")); diff -r 257c0be599ab src/include/pg_config.h.in --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -44,6 +44,9 @@ /* Define to the default TCP port number as a string constant. */ #undef DEF_PGPORT_STR + +/* Define to 1 for mixed C/C++ build. (--enable-cplusplus) */ +#undef ENABLE_CPLUSPLUS /* Define to 1 to enable DTrace support. (--enable-dtrace) */ #undef ENABLE_DTRACE diff -r 9b2c774a6b05 src/backend/tcop/Makefile --- a/src/backend/tcop/Makefile +++ b/src/backend/tcop/Makefile @@ -14,6 +14,11 @@ OBJS= dest.o fastpath.o postgres.o pquery.o utility.o +# Designate modules to be compiled as C++ when 'configure --enable-cplusplus' +ifeq ($(enable_cplusplus),yes) +CXXOBJS = postgres.o +endif + ifneq (,$(filter $(PORTNAME),cygwin win32)) override CPPFLAGS += -DWIN32_STACK_RLIMIT=$(WIN32_STACK_RLIMIT) endif diff -r 9b2c774a6b05 src/backend/tcop/postgres.c --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -33,6 +33,17 @@ #endif #ifdef HAVE_GETOPT_H #include <getopt.h> +#endif + +#ifdef ENABLE_CPLUSPLUS +#ifndef __cplusplus +#error --enable-cplusplus configure option specified; this file should be compiled as C++ +#endif +#include <exception> +#endif + +#ifdef __cplusplus +extern "C" { #endif #ifndef HAVE_GETRUSAGE @@ -163,6 +174,11 @@ #endif /* TCOP_DONTUSENEWLINE */ +#ifdef __cplusplus +} /* extern "C" */ +#endif + + /* ---------------------------------------------------------------- * decls for routines only used in this file * ---------------------------------------------------------------- @@ -1212,7 +1228,7 @@ if (log_parser_stats) ResetUsage(); - query = parse_analyze_varparams(copyObject(raw_parse_tree), + query = parse_analyze_varparams((Node *)copyObject(raw_parse_tree), query_string, ¶mTypes, &numParams); @@ -1679,7 +1695,7 @@ * we have to make a copy of the parse trees. FIXME someday. */ oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal)); - query_list = copyObject(cplan->stmt_list); + query_list = (List *)copyObject(cplan->stmt_list); plan_list = pg_plan_queries(query_list, 0, params, true); MemoryContextSwitchTo(oldContext); @@ -2791,6 +2807,29 @@ return NULL; } + + +#ifdef ENABLE_CPLUSPLUS +/* + * PostgresMainUncaught + * Called when C++ code throws an exception which is not caught. + * + * NB: On some platforms when C++ code calls C code, and the C code calls + * a deeper layer of C++ code, the outer C++ code can't catch exceptions + * thrown by the inner C++ code. The search for a matching 'catch' is + * abandoned upon encountering an intervening C stack frame, and the + * exception is considered uncaught. + */ +static void +PostgresMainUncaught() +{ + /* Context callbacks might not work right if call stack has been unwound */ + error_context_stack = NULL; + + elog(FATAL, "Unexpected internal error: Unhandled C++ exception"); + abort(); /* not reached */ +} +#endif /* ENABLE_CPLUSPLUS */ /* ---------------------------------------------------------------- @@ -2850,6 +2889,11 @@ /* Set up reference point for stack depth checking */ stack_base_ptr = &stack_base; +#ifdef ENABLE_CPLUSPLUS + /* Any unhandled C++ exception is to be treated as a FATAL error. */ + std::set_terminate(PostgresMainUncaught); +#endif + /* Compute paths, if we didn't inherit them from postmaster */ if (my_exec_path[0] == '\0') { @@ -3108,10 +3152,10 @@ char *name; char *value; - name = lfirst(gucopts); + name = (char *)lfirst(gucopts); gucopts = lnext(gucopts); - value = lfirst(gucopts); + value = (char *)lfirst(gucopts); gucopts = lnext(gucopts); if (IsSuperuserConfigOption(name))
pgsql-hackers by date: