~vcs-imports/mammoth-replicator/trunk

« back to all changes in this revision

Viewing changes to src/backend/commands/conversioncmds.c

  • Committer: alvherre
  • Date: 2005-12-16 21:24:52 UTC
  • Revision ID: svn-v4:db760fc0-0f08-0410-9d63-cc6633f64896:trunk:1
Initial import of the REL8_0_3 sources from the Pgsql CVS repository.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-------------------------------------------------------------------------
 
2
 *
 
3
 * conversioncmds.c
 
4
 *        conversion creation command support code
 
5
 *
 
6
 * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
 
7
 * Portions Copyright (c) 1994, Regents of the University of California
 
8
 *
 
9
 *
 
10
 * IDENTIFICATION
 
11
 *        $PostgreSQL: pgsql/src/backend/commands/conversioncmds.c,v 1.16.4.1 2005-05-03 19:18:15 tgl Exp $
 
12
 *
 
13
 *-------------------------------------------------------------------------
 
14
 */
 
15
#include "postgres.h"
 
16
 
 
17
#include "catalog/pg_conversion.h"
 
18
#include "access/heapam.h"
 
19
#include "catalog/catalog.h"
 
20
#include "catalog/catname.h"
 
21
#include "catalog/indexing.h"
 
22
#include "catalog/namespace.h"
 
23
#include "catalog/pg_type.h"
 
24
#include "mb/pg_wchar.h"
 
25
#include "commands/conversioncmds.h"
 
26
#include "miscadmin.h"
 
27
#include "parser/parse_func.h"
 
28
#include "utils/acl.h"
 
29
#include "utils/builtins.h"
 
30
#include "utils/lsyscache.h"
 
31
#include "utils/syscache.h"
 
32
 
 
33
 
 
34
/*
 
35
 * CREATE CONVERSION
 
36
 */
 
37
void
 
38
CreateConversionCommand(CreateConversionStmt *stmt)
 
39
{
 
40
        Oid                     namespaceId;
 
41
        char       *conversion_name;
 
42
        AclResult       aclresult;
 
43
        int                     from_encoding;
 
44
        int                     to_encoding;
 
45
        Oid                     funcoid;
 
46
        const char *from_encoding_name = stmt->for_encoding_name;
 
47
        const char *to_encoding_name = stmt->to_encoding_name;
 
48
        List       *func_name = stmt->func_name;
 
49
        static Oid      funcargs[] = {INT4OID, INT4OID, CSTRINGOID, INTERNALOID, INT4OID};
 
50
 
 
51
        /* Convert list of names to a name and namespace */
 
52
        namespaceId = QualifiedNameGetCreationNamespace(stmt->conversion_name,
 
53
                                                                                                        &conversion_name);
 
54
 
 
55
        /* Check we have creation rights in target namespace */
 
56
        aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_CREATE);
 
57
        if (aclresult != ACLCHECK_OK)
 
58
                aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
 
59
                                           get_namespace_name(namespaceId));
 
60
 
 
61
        /* Check the encoding names */
 
62
        from_encoding = pg_char_to_encoding(from_encoding_name);
 
63
        if (from_encoding < 0)
 
64
                ereport(ERROR,
 
65
                                (errcode(ERRCODE_UNDEFINED_OBJECT),
 
66
                                 errmsg("source encoding \"%s\" does not exist",
 
67
                                                from_encoding_name)));
 
68
 
 
69
        to_encoding = pg_char_to_encoding(to_encoding_name);
 
70
        if (to_encoding < 0)
 
71
                ereport(ERROR,
 
72
                                (errcode(ERRCODE_UNDEFINED_OBJECT),
 
73
                                 errmsg("destination encoding \"%s\" does not exist",
 
74
                                                to_encoding_name)));
 
75
 
 
76
        /*
 
77
         * Check the existence of the conversion function. Function name could
 
78
         * be a qualified name.
 
79
         */
 
80
        funcoid = LookupFuncName(func_name, sizeof(funcargs) / sizeof(Oid),
 
81
                                                         funcargs, false);
 
82
 
 
83
        /* Check we have EXECUTE rights for the function */
 
84
        aclresult = pg_proc_aclcheck(funcoid, GetUserId(), ACL_EXECUTE);
 
85
        if (aclresult != ACLCHECK_OK)
 
86
                aclcheck_error(aclresult, ACL_KIND_PROC,
 
87
                                           NameListToString(func_name));
 
88
 
 
89
        /*
 
90
         * All seem ok, go ahead (possible failure would be a duplicate
 
91
         * conversion name)
 
92
         */
 
93
        ConversionCreate(conversion_name, namespaceId, GetUserId(),
 
94
                                         from_encoding, to_encoding, funcoid, stmt->def);
 
95
}
 
96
 
 
97
/*
 
98
 * DROP CONVERSION
 
99
 */
 
100
void
 
101
DropConversionCommand(List *name, DropBehavior behavior)
 
102
{
 
103
        Oid                     conversionOid;
 
104
 
 
105
        conversionOid = FindConversionByName(name);
 
106
        if (!OidIsValid(conversionOid))
 
107
                ereport(ERROR,
 
108
                                (errcode(ERRCODE_UNDEFINED_OBJECT),
 
109
                                 errmsg("conversion \"%s\" does not exist",
 
110
                                                NameListToString(name))));
 
111
 
 
112
        ConversionDrop(conversionOid, behavior);
 
113
}
 
