diff --git a/src/backend/utils/adt/Makefile b/src/backend/utils/adt/Makefile
index c5b0a75..a3abb56 100644
--- a/src/backend/utils/adt/Makefile
+++ b/src/backend/utils/adt/Makefile
@@ -19,7 +19,7 @@ OBJS = acl.o arrayfuncs.o array_selfuncs.o array_typanalyze.o \
 	array_userfuncs.o arrayutils.o bool.o \
 	cash.o char.o date.o datetime.o datum.o domains.o \
 	enum.o float.o format_type.o \
-	geo_ops.o geo_selfuncs.o int.o int8.o json.o like.o lockfuncs.o \
+	geo_ops.o geo_selfuncs.o hostvars.o int.o int8.o json.o like.o lockfuncs.o \
 	misc.o nabstime.o name.o numeric.o numutils.o \
 	oid.o oracle_compat.o pseudotypes.o rangetypes.o rangetypes_gist.o \
 	rowtypes.o regexp.o regproc.o ruleutils.o selfuncs.o \
diff --git a/src/bin/psql/startup.c b/src/bin/psql/startup.c
index 9a6306b..65f3569 100644
--- a/src/bin/psql/startup.c
+++ b/src/bin/psql/startup.c
@@ -77,6 +77,24 @@ static void process_psqlrc_file(char *filename);
 static void showVersion(void);
 static void EstablishVariableSpace(void);
 
+static void
+hostvarReceiver(const char *varname, const char *value)
+{
+	SetVariable(pset.vars, varname, value);
+}
+
+static void
+hostvarSender(const char *varname, const char **value)
+{
+	char *content;
+
+	content = GetVariable(pset.vars, varname);
+	if (content == NULL)
+		*value = "";
+	else
+		*value = content;
+}
+
 /*
  *
  * main
@@ -230,6 +248,9 @@ main(int argc, char *argv[])
 
 	PQsetNoticeProcessor(pset.db, NoticeProcessor, NULL);
 
+	PQsetHostvarReceiver(pset.db, hostvarReceiver);
+	PQsetHostvarSender(pset.db, hostvarSender);
+
 	SyncVariables();
 
 	if (options.action == ACT_LIST_DB)
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index bee7154..cc43e39 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -4646,6 +4646,11 @@ DATA(insert OID = 4031 (  spg_text_leaf_consistent	PGNSP PGUID 12 1 0 0 0 f f f
 DESCR("SP-GiST support for suffix tree over text");
 
 
+DATA(insert OID = 3920 (  hgetvar PGNSP PGUID 12 1 0 0 0 f f f f t f v 1 0 25 "25" _null_ _null_ _null_ _null_  get_hostvar_text _null_ _null_ _null_ ));
+DATA(insert OID = 3921 (  hsetvar	PGNSP PGUID 12 1 0 0 0 f f f f t f v 2 0 2278 "25 25" _null_ _null_ _null_ _null_  set_hostvar_text _null_ _null_ _null_ ));
+
+
+
 /*
  * Symbolic values for provolatile column: these indicate whether the result
  * of a function is dependent *only* on the values of its explicit arguments,
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index 1063403..c79a2b4 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -1142,4 +1142,8 @@ extern Datum pg_prepared_statement(PG_FUNCTION_ARGS);
 /* utils/mmgr/portalmem.c */
 extern Datum pg_cursor(PG_FUNCTION_ARGS);
 
+/* adt/hostvars.c */
+extern Datum get_hostvar_text(PG_FUNCTION_ARGS);
+extern Datum set_hostvar_text(PG_FUNCTION_ARGS);
+
 #endif   /* BUILTINS_H */
diff --git a/src/interfaces/libpq/exports.txt b/src/interfaces/libpq/exports.txt
index 1251455..a0009c0 100644
--- a/src/interfaces/libpq/exports.txt
+++ b/src/interfaces/libpq/exports.txt
@@ -163,3 +163,5 @@ PQlibVersion              160
 PQsetRowProcessor         161
 PQgetRowProcessor         162
 PQskipResult              163
+PQsetHostvarReceiver      164
+PQsetHostvarSender        165
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 7c9fa34..143d641 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -2714,6 +2714,9 @@ makeEmptyPGconn(void)
 	conn->noticeHooks.noticeRec = defaultNoticeReceiver;
 	conn->noticeHooks.noticeProc = defaultNoticeProcessor;
 
+	conn->hostvarReceiver = NULL;
+	conn->hostvarSender = NULL;
+
 	conn->status = CONNECTION_BAD;
 	conn->asyncStatus = PGASYNC_IDLE;
 	conn->xactStatus = PQTRANS_IDLE;
@@ -5383,6 +5386,27 @@ PQsetNoticeProcessor(PGconn *conn, PQnoticeProcessor proc, void *arg)
 	return old;
 }
 
