Header And Logo

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

conversioncmds.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * conversioncmds.c
00004  *    conversion creation command support code
00005  *
00006  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00007  * Portions Copyright (c) 1994, Regents of the University of California
00008  *
00009  *
00010  * IDENTIFICATION
00011  *    src/backend/commands/conversioncmds.c
00012  *
00013  *-------------------------------------------------------------------------
00014  */
00015 #include "postgres.h"
00016 
00017 #include "access/heapam.h"
00018 #include "access/htup_details.h"
00019 #include "catalog/dependency.h"
00020 #include "catalog/indexing.h"
00021 #include "catalog/pg_conversion.h"
00022 #include "catalog/pg_conversion_fn.h"
00023 #include "catalog/pg_type.h"
00024 #include "commands/alter.h"
00025 #include "commands/conversioncmds.h"
00026 #include "mb/pg_wchar.h"
00027 #include "miscadmin.h"
00028 #include "parser/parse_func.h"
00029 #include "utils/builtins.h"
00030 #include "utils/lsyscache.h"
00031 #include "utils/rel.h"
00032 #include "utils/syscache.h"
00033 
00034 /*
00035  * CREATE CONVERSION
00036  */
00037 Oid
00038 CreateConversionCommand(CreateConversionStmt *stmt)
00039 {
00040     Oid         namespaceId;
00041     char       *conversion_name;
00042     AclResult   aclresult;
00043     int         from_encoding;
00044     int         to_encoding;
00045     Oid         funcoid;
00046     const char *from_encoding_name = stmt->for_encoding_name;
00047     const char *to_encoding_name = stmt->to_encoding_name;
00048     List       *func_name = stmt->func_name;
00049     static Oid  funcargs[] = {INT4OID, INT4OID, CSTRINGOID, INTERNALOID, INT4OID};
00050     char        result[1];
00051 
00052     /* Convert list of names to a name and namespace */
00053     namespaceId = QualifiedNameGetCreationNamespace(stmt->conversion_name,
00054                                                     &conversion_name);
00055 
00056     /* Check we have creation rights in target namespace */
00057     aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_CREATE);
00058     if (aclresult != ACLCHECK_OK)
00059         aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
00060                        get_namespace_name(namespaceId));
00061 
00062     /* Check the encoding names */
00063     from_encoding = pg_char_to_encoding(from_encoding_name);
00064     if (from_encoding < 0)
00065         ereport(ERROR,
00066                 (errcode(ERRCODE_UNDEFINED_OBJECT),
00067                  errmsg("source encoding \"%s\" does not exist",
00068                         from_encoding_name)));
00069 
00070     to_encoding = pg_char_to_encoding(to_encoding_name);
00071     if (to_encoding < 0)
00072         ereport(ERROR,
00073                 (errcode(ERRCODE_UNDEFINED_OBJECT),
00074                  errmsg("destination encoding \"%s\" does not exist",
00075                         to_encoding_name)));
00076 
00077     /*
00078      * Check the existence of the conversion function. Function name could be
00079      * a qualified name.
00080      */
00081     funcoid = LookupFuncName(func_name, sizeof(funcargs) / sizeof(Oid),
00082                              funcargs, false);
00083 
00084     /* Check it returns VOID, else it's probably the wrong function */
00085     if (get_func_rettype(funcoid) != VOIDOID)
00086         ereport(ERROR,
00087                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
00088           errmsg("encoding conversion function %s must return type \"void\"",
00089                  NameListToString(func_name))));
00090 
00091     /* Check we have EXECUTE rights for the function */
00092     aclresult = pg_proc_aclcheck(funcoid, GetUserId(), ACL_EXECUTE);
00093     if (aclresult != ACLCHECK_OK)
00094         aclcheck_error(aclresult, ACL_KIND_PROC,
00095                        NameListToString(func_name));
00096 
00097     /*
00098      * Check that the conversion function is suitable for the requested source
00099      * and target encodings. We do that by calling the function with an empty
00100      * string; the conversion function should throw an error if it can't
00101      * perform the requested conversion.
00102      */
00103     OidFunctionCall5(funcoid,
00104                      Int32GetDatum(from_encoding),
00105                      Int32GetDatum(to_encoding),
00106                      CStringGetDatum(""),
00107                      CStringGetDatum(result),
00108                      Int32GetDatum(0));
00109 
00110     /*
00111      * All seem ok, go ahead (possible failure would be a duplicate conversion
00112      * name)
00113      */
00114     return ConversionCreate(conversion_name, namespaceId, GetUserId(),
00115                             from_encoding, to_encoding, funcoid, stmt->def);
00116 }