Hi,

The extension mechanism we added in 9.1 is aimed at allowing a fully
integrated contrib management, which was big enough a goal to preclude
doing anything else in its first release.

Now we have it and we can think some more about what features we want
covered, and a pretty obvious one that's been left out is the ability to
define and update an extension without resorting to file system support
for those extensions that do not need a shared object library. We could
have been calling that “SQL ONLY” extensions, but to simplify the
grammar support I did use the “inline” keyword so there we go.

Please find attached a WIP patch implementing that.  Note that the main
core benefit to integrating this feature is the ability to easily add
regression tests for extension related features.  Which is not done yet
in the attached.

I'm sending this quite soon because of the pg_dump support.  When an
extension is inline, we want to dump its content, as we currently do in
the binary dump output.  I had in mind that we could output a full
CREATE EXTENSION INLINE script in between some dollar-quoting rather
than adding each extension's object with a ALTER EXTENSION ... ADD line
like what pg_upgrade compatibility is currently doing.

It seems like much more work though, and I'd appreciate input about how
exactly to do that (it looks like making pg_dump reentrant, somehow).
Or some reason not to bother and just rename and share the binary
upgrade facility that Bruce already has put into pg_dump.

Here's a usage example that will certainly end up in the docs:

  create extension pair inline version '1.0' schema pair not relocatable as 
  $pair$
    CREATE TYPE pair AS ( k text, v text );
    
    CREATE OR REPLACE FUNCTION pair(anyelement, text)
    RETURNS pair LANGUAGE SQL AS 'SELECT ROW($1, $2)::pair';
    
    CREATE OR REPLACE FUNCTION pair(text, anyelement)
    RETURNS pair LANGUAGE SQL AS 'SELECT ROW($1, $2)::pair';
    
    CREATE OR REPLACE FUNCTION pair(anyelement, anyelement)
    RETURNS pair LANGUAGE SQL AS 'SELECT ROW($1, $2)::pair';
    
    CREATE OR REPLACE FUNCTION pair(text, text)
    RETURNS pair LANGUAGE SQL AS 'SELECT ROW($1, $2)::pair;';
    
    CREATE OPERATOR ~> (LEFTARG = text, RIGHTARG = anyelement, PROCEDURE = 
pair);
    CREATE OPERATOR ~> (LEFTARG = anyelement, RIGHTARG = text, PROCEDURE = 
pair);
    CREATE OPERATOR ~> (LEFTARG = anyelement, RIGHTARG = anyelement, PROCEDURE 
= pair);
    CREATE OPERATOR ~> (LEFTARG = text, RIGHTARG = text, PROCEDURE = pair);
  $pair$;
  
  alter extension pair update from '1.0' to '1.1' with
  $pair$
    CREATE OR REPLACE FUNCTION key(pair)
    RETURNS text LANGUAGE SQL AS 'SELECT ($1).k;';
  
    CREATE OR REPLACE FUNCTION value(pair)
    RETURNS text LANGUAGE SQL AS 'SELECT ($1).v;';
  
    CREATE OPERATOR %% (RIGHTARG = pair, PROCEDURE = key);
    CREATE OPERATOR %# (RIGHTARG = pair, PROCEDURE = value);
  $pair$;

Regards,
-- 
Dimitri Fontaine
http://2ndQuadrant.fr     PostgreSQL : Expertise, Formation et Support

diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index be4bbc7..4d1c18c 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -3020,6 +3020,13 @@
      </row>
 
      <row>
+      <entry><structfield>extinline</structfield></entry>
+      <entry><type>bool</type></entry>
+      <entry></entry>
+      <entry>True if extension has been created inline</entry>
+     </row>
+
+     <row>
       <entry><structfield>extversion</structfield></entry>
       <entry><type>text</type></entry>
       <entry></entry>
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index 7192c45..7157bc3 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -73,6 +73,8 @@ typedef struct ExtensionControlFile
 	bool		superuser;		/* must be superuser to install? */
 	int			encoding;		/* encoding of the script file, or -1 */
 	List	   *requires;		/* names of prerequisite extensions */
