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_namespace.h"
#include "catalog/pg_proc.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 39 of file conversioncmds.c.

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

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_aclcheck(), OBJECT_FUNCTION, OBJECT_SCHEMA, OidFunctionCall6, pg_char_to_encoding(), PG_SQL_ASCII, QualifiedNameGetCreationNamespace(), and CreateConversionStmt::to_encoding_name.

Referenced by ProcessUtilitySlow().