PostgreSQL Source Code  git master
conversioncmds.c File Reference
#include "postgres.h"
#include "catalog/pg_conversion.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "commands/conversioncmds.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "parser/parse_func.h"
#include "utils/acl.h"
#include "utils/lsyscache.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 32 of file conversioncmds.c.

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

References ACL_CREATE, ACL_EXECUTE, aclcheck_error(), ACLCHECK_OK, BoolGetDatum(), ConversionCreate(), CStringGetDatum(), DatumGetInt32(), ereport, errcode(), errmsg(), ERROR, 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 stmt.

Referenced by ProcessUtilitySlow().