Header And Logo

PostgreSQL
| The world's most advanced open source database.

name.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * name.c
00004  *    Functions for the built-in type "name".
00005  *
00006  * name replaces char16 and is carefully implemented so that it
00007  * is a string of physical length NAMEDATALEN.
00008  * DO NOT use hard-coded constants anywhere
00009  * always use NAMEDATALEN as the symbolic constant!   - jolly 8/21/95
00010  *
00011  *
00012  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00013  * Portions Copyright (c) 1994, Regents of the University of California
00014  *
00015  *
00016  * IDENTIFICATION
00017  *    src/backend/utils/adt/name.c
00018  *
00019  *-------------------------------------------------------------------------
00020  */
00021 #include "postgres.h"
00022 
00023 #include "catalog/namespace.h"
00024 #include "catalog/pg_type.h"
00025 #include "libpq/pqformat.h"
00026 #include "mb/pg_wchar.h"
00027 #include "miscadmin.h"
00028 #include "utils/array.h"
00029 #include "utils/builtins.h"
00030 #include "utils/lsyscache.h"
00031 
00032 
00033 /*****************************************************************************
00034  *   USER I/O ROUTINES (none)                                                *
00035  *****************************************************************************/
00036 
00037 
00038 /*
00039  *      namein  - converts "..." to internal representation
00040  *
00041  *      Note:
00042  *              [Old] Currently if strlen(s) < NAMEDATALEN, the extra chars are nulls
00043  *              Now, always NULL terminated
00044  */
00045 Datum
00046 namein(PG_FUNCTION_ARGS)
00047 {
00048     char       *s = PG_GETARG_CSTRING(0);
00049     Name        result;
00050     int         len;
00051 
00052     len = strlen(s);
00053 
00054     /* Truncate oversize input */
00055     if (len >= NAMEDATALEN)
00056         len = pg_mbcliplen(s, len, NAMEDATALEN - 1);
00057 
00058     /* We use palloc0 here to ensure result is zero-padded */
00059     result = (Name) palloc0(NAMEDATALEN);
00060     memcpy(NameStr(*result), s, len);
00061 
00062     PG_RETURN_NAME(result);
00063 }
00064 
00065 /*
00066  *      nameout - converts internal representation to "..."
00067  */
00068 Datum
00069 nameout(PG_FUNCTION_ARGS)
00070 {
00071     Name        s = PG_GETARG_NAME(0);
00072 
00073     PG_RETURN_CSTRING(pstrdup(NameStr(*s)));
00074 }
00075 
00076 /*
00077  *      namerecv            - converts external binary format to name
00078  */
00079 Datum
00080 namerecv(PG_FUNCTION_ARGS)
00081 {
00082     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
00083     Name        result;
00084     char       *str;
00085     int         nbytes;
00086 
00087     str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
00088     if (nbytes >= NAMEDATALEN)
00089         ereport(ERROR,
00090                 (errcode(ERRCODE_NAME_TOO_LONG),
00091                  errmsg("identifier too long"),
00092                  errdetail("Identifier must be less than %d characters.",
00093                            NAMEDATALEN)));
00094     result = (NameData *) palloc0(NAMEDATALEN);
00095     memcpy(result, str, nbytes);
00096     pfree(str);
00097     PG_RETURN_NAME(result);
00098 }
00099 
00100 /*
00101  *      namesend            - converts name to binary format
00102  */
00103 Datum
00104 namesend(PG_FUNCTION_ARGS)
00105 {
00106     Name        s = PG_GETARG_NAME(0);
00107     StringInfoData buf;
00108 
00109     pq_begintypsend(&buf);
00110     pq_sendtext(&buf, NameStr(*s), strlen(NameStr(*s)));
00111     PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
00112 }
00113 
00114 
00115 /*****************************************************************************
00116  *   PUBLIC ROUTINES                                                         *
00117  *****************************************************************************/
00118 
00119 /*
00120  *      nameeq  - returns 1 iff arguments are equal
00121  *      namene  - returns 1 iff arguments are not equal
00122  *
00123  *      BUGS:
00124  *              Assumes that "xy\0\0a" should be equal to "xy\0b".
00125  *              If not, can do the comparison backwards for efficiency.
00126  *
00127  *      namelt  - returns 1 iff a < b
00128  *      namele  - returns 1 iff a <= b
00129  *      namegt  - returns 1 iff a > b
00130  *      namege  - returns 1 iff a >= b
00131  *
00132  */
00133 Datum
00134 nameeq(PG_FUNCTION_ARGS)
00135 {
00136     Name        arg1 = PG_GETARG_NAME(0);
00137     Name        arg2 = PG_GETARG_NAME(1);
00138 
00139     PG_RETURN_BOOL(strncmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN) == 0);
00140 }
00141 
00142 Datum
00143 namene(PG_FUNCTION_ARGS)
00144 {
00145     Name        arg1 = PG_GETARG_NAME(0);
00146     Name        arg2 = PG_GETARG_NAME(1);
00147 
00148     PG_RETURN_BOOL(strncmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN) != 0);
00149 }
00150 
00151 Datum
00152 namelt(PG_FUNCTION_ARGS)
00153 {
00154     Name        arg1 = PG_GETARG_NAME(0);
00155     Name        arg2 = PG_GETARG_NAME(1);
00156 
00157     PG_RETURN_BOOL(strncmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN) < 0);
00158 }
00159 
00160 Datum
00161 namele(PG_FUNCTION_ARGS)
00162 {
00163     Name        arg1 = PG_GETARG_NAME(0);
00164     Name        arg2 = PG_GETARG_NAME(1);
00165 
00166     PG_RETURN_BOOL(strncmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN) <= 0);
00167 }
00168 
00169 Datum
00170 namegt(PG_FUNCTION_ARGS)
00171 {
00172     Name        arg1 = PG_GETARG_NAME(0);
00173     Name        arg2 = PG_GETARG_NAME(1);
00174 
00175     PG_RETURN_BOOL(strncmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN) > 0);
00176 }
00177 
00178 Datum
00179 namege(PG_FUNCTION_ARGS)
00180 {
00181     Name        arg1 = PG_GETARG_NAME(0);
00182     Name        arg2 = PG_GETARG_NAME(1);
00183 
00184     PG_RETURN_BOOL(strncmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN) >= 0);
00185 }
00186 
00187 
00188 /* (see char.c for comparison/operation routines) */
00189 
00190 int
00191 namecpy(Name n1, Name n2)
00192 {
00193     if (!n1 || !n2)
00194         return -1;
00195     strncpy(NameStr(*n1), NameStr(*n2), NAMEDATALEN);
00196     return 0;
00197 }
00198 
00199 #ifdef NOT_USED
00200 int
00201 namecat(Name n1, Name n2)
00202 {
00203     return namestrcat(n1, NameStr(*n2));        /* n2 can't be any longer than
00204                                                  * n1 */
00205 }
00206 #endif
00207 
00208 #ifdef NOT_USED
00209 int
00210 namecmp(Name n1, Name n2)
00211 {
00212     return strncmp(NameStr(*n1), NameStr(*n2), NAMEDATALEN);
00213 }
00214 #endif
00215 
00216 int
00217 namestrcpy(Name name, const char *str)
00218 {
00219     if (!name || !str)
00220         return -1;
00221     StrNCpy(NameStr(*name), str, NAMEDATALEN);
00222     return 0;
00223 }
00224 
00225 #ifdef NOT_USED
00226 int
00227 namestrcat(Name name, const char *str)
00228 {
00229     int         i;
00230     char       *p,
00231                *q;
00232 
00233     if (!name || !str)
00234         return -1;
00235     for (i = 0, p = NameStr(*name); i < NAMEDATALEN && *p; ++i, ++p)
00236         ;
00237     for (q = str; i < NAMEDATALEN; ++i, ++p, ++q)
00238     {
00239         *p = *q;
00240         if (!*q)
00241             break;
00242     }
00243     return 0;
00244 }
00245 #endif
00246 
00247 int
00248 namestrcmp(Name name, const char *str)
00249 {
00250     if (!name && !str)
00251         return 0;
00252     if (!name)
00253         return -1;              /* NULL < anything */
00254     if (!str)
00255         return 1;               /* NULL < anything */
00256     return strncmp(NameStr(*name), str, NAMEDATALEN);
00257 }
00258 
00259 
00260 /*
00261  * SQL-functions CURRENT_USER, SESSION_USER
00262  */
00263 Datum
00264 current_user(PG_FUNCTION_ARGS)
00265 {
00266     PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(GetUserNameFromId(GetUserId()))));
00267 }
00268 
00269 Datum
00270 session_user(PG_FUNCTION_ARGS)
00271 {
00272     PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(GetUserNameFromId(GetSessionUserId()))));
00273 }
00274 
00275 
00276 /*
00277  * SQL-functions CURRENT_SCHEMA, CURRENT_SCHEMAS
00278  */
00279 Datum
00280 current_schema(PG_FUNCTION_ARGS)
00281 {
00282     List       *search_path = fetch_search_path(false);
00283     char       *nspname;
00284 
00285     if (search_path == NIL)
00286         PG_RETURN_NULL();
00287     nspname = get_namespace_name(linitial_oid(search_path));
00288     list_free(search_path);
00289     if (!nspname)
00290         PG_RETURN_NULL();       /* recently-deleted namespace? */
00291     PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(nspname)));
00292 }
00293 
00294 Datum
00295 current_schemas(PG_FUNCTION_ARGS)
00296 {
00297     List       *search_path = fetch_search_path(PG_GETARG_BOOL(0));
00298     ListCell   *l;
00299     Datum      *names;
00300     int         i;
00301     ArrayType  *array;
00302 
00303     names = (Datum *) palloc(list_length(search_path) * sizeof(Datum));
00304     i = 0;
00305     foreach(l, search_path)
00306     {
00307         char       *nspname;
00308 
00309         nspname = get_namespace_name(lfirst_oid(l));
00310         if (nspname)            /* watch out for deleted namespace */
00311         {
00312             names[i] = DirectFunctionCall1(namein, CStringGetDatum(nspname));
00313             i++;
00314         }
00315     }
00316     list_free(search_path);
00317 
00318     array = construct_array(names, i,
00319                             NAMEOID,
00320                             NAMEDATALEN,        /* sizeof(Name) */
00321                             false,      /* Name is not by-val */
00322                             'c');       /* alignment of Name */
00323 
00324     PG_RETURN_POINTER(array);
00325 }