2525#include  "parser/parse_coerce.h" 
2626#include  "utils/array.h" 
2727#include  "utils/builtins.h" 
28+ #include  "utils/date.h" 
2829#include  "utils/datetime.h" 
2930#include  "utils/lsyscache.h" 
3031#include  "utils/json.h" 
@@ -55,8 +56,9 @@ typedef enum					/* type categories for datum_to_json */
5556	JSONTYPE_NULL ,				/* null, so we didn't bother to identify */ 
5657	JSONTYPE_BOOL ,				/* boolean (built-in types only) */ 
5758	JSONTYPE_NUMERIC ,			/* numeric (ditto) */ 
58- 	JSONTYPE_TIMESTAMP ,         /* we use special formatting for timestamp */ 
59- 	JSONTYPE_TIMESTAMPTZ ,       /* ... and timestamptz */ 
59+ 	JSONTYPE_DATE ,				/* we use special formatting for datetimes */ 
60+ 	JSONTYPE_TIMESTAMP ,
61+ 	JSONTYPE_TIMESTAMPTZ ,
6062	JSONTYPE_JSON ,				/* JSON itself (and JSONB) */ 
6163	JSONTYPE_ARRAY ,				/* array */ 
6264	JSONTYPE_COMPOSITE ,			/* composite */ 
@@ -1267,6 +1269,10 @@ json_categorize_type(Oid typoid,
12671269			* tcategory  =  JSONTYPE_NUMERIC ;
12681270			break ;
12691271
1272+ 		case  DATEOID :
1273+ 			* tcategory  =  JSONTYPE_DATE ;
1274+ 			break ;
1275+ 
12701276		case  TIMESTAMPOID :
12711277			* tcategory  =  JSONTYPE_TIMESTAMP ;
12721278			break ;
@@ -1348,7 +1354,7 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
13481354		 tcategory  ==  JSONTYPE_CAST ))
13491355		ereport (ERROR ,
13501356				(errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
1351- 		   errmsg ("key value must be scalar, not array, composite, or json" )));
1357+ 		 errmsg ("key value must be scalar, not array, composite, or json" )));
13521358
13531359	switch  (tcategory )
13541360	{
@@ -1388,6 +1394,30 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
13881394			}
13891395			pfree (outputstr );
13901396			break ;
1397+ 		case  JSONTYPE_DATE :
1398+ 			{
1399+ 				DateADT 		date ;
1400+ 				struct  pg_tm  tm ;
1401+ 				char 		buf [MAXDATELEN  +  1 ];
1402+ 
1403+ 				date  =  DatumGetDateADT (val );
1404+ 
1405+ 				/* XSD doesn't support infinite values */ 
1406+ 				if  (DATE_NOT_FINITE (date ))
1407+ 					ereport (ERROR ,
1408+ 							(errcode (ERRCODE_DATETIME_VALUE_OUT_OF_RANGE ),
1409+ 							 errmsg ("date out of range" ),
1410+ 							 errdetail ("JSON does not support infinite date values." )));
1411+ 				else 
1412+ 				{
1413+ 					j2date (date  +  POSTGRES_EPOCH_JDATE ,
1414+ 						   & (tm .tm_year ), & (tm .tm_mon ), & (tm .tm_mday ));
1415+ 					EncodeDateOnly (& tm , USE_XSD_DATES , buf );
1416+ 				}
1417+ 
1418+ 				appendStringInfo (result , "\"%s\"" , buf );
1419+ 			}
1420+ 			break ;
13911421		case  JSONTYPE_TIMESTAMP :
13921422			{
13931423				Timestamp 	timestamp ;
@@ -1410,7 +1440,7 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
14101440							(errcode (ERRCODE_DATETIME_VALUE_OUT_OF_RANGE ),
14111441							 errmsg ("timestamp out of range" )));
14121442
1413- 				appendStringInfo (result ,"\"%s\"" ,buf );
1443+ 				appendStringInfo (result ,  "\"%s\"" ,  buf );
14141444			}
14151445			break ;
14161446		case  JSONTYPE_TIMESTAMPTZ :
@@ -1437,7 +1467,7 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
14371467							(errcode (ERRCODE_DATETIME_VALUE_OUT_OF_RANGE ),
14381468							 errmsg ("timestamp out of range" )));
14391469
1440- 				appendStringInfo (result ,"\"%s\"" ,buf );
1470+ 				appendStringInfo (result ,  "\"%s\"" ,  buf );
14411471			}
14421472			break ;
14431473		case  JSONTYPE_JSON :
@@ -2305,20 +2335,21 @@ escape_json(StringInfo buf, const char *str)
23052335				appendStringInfoString (buf , "\\\"" );
23062336				break ;
23072337			case  '\\' :
2338+ 
23082339				/* 
23092340				 * Unicode escapes are passed through as is. There is no 
23102341				 * requirement that they denote a valid character in the 
23112342				 * server encoding - indeed that is a big part of their 
23122343				 * usefulness. 
23132344				 * 
2314- 				 * All we require is that they consist of \uXXXX where 
2315- 				 * the Xs  are hexadecimal digits. It is the responsibility 
2316- 				 * of the  caller of, say, to_json() to make sure that the 
2317- 				 * unicode  escape is valid. 
2345+ 				 * All we require is that they consist of \uXXXX where the Xs  
2346+ 				 * are hexadecimal digits. It is the responsibility of the  
2347+ 				 * caller of, say, to_json() to make sure that the unicode  
2348+ 				 * escape is valid. 
23182349				 * 
2319- 				 * In the case of a jsonb string value being escaped, the 
2320- 				 * only  unicode escape that should be present is \u0000, 
2321- 				 * all the  other unicode escapes will have been resolved. 
2350+ 				 * In the case of a jsonb string value being escaped, the only  
2351+ 				 * unicode escape that should be present is \u0000, all the  
2352+ 				 * other unicode escapes will have been resolved. 
23222353				 */ 
23232354				if  (p [1 ] ==  'u'  && 
23242355					isxdigit ((unsigned char  ) p [2 ]) && 
0 commit comments