114
 
 
115
/*
 
116
 * Rename conversion
 
117
 */
 
118
void
 
119
RenameConversion(List *name, const char *newname)
 
120
{
 
121
        Oid                     conversionOid;
 
122
        Oid                     namespaceOid;
 
123
        HeapTuple       tup;
 
124
        Relation        rel;
 
125
        AclResult       aclresult;
 
126
 
 
127
        rel = heap_openr(ConversionRelationName, RowExclusiveLock);
 
128
 
 
129
        conversionOid = FindConversionByName(name);
 
130
        if (!OidIsValid(conversionOid))
 
131
                ereport(ERROR,
 
132
                                (errcode(ERRCODE_UNDEFINED_OBJECT),
 
133
                                 errmsg("conversion \"%s\" does not exist",
 
134
                                                NameListToString(name))));
 
135
 
 
136
        tup = SearchSysCacheCopy(CONOID,
 
137
                                                         ObjectIdGetDatum(conversionOid),
 
138
                                                         0, 0, 0);
 
139
        if (!HeapTupleIsValid(tup)) /* should not happen */
 
140
                elog(ERROR, "cache lookup failed for conversion %u", conversionOid);
 
141
 
 
142
        namespaceOid = ((Form_pg_conversion) GETSTRUCT(tup))->connamespace;
 
143
 
 
144
        /* make sure the new name doesn't exist */
 
145
        if (SearchSysCacheExists(CONNAMENSP,
 
146
                                                         CStringGetDatum(newname),
 
147
                                                         ObjectIdGetDatum(namespaceOid),
 
148
                                                         0, 0))
 
149
                ereport(ERROR,
 
150
                                (errcode(ERRCODE_DUPLICATE_OBJECT),
 
151
                          errmsg("conversion \"%s\" already exists in schema \"%s\"",
 
152
                                         newname, get_namespace_name(namespaceOid))));
 
153
 
 
154
        /* must be owner */
 
155
        if (!superuser() &&
 
156
                ((Form_pg_conversion) GETSTRUCT(tup))->conowner != GetUserId())
 
157
                aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CONVERSION,
 
158
                                           NameListToString(name));
 
159
 
 
160
        /* must have CREATE privilege on namespace */
 
161
        aclresult = pg_namespace_aclcheck(namespaceOid, GetUserId(), ACL_CREATE);
 
162
        if (aclresult != ACLCHECK_OK)
 
163
                aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
 
164
                                           get_namespace_name(namespaceOid));
 
165
 
 
166
        /* rename */
 
167
        namestrcpy(&(((Form_pg_conversion) GETSTRUCT(tup))->conname), newname);
 
168
        simple_heap_update(rel, &tup->t_self, tup);
 
169
        CatalogUpdateIndexes(rel, tup);
 
170
 
 
171
        heap_close(rel, NoLock);
 
172
        heap_freetuple(tup);
 
173
}
 
174
 
 
175
/*
 
176
 * Change conversion owner
 
177
 */
 
178
void
 
179
AlterConversionOwner(List *name, AclId newOwnerSysId)
 
180
{
 
181
        Oid                     conversionOid;
 
182
        HeapTuple       tup;
 
183
        Relation        rel;
 
184
        Form_pg_conversion convForm;
 
185
 
 
186
        rel = heap_openr(ConversionRelationName, RowExclusiveLock);
 
187
 
 
188
        conversionOid = FindConversionByName(name);
 
189
        if (!OidIsValid(conversionOid))
 
190
                ereport(ERROR,
 
191
                                (errcode(ERRCODE_UNDEFINED_OBJECT),
 
192
                                 errmsg("conversion \"%s\" does not exist",
 
193
                                                NameListToString(name))));
 
194
 
 
195
        tup = SearchSysCacheCopy(CONOID,
 
196
                                                         ObjectIdGetDatum(conversionOid),
 
197
                                                         0, 0, 0);
 
198
        if (!HeapTupleIsValid(tup)) /* should not happen */
 
199
                elog(ERROR, "cache lookup failed for conversion %u", conversionOid);
 
200
 
 
201
        convForm = (Form_pg_conversion) GETSTRUCT(tup);
 
202
 
 
203
        /*
 
204
         * If the new owner is the same as the existing owner, consider the
 
205
         * command to have succeeded.  This is for dump restoration purposes.
 
206
         */
 
207
        if (convForm->conowner != newOwnerSysId)
 
208
        {
 
209
                /* Otherwise, must be superuser to change object ownership */
 
210
                if (!superuser())
 
211
                        ereport(ERROR,
 
212
                                        (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
 
213
                                         errmsg("must be superuser to change owner")));
 
214
 
 
215
                /*
 
216
                 * Modify the owner --- okay to scribble on tup because it's a
 
217
                 * copy
 
218
                 */
 
219
                convForm->conowner = newOwnerSysId;
 
220
 
 
221
                simple_heap_update(rel, &tup->t_self, tup);
 
222
 
 
223
                CatalogUpdateIndexes(rel, tup);
 
224
        }
 
225
 
 
226
        heap_close(rel, NoLock);
 
227
        heap_freetuple(tup);
 
228
}