diff -U 5 -N -r -w ../orig.HEAD/doc/src/sgml/datatype.sgml ./doc/src/sgml/datatype.sgml
--- ../orig.HEAD/doc/src/sgml/datatype.sgml	2013-08-19 20:22:06.000000000 -0400
+++ ./doc/src/sgml/datatype.sgml	2013-08-19 20:54:00.000000000 -0400
@@ -159,10 +159,22 @@
        <entry></entry>
        <entry>currency amount</entry>
       </row>
 
       <row>
+       <entry><type>national character varying [ (<replaceable>n</replaceable>) ]</type></entry>
+       <entry><type>nvarchar [ (<replaceable>n</replaceable>) ]</type></entry>
+       <entry>variable-length national character string</entry>
+      </row>
+
+      <row>
+       <entry><type>national character [ (<replaceable>n</replaceable>) ]</type></entry>
+       <entry><type>nchar [ (<replaceable>n</replaceable>) ]</type></entry>
+       <entry>fixed-length national character string</entry>
+      </row>
+
+      <row>
        <entry><type>numeric [ (<replaceable>p</replaceable>,
          <replaceable>s</replaceable>) ]</type></entry>
        <entry><type>decimal [ (<replaceable>p</replaceable>,
          <replaceable>s</replaceable>) ]</type></entry>
        <entry>exact numeric of selectable precision</entry>
@@ -4661,6 +4673,195 @@
     <type>internal</> argument.
    </para>
 
   </sect1>
 
+  <sect1 id="datatype-national-character">
+   <title>National Character Types</title>
+
+   <indexterm zone="datatype-national-character">
+    <primary>national character string</primary>
+    <secondary>data types</secondary>
+   </indexterm>
+
+   <indexterm>
+    <primary>string</primary>
+    <see>national character string</see>
+   </indexterm>
+
+   <indexterm zone="datatype-national-character">
+    <primary>national character</primary>
+   </indexterm>
+
+   <indexterm zone="datatype-national-character">
+    <primary>national character varying</primary>
+   </indexterm>
+
+   <indexterm zone="datatype-national-character">
+    <primary>nchar</primary>
+   </indexterm>
+
+   <indexterm zone="datatype-national-character">
+    <primary>nvarchar</primary>
+   </indexterm>
+
+    <table id="datatype-national-character-table">
+     <title>National Character Types</title>
+     <tgroup cols="2">
+      <thead>
+       <row>
+        <entry>Name</entry>
+        <entry>Description</entry>
+       </row>
+      </thead>
+      <tbody>
+       <row>
+        <entry><type>national character varying(<replaceable>n</>)</type>, <type>nvarchar(<replaceable>n</>)</type></entry>
+        <entry>variable-length with limit</entry>
+       </row>
+       <row>
+        <entry><type>national character(<replaceable>n</>)</type>, <type>nchar(<replaceable>n</>)</type></entry>
+        <entry>fixed-length, blank padded</entry>
+       </row>
+     </tbody>
+     </tgroup>
+    </table>
+
+   <para>
+    <xref linkend="datatype-national-character-table"> shows the
+    general-purpose national character types available in
+    <productname>PostgreSQL</productname>.
+   </para>
+
+   <para>
+    <acronym>SQL</acronym> defines two primary national character types:
+    <type>national character varying(<replaceable>n</>)</type> and
+    <type>national character(<replaceable>n</>)</type>, where <replaceable>n</>
+    is a positive integer.  Both of these types can store strings up to
+    <replaceable>n</> national characters (not bytes) in length.  An attempt to store a
+    longer string into a column of these types will result in an
+    error, unless the excess characters are all spaces, in which case
+    the string will be truncated to the maximum length. 
+    If the string to be stored is shorter than the declared
+    length, values of type <type>national character</type> will be space-padded;
+    values of type <type>national character varying</type> will simply store the
+    shorter
+    string.
+   </para>
+
+   <para>
+    If one explicitly casts a value to <type>national character
+    varying(<replaceable>n</>)</type> or
+    <type>national character(<replaceable>n</>)</type>, then an over-length
+    value will be truncated to <replaceable>n</> characters without
+    raising an error. (This too is required by the
+    <acronym>SQL</acronym> standard.)
+   </para>
+
+   <para>
+    The notations <type>nvarchar(<replaceable>n</>)</type> and
+    <type>nchar(<replaceable>n</>)</type> are aliases for <type>national character
+    varying(<replaceable>n</>)</type> and
+    <type>national character(<replaceable>n</>)</type>, respectively.
+    <type>national character</type> without length specifier is equivalent to
+    <type>national character(1)</type>. If <type>national character varying</type> is used
+    without length specifier, the type accepts strings of any size. The
+    latter is a <productname>PostgreSQL</> extension.
+   </para>
+
+   <para>
+    Values of type <type>national character</type> are physically padded
+    with spaces to the specified width <replaceable>n</>, and are
+    stored and displayed that way.  However, the padding spaces are
+    treated as semantically insignificant.  Trailing spaces are
+    disregarded when comparing two values of type <type>national character</type>,
+    and they will be removed when converting a <type>national character</type> value
+    to one of the other string types.  Note that trailing spaces
+    <emphasis>are</> semantically significant in
+    <type>national character varying</type> values, and
+    when using pattern matching, e.g. <literal>LIKE</>,
+    regular expressions.
+   </para>
+
+   <para>
+    The storage requirement for a short string (up to 126 bytes) is 1 byte
+    plus the actual string, which includes the space padding in the case of
+    <type>national character</type>.  Longer strings have 4 bytes of overhead instead
+    of 1.  Long strings are compressed by the system automatically, so
+    the physical requirement on disk might be less. Very long values are also
+    stored in background tables so that they do not interfere with rapid
+    access to shorter column values. In any case, the longest
+    possible character string that can be stored is about 1 GB. (The
+    maximum value that will be allowed for <replaceable>n</> in the data
+    type declaration is less than that. It wouldn't be useful to
+    change this because with multibyte character encodings the number of
+    characters and bytes can be quite different. If you desire to
+    store long strings with no specific upper limit, use
+    <type>text</type> or <type>national character varying</type> without a length
+    specifier, rather than making up an arbitrary length limit.)
+   </para>
+
+   <tip>
+    <para>
+     There is no performance difference among these two types,
+     apart from increased storage space when using the blank-padded
+     type, and a few extra CPU cycles to check the length when storing into
+     a length-constrained column.  While
+     <type>national character(<replaceable>n</>)</type> has performance
+     advantages in some other database systems, there is no such advantage in
+     <productname>PostgreSQL</productname>; in fact
+     <type>national character(<replaceable>n</>)</type> is usually the slowest of
+     the three because of its additional storage costs.  In most situations
+     <type>text</type> or <type>national character varying</type> should be used
+     instead.
+    </para>
+   </tip>
+
+   <para>
+    Refer to <xref linkend="sql-syntax-strings"> for information about
+    the syntax of string literals, and to <xref linkend="functions">
+    for information about available operators and functions. The
+    database character set determines the character set used to store
+    textual values. The <type>national character varying</type> or <type>national character</type> types are supported only when the database encoding is UTF-8; for more information on character set support,
+    refer to <xref linkend="multibyte">.
+   </para>
+
+   <example>
+    <title>Using the National Character Types</title>
+
+<programlisting>
+CREATE TABLE test1 (a national character(4));
+INSERT INTO test1 VALUES (N'ok');
+SELECT a, char_length(a) FROM test1; -- <co id="co.datatype-nchar">
+<computeroutput>
+  a   | char_length
+------+-------------
+ ok   |           2
+</computeroutput>
+
+CREATE TABLE test2 (b nvarchar(5));
+INSERT INTO test2 VALUES (N'ok');
+INSERT INTO test2 VALUES (N'good      ');
+INSERT INTO test2 VALUES (N'too long');
+<computeroutput>ERROR:  value too long for type national character varying(5)</computeroutput>
+INSERT INTO test2 VALUES ('too long'::nvarchar(5)); -- explicit truncation
+SELECT b, char_length(b) FROM test2;
+<computeroutput>
+   b   | char_length
+-------+-------------
+ ok    |           2
+ good  |           5
+ too l |           5
+</computeroutput>
+</programlisting>
+    <calloutlist>
+     <callout arearefs="co.datatype-nchar">
+      <para>
+       The <function>char_length</function> function is discussed in
+       <xref linkend="functions-string">.
+      </para>
+     </callout>
+    </calloutlist>
+   </example>
+
+  </sect1>
  </chapter>
diff -U 5 -N -r -w ../orig.HEAD/doc/src/sgml/ecpg.sgml ./doc/src/sgml/ecpg.sgml
--- ../orig.HEAD/doc/src/sgml/ecpg.sgml	2013-08-19 20:22:06.000000000 -0400
+++ ./doc/src/sgml/ecpg.sgml	2013-08-19 20:54:00.000000000 -0400
@@ -888,10 +888,20 @@
 
       <row>
        <entry><type>boolean</type></entry>
        <entry><type>bool</type><footnote><para>declared in <filename>ecpglib.h</filename> if not native</para></footnote></entry>
       </row>
+      
+      <row>
+       <entry><type>national character(<replaceable>n</>)</type>, <type>nvarchar(<replaceable>n</>)</type></entry>
+       <entry><type>NCHAR[<replaceable>n</>+1]</type>, <type>NVARCHAR[<replaceable>n</>+1]</type></entry>
+      </row>
+      
+      <row>
+       <entry><type>national character(<replaceable>n</>)</type>, <type>nvarchar(<replaceable>n</>)</type>, <type>character(<replaceable>n</>)</type>, <type>varchar(<replaceable>n</>)</type>, <type>text</type></entry>
+       <entry><type>UVARCHAR[<replaceable>2*n</>]</type></entry>
+      </row>
      </tbody>
     </tgroup>
    </table>
 
    <sect3 id="ecpg-char">
@@ -966,10 +976,197 @@
      also hold values of other SQL types, which will be stored in
      their string forms.
     </para>
    </sect3>
 
+   <sect3 id="ecpg-nchar">
+    <title>Handling National Character Strings</title>
+
+    <para>
+     To handle SQL national character string data types, such
+     as <type>nvarchar</type> and <type>nchar</type>, there are two
+     possible ways to declare the host variables.
+    </para>
+
+    <para>
+     One way is using <type>NCHAR[]</type>, an array
+     of <type>NCHAR</type>, internally which is mapped to an array of <type>char</type> which is the most common way to handle
+     character data in C.
+<programlisting>
+EXEC SQL BEGIN DECLARE SECTION;
+    NCHAR str[50];
+EXEC SQL END DECLARE SECTION;
+</programlisting>
+     Note that you have to take care of the length yourself.  If you
+     use this host variable as the target variable of a query which
+     returns a string with more than 49 characters, a buffer overflow
+     occurs.
+    </para>
+
+    <para>
+     The other way is using the <type>NVARCHAR</type> type, which is a
+     special type provided by ECPG.  The definition on an array of
+     type <type>NVARCHAR</type> is converted into a
+     named <type>struct</> for every variable. A declaration like:
+<programlisting>
+NVARCHAR var[180];
+</programlisting>
+     is converted into:
+<programlisting>
+struct varchar_var { int len; char arr[180]; } var;
+</programlisting>
+     The member <structfield>arr</structfield> hosts the string
+     including a terminating zero byte.  Thus, to store a string in
+     a <type>NVARCHAR</type> host variable, the host variable has to be
+     declared with the length including the zero byte terminator.  The
+     member <structfield>len</structfield> holds the length of the
+     string stored in the <structfield>arr</structfield> without the
+     terminating zero byte.  When a host variable is used as input for
+     a query, if <literal>strlen(arr)</literal>
+     and <structfield>len</structfield> are different, the shorter one
+     is used.
+    </para>
+
+    <para>
+     Two or more <type>NVARCHAR</type> host variables cannot be defined
+     in single line statement.  The following code will confuse
+     the <command>ecpg</command> preprocessor:
+<programlisting>
+NVARCHAR v1[128], v2[128];   /* WRONG */
+</programlisting>
+     Two variables should be defined in separate statements like this:
+<programlisting>
+NVARCHAR v1[128];
+NVARCHAR v2[128];
+</programlisting>
+    </para>
+
+    <para>
+     <type>NVARCHAR</type> and <type>NCHAR</type> can be written in upper or lower case, but
+     not in mixed case.
+    </para>
+
+    <para>
+     <type>NCHAR</type> and <type>NVARCHAR</type> host variables can
+     also hold values of other SQL types, which will be stored in
+     their string forms. NVARCHAR type is pretty similar to VARCHAR type 
+     and added mainly for SQL standard compatibility.
+    </para>
+   </sect3>
+
+   <sect3 id="ecpg-uvarchar">
+    <title>Handling Strings with UVARCHAR type</title>
+
+    <para>
+     ECPG contains a special type <type>UVARCHAR</type> for defining host variables to store 
+     character string and national character string values from respective SQL types. 
+
+     This type is preprocessed into a structure with length and buffer fields.
+
+     <programlisting>
+      struct uvarchar_var { int len; char arr[180]; } uvc;
+     </programlisting>
+
+    The data stored by <type>UVARCHAR</type> type structure is always in UTF-16 encoding. There is an implicit conversion from UTF-8 to UTF-16 when UVARCHAR type is created.
+    </para>
+    
+    <para>
+     The sample usage of UVARCHAR to handle string data
+     
+     <programlisting>
+      #include &lt;stdio.h>
+ 
+      EXEC SQL INCLUDE sqlca;
+      EXEC SQL WHENEVER SQLERROR   SQLPRINT;
+      
+      int main( int argc, char * argv[] )
+      {
+          EXEC SQL BEGIN DECLARE SECTION;
+          UVARCHAR uv[100];
+          EXEC SQL END DECLARE SECTION;
+      
+          EXEC SQL CONNECT TO postgres;
+          EXEC SQL CREATE TABLE test (a nvarchar);
+          EXEC SQL INSERT INTO test (a) values ('ok'),
+      ...
+          EXEC SQL SELECT a INTO :uv FROM test;
+          printf("value=%s length=%d\n", uv.arr, uv.len);
+      ...
+      ...
+      }
+     </programlisting>
+
+     The member <structfield>arr</structfield> hosts the string
+     without a terminating zero byte.  As the default encoding for 
+     <type>UVARCHAR</type> is UTF-16, to store a string in a 
+     <type>UVARCHAR</type> host variable, the host variable has to be
+     declared with the minimum length of 2*n. The member <structfield>len</structfield> 
+     holds the length of the string stored in the <structfield>arr</structfield>.
+     When a host variable is used as input for a query, 
+     if <literal>strlen(arr)</literal> and <structfield>len</structfield> 
+     are different, the shorter one is used.
+
+    </para>
+
+   </sect3>
+
+   <sect3 id="ecpg-datatype-comparison">
+    <title>Comparison between VARCHAR, NVARCHAR and UVARCHAR Types</title>
+    <para>
+    The host data types used for handling string values, differ in few aspects like memory usage, encoding, performance etc.
+    <xref linkend="ecpg-datatype-comaprison-table"> shows the comparison of 
+    host data types.
+ 
+    </para>
+    <table id="ecpg-datatype-comaprison-table">
+     <title>Comparison between VARCHAR, NVARCHAR and UVARCHAR Types</title>
+
+     <tgroup cols="4">
+      <thead>
+       <row>
+        <entry></entry>
+        <entry>VARCHAR</entry>
+        <entry>NVARCHAR</entry>
+        <entry>UVARCHAR</entry>
+       </row>
+      </thead>
+
+      <tbody>
+       <row>
+        <entry><type>Maximum Size for 'n' characters</type></entry>
+        <entry><type>4*n + 1</type></entry>
+        <entry><type>4*n + 1</type></entry>
+        <entry><type>4*n</type></entry>
+       </row>
+       <row>
+        <entry><type>Minimum Size for 'n' characters</type></entry>
+        <entry><type>n + 1</type></entry>
+        <entry><type>n + 1</type></entry>
+        <entry><type>2*n</type></entry>
+       </row>
+       <row>
+        <entry><type>Encoding Used</type></entry>
+        <entry><type>client encoding</type></entry>
+        <entry><type>client encoding</type></entry>
+        <entry><type>UTF-16</type></entry>
+       </row>
+       <row>
+        <entry><type>Zero Terminated</type></entry>
+        <entry><type>Yes</type></entry>
+        <entry><type>Yes</type></entry>
+        <entry><type>No</type></entry>
+       </row>
+
+      </tbody>
+     </tgroup>
+    </table>
+
+	<para>
+     Please note that the data conversion from UTF-8 encoding to UTF-16 encoding will incur a negligible performance overhead in case of UVARCHAR Type.
+    </para>
+   </sect3>
+
    <sect3 id="ecpg-special-types">
     <title>Accessing Special Data Types</title>
 
     <para>
      ECPG contains some special types that help you to interact easily
diff -U 5 -N -r -w ../orig.HEAD/doc/src/sgml/syntax.sgml ./doc/src/sgml/syntax.sgml
--- ../orig.HEAD/doc/src/sgml/syntax.sgml	2013-08-19 20:22:06.000000000 -0400
+++ ./doc/src/sgml/syntax.sgml	2013-08-19 20:54:00.000000000 -0400
@@ -551,10 +551,37 @@
      To include the escape character in the string literally, write it
      twice.
     </para>
    </sect3>
 
+   <sect3 id="sql-syntax-strings-N">
+    <title>String Constants with prefix N</title>
+
+    <indexterm  zone="sql-syntax-strings-N">
+     <primary>Prefix N</primary>
+     <secondary>in string constants</secondary>
+    </indexterm>
+
+    <para>
+    The standard syntax for specifying national character type string constants 
+    is to add a prefix 'N' to the string constant. This string constant syntax
+    is supported only when the database encoding is UTF-8.
+    
+    The following trivial example shows how to pass a national character type 
+    string constant with prefix 'N'
+    
+        <programlisting>
+			INSERT INTO test VALUES (N'ok');
+		</programlisting>
+    
+    </para>
+    <para>
+    Please note that this syntax is optional and national character type string constants can also be specified bounded by single quotes (<literal>'</literal>), for example
+     <literal>'ok'</literal>.
+    </para>
+   </sect3>
+
    <sect3 id="sql-syntax-dollar-quoting">
     <title>Dollar-quoted String Constants</title>
 
      <indexterm>
       <primary>dollar quoting</primary>
diff -U 5 -N -r -w ../orig.HEAD/src/backend/catalog/information_schema.sql ./src/backend/catalog/information_schema.sql
--- ../orig.HEAD/src/backend/catalog/information_schema.sql	2013-08-19 20:22:07.000000000 -0400
+++ ./src/backend/catalog/information_schema.sql	2013-08-19 20:54:00.000000000 -0400
@@ -77,11 +77,11 @@
     RETURNS NULL ON NULL INPUT
     AS
 $$SELECT
   CASE WHEN $2 = -1 /* default typmod */
        THEN null
-       WHEN $1 IN (1042, 1043) /* char, varchar */
+       WHEN $1 IN (1042, 1043, 5001, 6001) /* char, varchar, nchar, nvarchar */
        THEN $2 - 4
        WHEN $1 IN (1560, 1562) /* bit, varbit */
        THEN $2
        ELSE null
   END$$;
@@ -90,11 +90,11 @@
     LANGUAGE sql
     IMMUTABLE
     RETURNS NULL ON NULL INPUT
     AS
 $$SELECT
-  CASE WHEN $1 IN (25, 1042, 1043) /* text, char, varchar */
+  CASE WHEN $1 IN (25, 1042, 1043, 5001, 6001) /* text, char, varchar, nchar, nvarchar */
        THEN CASE WHEN $2 = -1 /* default typmod */
                  THEN CAST(2^30 AS integer)
                  ELSE information_schema._pg_char_max_length($1, $2) *
                       pg_catalog.pg_encoding_max_length((SELECT encoding FROM pg_catalog.pg_database WHERE datname = pg_catalog.current_database()))
             END
diff -U 5 -N -r -w ../orig.HEAD/src/backend/parser/gram.y ./src/backend/parser/gram.y
--- ../orig.HEAD/src/backend/parser/gram.y	2013-08-19 20:22:08.000000000 -0400
+++ ./src/backend/parser/gram.y	2013-08-19 21:42:23.000000000 -0400
@@ -439,13 +439,15 @@
 
 %type <typnam>	Typename SimpleTypename ConstTypename
 				GenericType Numeric opt_float
 				Character ConstCharacter
 				CharacterWithLength CharacterWithoutLength
+				NCharacterWithLength NCharacterWithoutLength
 				ConstDatetime ConstInterval
 				Bit ConstBit BitWithLength BitWithoutLength
 %type <str>		character
+%type <str>             ncharacter
 %type <str>		extract_arg
 %type <str>		opt_charset
 %type <boolean> opt_varying opt_timezone opt_no_inherit
 
 %type <ival>	Iconst SignedIconst
@@ -562,10 +564,11 @@
 	MAPPING MATCH MATERIALIZED MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE
 
 	NAME_P NAMES NATIONAL NATURAL NCHAR NEXT NO NONE
 	NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF
 	NULLS_P NUMERIC
+	NVARCHAR
 
 	OBJECT_P OF OFF OFFSET OIDS ON ONLY OPERATOR OPTION OPTIONS OR
 	ORDER ORDINALITY OUT_P OUTER_P OVER OVERLAPS OVERLAY OWNED OWNER
 
 	PARSER PARTIAL PARTITION PASSING PASSWORD PLACING PLANS POSITION
@@ -10277,13 +10280,22 @@
 				}
 			| CharacterWithoutLength
 				{
 					$$ = $1;
 				}
+			| NCharacterWithLength
+				{
+					$$ = $1;
+				}
+			| NCharacterWithoutLength
+				{
+					$$ = $1;
+				}
 		;
 
-ConstCharacter:  CharacterWithLength
+ConstCharacter:
+			CharacterWithLength
 				{
 					$$ = $1;
 				}
 			| CharacterWithoutLength
 				{
@@ -10294,13 +10306,79 @@
 					 * was not specified.
 					 */
 					$$ = $1;
 					$$->typmods = NIL;
 				}
+			| NCharacterWithLength
+				{
+					$$ = $1;
+				}
+			| NCharacterWithoutLength
+				{
+					/* Length was not specified so allow to be unrestricted.
+					* This handles problems with fixed-length (bpchar) strings
+					* which in column definitions must default to a length
+					* of one, but should not be constrained if the length
+					* was not specified.
+					*/
+					$$ = $1;
+					$$->typmods = NIL;
+				}
 		;
 
