Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "postgres.h"
00022
00023 #include "access/htup_details.h"
00024 #include "access/tupconvert.h"
00025 #include "utils/builtins.h"
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065 TupleConversionMap *
00066 convert_tuples_by_position(TupleDesc indesc,
00067 TupleDesc outdesc,
00068 const char *msg)
00069 {
00070 TupleConversionMap *map;
00071 AttrNumber *attrMap;
00072 int nincols;
00073 int noutcols;
00074 int n;
00075 int i;
00076 int j;
00077 bool same;
00078
00079
00080 n = outdesc->natts;
00081 attrMap = (AttrNumber *) palloc0(n * sizeof(AttrNumber));
00082 j = 0;
00083 nincols = noutcols = 0;
00084 same = true;
00085 for (i = 0; i < n; i++)
00086 {
00087 Form_pg_attribute att = outdesc->attrs[i];
00088 Oid atttypid;
00089 int32 atttypmod;
00090
00091 if (att->attisdropped)
00092 continue;
00093 noutcols++;
00094 atttypid = att->atttypid;
00095 atttypmod = att->atttypmod;
00096 for (; j < indesc->natts; j++)
00097 {
00098 att = indesc->attrs[j];
00099 if (att->attisdropped)
00100 continue;
00101 nincols++;
00102
00103 if (atttypid != att->atttypid ||
00104 (atttypmod != att->atttypmod && atttypmod >= 0))
00105 ereport(ERROR,
00106 (errcode(ERRCODE_DATATYPE_MISMATCH),
00107 errmsg_internal("%s", _(msg)),
00108 errdetail("Returned type %s does not match expected type %s in column %d.",
00109 format_type_with_typemod(att->atttypid,
00110 att->atttypmod),
00111 format_type_with_typemod(atttypid,
00112 atttypmod),
00113 noutcols)));
00114 attrMap[i] = (AttrNumber) (j + 1);
00115 j++;
00116 break;
00117 }
00118 if (attrMap[i] == 0)
00119 same = false;
00120 }
00121
00122
00123 for (; j < indesc->natts; j++)
00124 {
00125 if (indesc->attrs[j]->attisdropped)
00126 continue;
00127 nincols++;
00128 same = false;
00129 }
00130
00131
00132 if (!same)
00133 ereport(ERROR,
00134 (errcode(ERRCODE_DATATYPE_MISMATCH),
00135 errmsg_internal("%s", _(msg)),
00136 errdetail("Number of returned columns (%d) does not match "
00137 "expected column count (%d).",
00138 nincols, noutcols)));
00139
00140
00141
00142
00143
00144
00145 if (indesc->natts == outdesc->natts &&
00146 indesc->tdtypeid == outdesc->tdtypeid)
00147 {
00148 for (i = 0; i < n; i++)
00149 {
00150 if (attrMap[i] == (i + 1))
00151 continue;
00152
00153
00154
00155
00156
00157
00158 if (attrMap[i] == 0 &&
00159 indesc->attrs[i]->attisdropped &&
00160 indesc->attrs[i]->attlen == outdesc->attrs[i]->attlen &&
00161 indesc->attrs[i]->attalign == outdesc->attrs[i]->attalign)
00162 continue;
00163
00164 same = false;
00165 break;
00166 }
00167 }
00168 else
00169 same = false;
00170
00171 if (same)
00172 {
00173
00174 pfree(attrMap);
00175 return NULL;
00176 }
00177
00178
00179 map = (TupleConversionMap *) palloc(sizeof(TupleConversionMap));
00180 map->indesc = indesc;
00181 map->outdesc = outdesc;
00182 map->attrMap = attrMap;
00183
00184 map->outvalues = (Datum *) palloc(n * sizeof(Datum));
00185 map->outisnull = (bool *) palloc(n * sizeof(bool));
00186 n = indesc->natts + 1;
00187 map->invalues = (Datum *) palloc(n * sizeof(Datum));
00188 map->inisnull = (bool *) palloc(n * sizeof(bool));
00189 map->invalues[0] = (Datum) 0;
00190 map->inisnull[0] = true;
00191
00192 return map;
00193 }
00194
00195
00196
00197
00198
00199
00200
00201
00202 TupleConversionMap *
00203 convert_tuples_by_name(TupleDesc indesc,
00204 TupleDesc outdesc,
00205 const char *msg)
00206 {
00207 TupleConversionMap *map;
00208 AttrNumber *attrMap;
00209 int n;
00210 int i;
00211 bool same;
00212
00213
00214 n = outdesc->natts;
00215 attrMap = (AttrNumber *) palloc0(n * sizeof(AttrNumber));
00216 for (i = 0; i < n; i++)
00217 {
00218 Form_pg_attribute att = outdesc->attrs[i];
00219 char *attname;
00220 Oid atttypid;
00221 int32 atttypmod;
00222 int j;
00223
00224 if (att->attisdropped)
00225 continue;
00226 attname = NameStr(att->attname);
00227 atttypid = att->atttypid;
00228 atttypmod = att->atttypmod;
00229 for (j = 0; j < indesc->natts; j++)
00230 {
00231 att = indesc->attrs[j];
00232 if (att->attisdropped)
00233 continue;
00234 if (strcmp(attname, NameStr(att->attname)) == 0)
00235 {
00236
00237 if (atttypid != att->atttypid || atttypmod != att->atttypmod)
00238 ereport(ERROR,
00239 (errcode(ERRCODE_DATATYPE_MISMATCH),
00240 errmsg_internal("%s", _(msg)),
00241 errdetail("Attribute \"%s\" of type %s does not match corresponding attribute of type %s.",
00242 attname,
00243 format_type_be(outdesc->tdtypeid),
00244 format_type_be(indesc->tdtypeid))));
00245 attrMap[i] = (AttrNumber) (j + 1);
00246 break;
00247 }
00248 }
00249 if (attrMap[i] == 0)
00250 ereport(ERROR,
00251 (errcode(ERRCODE_DATATYPE_MISMATCH),
00252 errmsg_internal("%s", _(msg)),
00253 errdetail("Attribute \"%s\" of type %s does not exist in type %s.",
00254 attname,
00255 format_type_be(outdesc->tdtypeid),
00256 format_type_be(indesc->tdtypeid))));
00257 }
00258
00259
00260
00261
00262
00263
00264 if (indesc->natts == outdesc->natts &&
00265 indesc->tdtypeid == outdesc->tdtypeid)
00266 {
00267 same = true;
00268 for (i = 0; i < n; i++)
00269 {
00270 if (attrMap[i] == (i + 1))
00271 continue;
00272
00273
00274
00275
00276
00277
00278 if (attrMap[i] == 0 &&
00279 indesc->attrs[i]->attisdropped &&
00280 indesc->attrs[i]->attlen == outdesc->attrs[i]->attlen &&
00281 indesc->attrs[i]->attalign == outdesc->attrs[i]->attalign)
00282 continue;
00283
00284 same = false;
00285 break;
00286 }
00287 }
00288 else
00289 same = false;
00290
00291 if (same)
00292 {
00293
00294 pfree(attrMap);
00295 return NULL;
00296 }
00297
00298
00299 map = (TupleConversionMap *) palloc(sizeof(TupleConversionMap));
00300 map->indesc = indesc;
00301 map->outdesc = outdesc;
00302 map->attrMap = attrMap;
00303
00304 map->outvalues = (Datum *) palloc(n * sizeof(Datum));
00305 map->outisnull = (bool *) palloc(n * sizeof(bool));
00306 n = indesc->natts + 1;
00307 map->invalues = (Datum *) palloc(n * sizeof(Datum));
00308 map->inisnull = (bool *) palloc(n * sizeof(bool));
00309 map->invalues[0] = (Datum) 0;
00310 map->inisnull[0] = true;
00311
00312 return map;
00313 }
00314
00315
00316
00317
00318 HeapTuple
00319 do_convert_tuple(HeapTuple tuple, TupleConversionMap *map)
00320 {
00321 AttrNumber *attrMap = map->attrMap;
00322 Datum *invalues = map->invalues;
00323 bool *inisnull = map->inisnull;
00324 Datum *outvalues = map->outvalues;
00325 bool *outisnull = map->outisnull;
00326 int outnatts = map->outdesc->natts;
00327 int i;
00328
00329
00330
00331
00332
00333
00334 heap_deform_tuple(tuple, map->indesc, invalues + 1, inisnull + 1);
00335
00336
00337
00338
00339 for (i = 0; i < outnatts; i++)
00340 {
00341 int j = attrMap[i];
00342
00343 outvalues[i] = invalues[j];
00344 outisnull[i] = inisnull[j];
00345 }
00346
00347
00348
00349
00350 return heap_form_tuple(map->outdesc, outvalues, outisnull);
00351 }
00352
00353
00354
00355
00356 void
00357 free_conversion_map(TupleConversionMap *map)
00358 {
00359
00360 pfree(map->attrMap);
00361 pfree(map->invalues);
00362 pfree(map->inisnull);
00363 pfree(map->outvalues);
00364 pfree(map->outisnull);
00365 pfree(map);
00366 }