PostgreSQL Source Code  git master
conversioncmds.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/pg_conversion.h"
#include "catalog/pg_type.h"
#include "commands/alter.h"
#include "commands/conversioncmds.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "parser/parse_func.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
#include "utils/syscache.h"
Include dependency graph for conversioncmds.c:

Go to the source code of this file.

Functions

ObjectAddress CreateConversionCommand (CreateConversionStmt *stmt)
 

Function Documentation

◆ CreateConversionCommand()

ObjectAddress CreateConversionCommand ( CreateConversionStmt stmt)

Definition at line 37 of file conversioncmds.c.

References ACL_CREATE, ACL_EXECUTE, aclcheck_error(), ACLCHECK_OK, BoolGetDatum, CreateConversionStmt::conversion_name, ConversionCreate(), CStringGetDatum, DatumGetInt32, CreateConversionStmt::def, ereport, errcode(), errmsg(), ERROR, CreateConversionStmt::for_encoding_name, CreateConversionStmt::func_name, get_func_rettype(), get_namespace_name(), GetUserId(), Int32GetDatum, LookupFuncName(), NameListToString(), OBJECT_FUNCTION, OBJECT_SCHEMA, OidFunctionCall6, pg_char_to_encoding(), pg_namespace_aclcheck(), pg_proc_aclcheck(), PG_SQL_ASCII, QualifiedNameGetCreationNamespace(), and CreateConversionStmt::to_encoding_name.

Referenced by ProcessUtilitySlow().

38 {
39  Oid namespaceId;
40  char *conversion_name;
41  AclResult aclresult;
42  int from_encoding;
43  int to_encoding;
44  Oid funcoid;
45  const char *from_encoding_name = stmt->for_encoding_name;
46  const char *to_encoding_name = stmt->to_encoding_name;
47  List *func_name = stmt->func_name;
48  static const Oid funcargs[] = {INT4OID, INT4OID, CSTRINGOID, INTERNALOID, INT4OID, BOOLOID};
49  char result[1];
50  Datum funcresult;
51 
52  /* Convert list of names to a name and namespace */
54  &conversion_name);
55 
56  /* Check we have creation rights in target namespace */
57  aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_CREATE);
58  if (aclresult != ACLCHECK_OK)
59  aclcheck_error(aclresult, OBJECT_SCHEMA,
60  get_namespace_name(namespaceId));
61 
62  /* Check the encoding names */
63  from_encoding = pg_char_to_encoding(from_encoding_name);
64  if (from_encoding < 0)
65  ereport(ERROR,
66  (errcode(ERRCODE_UNDEFINED_OBJECT),
67  errmsg("source encoding \"%s\" does not exist",
68  from_encoding_name)));
69 
70  to_encoding = pg_char_to_encoding(to_encoding_name);
71  if (to_encoding < 0)
72  ereport(ERROR,
73  (errcode(ERRCODE_UNDEFINED_OBJECT),
74  errmsg("destination encoding \"%s\" does not exist",
75  to_encoding_name)));
76 
77  /*
78  * We consider conversions to or from SQL_ASCII to be meaningless. (If
79  * you wish to change this, note that pg_do_encoding_conversion() and its
80  * sister functions have hard-wired fast paths for any conversion in which
81  * the source or target encoding is SQL_ASCII, so that an encoding
82  * conversion function declared for such a case will never be used.)
83  */
84  if (from_encoding == PG_SQL_ASCII || to_encoding == PG_SQL_ASCII)
85  ereport(ERROR,
86  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
87  errmsg("encoding conversion to or from \"SQL_ASCII\" is not supported")));
88 
89  /*
90  * Check the existence of the conversion function. Function name could be
91  * a qualified name.
92  */
93  funcoid = LookupFuncName(func_name, sizeof(funcargs) / sizeof(Oid),
94  funcargs, false);
95 
96  /* Check it returns int4, else it's probably the wrong function */
97  if (get_func_rettype(funcoid) != INT4OID)
98  ereport(ERROR,
99  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
100  errmsg("encoding conversion function %s must return type %s",
101  NameListToString(func_name), "integer")));
102 
103  /* Check we have EXECUTE rights for the function */
104  aclresult = pg_proc_aclcheck(funcoid, GetUserId(), ACL_EXECUTE);
105  if (aclresult != ACLCHECK_OK)
106  aclcheck_error(aclresult, OBJECT_FUNCTION,
107  NameListToString(func_name));
108 
109  /*
110  * Check that the conversion function is suitable for the requested source
111  * and target encodings. We do that by calling the function with an empty
112  * string; the conversion function should throw an error if it can't
113  * perform the requested conversion.
114  */
115  funcresult = OidFunctionCall6(funcoid,
116  Int32GetDatum(from_encoding),
117  Int32GetDatum(to_encoding),
118  CStringGetDatum(""),
119  CStringGetDatum(result),
120  Int32GetDatum(0),
121  BoolGetDatum(false));
122 
123  /*
124  * The function should return 0 for empty input. Might as well check that,
125  * too.
126  */
127  if (DatumGetInt32(funcresult) != 0)
128  ereport(ERROR,
129  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
130  errmsg("encoding conversion function %s returned incorrect result for empty input",
131  NameListToString(func_name))));
132 
133  /*
134  * All seem ok, go ahead (possible failure would be a duplicate conversion
135  * name)
136  */
137  return ConversionCreate(conversion_name, namespaceId, GetUserId(),
138  from_encoding, to_encoding, funcoid, stmt->def);
139 }
int pg_char_to_encoding(const char *name)
Definition: encnames.c:550
#define OidFunctionCall6(functionId, arg1, arg2, arg3, arg4, arg5, arg6)
Definition: fmgr.h:674
#define DatumGetInt32(X)
Definition: postgres.h:516
Oid GetUserId(void)
Definition: miscinit.c:495
Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p)
Definition: namespace.c:3040
int errcode(int sqlerrcode)
Definition: elog.c:698
unsigned int Oid
Definition: postgres_ext.h:31
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4756
Oid get_func_rettype(Oid funcid)
Definition: lsyscache.c:1626
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3308
#define ERROR
Definition: elog.h:46
#define ACL_CREATE
Definition: parsenodes.h:92
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool missing_ok)
Definition: parse_func.c:2145
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3316
#define CStringGetDatum(X)
Definition: postgres.h:622
char * NameListToString(List *names)
Definition: namespace.c:3147
ObjectAddress ConversionCreate(const char *conname, Oid connamespace, Oid conowner, int32 conforencoding, int32 contoencoding, Oid conproc, bool def)
Definition: pg_conversion.c:41
AclResult
Definition: acl.h:177
uintptr_t Datum
Definition: postgres.h:411
#define BoolGetDatum(X)
Definition: postgres.h:446
#define ereport(elevel,...)
Definition: elog.h:157
#define Int32GetDatum(X)
Definition: postgres.h:523
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define ACL_EXECUTE
Definition: parsenodes.h:89
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4718
Definition: pg_list.h:50