-CharacterWithLength:  character '(' Iconst ')' opt_charset
+NCharacterWithLength:
+			NATIONAL ncharacter '(' Iconst ')' opt_charset
+				{
+					if (($6 != NULL) && (strcmp($6, "sql_text") != 0))
+				{
+						char *type;
+
+						type = palloc(strlen($2) + 1 + strlen($2) + 1);
+						strcpy(type, $2);
+						strcat(type, "_");
+						strcat(type, $6);
+						$1 = type;
+					}
+					$$ = SystemTypeName($2);
+					$$->typmods = list_make1(makeIntConst($4, @4));
+					$$->location = @1;
+				}
+		;
+
+NCharacterWithoutLength:
+			NATIONAL ncharacter opt_charset
+				{
+					if (($3 != NULL) && (strcmp($3, "sql_text") != 0))
+					{
+						char *type;
+
+						type = palloc(strlen($2) + 1 + strlen($3) + 1);
+						strcpy(type, $2);
+						strcat(type, "_");
+						strcat(type, $3);
+						$2 = type;
+					}
+					$$ = SystemTypeName($2);
+					/* nchar defaults to char(1), varchar to no limit */
+					if (strcmp($2, "nbpchar") == 0)
+						$$->typmods = list_make1(makeIntConst(1, -1));
+
+					$$->location = @1;
+				}
+		;
+
+ncharacter:
+			CHARACTER opt_varying
+				{ $$ = $2 ? "nvarchar": "nbpchar"; }
+			| CHAR_P opt_varying
+				{ $$ = $2 ? "nvarchar": "nbpchar"; }
+			| VARCHAR
+				{ $$ = "nvarchar"; }
+		;
+
+CharacterWithLength:
+			  character '(' Iconst ')' opt_charset
 				{
 					if (($5 != NULL) && (strcmp($5, "sql_text") != 0))
 					{
 						char *type;
 
@@ -10315,11 +10393,12 @@
 					$$->typmods = list_make1(makeIntConst($3, @3));
 					$$->location = @1;
 				}
 		;
 
-CharacterWithoutLength:	 character opt_charset
+CharacterWithoutLength:
+			 character opt_charset
 				{
 					if (($2 != NULL) && (strcmp($2, "sql_text") != 0))
 					{
 						char *type;
 
@@ -10330,30 +10409,29 @@
 						$1 = type;
 					}
 
 					$$ = SystemTypeName($1);
 
-					/* char defaults to char(1), varchar to no limit */
-					if (strcmp($1, "bpchar") == 0)
+					/* [n]char defaults to [national ]char(1), varchar to no limit */
+					if ((strcmp($1, "bpchar") == 0) || (strcmp($1, "nbpchar") == 0))
 						$$->typmods = list_make1(makeIntConst(1, -1));
 
 					$$->location = @1;
 				}
 		;
 
-character:	CHARACTER opt_varying
+character:
+			CHARACTER opt_varying
 										{ $$ = $2 ? "varchar": "bpchar"; }
 			| CHAR_P opt_varying
 										{ $$ = $2 ? "varchar": "bpchar"; }
 			| VARCHAR
 										{ $$ = "varchar"; }
-			| NATIONAL CHARACTER opt_varying
-										{ $$ = $3 ? "varchar": "bpchar"; }
-			| NATIONAL CHAR_P opt_varying
-										{ $$ = $3 ? "varchar": "bpchar"; }
 			| NCHAR opt_varying
-										{ $$ = $2 ? "varchar": "bpchar"; }
+				{ $$ = $2 ? "nvarchar": "nbpchar"; }
+			| NVARCHAR
+				{ $$ = "nvarchar"; }
 		;
 
 opt_varying:
 			VARYING									{ $$ = TRUE; }
 			| /*EMPTY*/								{ $$ = FALSE; }
@@ -12739,10 +12817,11 @@
 			| NATIONAL
 			| NCHAR
 			| NONE
 			| NULLIF
 			| NUMERIC
+			| NVARCHAR
 			| OUT_P
 			| OVERLAY
 			| POSITION
 			| PRECISION
 			| REAL
diff -U 5 -N -r -w ../orig.HEAD/src/backend/parser/scan.l ./src/backend/parser/scan.l
--- ../orig.HEAD/src/backend/parser/scan.l	2013-08-19 20:22:08.000000000 -0400
+++ ./src/backend/parser/scan.l	2013-08-19 22:27:02.000000000 -0400
@@ -480,11 +480,11 @@
 					const ScanKeyword *keyword;
 
 					SET_YYLLOC();
 					yyless(1);				/* eat only 'n' this time */
 
-					keyword = ScanKeywordLookup("nchar",
+					keyword = ScanKeywordLookup("nvarchar",
 												yyextra->keywords,
 												yyextra->num_keywords);
 					if (keyword != NULL)
 					{
 						yylval->keyword = keyword->name;
diff -U 5 -N -r -w ../orig.HEAD/src/backend/utils/adt/format_type.c ./src/backend/utils/adt/format_type.c
--- ../orig.HEAD/src/backend/utils/adt/format_type.c	2013-08-19 20:22:09.000000000 -0400
+++ ./src/backend/utils/adt/format_type.c	2013-08-19 20:54:00.000000000 -0400
@@ -216,10 +216,25 @@
 			}
 			else
 				buf = pstrdup("character");
 			break;
 
+		case NBPCHAROID:
+			if (with_typemod)
+				buf = printTypmod("national character", typemod, typeform->typmodout);
+			else if (typemod_given)
+			{
+				/*
+				 * bpchar with typmod -1 is not the same as CHARACTER, which
+				 * means CHARACTER(1) per SQL spec.  Report it as bpchar so
+				 * that parser will not assign a bogus typmod.
+				 */
+			}
+			else
+				buf = pstrdup("national character");
+			break;
+
 		case FLOAT4OID:
 			buf = pstrdup("real");
 			break;
 
 		case FLOAT8OID:
@@ -291,10 +306,17 @@
 			if (with_typemod)
 				buf = printTypmod("character varying", typemod, typeform->typmodout);
 			else
 				buf = pstrdup("character varying");
 			break;
+
+		case NVARCHAROID:
+			if (with_typemod)
+				buf = printTypmod("national character varying", typemod, typeform->typmodout);
+			else
+				buf = pstrdup("national character varying");
+			break;
 	}
 
 	if (buf == NULL)
 	{
 		/*
@@ -381,11 +403,13 @@
 		return -1;
 
 	switch (type_oid)
 	{
 		case BPCHAROID:
+		case NBPCHAROID:
 		case VARCHAROID:
+		case NVARCHAROID:
 			/* typemod includes varlena header */
 
 			/* typemod is in characters not bytes */
 			return (typemod - VARHDRSZ) *
 				pg_encoding_max_length(GetDatabaseEncoding())
diff -U 5 -N -r -w ../orig.HEAD/src/backend/utils/adt/Makefile ./src/backend/utils/adt/Makefile
--- ../orig.HEAD/src/backend/utils/adt/Makefile	2013-08-19 20:22:09.000000000 -0400
+++ ./src/backend/utils/adt/Makefile	2013-08-20 04:53:45.000000000 -0400
@@ -18,11 +18,11 @@
 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 jsonfuncs.o like.o \
-	lockfuncs.o misc.o nabstime.o name.o numeric.o numutils.o \
+	lockfuncs.o misc.o nabstime.o name.o numeric.o numutils.o nvarchar.o \
 	oid.o oracle_compat.o pseudotypes.o rangetypes.o rangetypes_gist.o \
 	rowtypes.o regexp.o regproc.o ruleutils.o selfuncs.o \
 	tid.o timestamp.o varbit.o varchar.o varlena.o version.o xid.o \
 	network.o mac.o inet_cidr_ntop.o inet_net_pton.o \
 	ri_triggers.o pg_lzcompress.o pg_locale.o formatting.o \
diff -U 5 -N -r -w ../orig.HEAD/src/backend/utils/adt/nvarchar.c ./src/backend/utils/adt/nvarchar.c
--- ../orig.HEAD/src/backend/utils/adt/nvarchar.c	1969-12-31 19:00:00.000000000 -0500
+++ ./src/backend/utils/adt/nvarchar.c	2013-08-20 04:54:06.000000000 -0400
@@ -0,0 +1,421 @@
+/*-------------------------------------------------------------------------
+ *
+ * nvarchar.c
+ *	  Functions for the built-in types nchar(n) and nvarchar(n).
+ *
+ * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *	  src/backend/utils/adt/nvarchar.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+
+#include "access/hash.h"
+#include "access/tuptoaster.h"
+#include "libpq/pqformat.h"
+#include "nodes/nodeFuncs.h"
+#include "utils/array.h"
+#include "utils/builtins.h"
+#include "mb/pg_wchar.h"
+#include "utils/formatting.h"
+#include "catalog/namespace.h"
+#include "catalog/pg_collation.h"
+
+/*
+ *		====================
+ *		FORWARD DECLARATIONS
+ *		====================
+ */
+static int32 ntextcmp(text *left, text *right, Oid collid);
+
+// being really dumb for ntext collation initially 
+static const char *ntext_collation = "C.UTF-8";
+
+/*
+ *      ===================
+ *      TYPE CAST FUNCTIONS
+ *      ===================
+ */
+
+/*
+ * convert text to ntext (the database encoding to UTF8)
+ */
+Datum
+text2nvarchar(PG_FUNCTION_ARGS)
+{
+    text       *in_val = PG_GETARG_TEXT_PP(0);
+    char       *in_string;
+    text       *out_val;
+
+    in_string = text_to_cstring(in_val);
+    out_val = cstring_to_text(pg_server_to_any(in_string, strlen(in_string), PG_UTF8));
+
+    PG_RETURN_TEXT_P(out_val);
+}
+
+/*
+ * convert ntext to text (UTF8 to the database encoding)
+ */
+Datum
+nvarchar2text(PG_FUNCTION_ARGS)
+{
+    text       *in_val = PG_GETARG_TEXT_PP(0);
+    char       *in_string;
+    text       *out_val;
+
+    in_string = text_to_cstring(in_val);
+    out_val = cstring_to_text(pg_any_to_server(in_string, strlen(in_string), PG_UTF8));
+
+    PG_RETURN_TEXT_P(out_val);
+}
+
+/*
+ * convert rtrimmed text to ntext (the database encoding to UTF8)
+ * used for conversion from char type to nvarchar type
+ */
+Datum
+rtrimtext2nvarchar(PG_FUNCTION_ARGS)
+{
+    text       *in_val = PG_GETARG_TEXT_PP(0);
+    char       *in_string;
+    text       *out_val;
+    text       *trimmed_val;
+
+	trimmed_val = dotrim(VARDATA_ANY(in_val), VARSIZE_ANY_EXHDR(in_val),
+				" ", 1,
+				false, true);
+    in_string = text_to_cstring(trimmed_val);
+    out_val = cstring_to_text(pg_server_to_any(in_string, strlen(in_string), PG_UTF8));
+
+    PG_RETURN_TEXT_P(out_val);
+}
+
+/*
+ * convert ntext to rtrimmed text (UTF8 to the database encoding)
+ * used for conversion from nchar types to varchar/text types
+ */
+Datum
+nvarchar2rtrimtext(PG_FUNCTION_ARGS)
+{
+    text       *in_val = PG_GETARG_TEXT_PP(0);
+    char       *in_string;
+    text       *out_val;
+	text       *trimmed_val;
+
+    in_string = text_to_cstring(in_val);
+    out_val = cstring_to_text(pg_any_to_server(in_string, strlen(in_string), PG_UTF8));
+    trimmed_val = dotrim(VARDATA_ANY(out_val), VARSIZE_ANY_EXHDR(out_val),
+                " ", 1,
+                false, true);
+    PG_RETURN_TEXT_P(trimmed_val);
+}
+
+
+
+/*
+ *		=================
+ *		UTILITY FUNCTIONS
+ *		=================
+ */
+
+/*
+ *      ntextin          - converts "..." (assume that "..." using db encoding we need decode it to UTF8) to internal representation
+ */
+
+Datum
+ntextin(PG_FUNCTION_ARGS)
+{
+    char       *in_val = PG_GETARG_CSTRING(0);
+
+    PG_RETURN_TEXT_P(cstring_to_text(pg_server_to_any(in_val, strlen(in_val), PG_UTF8)));
+}
+
+/*
+ *      ntextout         - converts internal representation to "..." (assume that "..." using db encoding we need decode it from UTF8)
+ */
+
+Datum
+ntextout(PG_FUNCTION_ARGS)
+{
+    text       *in_val = PG_GETARG_TEXT_PP(0);
+    char       *in_string;
+
+    in_string = text_to_cstring(in_val);
+    PG_RETURN_CSTRING(pg_any_to_server(in_string, strlen(in_string), PG_UTF8));
+}
+
+
+/*
+ * Convert a C string to VARCHAR internal representation.  atttypmod
+ * is the declared length of the type plus VARHDRSZ.
+ */
+Datum
+nvarcharin(PG_FUNCTION_ARGS)
+{
+    char       *s = PG_GETARG_CSTRING(0);
+#ifdef NOT_USED
+    Oid         typelem = PG_GETARG_OID(1);
+#endif
+    int32       atttypmod = PG_GETARG_INT32(2);
+    VarChar    *result;
+
+//    result = varchar_input(s, strlen(s), atttypmod);
+//    PG_RETURN_VARCHAR_P(result);
+	PG_RETURN_VARCHAR_P(cstring_to_text(pg_server_to_any(s, strlen(s), PG_UTF8)));
+}
+
+
+/*
+ * Convert a VARCHAR value to a C string.
+ *
+ * Uses the text to C string conversion function, which is only appropriate
+ * if VarChar and text are equivalent types.
+ */
+Datum
+nvarcharout(PG_FUNCTION_ARGS)
+{
+    Datum       txt = PG_GETARG_DATUM(0);
+    char        *in_string;
+
+    in_string = text_to_cstring(txt);
+    PG_RETURN_CSTRING(pg_any_to_server(in_string, strlen(txt), PG_UTF8));
+}
+
+
+Datum
+ntextlower(PG_FUNCTION_ARGS)
+{
+    text       *in_string = PG_GETARG_TEXT_PP(0);
+    char       *out_string;
+    text       *result;
+
+    out_string = str_tolower(VARDATA_ANY(in_string),
+                             VARSIZE_ANY_EXHDR(in_string),
+                             CollationGetCollid(ntext_collation));
+    result = cstring_to_text(out_string);
+    pfree(out_string);
+
+    PG_RETURN_TEXT_P(result);
+}
+
+Datum
+ntextupper(PG_FUNCTION_ARGS)
+{
+    text       *in_string = PG_GETARG_TEXT_PP(0);
+    char       *out_string;
+    text       *result;
+
+    out_string = str_toupper(VARDATA_ANY(in_string),
+                             VARSIZE_ANY_EXHDR(in_string),
+                             CollationGetCollid(ntext_collation));
+    result = cstring_to_text(out_string);
+    pfree(out_string);
+
+    PG_RETURN_TEXT_P(result);
+}
+
+
+/*
+ * actual octet length of an utf8 text 
+ */
+Datum
+ntextoctetlen(PG_FUNCTION_ARGS)
+{
+//        Datum           arg = PG_GETARG_DATUM(0);
+//        /* We need not detoast the input at all */
+//        PG_RETURN_INT32(toast_raw_datum_size(arg) - VARHDRSZ);
+	text       *in_val = PG_GETARG_TEXT_PP(0);
+	char       *in_string;
+	int		   len;
+
+	in_string = text_to_cstring(in_val);
+	len = strlen(in_string);
+
+	PG_RETURN_INT32(len);
+}
+
+/*
+ * ntextcmp()
+ * Internal comparison function for ntext strings.
+ * Returns int32 negative, zero, or positive.
+ */
+static int32
+ntextcmp(text *left, text *right, Oid collid)
+{
+	return varstr_cmp(VARDATA_ANY(left), VARSIZE_ANY_EXHDR(left),
+						VARDATA_ANY(right), VARSIZE_ANY_EXHDR(right),
+						collid);
+}
+
+/*
+ *		==================
+ *		INDEXING FUNCTIONS
+ *		==================
+ */
+Datum
+ntext_cmp(PG_FUNCTION_ARGS)
+{
+	text	   *left = PG_GETARG_TEXT_PP(0);
+	text	   *right = PG_GETARG_TEXT_PP(1);
+	int32		result;
+
+	result = ntextcmp(left, right, CollationGetCollid(ntext_collation));
+
+	PG_FREE_IF_COPY(left, 0);
+	PG_FREE_IF_COPY(right, 1);
+
+	PG_RETURN_INT32(result);
+}
+
+PG_FUNCTION_INFO_V1(ntext_hash);
+
+Datum
+ntext_hash(PG_FUNCTION_ARGS)
+{
+	text	    *txt = PG_GETARG_TEXT_PP(0);
+	Datum		result;
+
+	result = hash_any((unsigned char *) VARDATA_ANY(txt), VARSIZE_ANY_EXHDR(txt));
+
+	/* Avoid leaking memory for toasted inputs */
+	PG_FREE_IF_COPY(txt, 0);
+
+	PG_RETURN_DATUM(result);
+}
+
+/*
+ *		==================
+ *		OPERATOR FUNCTIONS
+ *		==================
+ */
+Datum
+ntext_eq(PG_FUNCTION_ARGS)
+{
+	text	   *left = PG_GETARG_TEXT_PP(0);
+	text	   *right = PG_GETARG_TEXT_PP(1);
+	bool		result;
+
+	/*
+	 * Since we only care about equality or not-equality, we can avoid all the
+	 * expense of strcoll() here, and just do bitwise comparison.
+	 */
+	result = (strcmp(text_to_cstring(left), text_to_cstring(right)) == 0);
+
+	PG_FREE_IF_COPY(left, 0);
+	PG_FREE_IF_COPY(right, 1);
+
+	PG_RETURN_BOOL(result);
+}
+
+Datum
+ntext_ne(PG_FUNCTION_ARGS)
+{
+	text	   *left = PG_GETARG_TEXT_PP(0);
+	text	   *right = PG_GETARG_TEXT_PP(1);
+	bool		result;
+
+	/*
+	 * Since we only care about equality or not-equality, we can avoid all the
+	 * expense of strcoll() here, and just do bitwise comparison.
+	 */
+	result = (strcmp(text_to_cstring(left), text_to_cstring(right)) != 0);
+
+	PG_FREE_IF_COPY(left, 0);
+	PG_FREE_IF_COPY(right, 1);
+
+	PG_RETURN_BOOL(result);
+}
+
+Datum
+ntext_lt(PG_FUNCTION_ARGS)
+{
+	text	   *left = PG_GETARG_TEXT_PP(0);
+	text	   *right = PG_GETARG_TEXT_PP(1);
+	bool		result;
+
+	result = ntextcmp(left, right, CollationGetCollid(ntext_collation)) < 0;
+
+	PG_FREE_IF_COPY(left, 0);
+	PG_FREE_IF_COPY(right, 1);
+
+	PG_RETURN_BOOL(result);
+}
+
+Datum
+ntext_le(PG_FUNCTION_ARGS)
+{
+	text	   *left = PG_GETARG_TEXT_PP(0);
+	text	   *right = PG_GETARG_TEXT_PP(1);
+	bool		result;
+
+	result = ntextcmp(left, right, CollationGetCollid(ntext_collation)) <= 0;
+
+	PG_FREE_IF_COPY(left, 0);
+	PG_FREE_IF_COPY(right, 1);
+
+	PG_RETURN_BOOL(result);
+}
+
+Datum
+ntext_gt(PG_FUNCTION_ARGS)
+{
+	text	   *left = PG_GETARG_TEXT_PP(0);
+	text	   *right = PG_GETARG_TEXT_PP(1);
+	bool		result;
+
+	result = ntextcmp(left, right, CollationGetCollid(ntext_collation)) > 0;
+
+	PG_FREE_IF_COPY(left, 0);
+	PG_FREE_IF_COPY(right, 1);
+
+	PG_RETURN_BOOL(result);
+}
+
+Datum
+ntext_ge(PG_FUNCTION_ARGS)
+{
+	text	   *left = PG_GETARG_TEXT_PP(0);
+	text	   *right = PG_GETARG_TEXT_PP(1);
+	bool		result;
+
+	result = ntextcmp(left, right, CollationGetCollid(ntext_collation)) >= 0;
+
+	PG_FREE_IF_COPY(left, 0);
+	PG_FREE_IF_COPY(right, 1);
+
+	PG_RETURN_BOOL(result);
+}
+
+/*
+ *		===================
+ *		AGGREGATE FUNCTIONS
+ *		===================
+ */
+Datum
+ntext_smaller(PG_FUNCTION_ARGS)
+{
+	text	   *left = PG_GETARG_TEXT_PP(0);
+	text	   *right = PG_GETARG_TEXT_PP(1);
+	text	   *result;
+
+	result = ntextcmp(left, right, CollationGetCollid(ntext_collation)) < 0 ? left : right;
+	PG_RETURN_TEXT_P(result);
+}
+
+Datum
+ntext_larger(PG_FUNCTION_ARGS)
+{
+	text	   *left = PG_GETARG_TEXT_PP(0);
+	text	   *right = PG_GETARG_TEXT_PP(1);
+	text	   *result;
+
+	result = ntextcmp(left, right, CollationGetCollid(ntext_collation)) > 0 ? left : right;
+	PG_RETURN_TEXT_P(result);
+}
+
+
diff -U 5 -N -r -w ../orig.HEAD/src/backend/utils/adt/oracle_compat.c ./src/backend/utils/adt/oracle_compat.c
--- ../orig.HEAD/src/backend/utils/adt/oracle_compat.c	2013-08-19 20:22:09.000000000 -0400
+++ ./src/backend/utils/adt/oracle_compat.c	2013-08-19 20:54:00.000000000 -0400
@@ -18,15 +18,10 @@
 #include "utils/builtins.h"
 #include "utils/formatting.h"
 #include "mb/pg_wchar.h"
 
 
-static text *dotrim(const char *string, int stringlen,
-	   const char *set, int setlen,
-	   bool doltrim, bool dortrim);
-
-
 /********************************************************************
  *
  * lower
  *
  * Syntax:
@@ -365,11 +360,11 @@
 }
 
 /*
  * Common implementation for btrim, ltrim, rtrim
  */
-static text *
+text *
 dotrim(const char *string, int stringlen,
 	   const char *set, int setlen,
 	   bool doltrim, bool dortrim)
 {
 	int			i;
diff -U 5 -N -r -w ../orig.HEAD/src/backend/utils/adt/selfuncs.c ./src/backend/utils/adt/selfuncs.c
--- ../orig.HEAD/src/backend/utils/adt/selfuncs.c	2013-08-19 20:22:09.000000000 -0400
+++ ./src/backend/utils/adt/selfuncs.c	2013-08-19 20:54:00.000000000 -0400
@@ -3624,11 +3624,13 @@
 			/*
 			 * Built-in string types
 			 */
 		case CHAROID:
 		case BPCHAROID:
+		case NBPCHAROID:
 		case VARCHAROID:
+		case NVARCHAROID:
 		case TEXTOID:
 		case NAMEOID:
 			{
 				char	   *valstr = convert_string_datum(value, valuetypid);
 				char	   *lostr = convert_string_datum(lobound, boundstypid);
@@ -3886,11 +3888,13 @@
 			val = (char *) palloc(2);
 			val[0] = DatumGetChar(value);
 			val[1] = '\0';
 			break;
 		case BPCHAROID:
+		case NBPCHAROID:
 		case VARCHAROID:
+		case NVARCHAROID:
 		case TEXTOID:
 			val = TextDatumGetCString(value);
 			break;
 		case NAMEOID:
 			{
@@ -5873,11 +5877,13 @@
 	 */
 	switch (datatype)
 	{
 		case TEXTOID:
 		case VARCHAROID:
+		case NVARCHAROID:
 		case BPCHAROID:
+		case NBPCHAROID:
 			collation = DEFAULT_COLLATION_OID;
 			constlen = -1;
 			break;
 
 		case NAMEOID:
diff -U 5 -N -r -w ../orig.HEAD/src/include/catalog/pg_amop.h ./src/include/catalog/pg_amop.h
--- ../orig.HEAD/src/include/catalog/pg_amop.h	2013-08-19 20:22:12.000000000 -0400
+++ ./src/include/catalog/pg_amop.h	2013-08-19 20:54:00.000000000 -0400
@@ -251,10 +251,17 @@
 DATA(insert (	426   1042 1042 2 s 1059	403 0 ));
 DATA(insert (	426   1042 1042 3 s 1054	403 0 ));
 DATA(insert (	426   1042 1042 4 s 1061	403 0 ));
 DATA(insert (	426   1042 1042 5 s 1060	403 0 ));
 
+DATA(insert (   426   5001 5001 1 s 5058        403 0 ));
+DATA(insert (   426   5001 5001 2 s 5059        403 0 ));
+DATA(insert (   426   5001 5001 3 s 5054        403 0 ));
+DATA(insert (   426   5001 5001 4 s 5061        403 0 ));
+DATA(insert (   426   5001 5001 5 s 5060        403 0 ));
+
+
 /*
  *	btree bytea_ops
  */
 
 DATA(insert (	428   17 17 1 s 1957	403 0 ));
@@ -506,10 +513,14 @@
  *	hash index _ops
  */
 
 /* bpchar_ops */
 DATA(insert (	427   1042 1042 1 s 1054	405 0 ));
+
+/* nbpchar_ops */
+DATA(insert (   427   5001 5001 1 s 5054        405 0 ));
+
 /* char_ops */
 DATA(insert (	431   18 18 1 s 92	405 0 ));
 /* date_ops */
 DATA(insert (	435   1082 1082 1 s 1093	405 0 ));
 /* float_ops */
diff -U 5 -N -r -w ../orig.HEAD/src/include/catalog/pg_amproc.h ./src/include/catalog/pg_amproc.h
--- ../orig.HEAD/src/include/catalog/pg_amproc.h	2013-08-19 20:22:12.000000000 -0400
+++ ./src/include/catalog/pg_amproc.h	2013-08-19 20:54:00.000000000 -0400
@@ -78,10 +78,11 @@
 DATA(insert (	397   2277 2277 1 382 ));
 DATA(insert (	421   702 702 1 357 ));
 DATA(insert (	423   1560 1560 1 1596 ));
 DATA(insert (	424   16 16 1 1693 ));
 DATA(insert (	426   1042 1042 1 1078 ));
+DATA(insert (   426   5001 5001 1 1078 ));
 DATA(insert (	428   17 17 1 1954 ));
 DATA(insert (	429   18 18 1 358 ));
 DATA(insert (	434   1082 1082 1 1092 ));
 DATA(insert (	434   1082 1082 2 3136 ));
 DATA(insert (	434   1082 1114 1 2344 ));
@@ -126,20 +127,22 @@
 DATA(insert (	1996   1083 1083 1 1107 ));
 DATA(insert (	2000   1266 1266 1 1358 ));
 DATA(insert (	2002   1562 1562 1 1672 ));
 DATA(insert (	2095   25 25 1 2166 ));
 DATA(insert (	2097   1042 1042 1 2180 ));
+DATA(insert (   2097   5001 5001 1 2180 ));
 DATA(insert (	2099   790 790 1  377 ));
 DATA(insert (	2233   703 703 1  380 ));
 DATA(insert (	2234   704 704 1  381 ));
 DATA(insert (	2789   27 27 1 2794 ));
 DATA(insert (	2968   2950 2950 1 2960 ));
 DATA(insert (	3522   3500 3500 1 3514 ));
 
 
 /* hash */
 DATA(insert (	427   1042 1042 1 1080 ));
+DATA(insert (   427   5001 5001 1 1080 ));
 DATA(insert (	431   18 18 1 454 ));
 DATA(insert (	435   1082 1082 1 450 ));
 DATA(insert (	627   2277 2277 1 626 ));
 DATA(insert (	1971   700 700 1 451 ));
 DATA(insert (	1971   701 701 1 452 ));
@@ -165,10 +168,11 @@
 DATA(insert (	2226   29 29 1 450 ));
 DATA(insert (	2227   702 702 1 450 ));
 DATA(insert (	2228   703 703 1 450 ));
 DATA(insert (	2229   25 25 1 400 ));
 DATA(insert (	2231   1042 1042 1 1080 ));
+DATA(insert (   2231   5001 5001 1 1080 ));
 DATA(insert (	2235   1033 1033 1 329 ));
 DATA(insert (	2969   2950 2950 1 2963 ));
 DATA(insert (	3523   3500 3500 1 3515 ));
 
 
diff -U 5 -N -r -w ../orig.HEAD/src/include/catalog/pg_cast.h ./src/include/catalog/pg_cast.h
--- ../orig.HEAD/src/include/catalog/pg_cast.h	2013-08-19 20:22:12.000000000 -0400
+++ ./src/include/catalog/pg_cast.h	2013-08-19 20:54:00.000000000 -0400
@@ -212,16 +212,77 @@
 DATA(insert ( 1043 2205 1079 i f ));
 
 /*
  * String category
  */
-DATA(insert (	25 1042    0 i b ));
-DATA(insert (	25 1043    0 i b ));
+/*
+ * 501  UTF8 conversion to database encoding
+ * 502  database encoding to UTF8
+ * 401  rtrim
+ * 503  conversion from UTF8 + rtrim 
+ * 504  rtrim + conversion to UTF8
+ * national -> common is always 'a' = assigment autocasts (and they could fail if encoding error happen)
+ * common -> nactional is always 'i' = implicit (because they should work always)
+ * temporary assume rtrim not depend on actual encoding (which is definitely wrong assumption)
+*/
+
+/*
+ * char -> text
+ * char -> varchar
+ * char -> nchar
+ * char -> nvarchar
+*/
 DATA(insert ( 1042	 25  401 i f ));
 DATA(insert ( 1042 1043  401 i f ));
+DATA(insert ( 1042 5001  502 i f ));
+DATA(insert ( 1042 6001  504 i f ));
+
+/*
+ * varchar -> text
+ * varchar -> char
+ * varchar -> nvarchar
+ * varchar -> nchar
+*/
 DATA(insert ( 1043	 25    0 i b ));
 DATA(insert ( 1043 1042    0 i b ));
+DATA(insert ( 1043 6001 502 i f ));
+DATA(insert ( 1043 5001 502 i f ));
+
+/*
+ * text -> varchar
+ * text -> char
+ * text -> nchar
+ * text -> nvarchar
+*/
+DATA(insert (   25 1043   0 i b ));
+DATA(insert (   25 1042   0 i b ));
+DATA(insert (   25 5001 502 i f ));
+DATA(insert (   25 6001 502 i f ));
+
+/*
+ * nvarchar -> text
+ * nvarchar -> varchar
+ * nvarchar -> char
+ * nvarchar -> nchar
+*/
+DATA(insert ( 6001   25  501 a f ));
+DATA(insert ( 6001 1043  501 a f ));
+DATA(insert ( 6001 1042  501 a f ));
+DATA(insert ( 6001 5001  0   i f ));
+
+/*
+ * nchar -> text
+ * nchar -> varchar
+ * nchar -> char
+ * nchar -> nvarchar
+*/
+DATA(insert ( 5001   25  503 a f ));
+DATA(insert ( 5001 1042  503 a f ));
+DATA(insert ( 5001 1043  501 a f ));
+DATA(insert ( 5001 6001  401 i f ));
+
+
 DATA(insert (	18	 25  946 i f ));
 DATA(insert (	18 1042  860 a f ));
 DATA(insert (	18 1043  946 a f ));
 DATA(insert (	19	 25  406 i f ));
 DATA(insert (	19 1042  408 a f ));
@@ -347,11 +408,13 @@
 
 /*
  * Length-coercion functions
  */
 DATA(insert ( 1042 1042  668 i f ));
+DATA(insert ( 5001 5001 5668 i f ));
 DATA(insert ( 1043 1043  669 i f ));
+DATA(insert ( 6001 6001 5669 i f ));
 DATA(insert ( 1083 1083 1968 i f ));
 DATA(insert ( 1114 1114 1961 i f ));
 DATA(insert ( 1184 1184 1967 i f ));
 DATA(insert ( 1186 1186 1200 i f ));
 DATA(insert ( 1266 1266 1969 i f ));
diff -U 5 -N -r -w ../orig.HEAD/src/include/catalog/pg_opclass.h ./src/include/catalog/pg_opclass.h
--- ../orig.HEAD/src/include/catalog/pg_opclass.h	2013-08-19 20:22:12.000000000 -0400
+++ ./src/include/catalog/pg_opclass.h	2013-08-19 20:54:00.000000000 -0400
@@ -95,10 +95,12 @@
 DATA(insert (	405		array_ops			PGNSP PGUID  627 2277 t 0 ));
 DATA(insert (	403		bit_ops				PGNSP PGUID  423 1560 t 0 ));
 DATA(insert (	403		bool_ops			PGNSP PGUID  424   16 t 0 ));
 DATA(insert (	403		bpchar_ops			PGNSP PGUID  426 1042 t 0 ));
 DATA(insert (	405		bpchar_ops			PGNSP PGUID  427 1042 t 0 ));
+DATA(insert (	403				nbpchar_ops						PGNSP PGUID  426 5001 t 0 ));
+DATA(insert (	405				nbpchar_ops						PGNSP PGUID  427 5001 t 0 ));
 DATA(insert (	403		bytea_ops			PGNSP PGUID  428   17 t 0 ));
 DATA(insert (	403		char_ops			PGNSP PGUID  429   18 t 0 ));
 DATA(insert (	405		char_ops			PGNSP PGUID  431   18 t 0 ));
 DATA(insert (	403		cidr_ops			PGNSP PGUID 1974  869 f 0 ));
 DATA(insert (	405		cidr_ops			PGNSP PGUID 1975  869 f 0 ));
@@ -154,10 +156,12 @@
 DATA(insert (	403		timetz_ops			PGNSP PGUID 2000 1266 t 0 ));
 DATA(insert (	405		timetz_ops			PGNSP PGUID 2001 1266 t 0 ));
 DATA(insert (	403		varbit_ops			PGNSP PGUID 2002 1562 t 0 ));
 DATA(insert (	403		varchar_ops			PGNSP PGUID 1994   25 f 0 ));
 DATA(insert (	405		varchar_ops			PGNSP PGUID 1995   25 f 0 ));
+DATA(insert (	403				nvarchar_ops					PGNSP PGUID 1994   25 f 0 ));
+DATA(insert (	405				nvarchar_ops					PGNSP PGUID 1995   25 f 0 ));
 DATA(insert OID = 3128 ( 403	timestamp_ops	PGNSP PGUID  434 1114 t 0 ));
 #define TIMESTAMP_BTREE_OPS_OID 3128
 DATA(insert (	405		timestamp_ops		PGNSP PGUID 2040 1114 t 0 ));
 DATA(insert (	403		text_pattern_ops	PGNSP PGUID 2095   25 f 0 ));
 DATA(insert (	403		varchar_pattern_ops PGNSP PGUID 2095   25 f 0 ));
@@ -185,10 +189,11 @@
 DATA(insert (	2742	_text_ops			PGNSP PGUID 2745  1009 t 25 ));
 DATA(insert (	2742	_abstime_ops		PGNSP PGUID 2745  1023 t 702 ));
 DATA(insert (	2742	_bit_ops			PGNSP PGUID 2745  1561 t 1560 ));
 DATA(insert (	2742	_bool_ops			PGNSP PGUID 2745  1000 t 16 ));
 DATA(insert (	2742	_bpchar_ops			PGNSP PGUID 2745  1014 t 1042 ));
+DATA(insert (	2742	_nbpchar_ops					PGNSP PGUID 2745  5014 t 5001 ));
 DATA(insert (	2742	_bytea_ops			PGNSP PGUID 2745  1001 t 17 ));
 DATA(insert (	2742	_char_ops			PGNSP PGUID 2745  1002 t 18 ));
 DATA(insert (	2742	_cidr_ops			PGNSP PGUID 2745  651 t 650 ));
 DATA(insert (	2742	_date_ops			PGNSP PGUID 2745  1182 t 1082 ));
 DATA(insert (	2742	_float4_ops			PGNSP PGUID 2745  1021 t 700 ));
@@ -205,10 +210,11 @@
 DATA(insert (	2742	_time_ops			PGNSP PGUID 2745  1183 t 1083 ));
 DATA(insert (	2742	_timestamptz_ops	PGNSP PGUID 2745  1185 t 1184 ));
 DATA(insert (	2742	_timetz_ops			PGNSP PGUID 2745  1270 t 1266 ));
 DATA(insert (	2742	_varbit_ops			PGNSP PGUID 2745  1563 t 1562 ));
 DATA(insert (	2742	_varchar_ops		PGNSP PGUID 2745  1015 t 1043 ));
+DATA(insert (	2742	_nvarchar_ops			PGNSP PGUID 2745  5015 t 6001 ));
 DATA(insert (	2742	_timestamp_ops		PGNSP PGUID 2745  1115 t 1114 ));
 DATA(insert (	2742	_money_ops			PGNSP PGUID 2745  791 t 790 ));
 DATA(insert (	2742	_reltime_ops		PGNSP PGUID 2745  1024 t 703 ));
 DATA(insert (	2742	_tinterval_ops		PGNSP PGUID 2745  1025 t 704 ));
 DATA(insert (	403		uuid_ops			PGNSP PGUID 2968  2950 t 0 ));
diff -U 5 -N -r -w ../orig.HEAD/src/include/catalog/pg_operator.h ./src/include/catalog/pg_operator.h
--- ../orig.HEAD/src/include/catalog/pg_operator.h	2013-08-19 20:22:12.000000000 -0400
+++ ./src/include/catalog/pg_operator.h	2013-08-19 20:54:00.000000000 -0400
@@ -741,26 +741,50 @@
 DATA(insert OID =  971 (  "@@"	   PGNSP PGUID l f f	0  604	600    0  0 poly_center - - ));
 DESCR("center of");
 
 DATA(insert OID = 1054 ( "="	   PGNSP PGUID b t t 1042 1042	 16 1054 1057 bpchareq eqsel eqjoinsel ));
 DESCR("equal");
+DATA(insert OID = 5054 ( "="       PGNSP PGUID b t t 5001 5001   16 5054 5057 nbpchareq eqsel eqjoinsel ));
+DESCR("equal");
 
 DATA(insert OID = 1055 ( "~"	   PGNSP PGUID b f f 1042 25	 16    0 1056 bpcharregexeq regexeqsel regexeqjoinsel ));
 DESCR("matches regular expression, case-sensitive");
+DATA(insert OID = 5055 ( "~"       PGNSP PGUID b f f 5001 25     16    0 5056 nbpcharregexeq regexeqsel regexeqjoinsel ));
+DESCR("matches regular expression, case-sensitive");
+
 #define OID_BPCHAR_REGEXEQ_OP		1055
 DATA(insert OID = 1056 ( "!~"	   PGNSP PGUID b f f 1042 25	 16    0 1055 bpcharregexne regexnesel regexnejoinsel ));
 DESCR("does not match regular expression, case-sensitive");
+DATA(insert OID = 5056 ( "!~"      PGNSP PGUID b f f 5001 25     16    0 5055 nbpcharregexne regexnesel regexnejoinsel ));
+DESCR("does not match regular expression, case-sensitive");
+
 DATA(insert OID = 1057 ( "<>"	   PGNSP PGUID b f f 1042 1042	 16 1057 1054 bpcharne neqsel neqjoinsel ));
 DESCR("not equal");
+DATA(insert OID = 5057 ( "<>"      PGNSP PGUID b f f 5001 5001   16 5057 5054 nbpcharne neqsel neqjoinsel ));
+DESCR("not equal");
+
 DATA(insert OID = 1058 ( "<"	   PGNSP PGUID b f f 1042 1042	 16 1060 1061 bpcharlt scalarltsel scalarltjoinsel ));
 DESCR("less than");
+DATA(insert OID = 5058 ( "<"       PGNSP PGUID b f f 5001 5001   16 5060 5061 nbpcharlt scalarltsel scalarltjoinsel ));
+DESCR("less than");
+
 DATA(insert OID = 1059 ( "<="	   PGNSP PGUID b f f 1042 1042	 16 1061 1060 bpcharle scalarltsel scalarltjoinsel ));
 DESCR("less than or equal");
+DATA(insert OID = 5059 ( "<="      PGNSP PGUID b f f 5001 5001   16 5061 5060 nbpcharle scalarltsel scalarltjoinsel ));
+DESCR("less than or equal");
+
 DATA(insert OID = 1060 ( ">"	   PGNSP PGUID b f f 1042 1042	 16 1058 1059 bpchargt scalargtsel scalargtjoinsel ));
 DESCR("greater than");
+DATA(insert OID = 5060 ( ">"       PGNSP PGUID b f f 5001 5001   16 5058 5059 nbpchargt scalargtsel scalargtjoinsel ));
+DESCR("greater than");
+
+
 DATA(insert OID = 1061 ( ">="	   PGNSP PGUID b f f 1042 1042	 16 1059 1058 bpcharge scalargtsel scalargtjoinsel ));
 DESCR("greater than or equal");
+DATA(insert OID = 5061 ( ">="      PGNSP PGUID b f f 5001 5001   16 5059 5058 nbpcharge scalargtsel scalargtjoinsel ));
+DESCR("greater than or equal");
+
 
 /* generic array comparison operators */
 DATA(insert OID = 1070 (  "="	   PGNSP PGUID b t t 2277 2277 16 1070 1071 array_eq eqsel eqjoinsel ));
 DESCR("equal");
 #define ARRAY_EQ_OP 1070
@@ -885,13 +909,18 @@
 #define OID_TEXT_LIKE_OP		1209
 DATA(insert OID = 1210 (  "!~~"   PGNSP PGUID b f f  25 25	16 0 1209 textnlike nlikesel nlikejoinsel ));
 DESCR("does not match LIKE expression");
 DATA(insert OID = 1211 (  "~~"	  PGNSP PGUID b f f  1042 25	16 0 1212 bpcharlike likesel likejoinsel ));
 DESCR("matches LIKE expression");
+DATA(insert OID = 5211 (  "~~"    PGNSP PGUID b f f  5001 25    16 0 5212 nbpcharlike likesel likejoinsel ));
+DESCR("matches LIKE expression");
+
 #define OID_BPCHAR_LIKE_OP		1211
 DATA(insert OID = 1212 (  "!~~"   PGNSP PGUID b f f  1042 25	16 0 1211 bpcharnlike nlikesel nlikejoinsel ));
 DESCR("does not match LIKE expression");
+DATA(insert OID = 5212 (  "!~~"   PGNSP PGUID b f f  5001 25    16 0 5211 nbpcharnlike nlikesel nlikejoinsel ));
+DESCR("does not match LIKE expression");
 
 /* case-insensitive regex hacks */
 DATA(insert OID = 1226 (  "~*"		 PGNSP PGUID b f f	19	25	16 0 1227 nameicregexeq icregexeqsel icregexeqjoinsel ));
 DESCR("matches regular expression, case-insensitive");
 #define OID_NAME_ICREGEXEQ_OP		1226
@@ -902,13 +931,18 @@
 #define OID_TEXT_ICREGEXEQ_OP		1228
 DATA(insert OID = 1229 (  "!~*"		 PGNSP PGUID b f f	25	25	16 0 1228 texticregexne icregexnesel icregexnejoinsel ));
 DESCR("does not match regular expression, case-insensitive");
 DATA(insert OID = 1234 (  "~*"		PGNSP PGUID b f f  1042  25  16 0 1235 bpcharicregexeq icregexeqsel icregexeqjoinsel ));
 DESCR("matches regular expression, case-insensitive");
+DATA(insert OID = 5234 (  "~*"          PGNSP PGUID b f f  5001  25  16 0 5235 nbpcharicregexeq icregexeqsel icregexeqjoinsel ));
+DESCR("matches regular expression, case-insensitive");
+
 #define OID_BPCHAR_ICREGEXEQ_OP		1234
 DATA(insert OID = 1235 ( "!~*"		PGNSP PGUID b f f  1042  25  16 0 1234 bpcharicregexne icregexnesel icregexnejoinsel ));
 DESCR("does not match regular expression, case-insensitive");
+DATA(insert OID = 5235 ( "!~*"          PGNSP PGUID b f f  5001  25  16 0 5234 nbpcharicregexne icregexnesel icregexnejoinsel ));
+DESCR("does not match regular expression, case-insensitive");
 
 /* timestamptz operators */
 DATA(insert OID = 1320 (  "="	   PGNSP PGUID b t t 1184 1184	 16 1320 1321 timestamptz_eq eqsel eqjoinsel ));
 DESCR("equal");
 DATA(insert OID = 1321 (  "<>"	   PGNSP PGUID b f f 1184 1184	 16 1321 1320 timestamptz_ne neqsel neqjoinsel ));
@@ -1176,13 +1210,18 @@
 #define OID_TEXT_ICLIKE_OP		1627
 DATA(insert OID = 1628 (  "!~~*"  PGNSP PGUID b f f  25 25	16 0 1627 texticnlike icnlikesel icnlikejoinsel ));
 DESCR("does not match LIKE expression, case-insensitive");
 DATA(insert OID = 1629 (  "~~*"   PGNSP PGUID b f f  1042 25	16 0 1630 bpchariclike iclikesel iclikejoinsel ));
 DESCR("matches LIKE expression, case-insensitive");
+DATA(insert OID = 5629 (  "~~*"   PGNSP PGUID b f f  5001 25    16 0 5630 nbpchariclike iclikesel iclikejoinsel ));
+DESCR("matches LIKE expression, case-insensitive");
 #define OID_BPCHAR_ICLIKE_OP	1629
 DATA(insert OID = 1630 (  "!~~*"  PGNSP PGUID b f f  1042 25	16 0 1629 bpcharicnlike icnlikesel icnlikejoinsel ));
 DESCR("does not match LIKE expression, case-insensitive");
+DATA(insert OID = 5630 (  "!~~*"  PGNSP PGUID b f f  5001 25    16 0 5629 nbpcharicnlike icnlikesel icnlikejoinsel ));
+DESCR("does not match LIKE expression, case-insensitive");
+
 
 /* NUMERIC type - OID's 1700-1799 */
 DATA(insert OID = 1751 (  "-"	   PGNSP PGUID l f f	0 1700 1700    0	0 numeric_uminus - - ));
 DESCR("negate");
 DATA(insert OID = 1752 (  "="	   PGNSP PGUID b t t 1700 1700	 16 1752 1753 numeric_eq eqsel eqjoinsel ));
@@ -1395,16 +1434,27 @@
 DATA(insert OID = 2318 ( "~>~"	PGNSP PGUID b f f 25 25 16 2314 2315 text_pattern_gt scalargtsel scalargtjoinsel ));
 DESCR("greater than");
 
 DATA(insert OID = 2326 ( "~<~"	PGNSP PGUID b f f 1042 1042 16 2330 2329 bpchar_pattern_lt scalarltsel scalarltjoinsel ));
 DESCR("less than");
+DATA(insert OID = 5326 ( "~<~"  PGNSP PGUID b f f 5001 5001 16 5330 5329 nbpchar_pattern_lt scalarltsel scalarltjoinsel ));
+DESCR("less than");
+
 DATA(insert OID = 2327 ( "~<=~" PGNSP PGUID b f f 1042 1042 16 2329 2330 bpchar_pattern_le scalarltsel scalarltjoinsel ));
 DESCR("less than or equal");
+DATA(insert OID = 5327 ( "~<=~" PGNSP PGUID b f f 5001 5001 16 5329 5330 nbpchar_pattern_le scalarltsel scalarltjoinsel ));
+DESCR("less than or equal");
+
 DATA(insert OID = 2329 ( "~>=~" PGNSP PGUID b f f 1042 1042 16 2327 2326 bpchar_pattern_ge scalargtsel scalargtjoinsel ));
 DESCR("greater than or equal");
+DATA(insert OID = 5329 ( "~>=~" PGNSP PGUID b f f 5001 5001 16 5327 5326 nbpchar_pattern_ge scalargtsel scalargtjoinsel ));
+DESCR("greater than or equal");
+
 DATA(insert OID = 2330 ( "~>~"	PGNSP PGUID b f f 1042 1042 16 2326 2327 bpchar_pattern_gt scalargtsel scalargtjoinsel ));
 DESCR("greater than");
+DATA(insert OID = 5330 ( "~>~"  PGNSP PGUID b f f 5001 5001 16 5326 5327 nbpchar_pattern_gt scalargtsel scalargtjoinsel ));
+DESCR("greater than");
 
 /* crosstype operations for date vs. timestamp and timestamptz */
 
 DATA(insert OID = 2345 ( "<"	   PGNSP PGUID b f f	1082	1114   16 2375 2348 date_lt_timestamp scalarltsel scalarltjoinsel ));
 DESCR("less than");
diff -U 5 -N -r -w ../orig.HEAD/src/include/catalog/pg_proc.h ./src/include/catalog/pg_proc.h
--- ../orig.HEAD/src/include/catalog/pg_proc.h	2013-08-19 20:22:12.000000000 -0400
+++ ./src/include/catalog/pg_proc.h	2013-08-19 20:54:00.000000000 -0400
@@ -743,10 +743,19 @@
 DESCR("convert int8 to float8");
 DATA(insert OID = 483 (  int8			   PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 20 "701" _null_ _null_ _null_ _null_	dtoi8 _null_ _null_ _null_ ));
 DESCR("convert float8 to int8");
 
 /* OIDS 500 - 599 */
+/* national characters support functions */
+DATA(insert OID =  501 (  text             PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 25 "6001" _null_ _null_ _null_ _null_   nvarchar2text _null_ _null_ _null_ ));
+DESCR("convert nvarchar to text");
+DATA(insert OID =  502 (  nvarchar         PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 6001 "25" _null_ _null_ _null_ _null_   text2nvarchar _null_ _null_ _null_ ));
+DESCR("convert text to nvarchar");
+DATA(insert OID =  503 (  text             PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 25 "5001" _null_ _null_ _null_ _null_   nvarchar2rtrimtext _null_ _null_ _null_ ));
+DESCR("convert nbpvarchar to rtrimmed text");
+DATA(insert OID =  504 (  nvarchar         PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 6001 "1042" _null_ _null_ _null_ _null_   rtrimtext2nvarchar _null_ _null_ _null_ ));
+DESCR("convert trimmed text (bpchar) to nvarchar");
 
 /* OIDS 600 - 699 */
 
 DATA(insert OID = 626 (  hash_array		   PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 23 "2277" _null_ _null_ _null_ _null_ hash_array _null_ _null_ _null_ ));
 DESCR("hash");
@@ -767,14 +776,23 @@
 DATA(insert OID = 658 (  namege			   PGNSP PGUID 12 1 0 0 0 f f f t t f i 2 0 16 "19 19" _null_ _null_ _null_ _null_ namege _null_ _null_ _null_ ));
 DATA(insert OID = 659 (  namene			   PGNSP PGUID 12 1 0 0 0 f f f t t f i 2 0 16 "19 19" _null_ _null_ _null_ _null_ namene _null_ _null_ _null_ ));
 
 DATA(insert OID = 668 (  bpchar			   PGNSP PGUID 12 1 0 0 0 f f f f t f i 3 0 1042 "1042 23 16" _null_ _null_ _null_ _null_ bpchar _null_ _null_ _null_ ));
 DESCR("adjust char() to typmod length");
+DATA(insert OID = 5668 (  nbpchar                    PGNSP PGUID 12 1 0 0 0 f f f f t f i 3 0 5001 "5001 23 16" _null_ _null_ _null_ _null_ bpchar _null_ _null_ _null_ ));
+DESCR("adjust char() to typmod length");
+
 DATA(insert OID = 3097 ( varchar_transform PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2281 "2281" _null_ _null_ _null_ _null_ varchar_transform _null_ _null_ _null_ ));
 DESCR("transform a varchar length coercion");
+DATA(insert OID = 5097 ( nvarchar_transform PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2281 "2281" _null_ _null_ _null_ _null_ varchar_transform _null_ _null_ _null_ ));
+DESCR("transform a nvarchar length coercion");
+
 DATA(insert OID = 669 (  varchar		   PGNSP PGUID 12 1 0 0 varchar_transform f f f f t f i 3 0 1043 "1043 23 16" _null_ _null_ _null_ _null_ varchar _null_ _null_ _null_ ));
 DESCR("adjust varchar() to typmod length");
+DATA(insert OID = 5669 (  nvarchar                   PGNSP PGUID 12 1 0 0 nvarchar_transform f f f f t f i 3 0 6001 "6001 23 16" _null_ _null_ _null_ _null_ varchar _null_ _null_ _null_ ));
+DESCR("adjust nvarchar() to typmod length");
+
 
 DATA(insert OID = 676 (  mktinterval	   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 704 "702 702" _null_ _null_ _null_ _null_ mktinterval _null_ _null_ _null_ ));
 
 DATA(insert OID = 619 (  oidvectorne	   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "30 30" _null_ _null_ _null_ _null_ oidvectorne _null_ _null_ _null_ ));
 DATA(insert OID = 677 (  oidvectorlt	   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "30 30" _null_ _null_ _null_ _null_ oidvectorlt _null_ _null_ _null_ ));
@@ -1118,38 +1136,79 @@
 DESCR("make ACL item");
 DATA(insert OID = 3943 (  acldefault	PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1034 "18 26" _null_ _null_ _null_ _null_  acldefault_sql _null_ _null_ _null_ ));
 DESCR("TODO");
 DATA(insert OID = 1689 (  aclexplode	PGNSP PGUID 12 1 10 0 0 f f f f t t s 1 0 2249 "1034" "{1034,26,26,25,16}" "{i,o,o,o,o}" "{acl,grantor,grantee,privilege_type,is_grantable}" _null_ aclexplode _null_ _null_ _null_ ));
 DESCR("convert ACL item array to table, for use by information schema");
-DATA(insert OID = 1044 (  bpcharin		   PGNSP PGUID 12 1 0 0 0 f f f f t f i 3 0 1042 "2275 26 23" _null_ _null_ _null_ _null_ bpcharin _null_ _null_ _null_ ));
+
+DATA(insert OID = 1043 (  bpcharin		   PGNSP PGUID 12 1 0 0 0 f f f f t f i 3 0 1042 "2275 26 23" _null_ _null_ _null_ _null_ bpcharin _null_ _null_ _null_ ));
 DESCR("I/O");
 DATA(insert OID = 1045 (  bpcharout		   PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2275 "1042" _null_ _null_ _null_ _null_ bpcharout _null_ _null_ _null_ ));
 DESCR("I/O");
+
+DATA(insert OID = 5101 (  nbpcharin                 PGNSP PGUID 12 1 0 0 0 f f f f t f i 3 0 5001 "2275 26 23" _null_ _null_ _null_ _null_ bpcharin _null_ _null_ _null_ ));
+DESCR("I/O");
+DATA(insert OID = 5045 (  nbpcharout                PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2275 "5001" _null_ _null_ _null_ _null_ bpcharout _null_ _null_ _null_ ));
+DESCR("I/O");
+
 DATA(insert OID = 2913 (  bpchartypmodin   PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 23 "1263" _null_ _null_ _null_ _null_	bpchartypmodin _null_ _null_ _null_ ));
 DESCR("I/O typmod");
 DATA(insert OID = 2914 (  bpchartypmodout  PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2275 "23" _null_ _null_ _null_ _null_	bpchartypmodout _null_ _null_ _null_ ));
 DESCR("I/O typmod");
+
+DATA(insert OID = 5913 (  nbpchartypmodin   PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 23 "1263" _null_ _null_ _null_ _null_       bpchartypmodin _null_ _null_ _null_ ));
+DESCR("I/O typmod");
+DATA(insert OID = 5914 (  nbpchartypmodout  PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2275 "23" _null_ _null_ _null_ _null_       bpchartypmodout _null_ _null_ _null_ ));
+DESCR("I/O typmod");
+
 DATA(insert OID = 1046 (  varcharin		   PGNSP PGUID 12 1 0 0 0 f f f f t f i 3 0 1043 "2275 26 23" _null_ _null_ _null_ _null_ varcharin _null_ _null_ _null_ ));
 DESCR("I/O");
 DATA(insert OID = 1047 (  varcharout	   PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2275 "1043" _null_ _null_ _null_ _null_ varcharout _null_ _null_ _null_ ));
 DESCR("I/O");
+
+DATA(insert OID = 5046 (  nvarcharin       PGNSP PGUID 12 1 0 0 0 f f f f t f i 3 0 6001 "2275 26 23" _null_ _null_ _null_ _null_ nvarcharin _null_ _null_ _null_ ));
+DESCR("I/O");
+DATA(insert OID = 5047 (  nvarcharout      PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2275 "6001" _null_ _null_ _null_ _null_ nvarcharout _null_ _null_ _null_ ));
+DESCR("I/O");
+
 DATA(insert OID = 2915 (  varchartypmodin  PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 23 "1263" _null_ _null_ _null_ _null_	varchartypmodin _null_ _null_ _null_ ));
 DESCR("I/O typmod");
 DATA(insert OID = 2916 (  varchartypmodout PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2275 "23" _null_ _null_ _null_ _null_	varchartypmodout _null_ _null_ _null_ ));
 DESCR("I/O typmod");
+
+DATA(insert OID = 5915 (  nvarchartypmodin  PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 23 "1263" _null_ _null_ _null_ _null_       varchartypmodin _null_ _null_ _null_ ));
+DESCR("I/O typmod");
+DATA(insert OID = 5916 (  nvarchartypmodout PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2275 "23" _null_ _null_ _null_ _null_       varchartypmodout _null_ _null_ _null_ ));
+DESCR("I/O typmod");
+
 DATA(insert OID = 1048 (  bpchareq		   PGNSP PGUID 12 1 0 0 0 f f f t t f i 2 0 16 "1042 1042" _null_ _null_ _null_ _null_ bpchareq _null_ _null_ _null_ ));
 DATA(insert OID = 1049 (  bpcharlt		   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "1042 1042" _null_ _null_ _null_ _null_ bpcharlt _null_ _null_ _null_ ));
 DATA(insert OID = 1050 (  bpcharle		   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "1042 1042" _null_ _null_ _null_ _null_ bpcharle _null_ _null_ _null_ ));
 DATA(insert OID = 1051 (  bpchargt		   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "1042 1042" _null_ _null_ _null_ _null_ bpchargt _null_ _null_ _null_ ));
 DATA(insert OID = 1052 (  bpcharge		   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "1042 1042" _null_ _null_ _null_ _null_ bpcharge _null_ _null_ _null_ ));
 DATA(insert OID = 1053 (  bpcharne		   PGNSP PGUID 12 1 0 0 0 f f f t t f i 2 0 16 "1042 1042" _null_ _null_ _null_ _null_ bpcharne _null_ _null_ _null_ ));
+
+DATA(insert OID = 5048 (  nbpchareq                 PGNSP PGUID 12 1 0 0 0 f f f t t f i 2 0 16 "5001 5001" _null_ _null_ _null_ _null_ bpchareq _null_ _null_ _null_ ));
+DATA(insert OID = 5049 (  nbpcharlt                 PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "5001 5001" _null_ _null_ _null_ _null_ bpcharlt _null_ _null_ _null_ ));
+DATA(insert OID = 5050 (  nbpcharle                 PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "5001 5001" _null_ _null_ _null_ _null_ bpcharle _null_ _null_ _null_ ));
+DATA(insert OID = 5051 (  nbpchargt                 PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "5001 5001" _null_ _null_ _null_ _null_ bpchargt _null_ _null_ _null_ ));
+DATA(insert OID = 5052 (  nbpcharge                 PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "5001 5001" _null_ _null_ _null_ _null_ bpcharge _null_ _null_ _null_ ));
+DATA(insert OID = 5053 (  nbpcharne                 PGNSP PGUID 12 1 0 0 0 f f f t t f i 2 0 16 "5001 5001" _null_ _null_ _null_ _null_ bpcharne _null_ _null_ _null_ ));
+
 DATA(insert OID = 1063 (  bpchar_larger    PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1042 "1042 1042" _null_ _null_ _null_ _null_ bpchar_larger _null_ _null_ _null_ ));
 DESCR("larger of two");
 DATA(insert OID = 1064 (  bpchar_smaller   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1042 "1042 1042" _null_ _null_ _null_ _null_ bpchar_smaller _null_ _null_ _null_ ));
 DESCR("smaller of two");
 DATA(insert OID = 1078 (  bpcharcmp		   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 23 "1042 1042" _null_ _null_ _null_ _null_ bpcharcmp _null_ _null_ _null_ ));
 DESCR("less-equal-greater");
+
+DATA(insert OID = 5063 (  nbpchar_larger    PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 5001 "5001 5001" _null_ _null_ _null_ _null_ bpchar_larger _null_ _null_ _null_ ));
+DESCR("larger of two");
+DATA(insert OID = 5064 (  nbpchar_smaller   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 5001 "5001 5001" _null_ _null_ _null_ _null_ bpchar_smaller _null_ _null_ _null_ ));
+DESCR("smaller of two");
+DATA(insert OID = 5078 (  nbpcharcmp                PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 23 "5001 5001" _null_ _null_ _null_ _null_ bpcharcmp _null_ _null_ _null_ ));
+DESCR("less-equal-greater");
+
 DATA(insert OID = 1080 (  hashbpchar	   PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 23 "1042" _null_ _null_ _null_ _null_	hashbpchar _null_ _null_ _null_ ));
 DESCR("hash");
 DATA(insert OID = 1081 (  format_type	   PGNSP PGUID 12 1 0 0 0 f f f f f f s 2 0 25 "26 23" _null_ _null_ _null_ _null_ format_type _null_ _null_ _null_ ));
 DESCR("format a type oid and atttypmod to canonical SQL");
 DATA(insert OID = 1084 (  date_in		   PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 1082 "2275" _null_ _null_ _null_ _null_ date_in _null_ _null_ _null_ ));
@@ -1492,10 +1551,14 @@
 DESCR("character length");
 DATA(insert OID = 1374 (  octet_length			 PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 23 "25" _null_ _null_ _null_ _null_	textoctetlen _null_ _null_ _null_ ));
 DESCR("octet length");
 DATA(insert OID = 1375 (  octet_length			 PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 23 "1042" _null_ _null_ _null_ _null_ bpcharoctetlen _null_ _null_ _null_ ));
 DESCR("octet length");
+DATA(insert OID = 5374 (  octet_length                   PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 23 "5001" _null_ _null_ _null_ _null_ bpcharoctetlen _null_ _null_ _null_ ));
+DESCR("octet length");
+DATA(insert OID = 5375 (  octet_length                   PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 23 "6001" _null_ _null_ _null_ _null_ textoctetlen _null_ _null_ _null_ ));
+DESCR("octet length");
 
 DATA(insert OID = 1377 (  time_larger	   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1083 "1083 1083" _null_ _null_ _null_ _null_ time_larger _null_ _null_ _null_ ));
 DESCR("larger of two");
 DATA(insert OID = 1378 (  time_smaller	   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1083 "1083 1083" _null_ _null_ _null_ _null_ time_smaller _null_ _null_ _null_ ));
 DESCR("smaller of two");
@@ -1547,10 +1610,15 @@
 DATA(insert OID = 1400 (  name		   PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 19 "1043" _null_ _null_ _null_ _null_	text_name _null_ _null_ _null_ ));
 DESCR("convert varchar to name");
 DATA(insert OID = 1401 (  varchar	   PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 1043 "19" _null_ _null_ _null_ _null_	name_text _null_ _null_ _null_ ));
 DESCR("convert name to varchar");
 
+DATA(insert OID = 5400 (  name             PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 19 "6001" _null_ _null_ _null_ _null_       text_name _null_ _null_ _null_ ));
+DESCR("convert nvarchar to name");
+DATA(insert OID = 5401 (  nvarchar         PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 6001 "19" _null_ _null_ _null_ _null_       name_text _null_ _null_ _null_ ));
+DESCR("convert name to nvarchar");
+
 DATA(insert OID = 1402 (  current_schema	PGNSP PGUID 12 1 0 0 0 f f f f t f s 0 0 19 "" _null_ _null_ _null_ _null_ current_schema _null_ _null_ _null_ ));
 DESCR("current schema name");
 DATA(insert OID = 1403 (  current_schemas	PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 1003 "16" _null_ _null_ _null_ _null_	current_schemas _null_ _null_ _null_ ));
 DESCR("current schema search list");
 
@@ -1821,10 +1889,13 @@
 
 DATA(insert OID = 1624 (  mul_d_interval	PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1186 "701 1186" _null_ _null_ _null_ _null_ mul_d_interval _null_ _null_ _null_ ));
 
 DATA(insert OID = 1631 (  bpcharlike	   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "1042 25" _null_ _null_ _null_ _null_ textlike _null_ _null_ _null_ ));
 DATA(insert OID = 1632 (  bpcharnlike	   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "1042 25" _null_ _null_ _null_ _null_ textnlike _null_ _null_ _null_ ));
+DATA(insert OID = 5631 (  nbpcharlike       PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "5001 25" _null_ _null_ _null_ _null_ textlike _null_ _null_ _null_ ));
+DATA(insert OID = 5632 (  nbpcharnlike      PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "5001 25" _null_ _null_ _null_ _null_ textnlike _null_ _null_ _null_ ));
+
 
 DATA(insert OID = 1633 (  texticlike		PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "25 25" _null_ _null_ _null_ _null_ texticlike _null_ _null_ _null_ ));
 DATA(insert OID = 1634 (  texticnlike		PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "25 25" _null_ _null_ _null_ _null_ texticnlike _null_ _null_ _null_ ));
 DATA(insert OID = 1635 (  nameiclike		PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "19 25" _null_ _null_ _null_ _null_ nameiclike _null_ _null_ _null_ ));
 DATA(insert OID = 1636 (  nameicnlike		PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "19 25" _null_ _null_ _null_ _null_ nameicnlike _null_ _null_ _null_ ));
@@ -1836,10 +1907,18 @@
 DATA(insert OID = 1658 (  bpcharregexeq    PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "1042 25" _null_ _null_ _null_ _null_ textregexeq _null_ _null_ _null_ ));
 DATA(insert OID = 1659 (  bpcharregexne    PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "1042 25" _null_ _null_ _null_ _null_ textregexne _null_ _null_ _null_ ));
 DATA(insert OID = 1660 (  bpchariclike		PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "1042 25" _null_ _null_ _null_ _null_ texticlike _null_ _null_ _null_ ));
 DATA(insert OID = 1661 (  bpcharicnlike		PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "1042 25" _null_ _null_ _null_ _null_ texticnlike _null_ _null_ _null_ ));
 
+DATA(insert OID = 5656 (  nbpcharicregexeq        PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "5001 25" _null_ _null_ _null_ _null_ texticregexeq _null_ _null_ _null_ ));
+DATA(insert OID = 5657 (  nbpcharicregexne        PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "5001 25" _null_ _null_ _null_ _null_ texticregexne _null_ _null_ _null_ ));
+DATA(insert OID = 5658 (  nbpcharregexeq    PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "5001 25" _null_ _null_ _null_ _null_ textregexeq _null_ _null_ _null_ ));
+DATA(insert OID = 5659 (  nbpcharregexne    PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "5001 25" _null_ _null_ _null_ _null_ textregexne _null_ _null_ _null_ ));
+DATA(insert OID = 5660 (  nbpchariclike          PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "5001 25" _null_ _null_ _null_ _null_ texticlike _null_ _null_ _null_ ));
+DATA(insert OID = 5661 (  nbpcharicnlike         PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "5001 25" _null_ _null_ _null_ _null_ texticnlike _null_ _null_ _null_ ));
+
+
 /* Oracle Compatibility Related Functions - By Edmund Mergl <E.Mergl@bawue.de> */
 DATA(insert OID =  868 (  strpos	   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 23 "25 25" _null_ _null_ _null_ _null_ textpos _null_ _null_ _null_ ));
 DESCR("position of substring");
 DATA(insert OID =  870 (  lower		   PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 25 "25" _null_ _null_ _null_ _null_ lower _null_ _null_ _null_ ));
 DESCR("lowercase");
@@ -3256,10 +3335,18 @@
 DATA(insert OID = 2177 ( bpchar_pattern_ge	  PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "1042 1042" _null_ _null_ _null_ _null_ bpchar_pattern_ge _null_ _null_ _null_ ));
 DATA(insert OID = 2178 ( bpchar_pattern_gt	  PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "1042 1042" _null_ _null_ _null_ _null_ bpchar_pattern_gt _null_ _null_ _null_ ));
 DATA(insert OID = 2180 ( btbpchar_pattern_cmp PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 23 "1042 1042" _null_ _null_ _null_ _null_ btbpchar_pattern_cmp _null_ _null_ _null_ ));
 DESCR("less-equal-greater");
 
+DATA(insert OID = 5174 ( nbpchar_pattern_lt        PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "5001 5001" _null_ _null_ _null_ _null_ bpchar_pattern_lt _null_ _null_ _null_ ));
+DATA(insert OID = 5175 ( nbpchar_pattern_le        PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "5001 5001" _null_ _null_ _null_ _null_ bpchar_pattern_le _null_ _null_ _null_ ));
+DATA(insert OID = 5177 ( nbpchar_pattern_ge        PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "5001 5001" _null_ _null_ _null_ _null_ bpchar_pattern_ge _null_ _null_ _null_ ));
+DATA(insert OID = 5178 ( nbpchar_pattern_gt        PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "5001 5001" _null_ _null_ _null_ _null_ bpchar_pattern_gt _null_ _null_ _null_ ));
+DATA(insert OID = 5180 ( nbtbpchar_pattern_cmp PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 23 "5001 5001" _null_ _null_ _null_ _null_ btbpchar_pattern_cmp _null_ _null_ _null_ ));
+DESCR("less-equal-greater");
+
+
 DATA(insert OID = 2188 ( btint48cmp			PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 23 "23 20" _null_ _null_ _null_ _null_ btint48cmp _null_ _null_ _null_ ));
 DESCR("less-equal-greater");
 DATA(insert OID = 2189 ( btint84cmp			PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 23 "20 23" _null_ _null_ _null_ _null_ btint84cmp _null_ _null_ _null_ ));
 DESCR("less-equal-greater");
 DATA(insert OID = 2190 ( btint24cmp			PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 23 "21 23" _null_ _null_ _null_ _null_ btint24cmp _null_ _null_ _null_ ));
@@ -3643,14 +3730,22 @@
 DESCR("I/O");
 DATA(insert OID = 2430 (  bpcharrecv		   PGNSP PGUID 12 1 0 0 0 f f f f t f s 3 0 1042 "2281 26 23" _null_ _null_ _null_ _null_  bpcharrecv _null_ _null_ _null_ ));
 DESCR("I/O");
 DATA(insert OID = 2431 (  bpcharsend		   PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 17 "1042" _null_ _null_ _null_ _null_	bpcharsend _null_ _null_ _null_ ));
 DESCR("I/O");
+DATA(insert OID = 5430 (  nbpcharrecv              PGNSP PGUID 12 1 0 0 0 f f f f t f s 3 0 5001 "2281 26 23" _null_ _null_ _null_ _null_  bpcharrecv _null_ _null_ _null_ ));
+DESCR("I/O");
+DATA(insert OID = 5431 (  nbpcharsend              PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 17 "5001" _null_ _null_ _null_ _null_       bpcharsend _null_ _null_ _null_ ));
+DESCR("I/O");
 DATA(insert OID = 2432 (  varcharrecv		   PGNSP PGUID 12 1 0 0 0 f f f f t f s 3 0 1043 "2281 26 23" _null_ _null_ _null_ _null_  varcharrecv _null_ _null_ _null_ ));
 DESCR("I/O");
 DATA(insert OID = 2433 (  varcharsend		   PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 17 "1043" _null_ _null_ _null_ _null_	varcharsend _null_ _null_ _null_ ));
 DESCR("I/O");
+DATA(insert OID = 5432 (  nvarcharrecv             PGNSP PGUID 12 1 0 0 0 f f f f t f s 3 0 6001 "2281 26 23" _null_ _null_ _null_ _null_  varcharrecv _null_ _null_ _null_ ));
+DESCR("I/O");
+DATA(insert OID = 5433 (  nvarcharsend             PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 17 "6001" _null_ _null_ _null_ _null_       varcharsend _null_ _null_ _null_ ));
+DESCR("I/O");
 DATA(insert OID = 2434 (  charrecv			   PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 18 "2281" _null_ _null_ _null_ _null_	charrecv _null_ _null_ _null_ ));
 DESCR("I/O");
 DATA(insert OID = 2435 (  charsend			   PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 17 "18" _null_ _null_ _null_ _null_ charsend _null_ _null_ _null_ ));
 DESCR("I/O");
 DATA(insert OID = 2436 (  boolrecv			   PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 16 "2281" _null_ _null_ _null_ _null_	boolrecv _null_ _null_ _null_ ));
diff -U 5 -N -r -w ../orig.HEAD/src/include/catalog/pg_type.h ./src/include/catalog/pg_type.h
--- ../orig.HEAD/src/include/catalog/pg_type.h	2013-08-19 20:22:12.000000000 -0400
+++ ./src/include/catalog/pg_type.h	2013-08-19 20:54:00.000000000 -0400
@@ -457,11 +457,13 @@
 DATA(insert OID = 1010 (  _tid		 PGNSP PGUID -1 f b A f t \054 0	27 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
 DATA(insert OID = 1011 (  _xid		 PGNSP PGUID -1 f b A f t \054 0	28 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
 DATA(insert OID = 1012 (  _cid		 PGNSP PGUID -1 f b A f t \054 0	29 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
 DATA(insert OID = 1013 (  _oidvector PGNSP PGUID -1 f b A f t \054 0	30 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
 DATA(insert OID = 1014 (  _bpchar	 PGNSP PGUID -1 f b A f t \054 0 1042 0 array_in array_out array_recv array_send bpchartypmodin bpchartypmodout array_typanalyze i x f 0 -1 0 100 _null_ _null_ _null_ ));
+DATA(insert OID = 5014 (  _nbpchar       PGNSP PGUID -1 f b A f t \054 0 5001 0 array_in array_out array_recv array_send nbpchartypmodin nbpchartypmodout array_typanalyze i x f 0 -1 0 100 _null_ _null_ _null_ ));
 DATA(insert OID = 1015 (  _varchar	 PGNSP PGUID -1 f b A f t \054 0 1043 0 array_in array_out array_recv array_send varchartypmodin varchartypmodout array_typanalyze i x f 0 -1 0 100 _null_ _null_ _null_ ));
+DATA(insert OID = 5015 (  _nvarchar       PGNSP PGUID -1 f b A f t \054 0 6001 0 array_in array_out array_recv array_send nvarchartypmodin nvarchartypmodout array_typanalyze i x f 0 -1 0 100 _null_ _null_ _null_ ));
 DATA(insert OID = 1016 (  _int8		 PGNSP PGUID -1 f b A f t \054 0	20 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 _null_ _null_ _null_ ));
 DATA(insert OID = 1017 (  _point	 PGNSP PGUID -1 f b A f t \054 0 600 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 _null_ _null_ _null_ ));
 DATA(insert OID = 1018 (  _lseg		 PGNSP PGUID -1 f b A f t \054 0 601 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 _null_ _null_ _null_ ));
 DATA(insert OID = 1019 (  _path		 PGNSP PGUID -1 f b A f t \054 0 602 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 _null_ _null_ _null_ ));
 DATA(insert OID = 1020 (  _box		 PGNSP PGUID -1 f b A f t \073 0 603 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 _null_ _null_ _null_ ));
@@ -483,14 +485,23 @@
 #define CSTRINGARRAYOID		1263
 
 DATA(insert OID = 1042 ( bpchar		 PGNSP PGUID -1 f b S f t \054 0	0 1014 bpcharin bpcharout bpcharrecv bpcharsend bpchartypmodin bpchartypmodout - i x f 0 -1 0 100 _null_ _null_ _null_ ));
 DESCR("char(length), blank-padded string, fixed storage length");
 #define BPCHAROID		1042
+
+DATA(insert OID = 5001 ( nbpchar         PGNSP PGUID -1 f b S f t \054 0        0 5014 nbpcharin nbpcharout nbpcharrecv nbpcharsend nbpchartypmodin nbpchartypmodout - i x f 0 -1 0 100 _null_ _null_ _null_ ));
+DESCR("nchar(length), blank-padded national string, fixed storage length");
+#define NBPCHAROID              5001
+
 DATA(insert OID = 1043 ( varchar	 PGNSP PGUID -1 f b S f t \054 0	0 1015 varcharin varcharout varcharrecv varcharsend varchartypmodin varchartypmodout - i x f 0 -1 0 100 _null_ _null_ _null_ ));
 DESCR("varchar(length), non-blank-padded string, variable storage length");
 #define VARCHAROID		1043
 
+DATA(insert OID = 6001 ( nvarchar         PGNSP PGUID -1 f b S f t \054 0        0 5015 nvarcharin nvarcharout nvarcharrecv nvarcharsend nvarchartypmodin nvarchartypmodout - i x f 0 -1 0 100 _null_ _null_ _null_ ));
+DESCR("nvarchar(length), non-blank-padded national string, variable storage length");
+#define NVARCHAROID		6001
+
 DATA(insert OID = 1082 ( date		 PGNSP PGUID	4 t b D f t \054 0	0 1182 date_in date_out date_recv date_send - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
 DESCR("date");
 #define DATEOID			1082
 DATA(insert OID = 1083 ( time		 PGNSP PGUID	8 FLOAT8PASSBYVAL b D f t \054 0	0 1183 time_in time_out time_recv time_send timetypmodin timetypmodout - d p f 0 -1 0 0 _null_ _null_ _null_ ));
 DESCR("time of day");
diff -U 5 -N -r -w ../orig.HEAD/src/include/parser/kwlist.h ./src/include/parser/kwlist.h
--- ../orig.HEAD/src/include/parser/kwlist.h	2013-08-19 20:22:12.000000000 -0400
+++ ./src/include/parser/kwlist.h	2013-08-19 20:54:00.000000000 -0400
@@ -255,10 +255,11 @@
 PG_KEYWORD("nowait", NOWAIT, UNRESERVED_KEYWORD)
 PG_KEYWORD("null", NULL_P, RESERVED_KEYWORD)
 PG_KEYWORD("nullif", NULLIF, COL_NAME_KEYWORD)
 PG_KEYWORD("nulls", NULLS_P, UNRESERVED_KEYWORD)
 PG_KEYWORD("numeric", NUMERIC, COL_NAME_KEYWORD)
+PG_KEYWORD("nvarchar", NVARCHAR, COL_NAME_KEYWORD)
 PG_KEYWORD("object", OBJECT_P, UNRESERVED_KEYWORD)
 PG_KEYWORD("of", OF, UNRESERVED_KEYWORD)
 PG_KEYWORD("off", OFF, UNRESERVED_KEYWORD)
 PG_KEYWORD("offset", OFFSET, RESERVED_KEYWORD)
 PG_KEYWORD("oids", OIDS, UNRESERVED_KEYWORD)
diff -U 5 -N -r -w ../orig.HEAD/src/include/utils/builtins.h ./src/include/utils/builtins.h
--- ../orig.HEAD/src/include/utils/builtins.h	2013-08-19 20:22:13.000000000 -0400
+++ ./src/include/utils/builtins.h	2013-08-19 20:54:00.000000000 -0400
@@ -324,10 +324,33 @@
 extern Datum btfloat4sortsupport(PG_FUNCTION_ARGS);
 extern Datum btfloat8sortsupport(PG_FUNCTION_ARGS);
 extern Datum btoidsortsupport(PG_FUNCTION_ARGS);
 extern Datum btnamesortsupport(PG_FUNCTION_ARGS);
 
+/* nvarchar.c */
+extern Datum ntextin(PG_FUNCTION_ARGS);
+extern Datum ntextout(PG_FUNCTION_ARGS);
+extern Datum nvarcharin(PG_FUNCTION_ARGS);
+extern Datum nvarcharout(PG_FUNCTION_ARGS);
+extern Datum ntextlower(PG_FUNCTION_ARGS);
+extern Datum ntextupper(PG_FUNCTION_ARGS);
+extern Datum ntextoctetlen(PG_FUNCTION_ARGS);
+extern Datum nvarchar2text(PG_FUNCTION_ARGS);
+extern Datum text2nvarchar(PG_FUNCTION_ARGS);
+extern Datum nvarchar2rtrimtext(PG_FUNCTION_ARGS);
+extern Datum rtrimtext2nvarchar(PG_FUNCTION_ARGS);
+extern Datum ntext_cmp(PG_FUNCTION_ARGS);
+extern Datum ntext_hash(PG_FUNCTION_ARGS);
+extern Datum ntext_eq(PG_FUNCTION_ARGS);
+extern Datum ntext_ne(PG_FUNCTION_ARGS);
+extern Datum ntext_gt(PG_FUNCTION_ARGS);
+extern Datum ntext_ge(PG_FUNCTION_ARGS);
+extern Datum ntext_lt(PG_FUNCTION_ARGS);
+extern Datum ntext_le(PG_FUNCTION_ARGS);
+extern Datum ntext_smaller(PG_FUNCTION_ARGS);
+extern Datum ntext_larger(PG_FUNCTION_ARGS);
+
 /* float.c */
 extern PGDLLIMPORT int extra_float_digits;
 
 extern double get_float8_infinity(void);
 extern float get_float4_infinity(void);
@@ -831,10 +854,13 @@
 extern Datum byteanlike(PG_FUNCTION_ARGS);
 extern Datum like_escape(PG_FUNCTION_ARGS);
 extern Datum like_escape_bytea(PG_FUNCTION_ARGS);
 
 /* oracle_compat.c */
+extern text *dotrim(const char *string, int stringlen,
+       const char *set, int setlen,
+       bool doltrim, bool dortrim);
 extern Datum lower(PG_FUNCTION_ARGS);
 extern Datum upper(PG_FUNCTION_ARGS);
 extern Datum initcap(PG_FUNCTION_ARGS);
 extern Datum lpad(PG_FUNCTION_ARGS);
 extern Datum rpad(PG_FUNCTION_ARGS);
diff -U 5 -N -r -w ../orig.HEAD/src/interfaces/ecpg/ecpglib/data.c ./src/interfaces/ecpg/ecpglib/data.c
--- ../orig.HEAD/src/interfaces/ecpg/ecpglib/data.c	2013-08-19 20:22:13.000000000 -0400
+++ ./src/interfaces/ecpg/ecpglib/data.c	2013-08-20 05:02:12.000000000 -0400
@@ -225,12 +225,14 @@
 		}
 
 		switch (type)
 		{
 			case ECPGt_char:
+			case ECPGt_nchar:
 			case ECPGt_unsigned_char:
 			case ECPGt_varchar:
+			case ECPGt_nvarchar:
 			case ECPGt_string:
 				break;
 
 			default:
 				pval++;
@@ -448,10 +450,11 @@
 							   ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
 					return (false);
 					break;
 
 				case ECPGt_char:
+				case ECPGt_nchar:
 				case ECPGt_unsigned_char:
 				case ECPGt_string:
 					{
 						char	   *str = (char *) (var + offset * act_tuple);
 
@@ -506,10 +509,11 @@
 						pval += size;
 					}
 					break;
 
 				case ECPGt_varchar:
+				case ECPGt_nvarchar:
 					{
 						struct ECPGgeneric_varchar *variable =
 						(struct ECPGgeneric_varchar *) (var + offset * act_tuple);
 
 						variable->len = size;
@@ -545,17 +549,20 @@
 									default:
 										break;
 								}
 								sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
 
+								/*
+								 * it will be not too good result if it
+								 * truncate in middle of utf byte-sequence
+								 */
 								variable->len = varcharsize;
 							}
 						}
 						pval += size;
 					}
 					break;
-
 				case ECPGt_decimal:
 				case ECPGt_numeric:
 					if (isarray && *pval == '"')
 						nres = PGTYPESnumeric_from_asc(pval + 1, &scan_length);
 					else
diff -U 5 -N -r -w ../orig.HEAD/src/interfaces/ecpg/ecpglib/descriptor.c ./src/interfaces/ecpg/ecpglib/descriptor.c
--- ../orig.HEAD/src/interfaces/ecpg/ecpglib/descriptor.c	2013-08-19 20:22:13.000000000 -0400
+++ ./src/interfaces/ecpg/ecpglib/descriptor.c	2013-08-20 05:00:38.000000000 -0400
@@ -198,15 +198,17 @@
 get_char_item(int lineno, void *var, enum ECPGttype vartype, char *value, int varcharsize)
 {
 	switch (vartype)
 	{
 		case ECPGt_char:
+		case ECPGt_nchar:
 		case ECPGt_unsigned_char:
 		case ECPGt_string:
 			strncpy((char *) var, value, varcharsize);
 			break;
 		case ECPGt_varchar:
+		case ECPGt_nvarchar:
 			{
 				struct ECPGgeneric_varchar *variable =
 				(struct ECPGgeneric_varchar *) var;
 
 				if (varcharsize == 0)
diff -U 5 -N -r -w ../orig.HEAD/src/interfaces/ecpg/ecpglib/error.c ./src/interfaces/ecpg/ecpglib/error.c
--- ../orig.HEAD/src/interfaces/ecpg/ecpglib/error.c	2013-08-19 20:22:13.000000000 -0400
+++ ./src/interfaces/ecpg/ecpglib/error.c	2013-08-19 20:54:00.000000000 -0400
@@ -37,10 +37,20 @@
 			 * expanded.
 			 */
 					 ecpg_gettext("out of memory on line %d"), line);
 			break;
 
+		case ECPG_ENCODING_ERROR:
+            snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
+
+            /*
+             * translator: this string will be truncated at 149 characters
+             * expanded.
+             */
+                     ecpg_gettext("encoding conversion error on line %d"), line);
+            break;
+
 		case ECPG_UNSUPPORTED:
 			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
 
 			/*
 			 * translator: this string will be truncated at 149 characters
diff -U 5 -N -r -w ../orig.HEAD/src/interfaces/ecpg/ecpglib/execute.c ./src/interfaces/ecpg/ecpglib/execute.c
--- ../orig.HEAD/src/interfaces/ecpg/ecpglib/execute.c	2013-08-19 20:22:13.000000000 -0400
+++ ./src/interfaces/ecpg/ecpglib/execute.c	2013-08-20 05:05:56.000000000 -0400
@@ -244,12 +244,16 @@
 			return (ECPG_ARRAY_ERROR);
 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), CIDROID, ECPG_ARRAY_NONE, stmt->lineno))
 			return (ECPG_ARRAY_ERROR);
 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), BPCHAROID, ECPG_ARRAY_NONE, stmt->lineno))
 			return (ECPG_ARRAY_ERROR);
+		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), NBPCHAROID, ECPG_ARRAY_NONE, stmt->lineno))
+			return (ECPG_ARRAY_ERROR);
 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), VARCHAROID, ECPG_ARRAY_NONE, stmt->lineno))
 			return (ECPG_ARRAY_ERROR);
+		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), NVARCHAROID, ECPG_ARRAY_NONE, stmt->lineno))
+			return (ECPG_ARRAY_ERROR);
 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), DATEOID, ECPG_ARRAY_NONE, stmt->lineno))
 			return (ECPG_ARRAY_ERROR);
 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), TIMEOID, ECPG_ARRAY_NONE, stmt->lineno))
 			return (ECPG_ARRAY_ERROR);
 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), TIMESTAMPOID, ECPG_ARRAY_NONE, stmt->lineno))
@@ -360,10 +364,11 @@
 		if (!PQfformat(results, act_field))
 		{
 			switch (var->type)
 			{
 				case ECPGt_char:
+				case ECPGt_nchar:
 				case ECPGt_unsigned_char:
 				case ECPGt_string:
 					if (!var->varcharsize && !var->arrsize)
 					{
 						/* special mode for handling char**foo=0 */
@@ -385,10 +390,11 @@
 						}
 						var->offset *= var->varcharsize;
 						len = var->offset * ntuples;
 					}
 					break;
+				case ECPGt_nvarchar:
 				case ECPGt_varchar:
 					len = ntuples * (var->varcharsize + sizeof(int));
 					break;
 				default:
 					len = var->offset * ntuples;
@@ -421,11 +427,11 @@
 		ecpg_add_mem(var->ind_value, stmt->lineno);
 	}
 
 	/* fill the variable with the tuple(s) */
 	if (!var->varcharsize && !var->arrsize &&
-		(var->type == ECPGt_char || var->type == ECPGt_unsigned_char || var->type == ECPGt_string))
+		(var->type == ECPGt_char || var->type == ECPGt_unsigned_char || var->type == ECPGt_string || var->type == ECPGt_nchar))
 	{
 		/* special mode for handling char**foo=0 */
 
 		/* filling the array of (char*)s */
 		char	  **current_string = (char **) var->value;
@@ -791,10 +797,11 @@
 
 				*tobeinserted_p = mallocedval;
 				break;
 
 			case ECPGt_char:
+			case ECPGt_nchar:
 			case ECPGt_unsigned_char:
 			case ECPGt_string:
 				{
 					/* set slen to string length if type is char * */
 					int			slen = (var->varcharsize == 0) ? strlen((char *) var->value) : (unsigned int) var->varcharsize;
@@ -825,10 +832,11 @@
 
 					*tobeinserted_p = mallocedval;
 				}
 				break;
 			case ECPGt_varchar:
+			case ECPGt_nvarchar:
 				{
 					struct ECPGgeneric_varchar *variable =
 					(struct ECPGgeneric_varchar *) (var->value);
 
 					if (!(newcopy = (char *) ecpg_alloc(variable->len + 1, lineno)))
@@ -842,11 +850,10 @@
 						return false;
 
 					*tobeinserted_p = mallocedval;
 				}
 				break;
-
 			case ECPGt_decimal:
 			case ECPGt_numeric:
 				{
 					char	   *str = NULL;
 					int			slen;
@@ -1229,10 +1236,12 @@
 						desc_inlist.value = sqlda->sqlvar[i].sqldata;
 						desc_inlist.pointer = &(sqlda->sqlvar[i].sqldata);
 						switch (desc_inlist.type)
 						{
 							case ECPGt_char:
+							case ECPGt_nchar:
+							case ECPGt_nvarchar:
 							case ECPGt_varchar:
 								desc_inlist.varcharsize = strlen(sqlda->sqlvar[i].sqldata);
 								break;
 							default:
 								desc_inlist.varcharsize = 0;
@@ -1284,10 +1293,12 @@
 						desc_inlist.value = sqlda->sqlvar[i].sqldata;
 						desc_inlist.pointer = &(sqlda->sqlvar[i].sqldata);
 						switch (desc_inlist.type)
 						{
 							case ECPGt_char:
+							case ECPGt_nchar:
+							case ECPGt_nvarchar:
 							case ECPGt_varchar:
 								desc_inlist.varcharsize = strlen(sqlda->sqlvar[i].sqldata);
 								break;
 							default:
 								desc_inlist.varcharsize = 0;
diff -U 5 -N -r -w ../orig.HEAD/src/interfaces/ecpg/ecpglib/extern.h ./src/interfaces/ecpg/ecpglib/extern.h
--- ../orig.HEAD/src/interfaces/ecpg/ecpglib/extern.h	2013-08-19 20:22:13.000000000 -0400
+++ ./src/interfaces/ecpg/ecpglib/extern.h	2013-08-19 20:54:00.000000000 -0400
@@ -202,7 +202,8 @@
 #define ECPG_SQLSTATE_DUPLICATE_CURSOR		"42P03"
 
 /* implementation-defined internal errors of ecpg */
 #define ECPG_SQLSTATE_ECPG_INTERNAL_ERROR	"YE000"
 #define ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY	"YE001"
+#define ECPG_SQLSTATE_ECPG_ENCODING_ERROR   "YE002"
 
 #endif   /* _ECPG_LIB_EXTERN_H */
diff -U 5 -N -r -w ../orig.HEAD/src/interfaces/ecpg/ecpglib/misc.c ./src/interfaces/ecpg/ecpglib/misc.c
--- ../orig.HEAD/src/interfaces/ecpg/ecpglib/misc.c	2013-08-19 20:22:13.000000000 -0400
+++ ./src/interfaces/ecpg/ecpglib/misc.c	2013-08-20 05:04:28.000000000 -0400
@@ -303,10 +303,11 @@
 ECPGset_noind_null(enum ECPGttype type, void *ptr)
 {
 	switch (type)
 	{
 		case ECPGt_char:
+		case ECPGt_nchar:
 		case ECPGt_unsigned_char:
 		case ECPGt_string:
 			*((char *) ptr) = '\0';
 			break;
 		case ECPGt_short:
@@ -332,10 +333,11 @@
 			memset((char *) ptr, 0xff, sizeof(float));
 			break;
 		case ECPGt_double:
 			memset((char *) ptr, 0xff, sizeof(double));
 			break;
+		case ECPGt_nvarchar:
 		case ECPGt_varchar:
 			*(((struct ECPGgeneric_varchar *) ptr)->arr) = 0x00;
 			((struct ECPGgeneric_varchar *) ptr)->len = 0;
 			break;
 		case ECPGt_decimal:
@@ -405,10 +407,11 @@
 			return (_check(ptr, sizeof(float)));
 			break;
 		case ECPGt_double:
 			return (_check(ptr, sizeof(double)));
 			break;
+		case ECPGt_nvarchar:
 		case ECPGt_varchar:
 			if (*(((struct ECPGgeneric_varchar *) ptr)->arr) == 0x00)
 				return true;
 			break;
 		case ECPGt_decimal:
@@ -546,5 +549,6 @@
 	struct var_list *ptr;
 
 	for (ptr = ivlist; ptr != NULL && ptr->number != number; ptr = ptr->next);
 	return (ptr) ? ptr->pointer : NULL;
 }
+
diff -U 5 -N -r -w ../orig.HEAD/src/interfaces/ecpg/ecpglib/pg_type.h ./src/interfaces/ecpg/ecpglib/pg_type.h
--- ../orig.HEAD/src/interfaces/ecpg/ecpglib/pg_type.h	2013-08-19 20:22:13.000000000 -0400
+++ ./src/interfaces/ecpg/ecpglib/pg_type.h	2013-08-19 20:54:00.000000000 -0400
@@ -46,10 +46,12 @@
 #define CASHOID 790
 #define INETOID 869
 #define CIDROID 650
 #define BPCHAROID		1042
 #define VARCHAROID		1043
+#define NBPCHAROID              5001
+#define NVARCHAROID             6001
 #define DATEOID			1082
 #define TIMEOID			1083
 #define TIMESTAMPOID	1114
 #define TIMESTAMPTZOID	1184
 #define INTERVALOID		1186
diff -U 5 -N -r -w ../orig.HEAD/src/interfaces/ecpg/ecpglib/sqlda.c ./src/interfaces/ecpg/ecpglib/sqlda.c
--- ../orig.HEAD/src/interfaces/ecpg/ecpglib/sqlda.c	2013-08-19 20:22:13.000000000 -0400
+++ ./src/interfaces/ecpg/ecpglib/sqlda.c	2013-08-19 20:54:00.000000000 -0400
@@ -132,10 +132,11 @@
 				break;
 			case ECPGt_interval:
 				ecpg_sqlda_align_add_size(offset, sizeof(int64), sizeof(interval), &offset, &next_offset);
 				break;
 			case ECPGt_char:
+			case ECPGt_nchar:
 			case ECPGt_unsigned_char:
 			case ECPGt_string:
 			default:
 				{
 					long		datalen = strlen(PQgetvalue(res, row, i)) + 1;
@@ -371,10 +372,11 @@
 				ecpg_sqlda_align_add_size(offset, sizeof(int64), sizeof(interval), &offset, &next_offset);
 				sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
 				sqlda->sqlvar[i].sqllen = sizeof(interval);
 				break;
 			case ECPGt_char:
+			case ECPGt_nchar:
 			case ECPGt_unsigned_char:
 			case ECPGt_string:
 			default:
 				datalen = strlen(PQgetvalue(res, row, i)) + 1;
 				ecpg_sqlda_align_add_size(offset, sizeof(int), datalen, &offset, &next_offset);
@@ -560,10 +562,11 @@
 				ecpg_sqlda_align_add_size(offset, sizeof(int64), sizeof(interval), &offset, &next_offset);
 				sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
 				sqlda->sqlvar[i].sqllen = sizeof(interval);
 				break;
 			case ECPGt_char:
+			case ECPGt_nchar:
 			case ECPGt_unsigned_char:
 			case ECPGt_string:
 			default:
 				datalen = strlen(PQgetvalue(res, row, i)) + 1;
 				ecpg_sqlda_align_add_size(offset, sizeof(int), datalen, &offset, &next_offset);
diff -U 5 -N -r -w ../orig.HEAD/src/interfaces/ecpg/ecpglib/typename.c ./src/interfaces/ecpg/ecpglib/typename.c
--- ../orig.HEAD/src/interfaces/ecpg/ecpglib/typename.c	2013-08-19 20:22:13.000000000 -0400
+++ ./src/interfaces/ecpg/ecpglib/typename.c	2013-08-20 05:02:32.000000000 -0400
@@ -20,10 +20,12 @@
 	switch (typ)
 	{
 		case ECPGt_char:
 		case ECPGt_string:
 			return "char";
+		case ECPGt_nchar:
+			return "national char";
 		case ECPGt_unsigned_char:
 			return "unsigned char";
 		case ECPGt_short:
 			return "short";
 		case ECPGt_unsigned_short:
@@ -46,10 +48,12 @@
 			return "double";
 		case ECPGt_bool:
 			return "bool";
 		case ECPGt_varchar:
 			return "varchar";
+		case ECPGt_nvarchar:
+			return "nvarchar";
 		case ECPGt_char_variable:
 			return "char";
 		case ECPGt_decimal:
 			return "decimal";
 		case ECPGt_numeric:
@@ -85,12 +89,16 @@
 			return SQL3_REAL;	/* float4 */
 		case FLOAT8OID:
 			return SQL3_DOUBLE_PRECISION;		/* float8 */
 		case BPCHAROID:
 			return SQL3_CHARACTER;		/* bpchar */
+		case NBPCHAROID:
+			return SQL3_CHARACTER;		/* bpchar */
 		case VARCHAROID:
 			return SQL3_CHARACTER_VARYING;		/* varchar */
+		case NVARCHAROID:
+			return SQL3_CHARACTER_VARYING;		/* nvarchar */
 		case DATEOID:
 			return SQL3_DATE_TIME_TIMESTAMP;	/* date */
 		case TIMEOID:
 			return SQL3_DATE_TIME_TIMESTAMP;	/* time */
 		case TIMESTAMPOID:
@@ -107,11 +115,13 @@
 {
 	switch (type)
 	{
 		case CHAROID:
 		case VARCHAROID:
+		case NVARCHAROID:
 		case BPCHAROID:
+		case NBPCHAROID:
 		case TEXTOID:
 			return ECPGt_char;
 		case INT2OID:
 			return ECPGt_short;
 		case INT4OID:
diff -U 5 -N -r -w ../orig.HEAD/src/interfaces/ecpg/include/ecpgerrno.h ./src/interfaces/ecpg/include/ecpgerrno.h
--- ../orig.HEAD/src/interfaces/ecpg/include/ecpgerrno.h	2013-08-19 20:22:13.000000000 -0400
+++ ./src/interfaces/ecpg/include/ecpgerrno.h	2013-08-19 20:54:00.000000000 -0400
@@ -43,10 +43,13 @@
 #define ECPG_INVALID_DESCRIPTOR_INDEX	-241
 #define ECPG_UNKNOWN_DESCRIPTOR_ITEM	-242
 #define ECPG_VAR_NOT_NUMERIC		-243
 #define ECPG_VAR_NOT_CHAR		-244
 
+/*encoding conversion errors */
+#define ECPG_ENCODING_ERROR     -250
+
 /* finally the backend error messages, they start at 400 */
 #define ECPG_PGSQL			-400
 #define ECPG_TRANS			-401
 #define ECPG_CONNECT			-402
 #define ECPG_DUPLICATE_KEY		-403
diff -U 5 -N -r -w ../orig.HEAD/src/interfaces/ecpg/include/ecpgtype.h ./src/interfaces/ecpg/include/ecpgtype.h
--- ../orig.HEAD/src/interfaces/ecpg/include/ecpgtype.h	2013-08-19 20:22:13.000000000 -0400
+++ ./src/interfaces/ecpg/include/ecpgtype.h	2013-08-20 05:02:01.000000000 -0400
@@ -44,10 +44,12 @@
 	ECPGt_int, ECPGt_unsigned_int, ECPGt_long, ECPGt_unsigned_long,
 	ECPGt_long_long, ECPGt_unsigned_long_long,
 	ECPGt_bool,
 	ECPGt_float, ECPGt_double,
 	ECPGt_varchar, ECPGt_varchar2,
+	ECPGt_nvarchar,				/* the same as ECPGt_varchar actually */
+	ECPGt_nchar,                            /* converted to char *arr[N] */
 	ECPGt_numeric,				/* this is a decimal that stores its digits in
 								 * a malloced array */
 	ECPGt_decimal,				/* this is a decimal that stores its digits in
 								 * a fixed array */
 	ECPGt_date,
@@ -102,5 +104,6 @@
 #ifdef __cplusplus
 }
 #endif
 
 #endif   /* _ECPGTYPE_H */
+
diff -U 5 -N -r -w ../orig.HEAD/src/interfaces/ecpg/include/sqltypes.h ./src/interfaces/ecpg/include/sqltypes.h
--- ../orig.HEAD/src/interfaces/ecpg/include/sqltypes.h	2013-08-19 20:22:13.000000000 -0400
+++ ./src/interfaces/ecpg/include/sqltypes.h	2013-08-19 20:54:00.000000000 -0400
@@ -44,10 +44,11 @@
 #define	SQLTEXT		ECPGt_char
 #define	SQLVCHAR	ECPGt_char
 #define SQLINTERVAL     ECPGt_interval
 #define	SQLNCHAR	ECPGt_char
 #define	SQLNVCHAR	ECPGt_char
+#define SQLNVARCHAR     ECPGt_char
 #ifdef HAVE_LONG_LONG_INT_64
 #define	SQLINT8		ECPGt_long_long
 #define	SQLSERIAL8	ECPGt_long_long
 #else
 #define	SQLINT8		ECPGt_long
diff -U 5 -N -r -w ../orig.HEAD/src/interfaces/ecpg/preproc/c_keywords.c ./src/interfaces/ecpg/preproc/c_keywords.c
--- ../orig.HEAD/src/interfaces/ecpg/preproc/c_keywords.c	2013-08-19 20:22:13.000000000 -0400
+++ ./src/interfaces/ecpg/preproc/c_keywords.c	2013-08-20 05:09:08.000000000 -0400
@@ -25,10 +25,12 @@
 
 	/*
 	 * category is not needed in ecpg, it is only here so we can share the
 	 * data structure with the backend
 	 */
+	{"NCHAR", NCHAR, 0},
+	{"NVARCHAR", NVARCHAR, 0},
 	{"VARCHAR", VARCHAR, 0},
 	{"auto", S_AUTO, 0},
 	{"bool", SQL_BOOL, 0},
 	{"char", CHAR_P, 0},
 	{"const", S_CONST, 0},
@@ -38,10 +40,12 @@
 	{"hour", HOUR_P, 0},
 	{"int", INT_P, 0},
 	{"long", SQL_LONG, 0},
 	{"minute", MINUTE_P, 0},
 	{"month", MONTH_P, 0},
+	{"nchar", NCHAR, 0},
+	{"nvarchar", NVARCHAR, 0},
 	{"register", S_REGISTER, 0},
 	{"second", SECOND_P, 0},
 	{"short", SQL_SHORT, 0},
 	{"signed", SQL_SIGNED, 0},
 	{"static", S_STATIC, 0},
diff -U 5 -N -r -w ../orig.HEAD/src/interfaces/ecpg/preproc/ecpg.header ./src/interfaces/ecpg/preproc/ecpg.header
--- ../orig.HEAD/src/interfaces/ecpg/preproc/ecpg.header	2013-08-19 20:22:13.000000000 -0400
+++ ./src/interfaces/ecpg/preproc/ecpg.header	2013-08-20 05:08:24.000000000 -0400
@@ -267,11 +267,13 @@
 			{
 				newvar = ptr->variable;
 				skip_set_var = true;
 			}
 			else if ((ptr->variable->type->type != ECPGt_varchar
+					  && ptr->variable->type->type != ECPGt_nvarchar
 					  && ptr->variable->type->type != ECPGt_char
+					  && ptr->variable->type->type != ECPGt_nchar
 					  && ptr->variable->type->type != ECPGt_unsigned_char
 					  && ptr->variable->type->type != ECPGt_string)
 					 && atoi(ptr->variable->type->size) > 1)
 			{
 				newvar = new_variable(cat_str(4, mm_strdup("("),
@@ -283,11 +285,13 @@
 																			   ptr->variable->type->u.element->counter),
 														  ptr->variable->type->size),
 									  0);
 			}
 			else if ((ptr->variable->type->type == ECPGt_varchar
+					  || ptr->variable->type->type == ECPGt_nvarchar
 					  || ptr->variable->type->type == ECPGt_char
+					  || ptr->variable->type->type == ECPGt_nchar
 					  || ptr->variable->type->type == ECPGt_unsigned_char
 					  || ptr->variable->type->type == ECPGt_string)
 					 && atoi(ptr->variable->type->size) > 1)
 			{
 				newvar = new_variable(cat_str(4, mm_strdup("("),
@@ -296,11 +300,11 @@
 											  mm_strdup(var_text)),
 									  ECPGmake_simple_type(ptr->variable->type->type,
 														   ptr->variable->type->size,
 														   ptr->variable->type->counter),
 									  0);
-				if (ptr->variable->type->type == ECPGt_varchar)
+				if (ptr->variable->type->type == ECPGt_varchar || ptr->variable->type->type == ECPGt_nvarchar)
 					var_ptr = true;
 			}
 			else if (ptr->variable->type->type == ECPGt_struct
 					 || ptr->variable->type->type == ECPGt_union)
 			{
@@ -543,10 +547,11 @@
 		this->type->type_sizeof = ECPGstruct_sizeof;
 		this->struct_member_list = (type_enum == ECPGt_struct || type_enum == ECPGt_union) ?
 		ECPGstruct_member_dup(struct_member_list[struct_level]) : NULL;
 
 		if (type_enum != ECPGt_varchar &&
+			type_enum != ECPGt_nvarchar &&
 			type_enum != ECPGt_char &&
 			type_enum != ECPGt_unsigned_char &&
 			type_enum != ECPGt_string &&
 			atoi(this->type->type_index) >= 0)
 			mmerror(PARSE_ERROR, ET_ERROR, "multidimensional arrays for simple data types are not supported");
diff -U 5 -N -r -w ../orig.HEAD/src/interfaces/ecpg/preproc/ecpg.tokens ./src/interfaces/ecpg/preproc/ecpg.tokens
--- ../orig.HEAD/src/interfaces/ecpg/preproc/ecpg.tokens	2013-08-19 20:22:13.000000000 -0400
+++ ./src/interfaces/ecpg/preproc/ecpg.tokens	2013-08-20 05:07:52.000000000 -0400
@@ -14,14 +14,16 @@
                 SQL_RETURNED_LENGTH SQL_RETURNED_OCTET_LENGTH SQL_SCALE
                 SQL_SECTION SQL_SHORT SQL_SIGNED SQL_SQL SQL_SQLERROR
                 SQL_SQLPRINT SQL_SQLWARNING SQL_START SQL_STOP
                 SQL_STRUCT SQL_UNSIGNED SQL_VAR SQL_WHENEVER
 
+
 /* C tokens */
 %token  S_ADD S_AND S_ANYTHING S_AUTO S_CONST S_DEC S_DIV
                 S_DOTPOINT S_EQUAL S_EXTERN S_INC S_LSHIFT S_MEMPOINT
                 S_MEMBER S_MOD S_MUL S_NEQUAL S_OR S_REGISTER S_RSHIFT
                 S_STATIC S_SUB S_VOLATILE
                 S_TYPEDEF
 
 %token CSTRING CVARIABLE CPP_LINE IP
 %token DOLCONST ECONST NCONST UCONST UIDENT
+
diff -U 5 -N -r -w ../orig.HEAD/src/interfaces/ecpg/preproc/ecpg.trailer ./src/interfaces/ecpg/preproc/ecpg.trailer
--- ../orig.HEAD/src/interfaces/ecpg/preproc/ecpg.trailer	2013-08-19 20:22:13.000000000 -0400
+++ ./src/interfaces/ecpg/preproc/ecpg.trailer	2013-08-20 05:07:32.000000000 -0400
@@ -184,11 +184,11 @@
 			/* if array see what's inside */
 			if (type == ECPGt_array)
 				type = argsinsert->variable->type->u.element->type;
 
 			/* handle varchars */
-			if (type == ECPGt_varchar)
+			if (type == ECPGt_varchar || type == ECPGt_nvarchar)
 				$$ = make2_str(mm_strdup(argsinsert->variable->name), mm_strdup(".arr"));
 			else
 				$$ = mm_strdup(argsinsert->variable->name);
 		}
 		;
@@ -209,15 +209,17 @@
 					type = p->type->u.element->type;
 
 				switch (type)
 				{
 					case ECPGt_char:
+					case ECPGt_nchar:
 					case ECPGt_unsigned_char:
 					case ECPGt_string:
 						$$ = $1;
 						break;
 					case ECPGt_varchar:
+					case ECPGt_nvarchar:
 						$$ = make2_str($1, mm_strdup(".arr"));
 						break;
 					default:
 						mmerror(PARSE_ERROR, ET_ERROR, "invalid data type");
 						$$ = $1;
@@ -548,10 +550,26 @@
 				$$.type_str = EMPTY; /*mm_strdup("varchar");*/
 				$$.type_dimension = mm_strdup("-1");
 				$$.type_index = mm_strdup("-1");
 				$$.type_sizeof = NULL;
 			}
+			else if (strcmp($1, "nvarchar") == 0)
+            {
+                $$.type_enum = ECPGt_nvarchar;
+                $$.type_str = EMPTY; /*mm_strdup("nvarchar");*/
+                $$.type_dimension = mm_strdup("-1");
+                $$.type_index = mm_strdup("-1");
+                $$.type_sizeof = NULL;
+            }
+            else if (strcmp($1, "nchar") == 0)
+            {
+                $$.type_enum = ECPGt_nchar;
+                $$.type_str = EMPTY; /*mm_strdup("nchar");*/
+                $$.type_dimension = mm_strdup("-1");
+                $$.type_index = mm_strdup("-1");
+                $$.type_sizeof = NULL;
+            }
 			else if (strcmp($1, "float") == 0)
 			{
 				$$.type_enum = ECPGt_float;
 				$$.type_str = mm_strdup("float");
 				$$.type_dimension = mm_strdup("-1");
@@ -625,11 +643,11 @@
 			else
 			{
 				/* this is for typedef'ed types */
 				struct typedefs *this = get_typedef($1);
 
-				$$.type_str = (this->type->type_enum == ECPGt_varchar) ? EMPTY : mm_strdup(this->name);
+				$$.type_str = (this->type->type_enum == ECPGt_varchar || this->type->type_enum == ECPGt_nvarchar) ? EMPTY : mm_strdup(this->name);
 				$$.type_enum = this->type->type_enum;
 				$$.type_dimension = this->type->type_dimension;
 				$$.type_index = this->type->type_index;
 				if (this->type->type_sizeof && strlen(this->type->type_sizeof) != 0)
 					$$.type_sizeof = this->type->type_sizeof;
@@ -860,10 +878,11 @@
 						type = ECPGmake_array_type(ECPGmake_struct_type(struct_member_list[struct_level], actual_type[struct_level].type_enum, actual_type[struct_level].type_str, actual_type[struct_level].type_sizeof), dimension);
 
 					$$ = cat_str(5, $1, mm_strdup($2), $3.str, $4, $5);
 					break;
 
+				case ECPGt_nvarchar:
 				case ECPGt_varchar:
 					if (atoi(dimension) < 0)
 						type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length, varchar_counter);
 					else
 						type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length, varchar_counter), dimension);
@@ -884,10 +903,29 @@
 					else
 						$$ = cat_str(8, make2_str(mm_strdup(" struct varchar_"), vcn), mm_strdup(" { int len; char arr["), mm_strdup(length), mm_strdup("]; } "), mm_strdup($2), dim_str, $4, $5);
 					varchar_counter++;
 					break;
 
+				case ECPGt_nchar:
+                                        if (atoi(dimension) == -1)
+                                        {
+                                                int i = strlen($5);
+
+                                                if (atoi(length) == -1 && i > 0) /* char <var>[] = "string" */
+                                                {
+                                                        /* if we have an initializer but no string size set, let's use the initializer's length */
+                                                        free(length);
+                                                        length = mm_alloc(i+sizeof("sizeof()"));
+                                                        sprintf(length, "sizeof(%s)", $5+2);
+                                                }
+                                                type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length, 0);
+                                        }
+                                        else
+                                                type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length, 0), dimension);
+
+                                        $$ = cat_str(6, mm_strdup("char"), $1, mm_strdup($2), $3.str, $4, $5);
+                                        break;
 				case ECPGt_char:
 				case ECPGt_unsigned_char:
 				case ECPGt_string:
 					if (atoi(dimension) == -1)
 					{
@@ -1346,18 +1384,20 @@
 							type = ECPGmake_struct_type(struct_member_list[struct_level], $5.type_enum, $5.type_str, $5.type_sizeof);
 						else
 							type = ECPGmake_array_type(ECPGmake_struct_type(struct_member_list[struct_level], $5.type_enum, $5.type_str, $5.type_sizeof), dimension);
 						break;
 
+					case ECPGt_nvarchar:
 					case ECPGt_varchar:
 						if (atoi(dimension) == -1)
 							type = ECPGmake_simple_type($5.type_enum, length, 0);
 						else
 							type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, length, 0), dimension);
 						break;
 
 					case ECPGt_char:
+					case ECPGt_nchar:
 					case ECPGt_unsigned_char:
 					case ECPGt_string:
 						if (atoi(dimension) == -1)
 							type = ECPGmake_simple_type($5.type_enum, length, 0);
 						else
@@ -1842,10 +1882,12 @@
 		| CHAR_P			{ $$ = mm_strdup("char"); }
 		| FLOAT_P			{ $$ = mm_strdup("float"); }
 		| TO				{ $$ = mm_strdup("to"); }
 		| UNION				{ $$ = mm_strdup("union"); }
 		| VARCHAR			{ $$ = mm_strdup("varchar"); }
+		| NVARCHAR			{ $$ = mm_strdup("nvarchar"); }
+		| NCHAR				{ $$ = mm_strdup("nchar"); }
 		| '['				{ $$ = mm_strdup("["); }
 		| ']'				{ $$ = mm_strdup("]"); }
 		| '='				{ $$ = mm_strdup("="); }
 		| ':'				{ $$ = mm_strdup(":"); }
 		;
diff -U 5 -N -r -w ../orig.HEAD/src/interfaces/ecpg/preproc/type.c ./src/interfaces/ecpg/preproc/type.c
--- ../orig.HEAD/src/interfaces/ecpg/preproc/type.c	2013-08-19 20:22:13.000000000 -0400
+++ ./src/interfaces/ecpg/preproc/type.c	2013-08-20 05:08:51.000000000 -0400
@@ -135,10 +135,13 @@
 	switch (type)
 	{
 		case ECPGt_char:
 			return ("ECPGt_char");
 			break;
+		case ECPGt_nchar:
+			return ("ECPGt_nchar");
+			break;
 		case ECPGt_unsigned_char:
 			return ("ECPGt_unsigned_char");
 			break;
 		case ECPGt_short:
 			return ("ECPGt_short");
@@ -173,10 +176,14 @@
 		case ECPGt_bool:
 			return ("ECPGt_bool");
 			break;
 		case ECPGt_varchar:
 			return ("ECPGt_varchar");
+			break;
+		case ECPGt_nvarchar:
+			return ("ECPGt_nvarchar");
+			break;
 		case ECPGt_NO_INDICATOR:		/* no indicator */
 			return ("ECPGt_NO_INDICATOR");
 			break;
 		case ECPGt_char_variable:		/* string that should not be quoted */
 			return ("ECPGt_char_variable");
@@ -381,12 +388,12 @@
 				/*
 				 * we have to use the & operator except for arrays and
 				 * pointers
 				 */
 
+			case ECPGt_nvarchar:
 			case ECPGt_varchar:
-
 				/*
 				 * we have to use the pointer except for arrays with given
 				 * bounds
 				 */
 				if (((atoi(arrsize) > 0) ||
@@ -404,10 +411,11 @@
 					sprintf(offset, "sizeof(struct varchar_%d)", counter);
 				else
 					sprintf(offset, "sizeof(struct varchar)");
 				break;
 			case ECPGt_char:
+			case ECPGt_nchar:
 			case ECPGt_unsigned_char:
 			case ECPGt_char_variable:
 			case ECPGt_string:
 
 				/*
diff -U 5 -N -r -w ../orig.HEAD/src/interfaces/ecpg/preproc/variable.c ./src/interfaces/ecpg/preproc/variable.c
--- ../orig.HEAD/src/interfaces/ecpg/preproc/variable.c	2013-08-19 20:22:13.000000000 -0400
+++ ./src/interfaces/ecpg/preproc/variable.c	2013-08-20 05:04:08.000000000 -0400
@@ -527,11 +527,11 @@
 	if (pointer_len > 2)
 		mmerror(PARSE_ERROR, ET_FATAL, ngettext("multilevel pointers (more than 2 levels) are not supported; found %d level",
 												"multilevel pointers (more than 2 levels) are not supported; found %d levels", pointer_len),
 				pointer_len);
 
-	if (pointer_len > 1 && type_enum != ECPGt_char && type_enum != ECPGt_unsigned_char && type_enum != ECPGt_string)
+	if (pointer_len > 1 && type_enum != ECPGt_char && type_enum != ECPGt_nchar && type_enum != ECPGt_unsigned_char && type_enum != ECPGt_string)
 		mmerror(PARSE_ERROR, ET_FATAL, "pointer to pointer is not supported for this data type");
 
 	if (pointer_len > 1 && (atoi(*length) >= 0 || atoi(*dimension) >= 0))
 		mmerror(PARSE_ERROR, ET_FATAL, "multidimensional arrays are not supported");
 
@@ -552,10 +552,11 @@
 			if (atoi(*length) >= 0)
 				mmerror(PARSE_ERROR, ET_FATAL, "multidimensional arrays for structures are not supported");
 
 			break;
 		case ECPGt_varchar:
+		case ECPGt_nvarchar:
 			/* pointer has to get dimension 0 */
 			if (pointer_len)
 				*dimension = mm_strdup("0");
 
 			/* one index is the string length */
@@ -565,10 +566,11 @@
 				*dimension = mm_strdup("-1");
 			}
 
 			break;
 		case ECPGt_char:
+                case ECPGt_nchar:
 		case ECPGt_unsigned_char:
 		case ECPGt_string:
 			/* char ** */
 			if (pointer_len == 2)
 			{
diff -U 5 -N -r -w ../orig.HEAD/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c ./src/interfaces/ecpg/test/expected/compat_informix-sqlda.c
--- ../orig.HEAD/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c	2013-08-19 20:22:13.000000000 -0400
+++ ./src/interfaces/ecpg/test/expected/compat_informix-sqlda.c	2013-08-19 20:54:00.000000000 -0400
@@ -95,10 +95,11 @@
 #define	SQLTEXT		ECPGt_char
 #define	SQLVCHAR	ECPGt_char
 #define SQLINTERVAL     ECPGt_interval
 #define	SQLNCHAR	ECPGt_char
 #define	SQLNVCHAR	ECPGt_char
+#define SQLNVARCHAR     ECPGt_char
 #ifdef HAVE_LONG_LONG_INT_64
 #define	SQLINT8		ECPGt_long_long
 #define	SQLSERIAL8	ECPGt_long_long
 #else
 #define	SQLINT8		ECPGt_long
diff -U 5 -N -r -w ../orig.HEAD/src/interfaces/ecpg/test/expected/preproc-type.c ./src/interfaces/ecpg/test/expected/preproc-type.c
--- ../orig.HEAD/src/interfaces/ecpg/test/expected/preproc-type.c	2013-08-19 20:22:13.000000000 -0400
+++ ./src/interfaces/ecpg/test/expected/preproc-type.c	2013-08-19 20:54:00.000000000 -0400
@@ -81,10 +81,21 @@
   
   	 
 	 
    
   
+  
+         
+         
+   
+   
+  
+         
+         
+   
+
+  
 #line 29 "type.pgc"
  struct TBempl empl ;
  
 #line 30 "type.pgc"
  string str ;
@@ -98,48 +109,72 @@
  int len ;
  
 #line 35 "type.pgc"
  char text [ 10 ] ;
  } vc ;
+ 
+#line 41 "type.pgc"
+ struct nvarchar { 
+#line 39 "type.pgc"
+ int len ;
+ 
+#line 40 "type.pgc"
+ char text [ 10 ] ;
+ } nvc ;
+ 
+#line 46 "type.pgc"
+ struct uvarchar { 
+#line 44 "type.pgc"
+ int len ;
+ 
+#line 45 "type.pgc"
+ char text [ 20 ] ;
+ } uvc ;
 /* exec sql end declare section */
-#line 37 "type.pgc"
+#line 48 "type.pgc"
 
 
   /* exec sql var vc is [ 10 ] */
-#line 39 "type.pgc"
+#line 50 "type.pgc"
+
+  /* exec sql var nvc is [ 10 ] */
+#line 51 "type.pgc"
+
+  /* exec sql var uvc is [ 20 ] */
+#line 52 "type.pgc"
 
   ECPGdebug (1, stderr);
 
   empl.idnum = 1;
   { ECPGconnect(__LINE__, 0, "regress1" , NULL, NULL , NULL, 0); }
-#line 43 "type.pgc"
+#line 56 "type.pgc"
 
   if (sqlca.sqlcode)
     {
       printf ("connect error = %ld\n", sqlca.sqlcode);
       exit (sqlca.sqlcode);
     }
 
-  { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "create table empl ( idnum integer , name char ( 20 ) , accs smallint , string1 char ( 10 ) , string2 char ( 10 ) , string3 char ( 10 ) )", ECPGt_EOIT, ECPGt_EORT);}
-#line 51 "type.pgc"
+  { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "create table empl ( idnum integer , name char ( 20 ) , accs smallint , string1 char ( 10 ) , string2 char ( 10 ) , string3 char ( 10 ) , string4 char ( 10 ) , string5 char ( 10 ) )", ECPGt_EOIT, ECPGt_EORT);}
+#line 64 "type.pgc"
 
   if (sqlca.sqlcode)
     {
       printf ("create error = %ld\n", sqlca.sqlcode);
       exit (sqlca.sqlcode);
     }
 
-  { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into empl values ( 1 , 'user name' , 320 , 'first str' , 'second str' , 'third str' )", ECPGt_EOIT, ECPGt_EORT);}
-#line 58 "type.pgc"
+  { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into empl values ( 1 , 'user name' , 320 , 'first str' , 'second str' , 'third str' , 'fourth str' , 'fifth str' )", ECPGt_EOIT, ECPGt_EORT);}
+#line 71 "type.pgc"
 
   if (sqlca.sqlcode)
     {
       printf ("insert error = %ld\n", sqlca.sqlcode);
       exit (sqlca.sqlcode);
     }
 
-  { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select idnum , name , accs , string1 , string2 , string3 from empl where idnum = $1 ", 
+  { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select idnum , name , accs , string1 , string2 , string3 , string4 , string5 from empl where idnum = $1 ", 
 	ECPGt_long,&(empl.idnum),(long)1,(long)1,sizeof(long), 
 	ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, 
 	ECPGt_long,&(empl.idnum),(long)1,(long)1,sizeof(long), 
 	ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, 
 	ECPGt_char,&(empl.name),(long)21,(long)1,(21)*sizeof(char), 
@@ -149,22 +184,27 @@
 	ECPGt_char,(str),(long)11,(long)1,(11)*sizeof(char), 
 	ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, 
 	ECPGt_char,&(ptr),(long)0,(long)1,(1)*sizeof(char), 
 	ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, 
 	ECPGt_varchar,&(vc),(long)10,(long)1,sizeof(struct varchar), 
+	ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, 
+	ECPGt_nvarchar,&(nvc),(long)10,(long)1,sizeof(struct varchar), 
+	ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, 
+	ECPGt_uvarchar,&(uvc),(long)20,(long)1,sizeof(struct varchar), 
 	ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
-#line 68 "type.pgc"
+#line 81 "type.pgc"
 
   if (sqlca.sqlcode)
     {
       printf ("select error = %ld\n", sqlca.sqlcode);
       exit (sqlca.sqlcode);
     }
-  printf ("id=%ld name='%s' accs=%d str='%s' ptr='%s' vc='%10.10s'\n", empl.idnum, empl.name, empl.accs, str, ptr, vc.text);
+  printf ("id=%ld name='%s' accs=%d str='%s' ptr='%s' vc='%10.10s' vc.len='%d' nvc='%10.10s' nvc.len='%d' uvc='%20.20s' uvc.len='%d'\n", empl.idnum, empl.name, empl.accs, str, ptr, vc.text, vc.len, nvc.text, nvc.len, uvc.text, uvc.len);
 
   { ECPGdisconnect(__LINE__, "CURRENT");}
-#line 76 "type.pgc"
+#line 89 "type.pgc"
 
 
   free(ptr);
   exit (0);
 }
+
diff -U 5 -N -r -w ../orig.HEAD/src/interfaces/ecpg/test/expected/preproc-type.stderr ./src/interfaces/ecpg/test/expected/preproc-type.stderr
--- ../orig.HEAD/src/interfaces/ecpg/test/expected/preproc-type.stderr	2013-08-19 20:22:13.000000000 -0400
+++ ./src/interfaces/ecpg/test/expected/preproc-type.stderr	2013-08-19 20:54:00.000000000 -0400
@@ -1,40 +1,44 @@
 [NO_PID]: ECPGdebug: set to 1
 [NO_PID]: sqlca: code: 0, state: 00000
 [NO_PID]: ECPGconnect: opening database regress1 on <DEFAULT> port <DEFAULT>  
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 50: query: create table empl ( idnum integer , name char ( 20 ) , accs smallint , string1 char ( 10 ) , string2 char ( 10 ) , string3 char ( 10 ) ); with 0 parameter(s) on connection regress1
+[NO_PID]: ecpg_execute on line 63: query: create table empl ( idnum integer , name char ( 20 ) , accs smallint , string1 char ( 10 ) , string2 char ( 10 ) , string3 char ( 10 ) , string4 char ( 10 ) , string5 char ( 10 ) ); with 0 parameter(s) on connection regress1
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 50: using PQexec
+[NO_PID]: ecpg_execute on line 63: using PQexec
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 50: OK: CREATE TABLE
+[NO_PID]: ecpg_execute on line 63: OK: CREATE TABLE
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 58: query: insert into empl values ( 1 , 'user name' , 320 , 'first str' , 'second str' , 'third str' ); with 0 parameter(s) on connection regress1
+[NO_PID]: ecpg_execute on line 71: query: insert into empl values ( 1 , 'user name' , 320 , 'first str' , 'second str' , 'third str' , 'fourth str' , 'fifth str' ); with 0 parameter(s) on connection regress1
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 58: using PQexec
+[NO_PID]: ecpg_execute on line 71: using PQexec
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 58: OK: INSERT 0 1
+[NO_PID]: ecpg_execute on line 71: OK: INSERT 0 1
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 65: query: select idnum , name , accs , string1 , string2 , string3 from empl where idnum = $1 ; with 1 parameter(s) on connection regress1
+[NO_PID]: ecpg_execute on line 78: query: select idnum , name , accs , string1 , string2 , string3 , string4 , string5 from empl where idnum = $1 ; with 1 parameter(s) on connection regress1
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 65: using PQexecParams
+[NO_PID]: ecpg_execute on line 78: using PQexecParams
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: free_params on line 65: parameter 1 = 1
+[NO_PID]: free_params on line 78: parameter 1 = 1
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 65: correctly got 1 tuples with 6 fields
+[NO_PID]: ecpg_execute on line 78: correctly got 1 tuples with 8 fields
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_get_data on line 65: RESULT: 1 offset: -1; array: no
+[NO_PID]: ecpg_get_data on line 78: RESULT: 1 offset: -1; array: no
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_get_data on line 65: RESULT: user name            offset: -1; array: no
+[NO_PID]: ecpg_get_data on line 78: RESULT: user name            offset: -1; array: no
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_get_data on line 65: RESULT: 320 offset: -1; array: no
+[NO_PID]: ecpg_get_data on line 78: RESULT: 320 offset: -1; array: no
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_get_data on line 65: RESULT: first str  offset: -1; array: no
+[NO_PID]: ecpg_get_data on line 78: RESULT: first str  offset: -1; array: no
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_store_result on line 65: allocating memory for 1 tuples
+[NO_PID]: ecpg_store_result on line 78: allocating memory for 1 tuples
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_get_data on line 65: RESULT: second str offset: -1; array: no
+[NO_PID]: ecpg_get_data on line 78: RESULT: second str offset: -1; array: no
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_get_data on line 65: RESULT: third str  offset: -1; array: no
+[NO_PID]: ecpg_get_data on line 78: RESULT: third str  offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 78: RESULT: fourth str offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 78: RESULT: fifth str  offset: -1; array: no
 [NO_PID]: sqlca: code: 0, state: 00000
 [NO_PID]: ecpg_finish: connection regress1 closed
 [NO_PID]: sqlca: code: 0, state: 00000
diff -U 5 -N -r -w ../orig.HEAD/src/interfaces/ecpg/test/expected/preproc-type.stdout ./src/interfaces/ecpg/test/expected/preproc-type.stdout
--- ../orig.HEAD/src/interfaces/ecpg/test/expected/preproc-type.stdout	2013-08-19 20:22:13.000000000 -0400
+++ ./src/interfaces/ecpg/test/expected/preproc-type.stdout	2013-08-19 20:54:00.000000000 -0400
@@ -1 +1 @@
-id=1 name='user name           ' accs=320 str='first str ' ptr='second str' vc='third str '
+id=1 name='user name           ' accs=320 str='first str ' ptr='second str' vc='third str ' vc.len='10' nvc='fourth str' nvc.len='10' uvc='                   f' uvc.len='20'
diff -U 5 -N -r -w ../orig.HEAD/src/interfaces/ecpg/test/expected/sql-fetch.c ./src/interfaces/ecpg/test/expected/sql-fetch.c
--- ../orig.HEAD/src/interfaces/ecpg/test/expected/sql-fetch.c	2013-08-19 20:22:13.000000000 -0400
+++ ./src/interfaces/ecpg/test/expected/sql-fetch.c	2013-08-19 20:54:00.000000000 -0400
@@ -25,210 +25,250 @@
 int main() {
   /* exec sql begin declare section */
      
       
   
+      
+     
+     
+  
 #line 9 "fetch.pgc"
  char str [ 25 ] ;
  
 #line 10 "fetch.pgc"
  int i , count = 1 ;
-/* exec sql end declare section */
+ 
 #line 11 "fetch.pgc"
+ char nstr [ 25 ] ;
+ 
+#line 12 "fetch.pgc"
+  struct varchar_1  { int len; char arr[ 25 ]; }  _varchar ;
+ 
+#line 13 "fetch.pgc"
+  struct varchar_2  { int len; char arr[ 25 ]; }  _nvarchar ;
+ 
+#line 14 "fetch.pgc"
+  struct varchar_3  { int len; char arr[ 25 ]; }  _uvarchar ;
+/* exec sql end declare section */
+#line 15 "fetch.pgc"
 
 
   ECPGdebug(1, stderr);
   { ECPGconnect(__LINE__, 0, "regress1" , NULL, NULL , NULL, 0); }
-#line 14 "fetch.pgc"
+#line 18 "fetch.pgc"
 
 
   /* exec sql whenever sql_warning  sqlprint ; */
-#line 16 "fetch.pgc"
+#line 20 "fetch.pgc"
 
   /* exec sql whenever sqlerror  sqlprint ; */
-#line 17 "fetch.pgc"
+#line 21 "fetch.pgc"
 
 
-  { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "create table My_Table ( Item1 int , Item2 text )", ECPGt_EOIT, ECPGt_EORT);
-#line 19 "fetch.pgc"
+  { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "create table My_Table ( Item1 int , Item2 text , Item3 text , Item4 varchar , Item5 varchar , Item6 varchar )", ECPGt_EOIT, ECPGt_EORT);
+#line 23 "fetch.pgc"
 
 if (sqlca.sqlwarn[0] == 'W') sqlprint();
-#line 19 "fetch.pgc"
+#line 23 "fetch.pgc"
 
 if (sqlca.sqlcode < 0) sqlprint();}
-#line 19 "fetch.pgc"
+#line 23 "fetch.pgc"
 
 
-  { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into My_Table values ( 1 , 'text1' )", ECPGt_EOIT, ECPGt_EORT);
-#line 21 "fetch.pgc"
+  { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into My_Table values ( 1 , 'text1' , 'text1' , 'text1' , 'text1' , 'text1' )", ECPGt_EOIT, ECPGt_EORT);
+#line 25 "fetch.pgc"
 
 if (sqlca.sqlwarn[0] == 'W') sqlprint();
-#line 21 "fetch.pgc"
+#line 25 "fetch.pgc"
 
 if (sqlca.sqlcode < 0) sqlprint();}
-#line 21 "fetch.pgc"
+#line 25 "fetch.pgc"
 
-  { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into My_Table values ( 2 , 'text2' )", ECPGt_EOIT, ECPGt_EORT);
-#line 22 "fetch.pgc"
+  { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into My_Table values ( 2 , 'text2' , 'text2' , 'text2' , 'text2' , 'text2' )", ECPGt_EOIT, ECPGt_EORT);
+#line 26 "fetch.pgc"
 
 if (sqlca.sqlwarn[0] == 'W') sqlprint();
-#line 22 "fetch.pgc"
+#line 26 "fetch.pgc"
 
 if (sqlca.sqlcode < 0) sqlprint();}
-#line 22 "fetch.pgc"
+#line 26 "fetch.pgc"
 
-  { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into My_Table values ( 3 , 'text3' )", ECPGt_EOIT, ECPGt_EORT);
-#line 23 "fetch.pgc"
+  { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into My_Table values ( 3 , 'text3' , 'text3' , 'text3' , 'text3' , 'text3' )", ECPGt_EOIT, ECPGt_EORT);
+#line 27 "fetch.pgc"
 
 if (sqlca.sqlwarn[0] == 'W') sqlprint();
-#line 23 "fetch.pgc"
+#line 27 "fetch.pgc"
 
 if (sqlca.sqlcode < 0) sqlprint();}
-#line 23 "fetch.pgc"
+#line 27 "fetch.pgc"
 
-  { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into My_Table values ( 4 , 'text4' )", ECPGt_EOIT, ECPGt_EORT);
-#line 24 "fetch.pgc"
+  { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into My_Table values ( 4 , 'text4' , 'text4' , 'text4' , 'text4' , 'text4' )", ECPGt_EOIT, ECPGt_EORT);
+#line 28 "fetch.pgc"
 
 if (sqlca.sqlwarn[0] == 'W') sqlprint();
-#line 24 "fetch.pgc"
+#line 28 "fetch.pgc"
 
 if (sqlca.sqlcode < 0) sqlprint();}
-#line 24 "fetch.pgc"
+#line 28 "fetch.pgc"
 
 
   /* declare C cursor for select * from My_Table */
-#line 26 "fetch.pgc"
+#line 30 "fetch.pgc"
 
 
   { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "declare C cursor for select * from My_Table", ECPGt_EOIT, ECPGt_EORT);
-#line 28 "fetch.pgc"
+#line 32 "fetch.pgc"
 
 if (sqlca.sqlwarn[0] == 'W') sqlprint();
-#line 28 "fetch.pgc"
+#line 32 "fetch.pgc"
 
 if (sqlca.sqlcode < 0) sqlprint();}
-#line 28 "fetch.pgc"
+#line 32 "fetch.pgc"
 
 
   /* exec sql whenever not found  break ; */
-#line 30 "fetch.pgc"
+#line 34 "fetch.pgc"
 
   while (1) {
   	{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch 1 in C", ECPGt_EOIT, 
 	ECPGt_int,&(i),(long)1,(long)1,sizeof(int), 
 	ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, 
 	ECPGt_char,(str),(long)25,(long)1,(25)*sizeof(char), 
+	ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, 
+	ECPGt_nchar,(nstr),(long)25,(long)1,(25)*sizeof(char), 
+	ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, 
+	ECPGt_varchar,&(_varchar),(long)25,(long)1,sizeof(struct varchar_1), 
+	ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, 
+	ECPGt_nvarchar,&(_nvarchar),(long)25,(long)1,sizeof(struct varchar_2), 
+	ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, 
+	ECPGt_uvarchar,&(_uvarchar),(long)25,(long)1,sizeof(struct varchar_3), 
 	ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
-#line 32 "fetch.pgc"
+#line 36 "fetch.pgc"
 
 if (sqlca.sqlcode == ECPG_NOT_FOUND) break;
-#line 32 "fetch.pgc"
+#line 36 "fetch.pgc"
 
 if (sqlca.sqlwarn[0] == 'W') sqlprint();
-#line 32 "fetch.pgc"
+#line 36 "fetch.pgc"
 
 if (sqlca.sqlcode < 0) sqlprint();}
-#line 32 "fetch.pgc"
+#line 36 "fetch.pgc"
 
-	printf("%d: %s\n", i, str);
+	printf("%d: %s, %s, %s, %s\n", i, str, nstr, _varchar.arr, _nvarchar.arr);
   }
 
   /* exec sql whenever not found  continue ; */
-#line 36 "fetch.pgc"
+#line 40 "fetch.pgc"
 
   { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "move backward 2 in C", ECPGt_EOIT, ECPGt_EORT);
-#line 37 "fetch.pgc"
+#line 41 "fetch.pgc"
 
 if (sqlca.sqlwarn[0] == 'W') sqlprint();
-#line 37 "fetch.pgc"
+#line 41 "fetch.pgc"
 
 if (sqlca.sqlcode < 0) sqlprint();}
-#line 37 "fetch.pgc"
+#line 41 "fetch.pgc"
 
 
   { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch $0 in C", 
 	ECPGt_int,&(count),(long)1,(long)1,sizeof(int), 
 	ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, 
 	ECPGt_int,&(i),(long)1,(long)1,sizeof(int), 
 	ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, 
 	ECPGt_char,(str),(long)25,(long)1,(25)*sizeof(char), 
+	ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, 
+	ECPGt_nchar,(nstr),(long)25,(long)1,(25)*sizeof(char), 
+	ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, 
+	ECPGt_varchar,&(_varchar),(long)25,(long)1,sizeof(struct varchar_1), 
+	ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, 
+	ECPGt_nvarchar,&(_nvarchar),(long)25,(long)1,sizeof(struct varchar_2), 
+	ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, 
+	ECPGt_uvarchar,&(_uvarchar),(long)25,(long)1,sizeof(struct varchar_3), 
 	ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
-#line 39 "fetch.pgc"
+#line 43 "fetch.pgc"
 
 if (sqlca.sqlwarn[0] == 'W') sqlprint();
-#line 39 "fetch.pgc"
+#line 43 "fetch.pgc"
 
 if (sqlca.sqlcode < 0) sqlprint();}
-#line 39 "fetch.pgc"
+#line 43 "fetch.pgc"
 
-  printf("%d: %s\n", i, str);
+  printf("%d: %s, %s, %s, %s\n", i, str, nstr, _varchar.arr, _nvarchar.arr);
 
   /* declare D cursor for select * from My_Table where Item1 = $1 */
-#line 42 "fetch.pgc"
+#line 46 "fetch.pgc"
 
 
   { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "declare D cursor for select * from My_Table where Item1 = $1", 
 	ECPGt_const,"1",(long)1,(long)1,strlen("1"), 
 	ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);
-#line 44 "fetch.pgc"
+#line 48 "fetch.pgc"
 
 if (sqlca.sqlwarn[0] == 'W') sqlprint();
-#line 44 "fetch.pgc"
+#line 48 "fetch.pgc"
 
 if (sqlca.sqlcode < 0) sqlprint();}
-#line 44 "fetch.pgc"
+#line 48 "fetch.pgc"
 
 
   /* exec sql whenever not found  break ; */
-#line 46 "fetch.pgc"
+#line 50 "fetch.pgc"
 
   while (1) {
   	{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch 1 in D", ECPGt_EOIT, 
 	ECPGt_int,&(i),(long)1,(long)1,sizeof(int), 
 	ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, 
 	ECPGt_char,(str),(long)25,(long)1,(25)*sizeof(char), 
+	ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, 
+	ECPGt_nchar,(nstr),(long)25,(long)1,(25)*sizeof(char), 
+	ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, 
+	ECPGt_varchar,&(_varchar),(long)25,(long)1,sizeof(struct varchar_1), 
+	ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, 
+	ECPGt_nvarchar,&(_nvarchar),(long)25,(long)1,sizeof(struct varchar_2), 
+	ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, 
+	ECPGt_uvarchar,&(_uvarchar),(long)25,(long)1,sizeof(struct varchar_3), 
 	ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
-#line 48 "fetch.pgc"
+#line 52 "fetch.pgc"
 
 if (sqlca.sqlcode == ECPG_NOT_FOUND) break;
-#line 48 "fetch.pgc"
+#line 52 "fetch.pgc"
 
 if (sqlca.sqlwarn[0] == 'W') sqlprint();
-#line 48 "fetch.pgc"
+#line 52 "fetch.pgc"
 
 if (sqlca.sqlcode < 0) sqlprint();}
-#line 48 "fetch.pgc"
+#line 52 "fetch.pgc"
 
-	printf("%d: %s\n", i, str);
+	printf("%d: %s, %s, %s, %s\n", i, str, nstr, _varchar.arr, _nvarchar.arr);
   }
   { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "close D", ECPGt_EOIT, ECPGt_EORT);
-#line 51 "fetch.pgc"
+#line 55 "fetch.pgc"
 
 if (sqlca.sqlwarn[0] == 'W') sqlprint();
-#line 51 "fetch.pgc"
+#line 55 "fetch.pgc"
 
 if (sqlca.sqlcode < 0) sqlprint();}
-#line 51 "fetch.pgc"
+#line 55 "fetch.pgc"
 
 
   { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "drop table My_Table", ECPGt_EOIT, ECPGt_EORT);
-#line 53 "fetch.pgc"
+#line 57 "fetch.pgc"
 
 if (sqlca.sqlwarn[0] == 'W') sqlprint();
-#line 53 "fetch.pgc"
+#line 57 "fetch.pgc"
 
 if (sqlca.sqlcode < 0) sqlprint();}
-#line 53 "fetch.pgc"
+#line 57 "fetch.pgc"
 
 
   { ECPGdisconnect(__LINE__, "ALL");
-#line 55 "fetch.pgc"
+#line 59 "fetch.pgc"
 
 if (sqlca.sqlwarn[0] == 'W') sqlprint();
-#line 55 "fetch.pgc"
+#line 59 "fetch.pgc"
 
 if (sqlca.sqlcode < 0) sqlprint();}
-#line 55 "fetch.pgc"
+#line 59 "fetch.pgc"
 
 
   return 0;
 }
diff -U 5 -N -r -w ../orig.HEAD/src/interfaces/ecpg/test/expected/sql-fetch.stderr ./src/interfaces/ecpg/test/expected/sql-fetch.stderr
--- ../orig.HEAD/src/interfaces/ecpg/test/expected/sql-fetch.stderr	2013-08-19 20:22:13.000000000 -0400
+++ ./src/interfaces/ecpg/test/expected/sql-fetch.stderr	2013-08-19 20:54:00.000000000 -0400
@@ -1,147 +1,195 @@
 [NO_PID]: ECPGdebug: set to 1
 [NO_PID]: sqlca: code: 0, state: 00000
 [NO_PID]: ECPGconnect: opening database regress1 on <DEFAULT> port <DEFAULT>  
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 19: query: create table My_Table ( Item1 int , Item2 text ); with 0 parameter(s) on connection regress1
+[NO_PID]: ecpg_execute on line 23: query: create table My_Table ( Item1 int , Item2 text , Item3 text , Item4 varchar , Item5 varchar , Item6 varchar ); with 0 parameter(s) on connection regress1
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 19: using PQexec
+[NO_PID]: ecpg_execute on line 23: using PQexec
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 19: OK: CREATE TABLE
+[NO_PID]: ecpg_execute on line 23: OK: CREATE TABLE
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 21: query: insert into My_Table values ( 1 , 'text1' ); with 0 parameter(s) on connection regress1
+[NO_PID]: ecpg_execute on line 25: query: insert into My_Table values ( 1 , 'text1' , 'text1' , 'text1' , 'text1' , 'text1' ); with 0 parameter(s) on connection regress1
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 21: using PQexec
+[NO_PID]: ecpg_execute on line 25: using PQexec
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 21: OK: INSERT 0 1
+[NO_PID]: ecpg_execute on line 25: OK: INSERT 0 1
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 22: query: insert into My_Table values ( 2 , 'text2' ); with 0 parameter(s) on connection regress1
+[NO_PID]: ecpg_execute on line 26: query: insert into My_Table values ( 2 , 'text2' , 'text2' , 'text2' , 'text2' , 'text2' ); with 0 parameter(s) on connection regress1
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 22: using PQexec
+[NO_PID]: ecpg_execute on line 26: using PQexec
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 22: OK: INSERT 0 1
+[NO_PID]: ecpg_execute on line 26: OK: INSERT 0 1
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 23: query: insert into My_Table values ( 3 , 'text3' ); with 0 parameter(s) on connection regress1
+[NO_PID]: ecpg_execute on line 27: query: insert into My_Table values ( 3 , 'text3' , 'text3' , 'text3' , 'text3' , 'text3' ); with 0 parameter(s) on connection regress1
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 23: using PQexec
+[NO_PID]: ecpg_execute on line 27: using PQexec
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 23: OK: INSERT 0 1
+[NO_PID]: ecpg_execute on line 27: OK: INSERT 0 1
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 24: query: insert into My_Table values ( 4 , 'text4' ); with 0 parameter(s) on connection regress1
+[NO_PID]: ecpg_execute on line 28: query: insert into My_Table values ( 4 , 'text4' , 'text4' , 'text4' , 'text4' , 'text4' ); with 0 parameter(s) on connection regress1
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 24: using PQexec
+[NO_PID]: ecpg_execute on line 28: using PQexec
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 24: OK: INSERT 0 1
+[NO_PID]: ecpg_execute on line 28: OK: INSERT 0 1
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 28: query: declare C cursor for select * from My_Table; with 0 parameter(s) on connection regress1
+[NO_PID]: ecpg_execute on line 32: query: declare C cursor for select * from My_Table; with 0 parameter(s) on connection regress1
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 28: using PQexec
+[NO_PID]: ecpg_execute on line 32: using PQexec
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 28: OK: DECLARE CURSOR
+[NO_PID]: ecpg_execute on line 32: OK: DECLARE CURSOR
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 32: query: fetch 1 in C; with 0 parameter(s) on connection regress1
+[NO_PID]: ecpg_execute on line 36: query: fetch 1 in C; with 0 parameter(s) on connection regress1
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 32: using PQexec
+[NO_PID]: ecpg_execute on line 36: using PQexec
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 32: correctly got 1 tuples with 2 fields
+[NO_PID]: ecpg_execute on line 36: correctly got 1 tuples with 6 fields
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_get_data on line 32: RESULT: 1 offset: -1; array: no
+[NO_PID]: ecpg_get_data on line 36: RESULT: 1 offset: -1; array: no
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_get_data on line 32: RESULT: text1 offset: -1; array: no
+[NO_PID]: ecpg_get_data on line 36: RESULT: text1 offset: -1; array: no
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 32: query: fetch 1 in C; with 0 parameter(s) on connection regress1
+[NO_PID]: ecpg_get_data on line 36: RESULT: text1 offset: -1; array: no
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 32: using PQexec
+[NO_PID]: ecpg_get_data on line 36: RESULT: text1 offset: -1; array: no
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 32: correctly got 1 tuples with 2 fields
+[NO_PID]: ecpg_get_data on line 36: RESULT: text1 offset: -1; array: no
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_get_data on line 32: RESULT: 2 offset: -1; array: no
+[NO_PID]: ecpg_get_data on line 36: RESULT: text1 offset: -1; array: no
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_get_data on line 32: RESULT: text2 offset: -1; array: no
+[NO_PID]: ecpg_execute on line 36: query: fetch 1 in C; with 0 parameter(s) on connection regress1
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 32: query: fetch 1 in C; with 0 parameter(s) on connection regress1
+[NO_PID]: ecpg_execute on line 36: using PQexec
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 32: using PQexec
+[NO_PID]: ecpg_execute on line 36: correctly got 1 tuples with 6 fields
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 32: correctly got 1 tuples with 2 fields
+[NO_PID]: ecpg_get_data on line 36: RESULT: 2 offset: -1; array: no
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_get_data on line 32: RESULT: 3 offset: -1; array: no
+[NO_PID]: ecpg_get_data on line 36: RESULT: text2 offset: -1; array: no
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_get_data on line 32: RESULT: text3 offset: -1; array: no
+[NO_PID]: ecpg_get_data on line 36: RESULT: text2 offset: -1; array: no
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 32: query: fetch 1 in C; with 0 parameter(s) on connection regress1
+[NO_PID]: ecpg_get_data on line 36: RESULT: text2 offset: -1; array: no
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 32: using PQexec
+[NO_PID]: ecpg_get_data on line 36: RESULT: text2 offset: -1; array: no
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 32: correctly got 1 tuples with 2 fields
+[NO_PID]: ecpg_get_data on line 36: RESULT: text2 offset: -1; array: no
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_get_data on line 32: RESULT: 4 offset: -1; array: no
+[NO_PID]: ecpg_execute on line 36: query: fetch 1 in C; with 0 parameter(s) on connection regress1
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_get_data on line 32: RESULT: text4 offset: -1; array: no
+[NO_PID]: ecpg_execute on line 36: using PQexec
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 32: query: fetch 1 in C; with 0 parameter(s) on connection regress1
+[NO_PID]: ecpg_execute on line 36: correctly got 1 tuples with 6 fields
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 32: using PQexec
+[NO_PID]: ecpg_get_data on line 36: RESULT: 3 offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 36: RESULT: text3 offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 36: RESULT: text3 offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 36: RESULT: text3 offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 36: RESULT: text3 offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 36: RESULT: text3 offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 36: query: fetch 1 in C; with 0 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 36: using PQexec
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 32: correctly got 0 tuples with 2 fields
+[NO_PID]: ecpg_execute on line 36: correctly got 1 tuples with 6 fields
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: raising sqlcode 100 on line 32: no data found on line 32
+[NO_PID]: ecpg_get_data on line 36: RESULT: 4 offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 36: RESULT: text4 offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 36: RESULT: text4 offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 36: RESULT: text4 offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 36: RESULT: text4 offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 36: RESULT: text4 offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 36: query: fetch 1 in C; with 0 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 36: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 36: correctly got 0 tuples with 6 fields
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: raising sqlcode 100 on line 36: no data found on line 36
 [NO_PID]: sqlca: code: 100, state: 02000
-[NO_PID]: ecpg_execute on line 37: query: move backward 2 in C; with 0 parameter(s) on connection regress1
+[NO_PID]: ecpg_execute on line 41: query: move backward 2 in C; with 0 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 41: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 41: OK: MOVE 2
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 43: query: fetch 1 in C; with 0 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 43: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 43: correctly got 1 tuples with 6 fields
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 43: RESULT: 4 offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 43: RESULT: text4 offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 43: RESULT: text4 offset: -1; array: no
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 37: using PQexec
+[NO_PID]: ecpg_get_data on line 43: RESULT: text4 offset: -1; array: no
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 37: OK: MOVE 2
+[NO_PID]: ecpg_get_data on line 43: RESULT: text4 offset: -1; array: no
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 39: query: fetch 1 in C; with 0 parameter(s) on connection regress1
+[NO_PID]: ecpg_get_data on line 43: RESULT: text4 offset: -1; array: no
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 39: using PQexec
+[NO_PID]: ecpg_execute on line 48: query: declare D cursor for select * from My_Table where Item1 = $1; with 1 parameter(s) on connection regress1
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 39: correctly got 1 tuples with 2 fields
+[NO_PID]: ecpg_execute on line 48: using PQexecParams
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_get_data on line 39: RESULT: 4 offset: -1; array: no
+[NO_PID]: free_params on line 48: parameter 1 = 1
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_get_data on line 39: RESULT: text4 offset: -1; array: no
+[NO_PID]: ecpg_execute on line 48: OK: DECLARE CURSOR
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 44: query: declare D cursor for select * from My_Table where Item1 = $1; with 1 parameter(s) on connection regress1
+[NO_PID]: ecpg_execute on line 52: query: fetch 1 in D; with 0 parameter(s) on connection regress1
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 44: using PQexecParams
+[NO_PID]: ecpg_execute on line 52: using PQexec
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: free_params on line 44: parameter 1 = 1
+[NO_PID]: ecpg_execute on line 52: correctly got 1 tuples with 6 fields
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 44: OK: DECLARE CURSOR
+[NO_PID]: ecpg_get_data on line 52: RESULT: 1 offset: -1; array: no
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 48: query: fetch 1 in D; with 0 parameter(s) on connection regress1
+[NO_PID]: ecpg_get_data on line 52: RESULT: text1 offset: -1; array: no
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 48: using PQexec
+[NO_PID]: ecpg_get_data on line 52: RESULT: text1 offset: -1; array: no
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 48: correctly got 1 tuples with 2 fields
+[NO_PID]: ecpg_get_data on line 52: RESULT: text1 offset: -1; array: no
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_get_data on line 48: RESULT: 1 offset: -1; array: no
+[NO_PID]: ecpg_get_data on line 52: RESULT: text1 offset: -1; array: no
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_get_data on line 48: RESULT: text1 offset: -1; array: no
+[NO_PID]: ecpg_get_data on line 52: RESULT: text1 offset: -1; array: no
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 48: query: fetch 1 in D; with 0 parameter(s) on connection regress1
+[NO_PID]: ecpg_execute on line 52: query: fetch 1 in D; with 0 parameter(s) on connection regress1
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 48: using PQexec
+[NO_PID]: ecpg_execute on line 52: using PQexec
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 48: correctly got 0 tuples with 2 fields
+[NO_PID]: ecpg_execute on line 52: correctly got 0 tuples with 6 fields
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: raising sqlcode 100 on line 48: no data found on line 48
+[NO_PID]: raising sqlcode 100 on line 52: no data found on line 52
 [NO_PID]: sqlca: code: 100, state: 02000
-[NO_PID]: ecpg_execute on line 51: query: close D; with 0 parameter(s) on connection regress1
+[NO_PID]: ecpg_execute on line 55: query: close D; with 0 parameter(s) on connection regress1
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 51: using PQexec
+[NO_PID]: ecpg_execute on line 55: using PQexec
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 51: OK: CLOSE CURSOR
+[NO_PID]: ecpg_execute on line 55: OK: CLOSE CURSOR
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 53: query: drop table My_Table; with 0 parameter(s) on connection regress1
+[NO_PID]: ecpg_execute on line 57: query: drop table My_Table; with 0 parameter(s) on connection regress1
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 53: using PQexec
+[NO_PID]: ecpg_execute on line 57: using PQexec
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_check_PQresult on line 53: bad response - ERROR:  cannot DROP TABLE "my_table" because it is being used by active queries in this session
+[NO_PID]: ecpg_check_PQresult on line 57: bad response - ERROR:  cannot DROP TABLE "my_table" because it is being used by active queries in this session
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: raising sqlstate 55006 (sqlcode -400): cannot DROP TABLE "my_table" because it is being used by active queries in this session on line 53
+[NO_PID]: raising sqlstate 55006 (sqlcode -400): cannot DROP TABLE "my_table" because it is being used by active queries in this session on line 57
 [NO_PID]: sqlca: code: -400, state: 55006
-SQL error: cannot DROP TABLE "my_table" because it is being used by active queries in this session on line 53
+SQL error: cannot DROP TABLE "my_table" because it is being used by active queries in this session on line 57
 [NO_PID]: ecpg_finish: connection regress1 closed
 [NO_PID]: sqlca: code: 0, state: 00000
diff -U 5 -N -r -w ../orig.HEAD/src/interfaces/ecpg/test/expected/sql-fetch.stdout ./src/interfaces/ecpg/test/expected/sql-fetch.stdout
--- ../orig.HEAD/src/interfaces/ecpg/test/expected/sql-fetch.stdout	2013-08-19 20:22:13.000000000 -0400
+++ ./src/interfaces/ecpg/test/expected/sql-fetch.stdout	2013-08-19 20:54:00.000000000 -0400
@@ -1,6 +1,6 @@
-1: text1
-2: text2
-3: text3
-4: text4
-4: text4
-1: text1
+1: text1, text1, text1, text1
+2: text2, text2, text2, text2
+3: text3, text3, text3, text3
+4: text4, text4, text4, text4
+4: text4, text4, text4, text4
+1: text1, text1, text1, text1
diff -U 5 -N -r -w ../orig.HEAD/src/interfaces/ecpg/test/preproc/type.pgc ./src/interfaces/ecpg/test/preproc/type.pgc
--- ../orig.HEAD/src/interfaces/ecpg/test/preproc/type.pgc	2013-08-19 20:22:13.000000000 -0400
+++ ./src/interfaces/ecpg/test/preproc/type.pgc	2013-08-19 20:54:00.000000000 -0400
@@ -32,13 +32,26 @@
   struct varchar
   {
   	int len;
 	char text[10];
   } vc;
+  struct nvarchar
+  {
+        int len;
+        char text[10];
+  } nvc;
+  struct uvarchar
+  {
+        int len;
+        char text[20];
+  } uvc;
+
   EXEC SQL END DECLARE SECTION;
 
   EXEC SQL var vc is varchar[10];
+  EXEC SQL var nvc is nvarchar[10];
+  EXEC SQL var uvc is uvarchar[20];
   ECPGdebug (1, stderr);
 
   empl.idnum = 1;
   EXEC SQL connect to REGRESSDB1;
   if (sqlca.sqlcode)
@@ -46,35 +59,36 @@
       printf ("connect error = %ld\n", sqlca.sqlcode);
       exit (sqlca.sqlcode);
     }
 
   EXEC SQL create table empl
-    (idnum integer, name char(20), accs smallint, string1 char(10), string2 char(10), string3 char(10));
+    (idnum integer, name char(20), accs smallint, string1 char(10), string2 char(10), string3 char(10), string4 char(10), string5 char(10));
   if (sqlca.sqlcode)
     {
       printf ("create error = %ld\n", sqlca.sqlcode);
       exit (sqlca.sqlcode);
     }
 
-  EXEC SQL insert into empl values (1, 'user name', 320, 'first str', 'second str', 'third str');
+  EXEC SQL insert into empl values (1, 'user name', 320, 'first str', 'second str', 'third str', 'fourth str', 'fifth str');
   if (sqlca.sqlcode)
     {
       printf ("insert error = %ld\n", sqlca.sqlcode);
       exit (sqlca.sqlcode);
     }
 
-  EXEC SQL select idnum, name, accs, string1, string2, string3
-	into :empl, :str, :ptr, :vc
+  EXEC SQL select idnum, name, accs, string1, string2, string3, string4, string5 
+	into :empl, :str, :ptr, :vc, :nvc, :uvc
 	from empl
 	where idnum =:empl.idnum;
   if (sqlca.sqlcode)
     {
       printf ("select error = %ld\n", sqlca.sqlcode);
       exit (sqlca.sqlcode);
     }
-  printf ("id=%ld name='%s' accs=%d str='%s' ptr='%s' vc='%10.10s'\n", empl.idnum, empl.name, empl.accs, str, ptr, vc.text);
+  printf ("id=%ld name='%s' accs=%d str='%s' ptr='%s' vc='%10.10s' vc.len='%d' nvc='%10.10s' nvc.len='%d' uvc='%20.20s' uvc.len='%d'\n", empl.idnum, empl.name, empl.accs, str, ptr, vc.text, vc.len, nvc.text, nvc.len, uvc.text, uvc.len);
 
   EXEC SQL disconnect;
 
   free(ptr);
   exit (0);
 }
+
diff -U 5 -N -r -w ../orig.HEAD/src/interfaces/ecpg/test/sql/fetch.pgc ./src/interfaces/ecpg/test/sql/fetch.pgc
--- ../orig.HEAD/src/interfaces/ecpg/test/sql/fetch.pgc	2013-08-19 20:22:13.000000000 -0400
+++ ./src/interfaces/ecpg/test/sql/fetch.pgc	2013-08-19 20:54:00.000000000 -0400
@@ -6,49 +6,53 @@
 
 int main() {
   EXEC SQL BEGIN DECLARE SECTION;
     char str[25];
     int i, count=1;
+    NCHAR nstr[25];
+    VARCHAR  _varchar[25];
+    NVARCHAR _nvarchar[25];
+    UVARCHAR _uvarchar[25];
   EXEC SQL END DECLARE SECTION;
 
   ECPGdebug(1, stderr);
   EXEC SQL CONNECT TO REGRESSDB1;
 
   EXEC SQL WHENEVER SQLWARNING SQLPRINT;
   EXEC SQL WHENEVER SQLERROR SQLPRINT;
 
-  EXEC SQL CREATE TABLE My_Table ( Item1 int, Item2 text );
+  EXEC SQL CREATE TABLE My_Table ( Item1 int, Item2 text, Item3 text, Item4 varchar, Item5 varchar, Item6 varchar );
 
-  EXEC SQL INSERT INTO My_Table VALUES ( 1, 'text1');
-  EXEC SQL INSERT INTO My_Table VALUES ( 2, 'text2');
-  EXEC SQL INSERT INTO My_Table VALUES ( 3, 'text3');
-  EXEC SQL INSERT INTO My_Table VALUES ( 4, 'text4');
+  EXEC SQL INSERT INTO My_Table VALUES ( 1, 'text1', 'text1', 'text1', 'text1', 'text1');
+  EXEC SQL INSERT INTO My_Table VALUES ( 2, 'text2', 'text2', 'text2', 'text2', 'text2');
+  EXEC SQL INSERT INTO My_Table VALUES ( 3, 'text3', 'text3', 'text3', 'text3', 'text3');
+  EXEC SQL INSERT INTO My_Table VALUES ( 4, 'text4', 'text4', 'text4', 'text4', 'text4');
 
   EXEC SQL DECLARE C CURSOR FOR SELECT * FROM My_Table;
 
   EXEC SQL OPEN C;
 
   EXEC SQL WHENEVER NOT FOUND DO BREAK;
   while (1) {
-  	EXEC SQL FETCH 1 IN C INTO :i, :str;
-	printf("%d: %s\n", i, str);
+  	EXEC SQL FETCH 1 IN C INTO :i, :str, :nstr, :_varchar, :_nvarchar, :_uvarchar;
+	printf("%d: %s, %s, %s, %s\n", i, str, nstr, _varchar.arr, _nvarchar.arr);
   }
 
   EXEC SQL WHENEVER NOT FOUND CONTINUE;
   EXEC SQL MOVE BACKWARD 2 IN C;
 
-  EXEC SQL FETCH :count IN C INTO :i, :str;
-  printf("%d: %s\n", i, str);
+  EXEC SQL FETCH :count IN C INTO :i, :str, :nstr, :_varchar, :_nvarchar, :_uvarchar;
+  printf("%d: %s, %s, %s, %s\n", i, str, nstr, _varchar.arr, _nvarchar.arr);
 
   EXEC SQL DECLARE D CURSOR FOR SELECT * FROM My_Table WHERE Item1 = $1;
 
   EXEC SQL OPEN D using 1;
 
   EXEC SQL WHENEVER NOT FOUND DO BREAK;
   while (1) {
-  	EXEC SQL FETCH 1 IN D INTO :i, :str;
-	printf("%d: %s\n", i, str);
+  	EXEC SQL FETCH 1 IN D INTO :i, :str, :nstr, :_varchar, :_nvarchar, :_uvarchar;
+	printf("%d: %s, %s, %s, %s\n", i, str, nstr, _varchar.arr, _nvarchar.arr);
   }
   EXEC SQL CLOSE D;
 
   EXEC SQL DROP TABLE My_Table;
 
diff -U 5 -N -r -w ../orig.HEAD/src/test/regress/expected/create_function_3.out ./src/test/regress/expected/create_function_3.out
--- ../orig.HEAD/src/test/regress/expected/create_function_3.out	2013-08-19 20:22:14.000000000 -0400
+++ ./src/test/regress/expected/create_function_3.out	2013-08-19 20:54:00.000000000 -0400
@@ -306,10 +306,12 @@
  namege         | boolean    | [0:1]={name,name}
  namegt         | boolean    | [0:1]={name,name}
  namele         | boolean    | [0:1]={name,name}
  namelt         | boolean    | [0:1]={name,name}
  namene         | boolean    | [0:1]={name,name}
+ nbpchareq      | boolean    | [0:1]={"national character","national character"}
+ nbpcharne      | boolean    | [0:1]={"national character","national character"}
  network_eq     | boolean    | [0:1]={inet,inet}
  network_ge     | boolean    | [0:1]={inet,inet}
  network_gt     | boolean    | [0:1]={inet,inet}
  network_le     | boolean    | [0:1]={inet,inet}
  network_lt     | boolean    | [0:1]={inet,inet}
@@ -381,11 +383,11 @@
  varbitgt       | boolean    | [0:1]={"bit varying","bit varying"}
  varbitle       | boolean    | [0:1]={"bit varying","bit varying"}
  varbitlt       | boolean    | [0:1]={"bit varying","bit varying"}
  varbitne       | boolean    | [0:1]={"bit varying","bit varying"}
  xideq          | boolean    | [0:1]={xid,xid}
-(228 rows)
+(230 rows)
 
 --
 -- CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT
 --
 CREATE FUNCTION functext_F_1(int) RETURNS bool LANGUAGE 'sql'
diff -U 5 -N -r -w ../orig.HEAD/src/test/regress/expected/nchar.out ./src/test/regress/expected/nchar.out
--- ../orig.HEAD/src/test/regress/expected/nchar.out	1969-12-31 19:00:00.000000000 -0500
+++ ./src/test/regress/expected/nchar.out	2013-08-19 23:31:45.000000000 -0400
@@ -0,0 +1,122 @@
+--
+-- NCHAR
+--
+-- fixed-length by value
+-- internally passed by value if <= 4 bytes in storage
+SELECT nchar 'c' = nchar 'c' AS true;
+ true 
+------
+ t
+(1 row)
+
+--
+-- Build a table for testing
+--
+CREATE TABLE NCHAR_TBL(f1 nchar);
+INSERT INTO NCHAR_TBL (f1) VALUES ('a');
+INSERT INTO NCHAR_TBL (f1) VALUES ('A');
+-- any of the following three input formats are acceptable
+INSERT INTO NCHAR_TBL (f1) VALUES ('1');
+INSERT INTO NCHAR_TBL (f1) VALUES (2);
+INSERT INTO NCHAR_TBL (f1) VALUES ('3');
+-- zero-length nchar
+INSERT INTO NCHAR_TBL (f1) VALUES ('');
+-- try nchar's of greater than 1 length
+INSERT INTO NCHAR_TBL (f1) VALUES ('cd');
+ERROR:  value too long for type character(1)
+INSERT INTO NCHAR_TBL (f1) VALUES ('c     ');
+SELECT '' AS seven, * FROM NCHAR_TBL;
+ seven | f1 
+-------+----
+       | a
+       | A
+       | 1
+       | 2
+       | 3
+       |  
+       | c
+(7 rows)
+
+SELECT '' AS six, c.*
+   FROM NCHAR_TBL c
+   WHERE c.f1 <> 'a';
+ six | f1 
+-----+----
+     | A
+     | 1
+     | 2
+     | 3
+     |  
+     | c
+(6 rows)
+
+SELECT '' AS one, c.*
+   FROM NCHAR_TBL c
+   WHERE c.f1 = 'a';
+ one | f1 
+-----+----
+     | a
+(1 row)
+
+SELECT '' AS five, c.*
+   FROM NCHAR_TBL c
+   WHERE c.f1 < 'a';
+ five | f1 
+------+----
+      | A
+      | 1
+      | 2
+      | 3
+      |  
+(5 rows)
+
+SELECT '' AS six, c.*
+   FROM NCHAR_TBL c
+   WHERE c.f1 <= 'a';
+ six | f1 
+-----+----
+     | a
+     | A
+     | 1
+     | 2
+     | 3
+     |  
+(6 rows)
+
+SELECT '' AS one, c.*
+   FROM NCHAR_TBL c
+   WHERE c.f1 > 'a';
+ one | f1 
+-----+----
+     | c
+(1 row)
+
+SELECT '' AS two, c.*
+   FROM NCHAR_TBL c
+   WHERE c.f1 >= 'a';
+ two | f1 
+-----+----
+     | a
+     | c
+(2 rows)
+
+DROP TABLE NCHAR_TBL;
+--
+-- Now test longer arrays of nchar
+--
+CREATE TABLE NCHAR_TBL(f1 nchar(4));
+INSERT INTO NCHAR_TBL (f1) VALUES ('a');
+INSERT INTO NCHAR_TBL (f1) VALUES ('ab');
+INSERT INTO NCHAR_TBL (f1) VALUES ('abcd');
+INSERT INTO NCHAR_TBL (f1) VALUES ('abcde');
+ERROR:  value too long for type character(4)
+INSERT INTO NCHAR_TBL (f1) VALUES ('abcd    ');
+SELECT '' AS four, * FROM NCHAR_TBL;
+ four |  f1  
+------+------
+      | a   
+      | ab  
+      | abcd
+      | abcd
+(4 rows)
+
diff -U 5 -N -r -w ../orig.HEAD/src/test/regress/expected/nvarchar_1.out ./src/test/regress/expected/nvarchar_1.out
--- ../orig.HEAD/src/test/regress/expected/nvarchar_1.out	1969-12-31 19:00:00.000000000 -0500
+++ ./src/test/regress/expected/nvarchar_1.out	2013-08-19 23:31:50.000000000 -0400
@@ -0,0 +1,111 @@
+--
+-- NVARCHAR
+--
+CREATE TABLE NVARCHAR_TBL(f1 nvarchar(1));
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('a');
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('A');
+-- any of the following three input formats are acceptable
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('1');
+INSERT INTO NVARCHAR_TBL (f1) VALUES (2);
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('3');
+-- zero-length nchar
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('');
+-- try nvarchar's of greater than 1 length
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('cd');
+ERROR:  value too long for type character varying(1)
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('c     ');
+SELECT '' AS seven, * FROM NVARCHAR_TBL;
+ seven | f1 
+-------+----
+       | a
+       | A
+       | 1
+       | 2
+       | 3
+       | 
+       | c
+(7 rows)
+
+SELECT '' AS six, c.*
+   FROM NVARCHAR_TBL c
+   WHERE c.f1 <> 'a';
+ six | f1 
+-----+----
+     | A
+     | 1
+     | 2
+     | 3
+     | 
+     | c
+(6 rows)
+
+SELECT '' AS one, c.*
+   FROM NVARCHAR_TBL c
+   WHERE c.f1 = 'a';
+ one | f1 
+-----+----
+     | a
+(1 row)
+
+SELECT '' AS five, c.*
+   FROM NVARCHAR_TBL c
+   WHERE c.f1 < 'a';
+ five | f1 
+------+----
+      | 1
+      | 2
+      | 3
+      | 
+(4 rows)
+
+SELECT '' AS six, c.*
+   FROM NVARCHAR_TBL c
+   WHERE c.f1 <= 'a';
+ six | f1 
+-----+----
+     | a
+     | 1
+     | 2
+     | 3
+     | 
+(5 rows)
+
+SELECT '' AS one, c.*
+   FROM NVARCHAR_TBL c
+   WHERE c.f1 > 'a';
+ one | f1 
+-----+----
+     | A
+     | c
+(2 rows)
+
+SELECT '' AS two, c.*
+   FROM NVARCHAR_TBL c
+   WHERE c.f1 >= 'a';
+ two | f1 
+-----+----
+     | a
+     | A
+     | c
+(3 rows)
+
+DROP TABLE NVARCHAR_TBL;
+--
+-- Now test longer arrays of nchar
+--
+CREATE TABLE NVARCHAR_TBL(f1 nvarchar(4));
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('a');
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('ab');
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('abcd');
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('abcde');
+ERROR:  value too long for type character varying(4)
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('abcd    ');
+SELECT '' AS four, * FROM NVARCHAR_TBL;
+ four |  f1  
+------+------
+      | a
+      | ab
+      | abcd
+      | abcd
+(4 rows)
+
diff -U 5 -N -r -w ../orig.HEAD/src/test/regress/expected/nvarchar_2.out ./src/test/regress/expected/nvarchar_2.out
--- ../orig.HEAD/src/test/regress/expected/nvarchar_2.out	1969-12-31 19:00:00.000000000 -0500
+++ ./src/test/regress/expected/nvarchar_2.out	2013-08-19 23:31:50.000000000 -0400
@@ -0,0 +1,111 @@
+--
+-- NVARCHAR
+--
+CREATE TABLE NVARCHAR_TBL(f1 nvarchar(1));
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('a');
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('A');
+-- any of the following three input formats are acceptable
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('1');
+INSERT INTO NVARCHAR_TBL (f1) VALUES (2);
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('3');
+-- zero-length nchar
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('');
+-- try nvarchar's of greater than 1 length
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('cd');
+ERROR:  value too long for type character varying(1)
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('c     ');
+SELECT '' AS seven, * FROM NVARCHAR_TBL;
+ seven | f1 
+-------+----
+       | a
+       | A
+       | 1
+       | 2
+       | 3
+       | 
+       | c
+(7 rows)
+
+SELECT '' AS six, c.*
+   FROM NVARCHAR_TBL c
+   WHERE c.f1 <> 'a';
+ six | f1 
+-----+----
+     | A
+     | 1
+     | 2
+     | 3
+     | 
+     | c
+(6 rows)
+
+SELECT '' AS one, c.*
+   FROM NVARCHAR_TBL c
+   WHERE c.f1 = 'a';
+ one | f1 
+-----+----
+     | a
+(1 row)
+
+SELECT '' AS five, c.*
+   FROM NVARCHAR_TBL c
+   WHERE c.f1 < 'a';
+ five | f1 
+------+----
+      | 
+(1 row)
+
+SELECT '' AS six, c.*
+   FROM NVARCHAR_TBL c
+   WHERE c.f1 <= 'a';
+ six | f1 
+-----+----
+     | a
+     | 
+(2 rows)
+
+SELECT '' AS one, c.*
+   FROM NVARCHAR_TBL c
+   WHERE c.f1 > 'a';
+ one | f1 
+-----+----
+     | A
+     | 1
+     | 2
+     | 3
+     | c
+(5 rows)
+
+SELECT '' AS two, c.*
+   FROM NVARCHAR_TBL c
+   WHERE c.f1 >= 'a';
+ two | f1 
+-----+----
+     | a
+     | A
+     | 1
+     | 2
+     | 3
+     | c
+(6 rows)
+
+DROP TABLE NVARCHAR_TBL;
+--
+-- Now test longer arrays of nchar
+--
+CREATE TABLE NVARCHAR_TBL(f1 nvarchar(4));
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('a');
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('ab');
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('abcd');
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('abcde');
+ERROR:  value too long for type character varying(4)
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('abcd    ');
+SELECT '' AS four, * FROM NVARCHAR_TBL;
+ four |  f1  
+------+------
+      | a
+      | ab
+      | abcd
+      | abcd
+(4 rows)
+
diff -U 5 -N -r -w ../orig.HEAD/src/test/regress/expected/nvarchar_alter.out ./src/test/regress/expected/nvarchar_alter.out
--- ../orig.HEAD/src/test/regress/expected/nvarchar_alter.out	1969-12-31 19:00:00.000000000 -0500
+++ ./src/test/regress/expected/nvarchar_alter.out	2013-08-19 23:31:50.000000000 -0400
@@ -0,0 +1,138 @@
+--create table
+create table nchar_test (f1 nchar(10) default N'a', f2 nvarchar(10) default N'b');
+--values
+values (N'abc各国語');
+  column1  
+-----------
+ abc各国語
+(1 row)
+
+--analyze
+analyze nchar_test(f1);
+analyze nchar_test(f2);
+--vacuum analyze
+vacuum analyze nchar_test(f1);
+vacuum analyze nchar_test(f2);
+--broken
+--set application_name to N'abc各国語';
+--select
+select f1,f2,N'abc各国語' from nchar_test;
+ f1 | f2 | nvarchar 
+----+----+----------
+(0 rows)
+
+--select into
+select f1,f2,N'abc各国語' into nchar_test1 from nchar_test;
+--revoke per column not supported
+--grant per column not supported
+--insert into/returning
+insert into nchar_test1 select f1,f2,N'abc各国語' from nchar_test returning f1,f2,nvarchar,N'abc各国語';
+ f1 | f2 | nvarchar | nvarchar 
+----+----+----------+----------
+(0 rows)
+
+--explain
+explain select f1,f2,N'abc各国語' from nchar_test;
+                          QUERY PLAN                          
+--------------------------------------------------------------
+ Seq Scan on nchar_test  (cost=0.00..17.70 rows=770 width=76)
+(1 row)
+
+--do
+do $$begin perform f1,f2,N'abc各国語' from nchar_test; end $$;
+--delete
+delete from nchar_test where f1=N'abc各国語' and f2=N'abc各国語';
+--create view
+create view v as select f1,f2,N'abc各国語' from nchar_test;
+--create index
+create index i2 on nchar_test(f2);
+create index i3 on nchar_test((f1||'abc各国語'));
+create index i1 on nchar_test(f1);
+--comment
+comment on COLUMN nchar_test.f1 is 'f1';
+comment on COLUMN nchar_test.f2 is 'f2';
+comment on type nvarchar is 'nvarchar';
+--analyze
+analyze nchar_test(f1);
+--copy
+copy nchar_test(f1, f2) to stdout;
+--alter view
+alter view v alter column f1 set default N'abc各国語';
+alter view v alter column f2 set default N'abc各国語';
+--alter table
+alter table nchar_test1 rename f1 to f3;
+alter table nchar_test1 rename f2 to f4;
+alter table nchar_test1 alter f3 type nchar(10);
+alter table nchar_test1 alter f4 type nvarchar;
+alter table nchar_test1 alter f3 set default N'abc各国語';
+alter table nchar_test1 alter f4 set default N'abc各国語';
+--declare cursor
+begin;declare qqq cursor for select f1,f2,N'abc各国語' from nchar_test;commit;
+--create trigger
+create trigger tr before update on nchar_test for each row when (OLD.f1=N'abc各国語') EXECUTE PROCEDURE suppress_redundant_updates_trigger();
+--foreign key
+alter table nchar_test1 add CONSTRAINT nchar_test1_pk primary key(f3);
+NOTICE:  ALTER TABLE / ADD PRIMARY KEY will create implicit index "nchar_test1_pk" for table "nchar_test1"
+alter table nchar_test add CONSTRAINT qqqq FOREIGN KEY (f1) references nchar_test1(f3);
+--update
+update nchar_test set f1=N'abc各国語', f2='abc各国語';
+select * from nchar_test1;
+ f3 | f4 | nvarchar 
+----+----+----------
+(0 rows)
+
+create domain test_nchar_domain as nchar(10) default (N'a') CHECK (value <> N'b');
+create domain test_nvarchar_domain as nvarchar(10) default (N'a') CHECK (value <> N'b');
+alter domain test_nchar_domain set default (N'b');
+alter domain test_nvarchar_domain set default (N'b');
+DROP DOMAIN test_nchar_domain;
+DROP DOMAIN test_nvarchar_domain;
+CREATE AGGREGATE test_nvarchar_agg (nvarchar) ( sfunc = array_append, stype = nvarchar[], initcond = '{}');
+CREATE AGGREGATE test_nchar_agg (nchar(10)) ( sfunc = array_append, stype = nchar(10)[], initcond = '{}');
+alter aggregate test_nvarchar_agg(nvarchar) rename to test_nvarchar_aggregate;
+alter aggregate test_nchar_agg (nchar(10)) rename to test_nchar_aggregate;
+drop aggregate test_nvarchar_aggregate(nvarchar);
+drop aggregate test_nchar_aggregate(nchar(10));
+CREATE TYPE test_nchar_type AS (f1 nchar(10));
+CREATE TYPE test_nvarchar_type AS (f1 nvarchar);
+drop type test_nchar_type;
+drop type test_nvarchar_type;
+drop view v;
+drop table nchar_test;
+drop table nchar_test1;
+create table nchar_test (f1 nchar(10), f2 nvarchar(10));
+select f1, f2, N'a'  from nchar_test where f1=N'a' and f2=N'b';
+ f1 | f2 | nvarchar 
+----+----+----------
+(0 rows)
+
+insert into nchar_test values (N'a', N'b') returning (f1, f2, N'c');
+        row         
+--------------------
+ ("a         ",b,c)
+(1 row)
+
+select f1, f2, N'a' into nchar_test1 from nchar_test;
+select * from nchar_test1;
+     f1     | f2 | nvarchar 
+------------+----+----------
+ a          | b  | a
+(1 row)
+
+prepare qqq(nchar(10), nvarchar(10)) AS select f1, f2, N'a'  from nchar_test where f1=N'a' and f2=N'b';
+execute qqq(N'a', N'b');
+     f1     | f2 | nvarchar 
+------------+----+----------
+ a          | b  | a
+(1 row)
+
+explain select f1, f2, N'a'  from nchar_test where f1=N'a' and f2=N'b';
+                          QUERY PLAN                          
+--------------------------------------------------------------
+ Seq Scan on nchar_test  (cost=0.00..21.55 rows=1 width=76)
+   Filter: ((f1 = 'a'::nbpchar) AND ((f2)::text = 'b'::text))
+(2 rows)
+
+delete from nchar_test1 where f1=N'a' and f2=N'b';
+drop table nchar_test;
+drop table nchar_test1;
diff -U 5 -N -r -w ../orig.HEAD/src/test/regress/expected/nvarchar_func.out ./src/test/regress/expected/nvarchar_func.out
--- ../orig.HEAD/src/test/regress/expected/nvarchar_func.out	1969-12-31 19:00:00.000000000 -0500
+++ ./src/test/regress/expected/nvarchar_func.out	2013-08-19 23:31:50.000000000 -0400
@@ -0,0 +1,258 @@
+SELECT N'各国' || N'文字';
+ ?column? 
+----------
+ 各国文字
+(1 row)
+
+SELECT N'各国' || 42;
+ ?column? 
+----------
+ 各国42
+(1 row)
+
+SELECT bit_length(N'各国');
+ bit_length 
+------------
+         48
+(1 row)
+
+SELECT char_length(N'各国');
+ char_length 
+-------------
+           2
+(1 row)
+
+SELECT lower(N'各国TOM');
+  lower  
+---------
+ 各国tom
+(1 row)
+
+SELECT octet_length(N'各国');
+ octet_length 
+--------------
+            6
+(1 row)
+
+SELECT overlay(N'各ＸＸ' placing N'文字' from 2 for 3);
+ overlay 
+---------
+ 各文字
+(1 row)
+
+SELECT position(N'文' in N'各国文字');
+ position 
+----------
+        3
+(1 row)
+
+SELECT substring(N'各国文字' from 3 for 3);
+ substring 
+-----------
+ 文字
+(1 row)
+
+SELECT substring(N'各国文字列' from N'...$');
+ substring 
+-----------
+ 文字列
+(1 row)
+
+SELECT substring(N'各国文字列国' from '%#"文_列#"_' for '#');
+ substring 
+-----------
+ 文字列
+(1 row)
+
+SELECT trim(both N'Ｘ' from N'Ｘ各国文字ＸＸ');
+  btrim   
+----------
+ 各国文字
+(1 row)
+
+SELECT upper(N'各国tom');
+  upper  
+---------
+ 各国TOM
+(1 row)
+
+SELECT ascii(N'数');
+ ascii 
+-------
+ 25968
+(1 row)
+
+SELECT btrim(N'ＸＹ各国Ｘ', N'ＸＹ');
+ btrim 
+-------
+ 各国
+(1 row)
+
+SELECT chr(25968);
+ chr 
+-----
+ 数
+(1 row)
+
+SELECT concat(N'各', N'国', NULL, N'語');
+ concat 
+--------
+ 各国語
+(1 row)
+
+SELECT concat_ws(N'＿', N'各国', NULL, N'文字');
+ concat_ws  
+------------
+ 各国＿文字
+(1 row)
+
+-- convert_to(N'各国', 'SJIS') = '\x8a658d91'
+-- convert_to(N'各国', 'UTF8') = '\xe59084e59bbd'
+SELECT convert('\x8a658d91'::bytea, 'SJIS', 'UTF8');
+    convert     
+----------------
+ \xe59084e59bbd
+(1 row)
+
+-- N'各国'::bytea = '\xe59084e59bbd'
+SELECT convert_from('\xe59084e59bbd'::bytea, 'UTF8');
+ convert_from 
+--------------
+ 各国
+(1 row)
+
+-- '\xe59084e59bbd'::bytea = N'各国'
+SELECT convert_to(N'各国', 'UTF8');
+   convert_to   
+----------------
+ \xe59084e59bbd
+(1 row)
+
+SELECT format('各国 %s, %1$s', N'文字');
+     format      
+-----------------
+ 各国 文字, 文字
+(1 row)
+
+SELECT initcap(N'hi 各国');
+ initcap 
+---------
+ Hi 各国
+(1 row)
+
+SELECT left(N'各国文字', 2);
+ left 
+------
+ 各国
+(1 row)
+
+SELECT length(N'各国文字');
+ length 
+--------
+      4
+(1 row)
+
+-- N'各国文字'::bytea = '\xe59084e59bbde69687e5ad97'
+SELECT length('\xe59084e59bbde69687e5ad97'::bytea , 'UTF8');
+ length 
+--------
+      4
+(1 row)
+
+SELECT lpad(N'文字', 3, N'各国');
+  lpad  
+--------
+ 各文字
+(1 row)
+
+SELECT ltrim(N'◯×各国', N'◯×');
+ ltrim 
+-------
+ 各国
+(1 row)
+
+SELECT regexp_matches(N'各国文字データ', N'(文字)(データ)');
+ regexp_matches 
+----------------
+ {文字,データ}
+(1 row)
+
+SELECT regexp_replace(N'各国x文字', '.[a-z]文.', N'語');
+ regexp_replace 
+----------------
+ 各語
+(1 row)
+
+SELECT regexp_split_to_array(N'各国 文字列', E'\\s+');
+ regexp_split_to_array 
+-----------------------
+ {各国,文字列}
+(1 row)
+
+SELECT regexp_split_to_table(N'各国 文字列', E'\\s+');
+ regexp_split_to_table 
+-----------------------
+ 各国
+ 文字列
+(2 rows)
+
+SELECT repeat(N'文字', 4);
+      repeat      
+------------------
+ 文字文字文字文字
+(1 row)
+
+SELECT replace(N'各国文字国', N'国', N'語');
+  replace   
+------------
+ 各語文字語
+(1 row)
+
+SELECT reverse(N'各国語');
+ reverse 
+---------
+ 語国各
+(1 row)
+
+SELECT right(N'各国語', 2);
+ right 
+-------
+ 国語
+(1 row)
+
+SELECT rpad(N'各国', 3, N'語');
+  rpad  
+--------
+ 各国語
+(1 row)
+
+SELECT rtrim(N'◯各国◯◯', N'◯');
+ rtrim 
+-------
+ ◯各国
+(1 row)
+
+SELECT split_part(N'各国◯語◯文字', N'◯', 3);
+ split_part 
+------------
+ 文字
+(1 row)
+
+SELECT strpos(N'各国語', N'語');
+ strpos 
+--------
+      3
+(1 row)
+
+SELECT substr(N'各国語', 3, 3);
+ substr 
+--------
+ 語
+(1 row)
+
+SELECT translate(N'各国文字', N'各字', N'◯×');
+ translate 
+-----------
+ ◯国文×
+(1 row)
+
diff -U 5 -N -r -w ../orig.HEAD/src/test/regress/expected/nvarchar_misc.out ./src/test/regress/expected/nvarchar_misc.out
--- ../orig.HEAD/src/test/regress/expected/nvarchar_misc.out	1969-12-31 19:00:00.000000000 -0500
+++ ./src/test/regress/expected/nvarchar_misc.out	2013-08-19 23:31:50.000000000 -0400
@@ -0,0 +1,126 @@
+select N'a '=N'a';
+ ?column? 
+----------
+ f
+(1 row)
+
+select N'a '='a';
+ ?column? 
+----------
+ f
+(1 row)
+
+select N'a'='a';
+ ?column? 
+----------
+ t
+(1 row)
+
+select N'a '='a'::char(1);
+ ?column? 
+----------
+ t
+(1 row)
+
+select N'a '='a'::nchar(1);
+ ?column? 
+----------
+ t
+(1 row)
+
+select N'a '='a'::varchar(1);
+ ?column? 
+----------
+ f
+(1 row)
+
+select N'a '='a'::nvarchar(1);
+ ?column? 
+----------
+ f
+(1 row)
+
+select N'a'='a'::nvarchar(1);
+ ?column? 
+----------
+ t
+(1 row)
+
+select N'a'='a'::varchar(1);
+ ?column? 
+----------
+ t
+(1 row)
+
+select N'a'='a'::char(1);
+ ?column? 
+----------
+ t
+(1 row)
+
+select N'a'='a'::nchar(1);
+ ?column? 
+----------
+ t
+(1 row)
+
+select 'a'::nchar(10)='a'::char(1);
+ ?column? 
+----------
+ t
+(1 row)
+
+select 'a'::nchar(10)='a'::nchar(1);
+ ?column? 
+----------
+ t
+(1 row)
+
+select 'a'::nchar(10)='a'::varchar(1);
+ ?column? 
+----------
+ t
+(1 row)
+
+select 'a'::nchar(10)='a'::nvarchar(1);
+ ?column? 
+----------
+ t
+(1 row)
+
+select 'a'::nvarchar(10)='a'::varchar(1);
+ ?column? 
+----------
+ t
+(1 row)
+
+select 'a'::nvarchar(10)='a'::varchar(10);
+ ?column? 
+----------
+ t
+(1 row)
+
+select 'a'::nvarchar(10)='a '::varchar(10);
+ ?column? 
+----------
+ f
+(1 row)
+
+select 'a'::nvarchar(10)='a '::char(10);
+ ?column? 
+----------
+ t
+(1 row)
+
+select 'a '::nchar(10)='a  '::nchar(5);
+ ?column? 
+----------
+ t
+(1 row)
+
+select 'a '::nchar(10)='a  '::char(5);
+ ?column? 
+----------
+ t
+(1 row)
+
diff -U 5 -N -r -w ../orig.HEAD/src/test/regress/expected/nvarchar.out ./src/test/regress/expected/nvarchar.out
--- ../orig.HEAD/src/test/regress/expected/nvarchar.out	1969-12-31 19:00:00.000000000 -0500
+++ ./src/test/regress/expected/nvarchar.out	2013-08-19 23:31:50.000000000 -0400
@@ -0,0 +1,111 @@
+--
+-- NVARCHAR
+--
+CREATE TABLE NVARCHAR_TBL(f1 nvarchar(1));
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('a');
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('A');
+-- any of the following three input formats are acceptable
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('1');
+INSERT INTO NVARCHAR_TBL (f1) VALUES (2);
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('3');
+-- zero-length char
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('');
+-- try nvarchar's of greater than 1 length
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('cd');
+ERROR:  value too long for type character varying(1)
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('c     ');
+SELECT '' AS seven, * FROM NVARCHAR_TBL;
+ seven | f1 
+-------+----
+       | a
+       | A
+       | 1
+       | 2
+       | 3
+       | 
+       | c
+(7 rows)
+
+SELECT '' AS six, c.*
+   FROM NVARCHAR_TBL c
+   WHERE c.f1 <> 'a';
+ six | f1 
+-----+----
+     | A
+     | 1
+     | 2
+     | 3
+     | 
+     | c
+(6 rows)
+
+SELECT '' AS one, c.*
+   FROM NVARCHAR_TBL c
+   WHERE c.f1 = 'a';
+ one | f1 
+-----+----
+     | a
+(1 row)
+
+SELECT '' AS five, c.*
+   FROM NVARCHAR_TBL c
+   WHERE c.f1 < 'a';
+ five | f1 
+------+----
+      | A
+      | 1
+      | 2
+      | 3
+      | 
+(5 rows)
+
+SELECT '' AS six, c.*
+   FROM NVARCHAR_TBL c
+   WHERE c.f1 <= 'a';
+ six | f1 
+-----+----
+     | a
+     | A
+     | 1
+     | 2
+     | 3
+     | 
+(6 rows)
+
+SELECT '' AS one, c.*
+   FROM NVARCHAR_TBL c
+   WHERE c.f1 > 'a';
+ one | f1 
+-----+----
+     | c
+(1 row)
+
+SELECT '' AS two, c.*
+   FROM NVARCHAR_TBL c
+   WHERE c.f1 >= 'a';
+ two | f1 
+-----+----
+     | a
+     | c
+(2 rows)
+
+DROP TABLE NVARCHAR_TBL;
+--
+-- Now test longer arrays of char
+--
+CREATE TABLE NVARCHAR_TBL(f1 nvarchar(4));
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('a');
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('ab');
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('abcd');
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('abcde');
+ERROR:  value too long for type character varying(4)
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('abcd    ');
+SELECT '' AS four, * FROM NVARCHAR_TBL;
+ four |  f1  
+------+------
+      | a
+      | ab
+      | abcd
+      | abcd
+(4 rows)
+
diff -U 5 -N -r -w ../orig.HEAD/src/test/regress/expected/opr_sanity.out ./src/test/regress/expected/opr_sanity.out
--- ../orig.HEAD/src/test/regress/expected/opr_sanity.out	2013-08-19 20:22:14.000000000 -0400
+++ ./src/test/regress/expected/opr_sanity.out	2013-08-19 20:54:00.000000000 -0400
@@ -152,12 +152,15 @@
     (p1.prorettype < p2.prorettype)
 ORDER BY 1, 2;
  prorettype | prorettype 
 ------------+------------
          25 |       1043
+         25 |       6001
+       1042 |       5001
+       1043 |       6001
        1114 |       1184
-(2 rows)
+(5 rows)
 
 SELECT DISTINCT p1.proargtypes[0], p2.proargtypes[0]
 FROM pg_proc AS p1, pg_proc AS p2
 WHERE p1.oid != p2.oid AND
     p1.prosrc = p2.prosrc AND
@@ -169,14 +172,18 @@
 ORDER BY 1, 2;
  proargtypes | proargtypes 
 -------------+-------------
           25 |        1042
           25 |        1043
+          25 |        5001
+          25 |        6001
+        1042 |        5001
+        1043 |        6001
         1114 |        1184
         1560 |        1562
         2277 |        2283
-(5 rows)
+(9 rows)
 
 SELECT DISTINCT p1.proargtypes[1], p2.proargtypes[1]
 FROM pg_proc AS p1, pg_proc AS p2
 WHERE p1.oid != p2.oid AND
     p1.prosrc = p2.prosrc AND
@@ -187,14 +194,15 @@
     (p1.proargtypes[1] < p2.proargtypes[1])
 ORDER BY 1, 2;
  proargtypes | proargtypes 
 -------------+-------------
           23 |          28
+        1042 |        5001
         1114 |        1184
         1560 |        1562
         2277 |        2283
-(4 rows)
+(5 rows)
 
 SELECT DISTINCT p1.proargtypes[2], p2.proargtypes[2]
 FROM pg_proc AS p1, pg_proc AS p2
 WHERE p1.oid != p2.oid AND
     p1.prosrc = p2.prosrc AND
@@ -433,19 +441,23 @@
     NOT EXISTS (SELECT 1 FROM pg_cast k
                 WHERE k.castmethod = 'b' AND
                     k.castsource = c.casttarget AND
                     k.casttarget = c.castsource);
     castsource     |    casttarget     | castfunc | castcontext 
--------------------+-------------------+----------+-------------
- text              | character         |        0 | i
+----------------------------+--------------------+----------+-------------
+ national character varying | character          |        0 | i
+ national character varying | national character |        0 | i
  character varying | character         |        0 | i
+ character varying          | national character |        0 | i
+ text                       | character          |        0 | i
+ text                       | national character |        0 | i
  pg_node_tree      | text              |        0 | i
  cidr              | inet              |        0 | i
  xml               | text              |        0 | a
  xml               | character varying |        0 | a
  xml               | character         |        0 | a
-(7 rows)
+(11 rows)
 
 -- **************** pg_operator ****************
 -- Look for illegal values in pg_operator fields.
 SELECT p1.oid, p1.oprname
 FROM pg_operator as p1
@@ -1211,11 +1223,13 @@
                  p3.amoplefttype = p1.amoplefttype AND
                  p3.amoprighttype = p2.amoplefttype AND
                  p3.amopstrategy = 1);
  amoplefttype | amoplefttype 
 --------------+--------------
-(0 rows)
+         1042 |         5001
+         5001 |         1042
+(2 rows)
 
 -- **************** pg_amproc ****************
 -- Look for illegal values in pg_amproc fields
 SELECT p1.amprocfamily, p1.amprocnum
 FROM pg_amproc as p1
@@ -1273,12 +1287,14 @@
 WHERE am.amname = 'btree' OR am.amname = 'gist' OR am.amname = 'gin'
 GROUP BY amname, amsupport, opcname, amprocfamily
 HAVING (count(*) != amsupport AND count(*) != amsupport - 1)
     OR amprocfamily IS NULL;
  amname | opcname | count 
---------+---------+-------
-(0 rows)
+--------+---------------+-------
+ gin    | _nbpchar_ops  |     1
+ gin    | _nvarchar_ops |     1
+(2 rows)
 
 -- Unfortunately, we can't check the amproc link very well because the
 -- signature of the function may be different for different support routines
 -- or different base data types.
 -- We can check that all the referenced instances of the same support
@@ -1316,12 +1332,14 @@
           WHEN amprocnum = 2
           THEN prorettype != 'void'::regtype OR proretset OR pronargs != 1
                OR proargtypes[0] != 'internal'::regtype
           ELSE true END);
  amprocfamily | amprocnum | oid | proname | opfname 
---------------+-----------+-----+---------+---------
-(0 rows)
+--------------+-----------+------+----------------------+--------------------
+          426 |         1 | 1078 | bpcharcmp            | bpchar_ops
+         2097 |         1 | 2180 | btbpchar_pattern_cmp | bpchar_pattern_ops
+(2 rows)
 
 -- For hash we can also do a little better: the support routines must be
 -- of the form hash(lefttype) returns int4.  There are several cases where
 -- we cheat and use a hash function that is physically compatible with the
 -- datatype even though there's no cast, so this check does find a small
diff -U 5 -N -r -w ../orig.HEAD/src/test/regress/expected/sanity_check.out ./src/test/regress/expected/sanity_check.out
--- ../orig.HEAD/src/test/regress/expected/sanity_check.out	2013-08-19 20:22:15.000000000 -0400
+++ ./src/test/regress/expected/sanity_check.out	2013-08-19 20:54:00.000000000 -0400
@@ -66,10 +66,11 @@
  kd_point_tbl            | t
  log_table               | f
  lseg_tbl                | f
  main_table              | f
  money_data              | f
+ nchar_tbl               | f
  num_data                | f
  num_exp_add             | t
  num_exp_div             | t
  num_exp_ln              | t
  num_exp_log10           | t
@@ -77,10 +78,11 @@
  num_exp_power_10_ln     | t
  num_exp_sqrt            | t
  num_exp_sub             | t
  num_input_test          | f
  num_result              | f
+ nvarchar_tbl            | f
  onek                    | t
  onek2                   | t
  path_tbl                | f
  person                  | f
  pg_aggregate            | t
diff -U 5 -N -r -w ../orig.HEAD/src/test/regress/expected/strings.out ./src/test/regress/expected/strings.out
--- ../orig.HEAD/src/test/regress/expected/strings.out	2013-08-19 20:22:15.000000000 -0400
+++ ./src/test/regress/expected/strings.out	2013-08-19 20:54:00.000000000 -0400
@@ -201,19 +201,37 @@
  ab
  abcd
  abcd
 (4 rows)
 
+SELECT CAST(f1 AS text) AS "text(nchar)" FROM NCHAR_TBL;
+ text(nchar) 
+-------------
+ a
+ ab
+ abcd
+ abcd
+(4 rows)
+
 SELECT CAST(f1 AS text) AS "text(varchar)" FROM VARCHAR_TBL;
  text(varchar) 
 ---------------
  a
  ab
  abcd
  abcd
 (4 rows)
 
+SELECT CAST(f1 AS text) AS "text(nvarchar)" FROM NVARCHAR_TBL;
+ text(nvarchar) 
+----------------
+ a
+ ab
+ abcd
+ abcd
+(4 rows)
+
 SELECT CAST(name 'namefield' AS text) AS "text(name)";
  text(name) 
 ------------
  namefield
 (1 row)
@@ -225,54 +243,106 @@
  doh!      
  hi de ho n
 (2 rows)
 
 -- note: implicit-cast case is tested in char.sql
+SELECT CAST(f1 AS nchar(10)) AS "nchar(text)" FROM TEXT_TBL;
+ nchar(text) 
+-------------
+ doh!      
+ hi de ho n
+(2 rows)
+
+-- note: implicit-cast case is tested in nchar.sql
 SELECT CAST(f1 AS char(20)) AS "char(text)" FROM TEXT_TBL;
       char(text)      
 ----------------------
  doh!                
  hi de ho neighbor   
 (2 rows)
 
+SELECT CAST(f1 AS nchar(20)) AS "nchar(text)" FROM TEXT_TBL;
+     nchar(text)      
+----------------------
+ doh!                
+ hi de ho neighbor   
+(2 rows)
+
 SELECT CAST(f1 AS char(10)) AS "char(varchar)" FROM VARCHAR_TBL;
  char(varchar) 
 ---------------
  a         
  ab        
  abcd      
  abcd      
 (4 rows)
 
+SELECT CAST(f1 AS nchar(10)) AS "nchar(nvarchar)" FROM NVARCHAR_TBL;
+ nchar(nvarchar) 
+-----------------
+ a         
+ ab        
+ abcd      
+ abcd      
+(4 rows)
+
 SELECT CAST(name 'namefield' AS char(10)) AS "char(name)";
  char(name) 
 ------------
  namefield 
 (1 row)
 
+SELECT CAST(name 'namefield' AS nchar(10)) AS "nchar(name)";
+ nchar(name) 
+-------------
+ namefield 
+(1 row)
+
 SELECT CAST(f1 AS varchar) AS "varchar(text)" FROM TEXT_TBL;
    varchar(text)   
 -------------------
  doh!
  hi de ho neighbor
 (2 rows)
 
+SELECT CAST(f1 AS nvarchar) AS "nvarchar(text)" FROM TEXT_TBL;
+  nvarchar(text)   
+-------------------
+ doh!
+ hi de ho neighbor
+(2 rows)
+
 SELECT CAST(f1 AS varchar) AS "varchar(char)" FROM CHAR_TBL;
  varchar(char) 
 ---------------
  a
  ab
  abcd
  abcd
 (4 rows)
 
+SELECT CAST(f1 AS nvarchar) AS "nvarchar(nchar)" FROM NCHAR_TBL;
+ nvarchar(nchar) 
+-----------------
+ a
+ ab
+ abcd
+ abcd
+(4 rows)
+
 SELECT CAST(name 'namefield' AS varchar) AS "varchar(name)";
  varchar(name) 
 ---------------
  namefield
 (1 row)
 
+SELECT CAST(name 'namefield' AS nvarchar) AS "nvarchar(name)";
+ nvarchar(name) 
+----------------
+ namefield
+(1 row)
+
 --
 -- test SQL string functions
 -- E### and T### are feature reference numbers from SQL99
 --
 -- E021-09 trim function
@@ -1103,22 +1173,40 @@
  Concat char to unknown type 
 -----------------------------
  characters and text
 (1 row)
 
+SELECT nchar(20) 'ncharacters' || ' and text' AS "Concat nchar to unknown type";
+ Concat nchar to unknown type 
+------------------------------
+ ncharacters and text
+(1 row)
+
 SELECT text 'text' || char(20) ' and characters' AS "Concat text to char";
  Concat text to char 
 ---------------------
  text and characters
 (1 row)
 
+SELECT text 'text' || nchar(20) ' and ncharacters' AS "Concat text to nchar";
+ Concat text to nchar 
+----------------------
+ text and ncharacters
+(1 row)
+
 SELECT text 'text' || varchar ' and varchar' AS "Concat text to varchar";
  Concat text to varchar 
 ------------------------
  text and varchar
 (1 row)
 
+SELECT text 'text' || nvarchar ' and nvarchar' AS "Concat text to nvarchar";
+ Concat text to nvarchar 
+-------------------------
+ text and nvarchar
+(1 row)
+
 --
 -- test substr with toasted text values
 --
 CREATE TABLE toasttest(f1 text);
 insert into toasttest values(repeat('1234567890',10000));
diff -U 5 -N -r -w ../orig.HEAD/src/test/regress/expected/union.out ./src/test/regress/expected/union.out
--- ../orig.HEAD/src/test/regress/expected/union.out	2013-08-19 20:22:15.000000000 -0400
+++ ./src/test/regress/expected/union.out	2013-08-19 20:54:00.000000000 -0400
@@ -255,10 +255,52 @@
  abcd
  doh!
  hi de ho neighbor
 (5 rows)
 
+--NVARCHAR specific
+SELECT f1 AS three FROM NVARCHAR_TBL
+UNION
+SELECT CAST(f1 AS nvarchar) FROM NCHAR_TBL
+ORDER BY 1;
+ three 
+-------
+ a
+ ab
+ abcd
+(3 rows)
+
+SELECT f1 AS eight FROM NVARCHAR_TBL
+UNION ALL
+SELECT f1 FROM NCHAR_TBL;
+ eight 
+-------
+ a
+ ab
+ abcd
+ abcd
+ a
+ ab
+ abcd
+ abcd
+(8 rows)
+
+SELECT f1 AS five FROM TEXT_TBL
+UNION
+SELECT f1 FROM NVARCHAR_TBL
+UNION
+SELECT TRIM(TRAILING FROM f1) FROM NCHAR_TBL
+ORDER BY 1;
+       five        
+-------------------
+ a
+ ab
+ abcd
+ doh!
+ hi de ho neighbor
+(5 rows)
+
 --
 -- INTERSECT and EXCEPT
 --
 SELECT q2 FROM int8_tbl INTERSECT SELECT q1 FROM int8_tbl;
         q2        
diff -U 5 -N -r -w ../orig.HEAD/src/test/regress/expected/update.out ./src/test/regress/expected/update.out
--- ../orig.HEAD/src/test/regress/expected/update.out	2013-08-19 20:22:15.000000000 -0400
+++ ./src/test/regress/expected/update.out	2013-08-19 20:54:00.000000000 -0400
@@ -2,75 +2,101 @@
 -- UPDATE syntax tests
 --
 CREATE TABLE update_test (
     a   INT DEFAULT 10,
     b   INT,
-    c   TEXT
+    c   TEXT,
+    d   nchar(10),
+    e   nvarchar
 );
-INSERT INTO update_test VALUES (5, 10, 'foo');
+INSERT INTO update_test VALUES (5, 10, 'foo', 'a', 'a');
 INSERT INTO update_test(b, a) VALUES (15, 10);
 SELECT * FROM update_test;
- a  | b  |  c  
-----+----+-----
-  5 | 10 | foo
- 10 | 15 | 
+ a  | b  |  c  |     d      | e 
+----+----+-----+------------+---
+  5 | 10 | foo | a          | a
+ 10 | 15 |     |            | 
+(2 rows)
+
+UPDATE update_test SET d='b', e='b';
+SELECT * FROM update_test;
+ a  | b  |  c  |     d      | e 
+----+----+-----+------------+---
+  5 | 10 | foo | b          | b
+ 10 | 15 |     | b          | b
+(2 rows)
+
+UPDATE update_test SET d='c' where e='b';
+SELECT * FROM update_test;
+ a  | b  |  c  |     d      | e 
+----+----+-----+------------+---
+  5 | 10 | foo | c          | b
+ 10 | 15 |     | c          | b
+(2 rows)
+
+UPDATE update_test SET d=N'e' where e=N'b';
+SELECT * FROM update_test;
+ a  | b  |  c  |     d      | e 
+----+----+-----+------------+---
+  5 | 10 | foo | e          | b
+ 10 | 15 |     | e          | b
 (2 rows)
 
 UPDATE update_test SET a = DEFAULT, b = DEFAULT;
 SELECT * FROM update_test;
- a  | b |  c  
-----+---+-----
- 10 |   | foo
- 10 |   | 
+ a  | b |  c  |     d      | e 
+----+---+-----+------------+---
+ 10 |   | foo | e          | b
+ 10 |   |     | e          | b
 (2 rows)
 
 -- aliases for the UPDATE target table
 UPDATE update_test AS t SET b = 10 WHERE t.a = 10;
 SELECT * FROM update_test;
- a  | b  |  c  
-----+----+-----
- 10 | 10 | foo
- 10 | 10 | 
+ a  | b  |  c  |     d      | e 
+----+----+-----+------------+---
+ 10 | 10 | foo | e          | b
+ 10 | 10 |     | e          | b
 (2 rows)
 
 UPDATE update_test t SET b = t.b + 10 WHERE t.a = 10;
 SELECT * FROM update_test;
- a  | b  |  c  
-----+----+-----
- 10 | 20 | foo
- 10 | 20 | 
+ a  | b  |  c  |     d      | e 
+----+----+-----+------------+---
+ 10 | 20 | foo | e          | b
+ 10 | 20 |     | e          | b
 (2 rows)
 
 --
 -- Test VALUES in FROM
 --
 UPDATE update_test SET a=v.i FROM (VALUES(100, 20)) AS v(i, j)
   WHERE update_test.b = v.j;
 SELECT * FROM update_test;
-  a  | b  |  c  
------+----+-----
- 100 | 20 | foo
- 100 | 20 | 
+  a  | b  |  c  |     d      | e 
+-----+----+-----+------------+---
+ 100 | 20 | foo | e          | b
+ 100 | 20 |     | e          | b
 (2 rows)
 
 --
 -- Test multiple-set-clause syntax
 --
 UPDATE update_test SET (c,b,a) = ('bugle', b+11, DEFAULT) WHERE c = 'foo';
 SELECT * FROM update_test;
-  a  | b  |   c   
------+----+-------
- 100 | 20 | 
-  10 | 31 | bugle
+  a  | b  |   c   |     d      | e 
+-----+----+-------+------------+---
+ 100 | 20 |       | e          | b
+  10 | 31 | bugle | e          | b
 (2 rows)
 
 UPDATE update_test SET (c,b) = ('car', a+b), a = a + 1 WHERE a = 10;
 SELECT * FROM update_test;
-  a  | b  |  c  
------+----+-----
- 100 | 20 | 
-  11 | 41 | car
+  a  | b  |  c  |     d      | e 
+-----+----+-----+------------+---
+ 100 | 20 |     | e          | b
+  11 | 41 | car | e          | b
 (2 rows)
 
 -- fail, multi assignment to same column:
 UPDATE update_test SET (c,b) = ('car', a+b), b = a + 1 WHERE a = 10;
 ERROR:  multiple assignments to same column "b"
diff -U 5 -N -r -w ../orig.HEAD/src/test/regress/output/misc.source ./src/test/regress/output/misc.source
--- ../orig.HEAD/src/test/regress/output/misc.source	2013-08-19 20:22:15.000000000 -0400
+++ ./src/test/regress/output/misc.source	2013-08-19 20:54:00.000000000 -0400
@@ -39,32 +39,32 @@
 --   SET age = age + 3
 --   WHERE name = 'linda';
 --
 -- copy
 --
-COPY onek TO '@abs_builddir@/results/onek.data';
+COPY onek TO '/home/mboguk/postgres/build_test/src/test/regress/results/onek.data';
 DELETE FROM onek;
-COPY onek FROM '@abs_builddir@/results/onek.data';
+COPY onek FROM '/home/mboguk/postgres/build_test/src/test/regress/results/onek.data';
 SELECT unique1 FROM onek WHERE unique1 < 2 ORDER BY unique1;
  unique1 
 ---------
        0
        1
 (2 rows)
 
 DELETE FROM onek2;
-COPY onek2 FROM '@abs_builddir@/results/onek.data';
+COPY onek2 FROM '/home/mboguk/postgres/build_test/src/test/regress/results/onek.data';
 SELECT unique1 FROM onek2 WHERE unique1 < 2 ORDER BY unique1;
  unique1 
 ---------
        0
        1
 (2 rows)
 
-COPY BINARY stud_emp TO '@abs_builddir@/results/stud_emp.data';
+COPY BINARY stud_emp TO '/home/mboguk/postgres/build_test/src/test/regress/results/stud_emp.data';
 DELETE FROM stud_emp;
-COPY BINARY stud_emp FROM '@abs_builddir@/results/stud_emp.data';
+COPY BINARY stud_emp FROM '/home/mboguk/postgres/build_test/src/test/regress/results/stud_emp.data';
 SELECT * FROM stud_emp;
  name  | age |  location  | salary | manager | gpa | percent 
 -------+-----+------------+--------+---------+-----+---------
  jeff  |  23 | (8,7.7)    |    600 | sharon  | 3.5 |        
  cim   |  30 | (10.5,4.7) |    400 |         | 3.4 |        
@@ -640,10 +640,11 @@
  kd_point_tbl
  log_table
  lseg_tbl
  main_table
  money_data
+ nchar_tbl
  num_data
  num_exp_add
  num_exp_div
  num_exp_ln
  num_exp_log10
@@ -651,10 +652,11 @@
  num_exp_power_10_ln
  num_exp_sqrt
  num_exp_sub
  num_input_test
  num_result
+ nvarchar_tbl
  onek
  onek2
  path_tbl
  person
  point_tbl
diff -U 5 -N -r -w ../orig.HEAD/src/test/regress/parallel_schedule ./src/test/regress/parallel_schedule
--- ../orig.HEAD/src/test/regress/parallel_schedule	2013-08-19 20:22:15.000000000 -0400
+++ ./src/test/regress/parallel_schedule	2013-08-19 20:54:00.000000000 -0400
@@ -11,11 +11,11 @@
 test: tablespace
 
 # ----------
 # The first group of parallel tests
 # ----------
-test: boolean char name varchar text int2 int4 int8 oid float4 float8 bit numeric txid uuid enum money rangetypes
+test: boolean char name varchar nchar nvarchar text int2 int4 int8 oid float4 float8 bit numeric txid uuid enum money rangetypes nvarchar_func nvarchar_alter nvarchar_misc
 
 # Depends on things setup during char, varchar and text
 test: strings
 # Depends on int2, int4, int8, float4, float8
 test: numerology
diff -U 5 -N -r -w ../orig.HEAD/src/test/regress/serial_schedule ./src/test/regress/serial_schedule
--- ../orig.HEAD/src/test/regress/serial_schedule	2013-08-19 20:22:15.000000000 -0400
+++ ./src/test/regress/serial_schedule	2013-08-19 20:54:00.000000000 -0400
@@ -3,10 +3,15 @@
 test: tablespace
 test: boolean
 test: char
 test: name
 test: varchar
+test: nvarchar
+test: nvarchar_alter
+test: nvarchar_func
+test: nvarchar_misc
+test: nchar
 test: text
 test: int2
 test: int4
 test: int8
 test: oid
diff -U 5 -N -r -w ../orig.HEAD/src/test/regress/sql/nchar.sql ./src/test/regress/sql/nchar.sql
--- ../orig.HEAD/src/test/regress/sql/nchar.sql	1969-12-31 19:00:00.000000000 -0500
+++ ./src/test/regress/sql/nchar.sql	2013-08-19 23:31:21.000000000 -0400
@@ -0,0 +1,75 @@
+--
+-- NCHAR
+--
+
+-- fixed-length by value
+-- internally passed by value if <= 4 bytes in storage
+
+SELECT nchar 'c' = nchar 'c' AS true;
+
+--
+-- Build a table for testing
+--
+
+CREATE TABLE NCHAR_TBL(f1 nchar);
+
+INSERT INTO NCHAR_TBL (f1) VALUES ('a');
+
+INSERT INTO NCHAR_TBL (f1) VALUES ('A');
+
+-- any of the following three input formats are acceptable
+INSERT INTO NCHAR_TBL (f1) VALUES ('1');
+
+INSERT INTO NCHAR_TBL (f1) VALUES (2);
+
+INSERT INTO NCHAR_TBL (f1) VALUES ('3');
+
+-- zero-length nchar
+INSERT INTO NCHAR_TBL (f1) VALUES ('');
+
+-- try nchar's of greater than 1 length
+INSERT INTO NCHAR_TBL (f1) VALUES ('cd');
+INSERT INTO NCHAR_TBL (f1) VALUES ('c     ');
+
+
+SELECT '' AS seven, * FROM NCHAR_TBL;
+
+SELECT '' AS six, c.*
+   FROM NCHAR_TBL c
+   WHERE c.f1 <> 'a';
+
+SELECT '' AS one, c.*
+   FROM NCHAR_TBL c
+   WHERE c.f1 = 'a';
+
+SELECT '' AS five, c.*
+   FROM NCHAR_TBL c
+   WHERE c.f1 < 'a';
+
+SELECT '' AS six, c.*
+   FROM NCHAR_TBL c
+   WHERE c.f1 <= 'a';
+
+SELECT '' AS one, c.*
+   FROM NCHAR_TBL c
+   WHERE c.f1 > 'a';
+
+SELECT '' AS two, c.*
+   FROM NCHAR_TBL c
+   WHERE c.f1 >= 'a';
+
+DROP TABLE NCHAR_TBL;
+
+--
+-- Now test longer arrays of nchar
+--
+
+CREATE TABLE NCHAR_TBL(f1 nchar(4));
+
+INSERT INTO NCHAR_TBL (f1) VALUES ('a');
+INSERT INTO NCHAR_TBL (f1) VALUES ('ab');
+INSERT INTO NCHAR_TBL (f1) VALUES ('abcd');
+INSERT INTO NCHAR_TBL (f1) VALUES ('abcde');
+INSERT INTO NCHAR_TBL (f1) VALUES ('abcd    ');
+
+SELECT '' AS four, * FROM NCHAR_TBL;
diff -U 5 -N -r -w ../orig.HEAD/src/test/regress/sql/nvarchar_alter.sql ./src/test/regress/sql/nvarchar_alter.sql
--- ../orig.HEAD/src/test/regress/sql/nvarchar_alter.sql	1969-12-31 19:00:00.000000000 -0500
+++ ./src/test/regress/sql/nvarchar_alter.sql	2013-08-19 23:31:15.000000000 -0400
@@ -0,0 +1,126 @@
+--create table
+create table nchar_test (f1 nchar(10) default N'a', f2 nvarchar(10) default N'b');
+
+--values
+values (N'abc各国語');
+
+--analyze
+analyze nchar_test(f1);
+analyze nchar_test(f2);
+
+--vacuum analyze
+vacuum analyze nchar_test(f1);
+vacuum analyze nchar_test(f2);
+
+--broken
+--set application_name to N'abc各国語';
+
+--select
+select f1,f2,N'abc各国語' from nchar_test;
+
+--select into
+select f1,f2,N'abc各国語' into nchar_test1 from nchar_test;
+
+--revoke per column not supported
+
+--grant per column not supported
+
+--insert into/returning
+insert into nchar_test1 select f1,f2,N'abc各国語' from nchar_test returning f1,f2,nvarchar,N'abc各国語';
+
+--explain
+explain select f1,f2,N'abc各国語' from nchar_test;
+
+--do
+do $$begin perform f1,f2,N'abc各国語' from nchar_test; end $$;
+
+--delete
+delete from nchar_test where f1=N'abc各国語' and f2=N'abc各国語';
+
+--create view
+create view v as select f1,f2,N'abc各国語' from nchar_test;
+
+--create index
+create index i2 on nchar_test(f2);
+create index i3 on nchar_test((f1||'abc各国語'));
+create index i1 on nchar_test(f1);
+
+--comment
+comment on COLUMN nchar_test.f1 is 'f1';
+comment on COLUMN nchar_test.f2 is 'f2';
+comment on type nvarchar is 'nvarchar';
+
+
+--analyze
+analyze nchar_test(f1);
+
+--copy
+copy nchar_test(f1, f2) to stdout;
+
+--alter view
+alter view v alter column f1 set default N'abc各国語';
+alter view v alter column f2 set default N'abc各国語';
+
+--alter table
+alter table nchar_test1 rename f1 to f3;
+alter table nchar_test1 rename f2 to f4;
+alter table nchar_test1 alter f3 type nchar(10);
+alter table nchar_test1 alter f4 type nvarchar;
+alter table nchar_test1 alter f3 set default N'abc各国語';
+alter table nchar_test1 alter f4 set default N'abc各国語';
+
+--declare cursor
+begin;declare qqq cursor for select f1,f2,N'abc各国語' from nchar_test;commit;
+
+--create trigger
+create trigger tr before update on nchar_test for each row when (OLD.f1=N'abc各国語') EXECUTE PROCEDURE suppress_redundant_updates_trigger();
+
+--foreign key
+alter table nchar_test1 add CONSTRAINT nchar_test1_pk primary key(f3);
+alter table nchar_test add CONSTRAINT qqqq FOREIGN KEY (f1) references nchar_test1(f3);
+
+--update
+update nchar_test set f1=N'abc各国語', f2='abc各国語';
+
+select * from nchar_test1;
+
+create domain test_nchar_domain as nchar(10) default (N'a') CHECK (value <> N'b');
+create domain test_nvarchar_domain as nvarchar(10) default (N'a') CHECK (value <> N'b');
+alter domain test_nchar_domain set default (N'b');
+alter domain test_nvarchar_domain set default (N'b');
+DROP DOMAIN test_nchar_domain;
+DROP DOMAIN test_nvarchar_domain;
+
+CREATE AGGREGATE test_nvarchar_agg (nvarchar) ( sfunc = array_append, stype = nvarchar[], initcond = '{}');
+CREATE AGGREGATE test_nchar_agg (nchar(10)) ( sfunc = array_append, stype = nchar(10)[], initcond = '{}');
+alter aggregate test_nvarchar_agg(nvarchar) rename to test_nvarchar_aggregate;
+alter aggregate test_nchar_agg (nchar(10)) rename to test_nchar_aggregate;
+drop aggregate test_nvarchar_aggregate(nvarchar);
+drop aggregate test_nchar_aggregate(nchar(10));
+
+CREATE TYPE test_nchar_type AS (f1 nchar(10));
+CREATE TYPE test_nvarchar_type AS (f1 nvarchar);
+drop type test_nchar_type;
+drop type test_nvarchar_type;
+
+
+drop view v;
+drop table nchar_test;
+drop table nchar_test1;
+
+create table nchar_test (f1 nchar(10), f2 nvarchar(10));
+select f1, f2, N'a'  from nchar_test where f1=N'a' and f2=N'b';
+insert into nchar_test values (N'a', N'b') returning (f1, f2, N'c');
+select f1, f2, N'a' into nchar_test1 from nchar_test;
+select * from nchar_test1;
+
+prepare qqq(nchar(10), nvarchar(10)) AS select f1, f2, N'a'  from nchar_test where f1=N'a' and f2=N'b';
+execute qqq(N'a', N'b');
+
+explain select f1, f2, N'a'  from nchar_test where f1=N'a' and f2=N'b';
+
+delete from nchar_test1 where f1=N'a' and f2=N'b';
+
+drop table nchar_test;
+drop table nchar_test1;
+
diff -U 5 -N -r -w ../orig.HEAD/src/test/regress/sql/nvarchar_func.sql ./src/test/regress/sql/nvarchar_func.sql
--- ../orig.HEAD/src/test/regress/sql/nvarchar_func.sql	1969-12-31 19:00:00.000000000 -0500
+++ ./src/test/regress/sql/nvarchar_func.sql	2013-08-19 23:31:15.000000000 -0400
@@ -0,0 +1,90 @@
+
+SELECT N'各国' || N'文字';
+
+SELECT N'各国' || 42;
+
+SELECT bit_length(N'各国');
+
+SELECT char_length(N'各国');
+
+SELECT lower(N'各国TOM');
+
+SELECT octet_length(N'各国');
+
+SELECT overlay(N'各ＸＸ' placing N'文字' from 2 for 3);
+
+SELECT position(N'文' in N'各国文字');
+
+SELECT substring(N'各国文字' from 3 for 3);
+
+SELECT substring(N'各国文字列' from N'...$');
+
+SELECT substring(N'各国文字列国' from '%#"文_列#"_' for '#');
+
+SELECT trim(both N'Ｘ' from N'Ｘ各国文字ＸＸ');
+
+SELECT upper(N'各国tom');
+
+SELECT ascii(N'数');
+
+SELECT btrim(N'ＸＹ各国Ｘ', N'ＸＹ');
+
+SELECT chr(25968);
+
+SELECT concat(N'各', N'国', NULL, N'語');
+
+SELECT concat_ws(N'＿', N'各国', NULL, N'文字');
+
+-- convert_to(N'各国', 'SJIS') = '\x8a658d91'
+-- convert_to(N'各国', 'UTF8') = '\xe59084e59bbd'
+SELECT convert('\x8a658d91'::bytea, 'SJIS', 'UTF8');
+
+-- N'各国'::bytea = '\xe59084e59bbd'
+SELECT convert_from('\xe59084e59bbd'::bytea, 'UTF8');
+
+-- '\xe59084e59bbd'::bytea = N'各国'
+SELECT convert_to(N'各国', 'UTF8');
+
+SELECT format('各国 %s, %1$s', N'文字');
+
+SELECT initcap(N'hi 各国');
+
+SELECT left(N'各国文字', 2);
+
+SELECT length(N'各国文字');
+
+-- N'各国文字'::bytea = '\xe59084e59bbde69687e5ad97'
+SELECT length('\xe59084e59bbde69687e5ad97'::bytea , 'UTF8');
+
+SELECT lpad(N'文字', 3, N'各国');
+
+SELECT ltrim(N'◯×各国', N'◯×');
+
+SELECT regexp_matches(N'各国文字データ', N'(文字)(データ)');
+
+SELECT regexp_replace(N'各国x文字', '.[a-z]文.', N'語');
+
+SELECT regexp_split_to_array(N'各国 文字列', E'\\s+');
+
+SELECT regexp_split_to_table(N'各国 文字列', E'\\s+');
+
+SELECT repeat(N'文字', 4);
+
+SELECT replace(N'各国文字国', N'国', N'語');
+
+SELECT reverse(N'各国語');
+
+SELECT right(N'各国語', 2);
+
+SELECT rpad(N'各国', 3, N'語');
+
+SELECT rtrim(N'◯各国◯◯', N'◯');
+
+SELECT split_part(N'各国◯語◯文字', N'◯', 3);
+
+SELECT strpos(N'各国語', N'語');
+
+SELECT substr(N'各国語', 3, 3);
+
+SELECT translate(N'各国文字', N'各字', N'◯×');
+
diff -U 5 -N -r -w ../orig.HEAD/src/test/regress/sql/nvarchar_misc.sql ./src/test/regress/sql/nvarchar_misc.sql
--- ../orig.HEAD/src/test/regress/sql/nvarchar_misc.sql	1969-12-31 19:00:00.000000000 -0500
+++ ./src/test/regress/sql/nvarchar_misc.sql	2013-08-19 23:31:15.000000000 -0400
@@ -0,0 +1,22 @@
+select N'a '=N'a';
+select N'a '='a';
+select N'a'='a';
+select N'a '='a'::char(1);
+select N'a '='a'::nchar(1);
+select N'a '='a'::varchar(1);
+select N'a '='a'::nvarchar(1);
+select N'a'='a'::nvarchar(1);
+select N'a'='a'::varchar(1);
+select N'a'='a'::char(1);
+select N'a'='a'::nchar(1);
+select 'a'::nchar(10)='a'::char(1);
+select 'a'::nchar(10)='a'::nchar(1);
+select 'a'::nchar(10)='a'::varchar(1);
+select 'a'::nchar(10)='a'::nvarchar(1);
+select 'a'::nvarchar(10)='a'::varchar(1);
+select 'a'::nvarchar(10)='a'::varchar(10);
+select 'a'::nvarchar(10)='a '::varchar(10);
+select 'a'::nvarchar(10)='a '::char(10);
+select 'a '::nchar(10)='a  '::nchar(5);
+select 'a '::nchar(10)='a  '::char(5);
+
diff -U 5 -N -r -w ../orig.HEAD/src/test/regress/sql/nvarchar.sql ./src/test/regress/sql/nvarchar.sql
--- ../orig.HEAD/src/test/regress/sql/nvarchar.sql	1969-12-31 19:00:00.000000000 -0500
+++ ./src/test/regress/sql/nvarchar.sql	2013-08-19 23:31:15.000000000 -0400
@@ -0,0 +1,66 @@
+--
+-- NVARCHAR
+--
+
+CREATE TABLE NVARCHAR_TBL(f1 nvarchar(1));
+
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('a');
+
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('A');
+
+-- any of the following three input formats are acceptable
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('1');
+
+INSERT INTO NVARCHAR_TBL (f1) VALUES (2);
+
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('3');
+
+-- zero-length nchar
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('');
+
+-- try nvarchar's of greater than 1 length
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('cd');
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('c     ');
+
+
+SELECT '' AS seven, * FROM NVARCHAR_TBL;
+
+SELECT '' AS six, c.*
+   FROM NVARCHAR_TBL c
+   WHERE c.f1 <> 'a';
+
+SELECT '' AS one, c.*
+   FROM NVARCHAR_TBL c
+   WHERE c.f1 = 'a';
+
+SELECT '' AS five, c.*
+   FROM NVARCHAR_TBL c
+   WHERE c.f1 < 'a';
+
+SELECT '' AS six, c.*
+   FROM NVARCHAR_TBL c
+   WHERE c.f1 <= 'a';
+
+SELECT '' AS one, c.*
+   FROM NVARCHAR_TBL c
+   WHERE c.f1 > 'a';
+
+SELECT '' AS two, c.*
+   FROM NVARCHAR_TBL c
+   WHERE c.f1 >= 'a';
+
+DROP TABLE NVARCHAR_TBL;
+
+--
+-- Now test longer arrays of nchar
+--
+
+CREATE TABLE NVARCHAR_TBL(f1 nvarchar(4));
+
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('a');
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('ab');
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('abcd');
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('abcde');
+INSERT INTO NVARCHAR_TBL (f1) VALUES ('abcd    ');
+
+SELECT '' AS four, * FROM NVARCHAR_TBL;
diff -U 5 -N -r -w ../orig.HEAD/src/test/regress/sql/strings.sql ./src/test/regress/sql/strings.sql
--- ../orig.HEAD/src/test/regress/sql/strings.sql	2013-08-19 20:22:15.000000000 -0400
+++ ./src/test/regress/sql/strings.sql	2013-08-19 20:54:00.000000000 -0400
@@ -68,30 +68,41 @@
 -- test conversions between various string types
 -- E021-10 implicit casting among the character data types
 --
 
 SELECT CAST(f1 AS text) AS "text(char)" FROM CHAR_TBL;
+SELECT CAST(f1 AS text) AS "text(nchar)" FROM NCHAR_TBL;
 
 SELECT CAST(f1 AS text) AS "text(varchar)" FROM VARCHAR_TBL;
+SELECT CAST(f1 AS text) AS "text(nvarchar)" FROM NVARCHAR_TBL;
 
 SELECT CAST(name 'namefield' AS text) AS "text(name)";
 
 -- since this is an explicit cast, it should truncate w/o error:
 SELECT CAST(f1 AS char(10)) AS "char(text)" FROM TEXT_TBL;
 -- note: implicit-cast case is tested in char.sql
+SELECT CAST(f1 AS nchar(10)) AS "nchar(text)" FROM TEXT_TBL;
+-- note: implicit-cast case is tested in nchar.sql
 
 SELECT CAST(f1 AS char(20)) AS "char(text)" FROM TEXT_TBL;
+SELECT CAST(f1 AS nchar(20)) AS "nchar(text)" FROM TEXT_TBL;
 
 SELECT CAST(f1 AS char(10)) AS "char(varchar)" FROM VARCHAR_TBL;
+SELECT CAST(f1 AS nchar(10)) AS "nchar(nvarchar)" FROM NVARCHAR_TBL;
+
 
 SELECT CAST(name 'namefield' AS char(10)) AS "char(name)";
+SELECT CAST(name 'namefield' AS nchar(10)) AS "nchar(name)";
 
 SELECT CAST(f1 AS varchar) AS "varchar(text)" FROM TEXT_TBL;
+SELECT CAST(f1 AS nvarchar) AS "nvarchar(text)" FROM TEXT_TBL;
 
 SELECT CAST(f1 AS varchar) AS "varchar(char)" FROM CHAR_TBL;
+SELECT CAST(f1 AS nvarchar) AS "nvarchar(nchar)" FROM NCHAR_TBL;
 
 SELECT CAST(name 'namefield' AS varchar) AS "varchar(name)";
+SELECT CAST(name 'namefield' AS nvarchar) AS "nvarchar(name)";
 
 --
 -- test SQL string functions
 -- E### and T### are feature reference numbers from SQL99
 --
@@ -328,14 +339,17 @@
 SELECT 'unknown' || ' and unknown' AS "Concat unknown types";
 
 SELECT text 'text' || ' and unknown' AS "Concat text to unknown type";
 
 SELECT char(20) 'characters' || ' and text' AS "Concat char to unknown type";
+SELECT nchar(20) 'ncharacters' || ' and text' AS "Concat nchar to unknown type";
 
 SELECT text 'text' || char(20) ' and characters' AS "Concat text to char";
+SELECT text 'text' || nchar(20) ' and ncharacters' AS "Concat text to nchar";
 
 SELECT text 'text' || varchar ' and varchar' AS "Concat text to varchar";
+SELECT text 'text' || nvarchar ' and nvarchar' AS "Concat text to nvarchar";
 
 --
 -- test substr with toasted text values
 --
 CREATE TABLE toasttest(f1 text);
diff -U 5 -N -r -w ../orig.HEAD/src/test/regress/sql/union.sql ./src/test/regress/sql/union.sql
--- ../orig.HEAD/src/test/regress/sql/union.sql	2013-08-19 20:22:15.000000000 -0400
+++ ./src/test/regress/sql/union.sql	2013-08-19 20:54:00.000000000 -0400
@@ -87,10 +87,27 @@
 SELECT f1 FROM VARCHAR_TBL
 UNION
 SELECT TRIM(TRAILING FROM f1) FROM CHAR_TBL
 ORDER BY 1;
 
+--NVARCHAR specific
+SELECT f1 AS three FROM NVARCHAR_TBL
+UNION
+SELECT CAST(f1 AS nvarchar) FROM NCHAR_TBL
+ORDER BY 1;
+
+SELECT f1 AS eight FROM NVARCHAR_TBL
+UNION ALL
+SELECT f1 FROM NCHAR_TBL;
+
+SELECT f1 AS five FROM TEXT_TBL
+UNION
+SELECT f1 FROM NVARCHAR_TBL
+UNION
+SELECT TRIM(TRAILING FROM f1) FROM NCHAR_TBL
+ORDER BY 1;
+
 --
 -- INTERSECT and EXCEPT
 --
 
 SELECT q2 FROM int8_tbl INTERSECT SELECT q1 FROM int8_tbl;
diff -U 5 -N -r -w ../orig.HEAD/src/test/regress/sql/update.sql ./src/test/regress/sql/update.sql
--- ../orig.HEAD/src/test/regress/sql/update.sql	2013-08-19 20:22:15.000000000 -0400
+++ ./src/test/regress/sql/update.sql	2013-08-19 20:54:00.000000000 -0400
@@ -3,18 +3,32 @@
 --
 
 CREATE TABLE update_test (
     a   INT DEFAULT 10,
     b   INT,
-    c   TEXT
+    c   TEXT,
+    d   nchar(10),
+    e   nvarchar
 );
 
-INSERT INTO update_test VALUES (5, 10, 'foo');
+INSERT INTO update_test VALUES (5, 10, 'foo', 'a', 'a');
 INSERT INTO update_test(b, a) VALUES (15, 10);
 
 SELECT * FROM update_test;
 
+UPDATE update_test SET d='b', e='b';
+
+SELECT * FROM update_test;
+
+UPDATE update_test SET d='c' where e='b';
+
+SELECT * FROM update_test;
+
+UPDATE update_test SET d=N'e' where e=N'b';
+
+SELECT * FROM update_test;
+
 UPDATE update_test SET a = DEFAULT, b = DEFAULT;
 
 SELECT * FROM update_test;
 
 -- aliases for the UPDATE target table
