00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "postgres.h"
00016
00017 #include "access/heapam.h"
00018 #include "access/htup_details.h"
00019 #include "access/sysattr.h"
00020 #include "catalog/dependency.h"
00021 #include "catalog/indexing.h"
00022 #include "catalog/objectaccess.h"
00023 #include "catalog/pg_conversion.h"
00024 #include "catalog/pg_conversion_fn.h"
00025 #include "catalog/pg_namespace.h"
00026 #include "catalog/pg_proc.h"
00027 #include "mb/pg_wchar.h"
00028 #include "utils/builtins.h"
00029 #include "utils/catcache.h"
00030 #include "utils/fmgroids.h"
00031 #include "utils/rel.h"
00032 #include "utils/syscache.h"
00033 #include "utils/tqual.h"
00034
00035
00036
00037
00038
00039
00040 Oid
00041 ConversionCreate(const char *conname, Oid connamespace,
00042 Oid conowner,
00043 int32 conforencoding, int32 contoencoding,
00044 Oid conproc, bool def)
00045 {
00046 int i;
00047 Relation rel;
00048 TupleDesc tupDesc;
00049 HeapTuple tup;
00050 bool nulls[Natts_pg_conversion];
00051 Datum values[Natts_pg_conversion];
00052 NameData cname;
00053 Oid oid;
00054 ObjectAddress myself,
00055 referenced;
00056
00057
00058 if (!conname)
00059 elog(ERROR, "no conversion name supplied");
00060
00061
00062 if (SearchSysCacheExists2(CONNAMENSP,
00063 PointerGetDatum(conname),
00064 ObjectIdGetDatum(connamespace)))
00065 ereport(ERROR,
00066 (errcode(ERRCODE_DUPLICATE_OBJECT),
00067 errmsg("conversion \"%s\" already exists", conname)));
00068
00069 if (def)
00070 {
00071
00072
00073
00074
00075 if (FindDefaultConversion(connamespace,
00076 conforencoding,
00077 contoencoding))
00078 ereport(ERROR,
00079 (errcode(ERRCODE_DUPLICATE_OBJECT),
00080 errmsg("default conversion for %s to %s already exists",
00081 pg_encoding_to_char(conforencoding),
00082 pg_encoding_to_char(contoencoding))));
00083 }
00084
00085
00086 rel = heap_open(ConversionRelationId, RowExclusiveLock);
00087 tupDesc = rel->rd_att;
00088
00089
00090 for (i = 0; i < Natts_pg_conversion; i++)
00091 {
00092 nulls[i] = false;
00093 values[i] = (Datum) NULL;
00094 }
00095
00096
00097 namestrcpy(&cname, conname);
00098 values[Anum_pg_conversion_conname - 1] = NameGetDatum(&cname);
00099 values[Anum_pg_conversion_connamespace - 1] = ObjectIdGetDatum(connamespace);
00100 values[Anum_pg_conversion_conowner - 1] = ObjectIdGetDatum(conowner);
00101 values[Anum_pg_conversion_conforencoding - 1] = Int32GetDatum(conforencoding);
00102 values[Anum_pg_conversion_contoencoding - 1] = Int32GetDatum(contoencoding);
00103 values[Anum_pg_conversion_conproc - 1] = ObjectIdGetDatum(conproc);
00104 values[Anum_pg_conversion_condefault - 1] = BoolGetDatum(def);
00105
00106 tup = heap_form_tuple(tupDesc, values, nulls);
00107
00108
00109 oid = simple_heap_insert(rel, tup);
00110 Assert(OidIsValid(oid));
00111
00112
00113 CatalogUpdateIndexes(rel, tup);
00114
00115 myself.classId = ConversionRelationId;
00116 myself.objectId = HeapTupleGetOid(tup);
00117 myself.objectSubId = 0;
00118
00119
00120 referenced.classId = ProcedureRelationId;
00121 referenced.objectId = conproc;
00122 referenced.objectSubId = 0;
00123 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
00124
00125
00126 referenced.classId = NamespaceRelationId;
00127 referenced.objectId = connamespace;
00128 referenced.objectSubId = 0;
00129 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
00130
00131
00132 recordDependencyOnOwner(ConversionRelationId, HeapTupleGetOid(tup),
00133 conowner);
00134
00135
00136 recordDependencyOnCurrentExtension(&myself, false);
00137
00138
00139 InvokeObjectPostCreateHook(ConversionRelationId, HeapTupleGetOid(tup), 0);
00140
00141 heap_freetuple(tup);
00142 heap_close(rel, RowExclusiveLock);
00143
00144 return oid;
00145 }
00146
00147
00148
00149
00150
00151
00152
00153 void
00154 RemoveConversionById(Oid conversionOid)
00155 {
00156 Relation rel;
00157 HeapTuple tuple;
00158 HeapScanDesc scan;
00159 ScanKeyData scanKeyData;
00160
00161 ScanKeyInit(&scanKeyData,
00162 ObjectIdAttributeNumber,
00163 BTEqualStrategyNumber, F_OIDEQ,
00164 ObjectIdGetDatum(conversionOid));
00165
00166
00167 rel = heap_open(ConversionRelationId, RowExclusiveLock);
00168
00169 scan = heap_beginscan(rel, SnapshotNow,
00170 1, &scanKeyData);
00171
00172
00173 if (HeapTupleIsValid(tuple = heap_getnext(scan, ForwardScanDirection)))
00174 simple_heap_delete(rel, &tuple->t_self);
00175 else
00176 elog(ERROR, "could not find tuple for conversion %u", conversionOid);
00177 heap_endscan(scan);
00178 heap_close(rel, RowExclusiveLock);
00179 }
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190 Oid
00191 FindDefaultConversion(Oid name_space, int32 for_encoding, int32 to_encoding)
00192 {
00193 CatCList *catlist;
00194 HeapTuple tuple;
00195 Form_pg_conversion body;
00196 Oid proc = InvalidOid;
00197 int i;
00198
00199 catlist = SearchSysCacheList3(CONDEFAULT,
00200 ObjectIdGetDatum(name_space),
00201 Int32GetDatum(for_encoding),
00202 Int32GetDatum(to_encoding));
00203
00204 for (i = 0; i < catlist->n_members; i++)
00205 {
00206 tuple = &catlist->members[i]->tuple;
00207 body = (Form_pg_conversion) GETSTRUCT(tuple);
00208 if (body->condefault)
00209 {
00210 proc = body->conproc;
00211 break;
00212 }
00213 }
00214 ReleaseSysCacheList(catlist);
00215 return proc;
00216 }