+void
+PQsetHostvarReceiver(PGconn *conn, PQhostvarReceiver proc)
+{
+	if (conn == NULL)
+		return;
+
+	if (proc)
+		conn->hostvarReceiver = proc;
+}
+
+void
+PQsetHostvarSender(PGconn *conn, PQhostvarSender proc)
+{
+	if (conn == NULL)
+		return;
+
+	if (proc)
+		conn->hostvarSender = proc;
+}
+
+
 /*
  * The default notice message receiver just gets the standard notice text
  * and sends it to the notice processor.  This two-level setup exists
diff --git a/src/interfaces/libpq/fe-protocol3.c b/src/interfaces/libpq/fe-protocol3.c
index 173af2e..f49d353 100644
--- a/src/interfaces/libpq/fe-protocol3.c
+++ b/src/interfaces/libpq/fe-protocol3.c
@@ -148,7 +148,61 @@ pqParseInput3(PGconn *conn)
 		 * from config file due to SIGHUP), but otherwise we hold off until
 		 * BUSY state.
 		 */
-		if (id == 'A')
+
+		if (id == 'v')
+		{
+			PQExpBufferData		varnameBuf, valueBuf;
+			char	result;
+			char *var;
+
+			initPQExpBuffer(&varnameBuf);
+			initPQExpBuffer(&valueBuf);
+
+			if (pqGetc(&result, conn))
+				return;
+
+			if (result == 1)
+			{
+				if (pqGets(&varnameBuf, conn))
+					return;
+
+				if (conn->hostvarSender != NULL)
+					(*conn->hostvarSender) (varnameBuf.data, &var);
+
+				if (pqPutMsgStart('v', false, conn) < 0 ||
+					pqPuts(var, conn) < 0 ||
+					pqPutMsgEnd(conn) < 0 ||
+					pqFlush(conn) < 0)
+				{
+
+					pqHandleSendFailure(conn);
+					return;
+				}
+
+				resetPQExpBuffer(&varnameBuf);
+			}
+			else if (result == 2)
+			{
+				if (pqGets(&varnameBuf, conn))
+					return;
+				if (pqGets(&valueBuf, conn))
+					return;
+
+				if (conn->hostvarReceiver != NULL)
+					(*conn->hostvarReceiver) (varnameBuf.data, valueBuf.data);
+
+				resetPQExpBuffer(&varnameBuf);
+				resetPQExpBuffer(&valueBuf);
+			}
+
+			if (pqGetc(&result, conn))
+				return;
+
+			if (result != '\0')
+				return;
+
+		}
+		else if (id == 'A')
 		{
 			if (getNotify(conn))
 				return;
diff --git a/src/interfaces/libpq/libpq-fe.h b/src/interfaces/libpq/libpq-fe.h
index 67db611..1c8ba3b 100644
--- a/src/interfaces/libpq/libpq-fe.h
+++ b/src/interfaces/libpq/libpq-fe.h
@@ -169,6 +169,11 @@ typedef int (*PQrowProcessor) (PGresult *res, const PGdataValue *columns,
 typedef void (*PQnoticeReceiver) (void *arg, const PGresult *res);
 typedef void (*PQnoticeProcessor) (void *arg, const char *message);
 
+/* Function types for hostvar handling callbacks */
+typedef void (*PQhostvarReceiver) (const char *varname, const char *value);
+typedef void (*PQhostvarSender) (const char *varname, const char **value);
+
+
 /* Print options for PQprint() */
 typedef char pqbool;
 
@@ -349,6 +354,10 @@ extern PQnoticeProcessor PQsetNoticeProcessor(PGconn *conn,
 					 PQnoticeProcessor proc,
 					 void *arg);
 
+extern void PQsetHostvarReceiver(PGconn *conn, PQhostvarReceiver proc);
+extern void PQsetHostvarSender(PGconn *conn, PQhostvarSender proc);
+
+
 /*
  *	   Used to set callback that prevents concurrent access to
  *	   non-thread safe functions that libpq needs.
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 4bc8926..0ed4761 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -157,6 +157,7 @@ typedef struct
 	void	   *noticeProcArg;
 } PGNoticeHooks;
 
+
 typedef struct PGEvent
 {
 	PGEventProc proc;			/* the function to call on events */
@@ -336,6 +337,10 @@ struct pg_conn
 	int			nEvents;		/* number of active events */
 	int			eventArraySize; /* allocated array size */
 
+	/* hostvar processing */
+	PQhostvarReceiver		hostvarReceiver;
+	PQhostvarSender			hostvarSender;
+
 	/* Status indicators */
 	ConnStatusType status;
 	PGAsyncStatusType asyncStatus;
diff --git a/src/test.sql b/src/test.sql
new file mode 100644
index 0000000..c3764ba
--- /dev/null
+++ b/src/test.sql
@@ -0,0 +1,14 @@
+\echo value of external paremeter is :"myvar"
+
+do $$
+begin
+  -- we can take any session variable on client side
+  -- it is safe against to SQL injection
+  raise notice 'external parameter accessed from plpgsql is "%"', hgetvar('myvar');
+
+  -- we can change this session variable and finish transaction
+  perform hsetvar('myvar', 'Hello, World');
+end;
+$$ language plpgsql;
+
+\echo new value of session variable is :"myvar"