+	bool		is_inline;		/* create extension inline */
+	char	   *script;			/* script when extension is inline */
 } ExtensionControlFile;
 
 /*
@@ -590,6 +592,7 @@ read_extension_control_file(const char *extname)
 	control->relocatable = false;
 	control->superuser = true;
 	control->encoding = -1;
+	control->is_inline = false;
 
 	/*
 	 * Parse the primary control file.
@@ -800,7 +803,10 @@ execute_extension_script(Oid extensionOid, ExtensionControlFile *control,
 					 errhint("Must be superuser to update this extension.")));
 	}
 
-	filename = get_extension_script_filename(control, from_version, version);
+	if (!control->is_inline)
+		filename = get_extension_script_filename(control, from_version, version);
+	else
+		filename = "INLINE";	/* make compiler happy */
 
 	/*
 	 * Force client_min_messages and log_min_messages to be at least WARNING,
@@ -856,11 +862,13 @@ execute_extension_script(Oid extensionOid, ExtensionControlFile *control,
 	CurrentExtensionObject = extensionOid;
 	PG_TRY();
 	{
-		char	   *c_sql = read_extension_script_file(control, filename);
 		Datum		t_sql;
 
+		if (!control->is_inline)
+			control->script = read_extension_script_file(control, filename);
+
 		/* We use various functions that want to operate on text datums */
-		t_sql = CStringGetTextDatum(c_sql);
+		t_sql = CStringGetTextDatum(control->script);
 
 		/*
 		 * Reduce any lines beginning with "\echo" to empty.  This allows
@@ -904,9 +912,9 @@ execute_extension_script(Oid extensionOid, ExtensionControlFile *control,
 		}
 
 		/* And now back to C string */
-		c_sql = text_to_cstring(DatumGetTextPP(t_sql));
+		control->script = text_to_cstring(DatumGetTextPP(t_sql));
 
