|
| 1 | +/*------------------------------------------------------------------------- |
| 2 | + * |
| 3 | + * pg_conversion.c |
| 4 | + * routines to support manipulation of the pg_conversion relation |
| 5 | + * |
| 6 | + * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group |
| 7 | + * Portions Copyright (c) 1994, Regents of the University of California |
| 8 | + * |
| 9 | + * |
| 10 | + * IDENTIFICATION |
| 11 | + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_conversion.c,v 1.1 2002/07/11 07:39:27 ishii Exp $ |
| 12 | + * |
| 13 | + *------------------------------------------------------------------------- |
| 14 | + */ |
| 15 | +#include"postgres.h" |
| 16 | + |
| 17 | +#include"access/heapam.h" |
| 18 | +#include"catalog/catname.h" |
| 19 | +#include"catalog/indexing.h" |
| 20 | +#include"catalog/pg_conversion.h" |
| 21 | +#include"catalog/namespace.h" |
| 22 | +#include"utils/builtins.h" |
| 23 | +#include"utils/syscache.h" |
| 24 | +#include"mb/pg_wchar.h" |
| 25 | +#include"utils/fmgroids.h" |
| 26 | +#include"utils/acl.h" |
| 27 | +#include"miscadmin.h" |
| 28 | + |
| 29 | +/* ---------------- |
| 30 | + * ConversionCreate |
| 31 | + * --------------- |
| 32 | + */ |
| 33 | +OidConversionCreate(constchar*conname,Oidconnamespace, |
| 34 | +int32conowner, |
| 35 | +int4conforencoding,int4contoencoding, |
| 36 | +Oidconproc,booldef) |
| 37 | +{ |
| 38 | +inti; |
| 39 | +Relationrel; |
| 40 | +TupleDesctupDesc; |
| 41 | +HeapTupletup; |
| 42 | +charnulls[Natts_pg_conversion]; |
| 43 | +Datumvalues[Natts_pg_conversion]; |
| 44 | +NameDatacname; |
| 45 | +Oidoid; |
| 46 | + |
| 47 | +/* sanity checks */ |
| 48 | +if (!conname) |
| 49 | +elog(ERROR,"no conversion name supplied"); |
| 50 | + |
| 51 | +/* make sure there is no existing conversion of same name */ |
| 52 | +if (SearchSysCacheExists(CONNAMESP, |
| 53 | +PointerGetDatum(conname), |
| 54 | +ObjectIdGetDatum(connamespace), |
| 55 | +0,0)) |
| 56 | +elog(ERROR,"conversion name \"%s\" already exists",conname); |
| 57 | + |
| 58 | +if (def) |
| 59 | +{ |
| 60 | +/* make sure there is no existing default |
| 61 | + <for encoding><to encoding> pair in this name space */ |
| 62 | +if (FindDefaultConversion(connamespace, |
| 63 | +conforencoding, |
| 64 | +contoencoding)) |
| 65 | +elog(ERROR,"default conversion for %s to %s already exists", |
| 66 | +pg_encoding_to_char(conforencoding),pg_encoding_to_char(contoencoding)); |
| 67 | +} |
| 68 | + |
| 69 | +/* open pg_conversion */ |
| 70 | +rel=heap_openr(ConversionRelationName,RowExclusiveLock); |
| 71 | +tupDesc=rel->rd_att; |
| 72 | + |
| 73 | +/* initialize nulls and values */ |
| 74 | +for (i=0;i<Natts_pg_conversion;i++) |
| 75 | +{ |
| 76 | +nulls[i]=' '; |
| 77 | +values[i]= (Datum)NULL; |
| 78 | +} |
| 79 | + |
| 80 | +/* form a tuple */ |
| 81 | +namestrcpy(&cname,conname); |
| 82 | +values[Anum_pg_conversion_conname-1]=NameGetDatum(&cname); |
| 83 | +values[Anum_pg_conversion_connamespace-1]=ObjectIdGetDatum(connamespace); |
| 84 | +values[Anum_pg_conversion_conowner-1]=Int32GetDatum(conowner); |
| 85 | +values[Anum_pg_conversion_conforencoding-1]=Int32GetDatum(conforencoding); |
| 86 | +values[Anum_pg_conversion_contoencoding-1]=Int32GetDatum(contoencoding); |
| 87 | +values[Anum_pg_conversion_conproc-1]=ObjectIdGetDatum(conproc); |
| 88 | +values[Anum_pg_conversion_condefault-1]=BoolGetDatum(def); |
| 89 | + |
| 90 | +tup=heap_formtuple(tupDesc,values,nulls); |
| 91 | + |
| 92 | +/* insert a new tuple */ |
| 93 | +oid=simple_heap_insert(rel,tup); |
| 94 | +Assert(OidIsValid(oid)); |
| 95 | + |
| 96 | +/* update the index if any */ |
| 97 | +if (RelationGetForm(rel)->relhasindex) |
| 98 | +{ |
| 99 | +Relationidescs[Num_pg_conversion_indices]; |
| 100 | + |
| 101 | +CatalogOpenIndices(Num_pg_conversion_indices,Name_pg_conversion_indices,idescs); |
| 102 | +CatalogIndexInsert(idescs,Num_pg_conversion_indices,rel,tup); |
| 103 | +CatalogCloseIndices(Num_pg_conversion_indices,idescs); |
| 104 | +} |
| 105 | + |
| 106 | +heap_close(rel,RowExclusiveLock); |
| 107 | + |
| 108 | +returnoid; |
| 109 | +} |
| 110 | + |
| 111 | +/* ---------------- |
| 112 | + * ConversionDrop |
| 113 | + * --------------- |
| 114 | + */ |
| 115 | +voidConversionDrop(constchar*conname,Oidconnamespace,int32conowner) |
| 116 | +{ |
| 117 | +Relationrel; |
| 118 | +TupleDesctupDesc; |
| 119 | +HeapTupletuple; |
| 120 | +HeapScanDescscan; |
| 121 | +ScanKeyDatascanKeyData; |
| 122 | +Form_pg_conversionbody; |
| 123 | + |
| 124 | +/* sanity checks */ |
| 125 | +if (!conname) |
| 126 | +elog(ERROR,"no conversion name supplied"); |
| 127 | + |
| 128 | +ScanKeyEntryInitialize(&scanKeyData, |
| 129 | +0, |
| 130 | +Anum_pg_conversion_connamespace, |
| 131 | +F_OIDEQ, |
| 132 | +ObjectIdGetDatum(connamespace)); |
| 133 | + |
| 134 | +/* open pg_conversion */ |
| 135 | +rel=heap_openr(ConversionRelationName,RowExclusiveLock); |
| 136 | +tupDesc=rel->rd_att; |
| 137 | + |
| 138 | +scan=heap_beginscan(rel,SnapshotNow, |
| 139 | +1,&scanKeyData); |
| 140 | + |
| 141 | +/* search for the target tuple */ |
| 142 | +while (HeapTupleIsValid(tuple=heap_getnext(scan,ForwardScanDirection))) |
| 143 | +{ |
| 144 | +body= (Form_pg_conversion)GETSTRUCT(tuple); |
| 145 | +if (!strncmp(NameStr(body->conname),conname,NAMEDATALEN)) |
| 146 | +break; |
| 147 | +} |
| 148 | + |
| 149 | +if (!HeapTupleIsValid(tuple)) |
| 150 | +{ |
| 151 | +elog(ERROR,"conversion %s not found",conname); |
| 152 | +return; |
| 153 | +} |
| 154 | + |
| 155 | +if (!superuser()&& ((Form_pg_conversion)GETSTRUCT(tuple))->conowner!=GetUserId()) |
| 156 | +elog(ERROR,"permission denied"); |
| 157 | + |
| 158 | +simple_heap_delete(rel,&tuple->t_self); |
| 159 | + |
| 160 | +heap_endscan(scan); |
| 161 | +heap_close(rel,RowExclusiveLock); |
| 162 | +} |
| 163 | + |
| 164 | +/* ---------------- |
| 165 | + * FindDefaultConversion |
| 166 | + * |
| 167 | + * find default conversion proc by for_encoding and to_encoding in this name space |
| 168 | + * --------------- |
| 169 | + */ |
| 170 | +OidFindDefaultConversion(Oidname_space,int4for_encoding,int4to_encoding) |
| 171 | +{ |
| 172 | +Relationrel; |
| 173 | +HeapScanDescscan; |
| 174 | +ScanKeyDatascanKeyData; |
| 175 | +HeapTupletuple; |
| 176 | +Form_pg_conversionbody; |
| 177 | +Oidproc=InvalidOid; |
| 178 | + |
| 179 | +/* Check we have usage rights in target namespace */ |
| 180 | +if (pg_namespace_aclcheck(name_space,GetUserId(),ACL_USAGE)!=ACLCHECK_OK) |
| 181 | +returnInvalidOid; |
| 182 | + |
| 183 | +ScanKeyEntryInitialize(&scanKeyData, |
| 184 | +0, |
| 185 | +Anum_pg_conversion_connamespace, |
| 186 | +F_OIDEQ, |
| 187 | +ObjectIdGetDatum(name_space)); |
| 188 | + |
| 189 | +rel=heap_openr(ConversionRelationName,AccessShareLock); |
| 190 | +scan=heap_beginscan(rel,SnapshotNow, |
| 191 | +1,&scanKeyData); |
| 192 | + |
| 193 | +while (HeapTupleIsValid(tuple=heap_getnext(scan,ForwardScanDirection))) |
| 194 | +{ |
| 195 | +body= (Form_pg_conversion)GETSTRUCT(tuple); |
| 196 | +if (body->conforencoding==for_encoding&& |
| 197 | +body->conforencoding==to_encoding&& |
| 198 | +body->condefault== TRUE) { |
| 199 | +proc=body->conproc; |
| 200 | +break; |
| 201 | +} |
| 202 | +} |
| 203 | +heap_endscan(scan); |
| 204 | +heap_close(rel,AccessShareLock); |
| 205 | +returnproc; |
| 206 | +} |
| 207 | + |
| 208 | +/* ---------------- |
| 209 | + * FindConversionByName |
| 210 | + * |
| 211 | + * find conversion proc by possibly qualified conversion name. |
| 212 | + * --------------- |
| 213 | + */ |
| 214 | +OidFindConversionByName(List*name) |
| 215 | +{ |
| 216 | +HeapTupletuple; |
| 217 | +char*conversion_name; |
| 218 | +OidnamespaceId; |
| 219 | +Oidprocoid; |
| 220 | +AclResultaclresult; |
| 221 | + |
| 222 | +/* Convert list of names to a name and namespace */ |
| 223 | +namespaceId=QualifiedNameGetCreationNamespace(name,&conversion_name); |
| 224 | + |
| 225 | +/* Check we have usage rights in target namespace */ |
| 226 | +if (pg_namespace_aclcheck(namespaceId,GetUserId(),ACL_USAGE)!=ACLCHECK_OK) |
| 227 | +returnInvalidOid; |
| 228 | + |
| 229 | +/* search pg_conversion by namespaceId and conversion name */ |
| 230 | +tuple=SearchSysCache(CONNAMESP, |
| 231 | +PointerGetDatum(conversion_name), |
| 232 | +ObjectIdGetDatum(namespaceId), |
| 233 | +0,0); |
| 234 | + |
| 235 | +if (!HeapTupleIsValid(tuple)) |
| 236 | +returnInvalidOid; |
| 237 | + |
| 238 | +procoid= ((Form_pg_conversion)GETSTRUCT(tuple))->conproc; |
| 239 | + |
| 240 | +ReleaseSysCache(tuple); |
| 241 | + |
| 242 | +/* Check we have execute rights for the function */ |
| 243 | +aclresult=pg_proc_aclcheck(procoid,GetUserId(),ACL_EXECUTE); |
| 244 | +if (aclresult!=ACLCHECK_OK) |
| 245 | +returnInvalidOid; |
| 246 | + |
| 247 | +returnprocoid; |
| 248 | +} |
| 249 | + |