00001 /*------------------------------------------------------------------------- 00002 * 00003 * char.c 00004 * Functions for the built-in type "char" (not to be confused with 00005 * bpchar, which is the SQL CHAR(n) type). 00006 * 00007 * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group 00008 * Portions Copyright (c) 1994, Regents of the University of California 00009 * 00010 * 00011 * IDENTIFICATION 00012 * src/backend/utils/adt/char.c 00013 * 00014 *------------------------------------------------------------------------- 00015 */ 00016 #include "postgres.h" 00017 00018 #include <limits.h> 00019 00020 #include "libpq/pqformat.h" 00021 #include "utils/builtins.h" 00022 00023 /***************************************************************************** 00024 * USER I/O ROUTINES * 00025 *****************************************************************************/ 00026 00027 /* 00028 * charin - converts "x" to 'x' 00029 * 00030 * Note that an empty input string will implicitly be converted to \0. 00031 */ 00032 Datum 00033 charin(PG_FUNCTION_ARGS) 00034 { 00035 char *ch = PG_GETARG_CSTRING(0); 00036 00037 PG_RETURN_CHAR(ch[0]); 00038 } 00039 00040 /* 00041 * charout - converts 'x' to "x" 00042 * 00043 * Note that if the char value is \0, the resulting string will appear 00044 * to be empty (null-terminated after zero characters). So this is the 00045 * inverse of the charin() function for such data. 00046 */ 00047 Datum 00048 charout(PG_FUNCTION_ARGS) 00049 { 00050 char ch = PG_GETARG_CHAR(0); 00051 char *result = (char *) palloc(2); 00052 00053 result[0] = ch; 00054 result[1] = '\0'; 00055 PG_RETURN_CSTRING(result); 00056 } 00057 00058 /* 00059 * charrecv - converts external binary format to char 00060 * 00061 * The external representation is one byte, with no character set 00062 * conversion. This is somewhat dubious, perhaps, but in many 00063 * cases people use char for a 1-byte binary type. 00064 */ 00065 Datum 00066 charrecv(PG_FUNCTION_ARGS) 00067 { 00068 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); 00069 00070 PG_RETURN_CHAR(pq_getmsgbyte(buf)); 00071 } 00072 00073 /* 00074 * charsend - converts char to binary format 00075 */ 00076 Datum 00077 charsend(PG_FUNCTION_ARGS) 00078 { 00079 char arg1 = PG_GETARG_CHAR(0); 00080 StringInfoData buf; 00081 00082 pq_begintypsend(&buf); 00083 pq_sendbyte(&buf, arg1); 00084 PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); 00085 } 00086 00087 /***************************************************************************** 00088 * PUBLIC ROUTINES * 00089 *****************************************************************************/ 00090 00091 /* 00092 * NOTE: comparisons are done as though char is unsigned (uint8). 00093 * Conversions to and from integer are done as though char is signed (int8). 00094 * 00095 * You wanted consistency? 00096 */ 00097 00098 Datum 00099 chareq(PG_FUNCTION_ARGS) 00100 { 00101 char arg1 = PG_GETARG_CHAR(0); 00102 char arg2 = PG_GETARG_CHAR(1); 00103 00104 PG_RETURN_BOOL(arg1 == arg2); 00105 } 00106 00107 Datum 00108 charne(PG_FUNCTION_ARGS) 00109 { 00110 char arg1 = PG_GETARG_CHAR(0); 00111 char arg2 = PG_GETARG_CHAR(1); 00112 00113 PG_RETURN_BOOL(arg1 != arg2); 00114 } 00115 00116 Datum 00117 charlt(PG_FUNCTION_ARGS) 00118 { 00119 char arg1 = PG_GETARG_CHAR(0); 00120 char arg2 = PG_GETARG_CHAR(1); 00121 00122 PG_RETURN_BOOL((uint8) arg1 < (uint8) arg2); 00123 } 00124 00125 Datum 00126 charle(PG_FUNCTION_ARGS) 00127 { 00128 char arg1 = PG_GETARG_CHAR(0); 00129 char arg2 = PG_GETARG_CHAR(1); 00130 00131 PG_RETURN_BOOL((uint8) arg1 <= (uint8) arg2); 00132 } 00133 00134 Datum 00135 chargt(PG_FUNCTION_ARGS) 00136 { 00137 char arg1 = PG_GETARG_CHAR(0); 00138 char arg2 = PG_GETARG_CHAR(1); 00139 00140 PG_RETURN_BOOL((uint8) arg1 > (uint8) arg2); 00141 } 00142 00143 Datum 00144 charge(PG_FUNCTION_ARGS) 00145 { 00146 char arg1 = PG_GETARG_CHAR(0); 00147 char arg2 = PG_GETARG_CHAR(1); 00148 00149 PG_RETURN_BOOL((uint8) arg1 >= (uint8) arg2); 00150 } 00151 00152 00153 Datum 00154 chartoi4(PG_FUNCTION_ARGS) 00155 { 00156 char arg1 = PG_GETARG_CHAR(0); 00157 00158 PG_RETURN_INT32((int32) ((int8) arg1)); 00159 } 00160 00161 Datum 00162 i4tochar(PG_FUNCTION_ARGS) 00163 { 00164 int32 arg1 = PG_GETARG_INT32(0); 00165 00166 if (arg1 < SCHAR_MIN || arg1 > SCHAR_MAX) 00167 ereport(ERROR, 00168 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), 00169 errmsg("\"char\" out of range"))); 00170 00171 PG_RETURN_CHAR((int8) arg1); 00172 } 00173 00174 00175 Datum 00176 text_char(PG_FUNCTION_ARGS) 00177 { 00178 text *arg1 = PG_GETARG_TEXT_P(0); 00179 char result; 00180 00181 /* 00182 * An empty input string is converted to \0 (for consistency with charin). 00183 * If the input is longer than one character, the excess data is silently 00184 * discarded. 00185 */ 00186 if (VARSIZE(arg1) > VARHDRSZ) 00187 result = *(VARDATA(arg1)); 00188 else 00189 result = '\0'; 00190 00191 PG_RETURN_CHAR(result); 00192 } 00193 00194 Datum 00195 char_text(PG_FUNCTION_ARGS) 00196 { 00197 char arg1 = PG_GETARG_CHAR(0); 00198 text *result = palloc(VARHDRSZ + 1); 00199 00200 /* 00201 * Convert \0 to an empty string, for consistency with charout (and 00202 * because the text stuff doesn't like embedded nulls all that well). 00203 */ 00204 if (arg1 != '\0') 00205 { 00206 SET_VARSIZE(result, VARHDRSZ + 1); 00207 *(VARDATA(result)) = arg1; 00208 } 00209 else 00210 SET_VARSIZE(result, VARHDRSZ); 00211 00212 PG_RETURN_TEXT_P(result); 00213 }