-		execute_sql_string(c_sql, filename);
+		execute_sql_string(control->script, filename);
 	}
 	PG_CATCH();
 	{
@@ -1178,6 +1186,11 @@ CreateExtension(CreateExtensionStmt *stmt)
 	DefElem    *d_schema = NULL;
 	DefElem    *d_new_version = NULL;
 	DefElem    *d_old_version = NULL;
+	DefElem    *d_relocatable = NULL;
+	DefElem    *d_comment = NULL;
+	DefElem    *d_module_pathname = NULL;
+	DefElem    *d_requires = NULL;
+	DefElem    *d_superuser = NULL;
 	char	   *schemaName;
 	Oid			schemaOid;
 	char	   *versionName;
@@ -1231,7 +1244,18 @@ CreateExtension(CreateExtensionStmt *stmt)
 	 * any non-ASCII data, so there is no need to worry about encoding at this
 	 * point.
 	 */
-	pcontrol = read_extension_control_file(stmt->extname);
+	if (!stmt->is_inline)
+		pcontrol = read_extension_control_file(stmt->extname);
+	else
+	{
+		/* we still need to initialize a default empty primary control file */
+		pcontrol = (ExtensionControlFile *) palloc0(sizeof(ExtensionControlFile));
+		pcontrol->name = pstrdup(stmt->extname);
+		pcontrol->relocatable = false;
+		pcontrol->superuser = true;
+		pcontrol->encoding = -1;
+		pcontrol->is_inline = true;
+	}
 
 	/*
 	 * Read the statement option list
@@ -1264,6 +1288,46 @@ CreateExtension(CreateExtensionStmt *stmt)
 						 errmsg("conflicting or redundant options")));
 			d_old_version = defel;
 		}
+		else if (strcmp(defel->defname, "relocatable") == 0)
+		{
+			if (d_relocatable || !stmt->is_inline)
+				ereport(ERROR,
+						(errcode(ERRCODE_SYNTAX_ERROR),
+						 errmsg("conflicting or redundant options")));
+			d_relocatable = defel;
+		}
+		else if (strcmp(defel->defname, "comment") == 0)
+		{
+			if (d_comment  || !stmt->is_inline)
+				ereport(ERROR,
+						(errcode(ERRCODE_SYNTAX_ERROR),
+						 errmsg("conflicting or redundant options")));
+			d_comment = defel;
+		}
+		else if (strcmp(defel->defname, "module_pathname") == 0)
+		{
+			if (d_module_pathname  || !stmt->is_inline)
+				ereport(ERROR,
+						(errcode(ERRCODE_SYNTAX_ERROR),
+						 errmsg("conflicting or redundant options")));
+			d_module_pathname = defel;
+		}
+		else if (strcmp(defel->defname, "requires") == 0)
+		{
+			if (d_requires  || !stmt->is_inline)
+				ereport(ERROR,
+						(errcode(ERRCODE_SYNTAX_ERROR),
+						 errmsg("conflicting or redundant options")));
+			d_requires = defel;
+		}
+		else if (strcmp(defel->defname, "superuser") == 0)
+		{
+			if (d_superuser  || !stmt->is_inline)
+				ereport(ERROR,
+						(errcode(ERRCODE_SYNTAX_ERROR),
+						 errmsg("conflicting or redundant options")));
+			d_superuser = defel;
+		}
 		else
 			elog(ERROR, "unrecognized option: %s", defel->defname);
 	}
@@ -1332,7 +1396,55 @@ CreateExtension(CreateExtensionStmt *stmt)
 	/*
 	 * Fetch control parameters for installation target version
 	 */
-	control = read_extension_aux_control_file(pcontrol, versionName);
+	if (!stmt->is_inline)
+		control = read_extension_aux_control_file(pcontrol, versionName);
+	else
+	{
+		/*
+		 * When the extension is inline we take the control parameters from the
+		 * statement
+		 */
+		control = (ExtensionControlFile *) palloc0(sizeof(ExtensionControlFile));
+		control->name = pstrdup(stmt->extname);
+		control->encoding = -1;
+		control->is_inline = true;
+		control->script = pstrdup(stmt->script);
+
+		if (d_relocatable)
+			control->relocatable = intVal(d_relocatable) != 0;
+
+		if (d_superuser)
+			control->superuser = intVal(d_superuser) != 0;
+
+		if (d_comment && d_comment->arg)
+			control->comment = strVal(d_comment->arg);
+
+		if (d_requires && d_requires->arg)
+		{
+			char *rawnames = pstrdup(strVal(d_requires->arg));
+
+			/* Parse string into list of identifiers */
+			if (!SplitIdentifierString(rawnames, ',', &pcontrol->requires))
+			{
+				/* syntax error in name list */
+				ereport(ERROR,
+						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 errmsg("requires must be a list of extension names")));
+			}
+		}
+
+		if (d_schema && d_schema->arg)
+		{
+			/* CREATE EXTENSION ... INLINE WITH SCHEMA ... NOT RELOCATABLE
+			 *
+			 * In the case of an inline extension we need to consider the
+			 * schema given by the command to be the same one as the one we
+			 * otherwise find in the control file.
+			 */
+			control->schema = strVal(d_schema->arg);
+			d_schema = NULL;
+		}
+	}
 
 	/*
 	 * Determine the target schema to install the extension into
@@ -1442,6 +1554,7 @@ CreateExtension(CreateExtensionStmt *stmt)
 	 */
 	extensionOid = InsertExtensionTuple(control->name, extowner,
 										schemaOid, control->relocatable,
+										control->is_inline,
 										versionName,
 										PointerGetDatum(NULL),
 										PointerGetDatum(NULL),
@@ -1484,7 +1597,8 @@ CreateExtension(CreateExtensionStmt *stmt)
  */
 Oid
 InsertExtensionTuple(const char *extName, Oid extOwner,
-					 Oid schemaOid, bool relocatable, const char *extVersion,
+					 Oid schemaOid, bool relocatable, bool is_inline,
+					 const char *extVersion,
 					 Datum extConfig, Datum extCondition,
 					 List *requiredExtensions)
 {
@@ -1510,6 +1624,7 @@ InsertExtensionTuple(const char *extName, Oid extOwner,
 	values[Anum_pg_extension_extowner - 1] = ObjectIdGetDatum(extOwner);
 	values[Anum_pg_extension_extnamespace - 1] = ObjectIdGetDatum(schemaOid);
 	values[Anum_pg_extension_extrelocatable - 1] = BoolGetDatum(relocatable);
+	values[Anum_pg_extension_extinline - 1] = BoolGetDatum(is_inline);
 	values[Anum_pg_extension_extversion - 1] = CStringGetTextDatum(extVersion);
 
 	if (extConfig == PointerGetDatum(NULL))
@@ -2351,6 +2466,7 @@ void
 ExecAlterExtensionStmt(AlterExtensionStmt *stmt)
 {
 	DefElem    *d_new_version = NULL;
+	DefElem    *d_old_version = NULL;
 	char	   *versionName;
 	char	   *oldVersionName;
 	ExtensionControlFile *control;
@@ -2397,6 +2513,26 @@ ExecAlterExtensionStmt(AlterExtensionStmt *stmt)
 	extensionOid = HeapTupleGetOid(extTup);
 
 	/*
+	 * We can only update inline an inline extension
+	 */
+	datum = heap_getattr(extTup, Anum_pg_extension_extinline,
+						 RelationGetDescr(extRel), &isnull);
+	if (isnull)
+		elog(ERROR, "extversion is null");
+
+	if (DatumGetBool(datum) != stmt->is_inline)
+	{
+		if (stmt->is_inline)
+			ereport(ERROR,
+					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+					 errmsg("inline update applies only to inline extension")));
+		else
+			ereport(ERROR,
+					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+					 errmsg("inline extension can only be updated inline")));
+	}
+
+	/*
 	 * Determine the existing version we are updating from
 	 */
 	datum = heap_getattr(extTup, Anum_pg_extension_extversion,
@@ -2419,7 +2555,23 @@ ExecAlterExtensionStmt(AlterExtensionStmt *stmt)
 	 * any non-ASCII data, so there is no need to worry about encoding at this
 	 * point.
 	 */
-	control = read_extension_control_file(stmt->extname);
+	if (!stmt->is_inline)
+		control = read_extension_control_file(stmt->extname);
+	else
+	{
+		/*
+		 * When the extension is inline we take the control parameters from the
+		 * statement
+		 */
+		control = (ExtensionControlFile *) palloc0(sizeof(ExtensionControlFile));
+		control->name = pstrdup(stmt->extname);
+		control->encoding = -1;
+		control->is_inline = true;
+		control->script = pstrdup(stmt->script);
+
+		/* TODO: add support for all other control properties in the statement */
+		control->relocatable = false;
+	}
 
 	/*
 	 * Read the statement option list
@@ -2436,11 +2588,35 @@ ExecAlterExtensionStmt(AlterExtensionStmt *stmt)
 						 errmsg("conflicting or redundant options")));
 			d_new_version = defel;
 		}
+		else if (strcmp(defel->defname, "old_version") == 0)
+		{
+			if (d_old_version)
+				ereport(ERROR,
+						(errcode(ERRCODE_SYNTAX_ERROR),
+						 errmsg("conflicting or redundant options")));
+			d_old_version = defel;
+		}
 		else
 			elog(ERROR, "unrecognized option: %s", defel->defname);
 	}
 
 	/*
+	 * Check that we've been asked to upgrade from the current version
+	 */
+	if (control->is_inline && !d_old_version)
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 errmsg("missing \"FROM\" option"),
+				 errdetail("Inline update of extension requires the FROM option")));
+
+	if (d_old_version && d_old_version->arg)
+		if (strcmp(oldVersionName, strVal(d_old_version->arg)) != 0)
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+					 errmsg("FROM version does not match current version, \"%s\"",
+							oldVersionName)));
+
+	/*
 	 * Determine the version to update to
 	 */
 	if (d_new_version && d_new_version->arg)
@@ -2470,9 +2646,23 @@ ExecAlterExtensionStmt(AlterExtensionStmt *stmt)
 	/*
 	 * Identify the series of update script files we need to execute
 	 */
-	updateVersions = identify_update_path(control,
-										  oldVersionName,
-										  versionName);
+	if (!control->is_inline)
+	{
+		updateVersions = identify_update_path(control,
+											  oldVersionName,
+											  versionName);
+	}
+	else
+	{
+		/*
+		 * In case of an inline update the script and control parameters are
+		 * all taken direcly from the statement itself. The origin version is
+		 * checked against the installed one.
+		 *
+		 * TODO: process all control properties from the statement.
+		 */
+		updateVersions = list_make1(versionName);
+	}
 
 	/*
 	 * Update the pg_extension row and execute the update scripts, one at a
@@ -2521,7 +2711,9 @@ ApplyExtensionUpdates(Oid extensionOid,
 		/*
 		 * Fetch parameters for specific version (pcontrol is not changed)
 		 */
-		control = read_extension_aux_control_file(pcontrol, versionName);
+		control = pcontrol;		/* make compiler happy */
+		if (!control->is_inline)
+			control = read_extension_aux_control_file(pcontrol, versionName);
 
 		/* Find the pg_extension tuple */
 		extRel = heap_open(ExtensionRelationId, RowExclusiveLock);
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 8943c5b..81f5f2b 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -242,8 +242,9 @@ static void processCASbits(int cas_bits, int location, const char *constrType,
 %type <list>	createdb_opt_list alterdb_opt_list copy_opt_list
 				transaction_mode_list
 				create_extension_opt_list alter_extension_opt_list
+                extension_feature_list create_extension_full_opt_list
 %type <defelt>	createdb_opt_item alterdb_opt_item copy_opt_item
-				transaction_mode_item
+				transaction_mode_item create_extension_full_opt_item
 				create_extension_opt_item alter_extension_opt_item
 
 %type <ival>	opt_lock lock_type cast_context
@@ -546,7 +547,7 @@ static void processCASbits(int cas_bits, int location, const char *constrType,
 	QUOTE
 
 	RANGE READ REAL REASSIGN RECHECK RECURSIVE REF REFERENCES REINDEX
-	RELATIVE_P RELEASE RENAME REPEATABLE REPLACE REPLICA
+	RELATIVE_P RELEASE RENAME REPEATABLE REPLACE REPLICA REQUIRES
 	RESET RESTART RESTRICT RETURNING RETURNS REVOKE RIGHT ROLE ROLLBACK
 	ROW ROWS RULE
 
@@ -3306,6 +3307,7 @@ CreateExtensionStmt: CREATE EXTENSION name opt_with create_extension_opt_list
 				{
 					CreateExtensionStmt *n = makeNode(CreateExtensionStmt);
 					n->extname = $3;
+					n->is_inline = false;
 					n->if_not_exists = false;
 					n->options = $5;
 					$$ = (Node *) n;
@@ -3314,10 +3316,36 @@ CreateExtensionStmt: CREATE EXTENSION name opt_with create_extension_opt_list
 				{
 					CreateExtensionStmt *n = makeNode(CreateExtensionStmt);
 					n->extname = $6;
+					n->is_inline = false;
 					n->if_not_exists = true;
 					n->options = $8;
 					$$ = (Node *) n;
 				}
+				/* we avoid shift/reduce using INLINE, the other way around
+				 * would be to accept the same option list for control file
+				 * based extension definitions and inline ones, and sort it out
+				 * in extension.c
+				 */
+				| CREATE EXTENSION name INLINE_P opt_with create_extension_full_opt_list
+				  AS Sconst
+				{
+					CreateExtensionStmt *n = makeNode(CreateExtensionStmt);
+					n->extname = $3;
+					n->is_inline = true;
+					n->if_not_exists = false;
+					n->options = $6;
+					n->script  = $8;
+					$$ = (Node *) n;
+				}
+		;
+
+create_extension_full_opt_list:
+			create_extension_full_opt_list create_extension_opt_item
+				{ $$ = lappend($1, $2); }
+			| create_extension_full_opt_list create_extension_full_opt_item
+				{ $$ = lappend($1, $2); }
+			| /* EMPTY */
+				{ $$ = NIL; }
 		;
 
 create_extension_opt_list:
@@ -3342,6 +3370,57 @@ create_extension_opt_item:
 				}
 		;
 
+create_extension_full_opt_item:
+			COMMENT Sconst
+				{
+					$$ = makeDefElem("comment", (Node *)makeString($2));
+				}
+			| REQUIRES extension_feature_list
+				{
+					$$ = makeDefElem("requires", (Node *)$2);
+				}
+			/*
+			 * We handle identifiers that aren't parser keywords with
+			 * the following special-case codes, to avoid bloating the
+			 * size of the main parser.
+			 */
+			| IDENT
+				{
+					if (strcasecmp($1, "superuser") == 0)
+						$$ = makeDefElem("superuser", (Node *)makeInteger(TRUE));
+					else if (strcasecmp($1, "relocatable") == 0)
+						$$ = makeDefElem("relocatable", (Node *)makeInteger(TRUE));
+					else
+						ereport(ERROR,
+								(errcode(ERRCODE_SYNTAX_ERROR),
+								 errmsg("unrecognized extension parameter \"%s\"", $1),
+									 parser_errposition(@1)));
+				}
+			| NOT IDENT
+				{
+					if (strcasecmp($2, "superuser") == 0)
+						$$ = makeDefElem("superuser", (Node *)makeInteger(FALSE));
+					else if (strcasecmp($2, "relocatable") == 0)
+						$$ = makeDefElem("relocatable", (Node *)makeInteger(FALSE));
+					else
+						ereport(ERROR,
+								(errcode(ERRCODE_SYNTAX_ERROR),
+								 errmsg("unrecognized extension parameter \"%s\"", $1),
+									 parser_errposition(@1)));
+				}
+		;
+
+extension_feature_list:
+			Sconst
+				{
+					$$ = list_make1($1);
+				}
+			| extension_feature_list ',' Sconst
+				{
+					$$ = lappend($1, $3);
+				}
+		;
+
 /*****************************************************************************
  *
  * ALTER EXTENSION name UPDATE [ TO version ]
@@ -3353,6 +3432,16 @@ AlterExtensionStmt: ALTER EXTENSION name UPDATE alter_extension_opt_list
 					AlterExtensionStmt *n = makeNode(AlterExtensionStmt);
 					n->extname = $3;
 					n->options = $5;
+					n->is_inline = false;
+					$$ = (Node *) n;
+				}
+				| ALTER EXTENSION name UPDATE alter_extension_opt_list WITH Sconst
+				{
+					AlterExtensionStmt *n = makeNode(AlterExtensionStmt);
+					n->extname = $3;
+					n->options = $5;
+					n->is_inline = true;
+					n->script  = $7;
 					$$ = (Node *) n;
 				}
 		;
@@ -3365,7 +3454,11 @@ alter_extension_opt_list:
 		;
 
 alter_extension_opt_item:
-			TO ColId_or_Sconst
+			FROM ColId_or_Sconst
+				{
+					$$ = makeDefElem("old_version", (Node *)makeString($2));
+				}
+			| TO ColId_or_Sconst
 				{
 					$$ = makeDefElem("new_version", (Node *)makeString($2));
 				}
@@ -12058,6 +12151,7 @@ unreserved_keyword:
 			| REPEATABLE
 			| REPLACE
 			| REPLICA
+			| REQUIRES
 			| RESET
 			| RESTART
 			| RESTRICT
diff --git a/src/include/catalog/pg_extension.h b/src/include/catalog/pg_extension.h
index 064b999..d28de9a 100644
--- a/src/include/catalog/pg_extension.h
+++ b/src/include/catalog/pg_extension.h
@@ -34,6 +34,7 @@ CATALOG(pg_extension,3079)
 	Oid			extowner;		/* extension owner */
 	Oid			extnamespace;	/* namespace of contained objects */
 	bool		extrelocatable; /* if true, allow ALTER EXTENSION SET SCHEMA */
+	bool		extinline;		/* if true, there's no control and script files */
 
 	/*
 	 * VARIABLE LENGTH FIELDS start here.
@@ -62,9 +63,10 @@ typedef FormData_pg_extension *Form_pg_extension;
 #define Anum_pg_extension_extowner			2
 #define Anum_pg_extension_extnamespace		3
 #define Anum_pg_extension_extrelocatable	4
-#define Anum_pg_extension_extversion		5
-#define Anum_pg_extension_extconfig			6
-#define Anum_pg_extension_extcondition		7
+#define Anum_pg_extension_extinline			5
+#define Anum_pg_extension_extversion		6
+#define Anum_pg_extension_extconfig			7
+#define Anum_pg_extension_extcondition		8
 
 /* ----------------
  *		pg_extension has no initial contents
diff --git a/src/include/commands/extension.h b/src/include/commands/extension.h
index f22ac80..ac27a60 100644
--- a/src/include/commands/extension.h
+++ b/src/include/commands/extension.h
@@ -32,9 +32,10 @@ extern void CreateExtension(CreateExtensionStmt *stmt);
 extern void RemoveExtensionById(Oid extId);
 
 extern Oid InsertExtensionTuple(const char *extName, Oid extOwner,
-					 Oid schemaOid, bool relocatable, const char *extVersion,
-					 Datum extConfig, Datum extCondition,
-					 List *requiredExtensions);
+								Oid schemaOid, bool relocatable, bool is_inline,
+								const char *extVersion,
+								Datum extConfig, Datum extCondition,
+								List *requiredExtensions);
 
 extern void ExecAlterExtensionStmt(AlterExtensionStmt *stmt);
 
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 6e8b110..24165ae 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -1593,8 +1593,10 @@ typedef struct CreateExtensionStmt
 {
 	NodeTag		type;
 	char	   *extname;
+	bool        is_inline;		/* no files, SQL only extension */
 	bool		if_not_exists;	/* just do nothing if it already exists? */
 	List	   *options;		/* List of DefElem nodes */
+	char       *script;			/* inline extensions stuff the script here */
 } CreateExtensionStmt;
 
 /* Only used for ALTER EXTENSION UPDATE; later might need an action field */
@@ -1603,6 +1605,8 @@ typedef struct AlterExtensionStmt
 	NodeTag		type;
 	char	   *extname;
 	List	   *options;		/* List of DefElem nodes */
+	bool        is_inline;		/* no files, SQL only extension */
+	char       *script;			/* inline extensions stuff the script here */
 } AlterExtensionStmt;
 
 typedef struct AlterExtensionContentsStmt
diff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.h
index 49aefed..4d64881 100644
--- a/src/include/parser/kwlist.h
+++ b/src/include/parser/kwlist.h
@@ -305,6 +305,7 @@ PG_KEYWORD("rename", RENAME, UNRESERVED_KEYWORD)
 PG_KEYWORD("repeatable", REPEATABLE, UNRESERVED_KEYWORD)
 PG_KEYWORD("replace", REPLACE, UNRESERVED_KEYWORD)
 PG_KEYWORD("replica", REPLICA, UNRESERVED_KEYWORD)
+PG_KEYWORD("requires", REQUIRES, UNRESERVED_KEYWORD)
 PG_KEYWORD("reset", RESET, UNRESERVED_KEYWORD)
 PG_KEYWORD("restart", RESTART, UNRESERVED_KEYWORD)
 PG_KEYWORD("restrict", RESTRICT, UNRESERVED_KEYWORD)
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to