00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "postgres.h"
00021
00022 #include "access/htup_details.h"
00023 #include "catalog/pg_type.h"
00024 #include "miscadmin.h"
00025 #include "parser/parse_type.h"
00026 #include "utils/acl.h"
00027 #include "utils/builtins.h"
00028 #include "utils/resowner_private.h"
00029 #include "utils/syscache.h"
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 TupleDesc
00040 CreateTemplateTupleDesc(int natts, bool hasoid)
00041 {
00042 TupleDesc desc;
00043 char *stg;
00044 int attroffset;
00045
00046
00047
00048
00049 AssertArg(natts >= 0);
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 attroffset = sizeof(struct tupleDesc) + natts * sizeof(Form_pg_attribute);
00065 attroffset = MAXALIGN(attroffset);
00066 stg = palloc(attroffset + natts * MAXALIGN(ATTRIBUTE_FIXED_PART_SIZE));
00067 desc = (TupleDesc) stg;
00068
00069 if (natts > 0)
00070 {
00071 Form_pg_attribute *attrs;
00072 int i;
00073
00074 attrs = (Form_pg_attribute *) (stg + sizeof(struct tupleDesc));
00075 desc->attrs = attrs;
00076 stg += attroffset;
00077 for (i = 0; i < natts; i++)
00078 {
00079 attrs[i] = (Form_pg_attribute) stg;
00080 stg += MAXALIGN(ATTRIBUTE_FIXED_PART_SIZE);
00081 }
00082 }
00083 else
00084 desc->attrs = NULL;
00085
00086
00087
00088
00089 desc->natts = natts;
00090 desc->constr = NULL;
00091 desc->tdtypeid = RECORDOID;
00092 desc->tdtypmod = -1;
00093 desc->tdhasoid = hasoid;
00094 desc->tdrefcount = -1;
00095
00096 return desc;
00097 }
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110 TupleDesc
00111 CreateTupleDesc(int natts, bool hasoid, Form_pg_attribute *attrs)
00112 {
00113 TupleDesc desc;
00114
00115
00116
00117
00118 AssertArg(natts >= 0);
00119
00120 desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
00121 desc->attrs = attrs;
00122 desc->natts = natts;
00123 desc->constr = NULL;
00124 desc->tdtypeid = RECORDOID;
00125 desc->tdtypmod = -1;
00126 desc->tdhasoid = hasoid;
00127 desc->tdrefcount = -1;
00128
00129 return desc;
00130 }
00131
00132
00133
00134
00135
00136
00137
00138
00139 TupleDesc
00140 CreateTupleDescCopy(TupleDesc tupdesc)
00141 {
00142 TupleDesc desc;
00143 int i;
00144
00145 desc = CreateTemplateTupleDesc(tupdesc->natts, tupdesc->tdhasoid);
00146
00147 for (i = 0; i < desc->natts; i++)
00148 {
00149 memcpy(desc->attrs[i], tupdesc->attrs[i], ATTRIBUTE_FIXED_PART_SIZE);
00150 desc->attrs[i]->attnotnull = false;
00151 desc->attrs[i]->atthasdef = false;
00152 }
00153
00154 desc->tdtypeid = tupdesc->tdtypeid;
00155 desc->tdtypmod = tupdesc->tdtypmod;
00156
00157 return desc;
00158 }
00159
00160
00161
00162
00163
00164
00165 TupleDesc
00166 CreateTupleDescCopyConstr(TupleDesc tupdesc)
00167 {
00168 TupleDesc desc;
00169 TupleConstr *constr = tupdesc->constr;
00170 int i;
00171
00172 desc = CreateTemplateTupleDesc(tupdesc->natts, tupdesc->tdhasoid);
00173
00174 for (i = 0; i < desc->natts; i++)
00175 {
00176 memcpy(desc->attrs[i], tupdesc->attrs[i], ATTRIBUTE_FIXED_PART_SIZE);
00177 }
00178
00179 if (constr)
00180 {
00181 TupleConstr *cpy = (TupleConstr *) palloc0(sizeof(TupleConstr));
00182
00183 cpy->has_not_null = constr->has_not_null;
00184
00185 if ((cpy->num_defval = constr->num_defval) > 0)
00186 {
00187 cpy->defval = (AttrDefault *) palloc(cpy->num_defval * sizeof(AttrDefault));
00188 memcpy(cpy->defval, constr->defval, cpy->num_defval * sizeof(AttrDefault));
00189 for (i = cpy->num_defval - 1; i >= 0; i--)
00190 {
00191 if (constr->defval[i].adbin)
00192 cpy->defval[i].adbin = pstrdup(constr->defval[i].adbin);
00193 }
00194 }
00195
00196 if ((cpy->num_check = constr->num_check) > 0)
00197 {
00198 cpy->check = (ConstrCheck *) palloc(cpy->num_check * sizeof(ConstrCheck));
00199 memcpy(cpy->check, constr->check, cpy->num_check * sizeof(ConstrCheck));
00200 for (i = cpy->num_check - 1; i >= 0; i--)
00201 {
00202 if (constr->check[i].ccname)
00203 cpy->check[i].ccname = pstrdup(constr->check[i].ccname);
00204 if (constr->check[i].ccbin)
00205 cpy->check[i].ccbin = pstrdup(constr->check[i].ccbin);
00206 cpy->check[i].ccvalid = constr->check[i].ccvalid;
00207 }
00208 }
00209
00210 desc->constr = cpy;
00211 }
00212
00213 desc->tdtypeid = tupdesc->tdtypeid;
00214 desc->tdtypmod = tupdesc->tdtypmod;
00215
00216 return desc;
00217 }
00218
00219
00220
00221
00222 void
00223 FreeTupleDesc(TupleDesc tupdesc)
00224 {
00225 int i;
00226
00227
00228
00229
00230
00231 Assert(tupdesc->tdrefcount <= 0);
00232
00233 if (tupdesc->constr)
00234 {
00235 if (tupdesc->constr->num_defval > 0)
00236 {
00237 AttrDefault *attrdef = tupdesc->constr->defval;
00238
00239 for (i = tupdesc->constr->num_defval - 1; i >= 0; i--)
00240 {
00241 if (attrdef[i].adbin)
00242 pfree(attrdef[i].adbin);
00243 }
00244 pfree(attrdef);
00245 }
00246 if (tupdesc->constr->num_check > 0)
00247 {
00248 ConstrCheck *check = tupdesc->constr->check;
00249
00250 for (i = tupdesc->constr->num_check - 1; i >= 0; i--)
00251 {
00252 if (check[i].ccname)
00253 pfree(check[i].ccname);
00254 if (check[i].ccbin)
00255 pfree(check[i].ccbin);
00256 }
00257 pfree(check);
00258 }
00259 pfree(tupdesc->constr);
00260 }
00261
00262 pfree(tupdesc);
00263 }
00264
00265
00266
00267
00268
00269
00270
00271
00272 void
00273 IncrTupleDescRefCount(TupleDesc tupdesc)
00274 {
00275 Assert(tupdesc->tdrefcount >= 0);
00276
00277 ResourceOwnerEnlargeTupleDescs(CurrentResourceOwner);
00278 tupdesc->tdrefcount++;
00279 ResourceOwnerRememberTupleDesc(CurrentResourceOwner, tupdesc);
00280 }
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290 void
00291 DecrTupleDescRefCount(TupleDesc tupdesc)
00292 {
00293 Assert(tupdesc->tdrefcount > 0);
00294
00295 ResourceOwnerForgetTupleDesc(CurrentResourceOwner, tupdesc);
00296 if (--tupdesc->tdrefcount == 0)
00297 FreeTupleDesc(tupdesc);
00298 }
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308 bool
00309 equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
00310 {
00311 int i,
00312 j,
00313 n;
00314
00315 if (tupdesc1->natts != tupdesc2->natts)
00316 return false;
00317 if (tupdesc1->tdtypeid != tupdesc2->tdtypeid)
00318 return false;
00319 if (tupdesc1->tdhasoid != tupdesc2->tdhasoid)
00320 return false;
00321
00322 for (i = 0; i < tupdesc1->natts; i++)
00323 {
00324 Form_pg_attribute attr1 = tupdesc1->attrs[i];
00325 Form_pg_attribute attr2 = tupdesc2->attrs[i];
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339 if (strcmp(NameStr(attr1->attname), NameStr(attr2->attname)) != 0)
00340 return false;
00341 if (attr1->atttypid != attr2->atttypid)
00342 return false;
00343 if (attr1->attstattarget != attr2->attstattarget)
00344 return false;
00345 if (attr1->attlen != attr2->attlen)
00346 return false;
00347 if (attr1->attndims != attr2->attndims)
00348 return false;
00349 if (attr1->atttypmod != attr2->atttypmod)
00350 return false;
00351 if (attr1->attbyval != attr2->attbyval)
00352 return false;
00353 if (attr1->attstorage != attr2->attstorage)
00354 return false;
00355 if (attr1->attalign != attr2->attalign)
00356 return false;
00357 if (attr1->attnotnull != attr2->attnotnull)
00358 return false;
00359 if (attr1->atthasdef != attr2->atthasdef)
00360 return false;
00361 if (attr1->attisdropped != attr2->attisdropped)
00362 return false;
00363 if (attr1->attislocal != attr2->attislocal)
00364 return false;
00365 if (attr1->attinhcount != attr2->attinhcount)
00366 return false;
00367 if (attr1->attcollation != attr2->attcollation)
00368 return false;
00369
00370 }
00371
00372 if (tupdesc1->constr != NULL)
00373 {
00374 TupleConstr *constr1 = tupdesc1->constr;
00375 TupleConstr *constr2 = tupdesc2->constr;
00376
00377 if (constr2 == NULL)
00378 return false;
00379 if (constr1->has_not_null != constr2->has_not_null)
00380 return false;
00381 n = constr1->num_defval;
00382 if (n != (int) constr2->num_defval)
00383 return false;
00384 for (i = 0; i < n; i++)
00385 {
00386 AttrDefault *defval1 = constr1->defval + i;
00387 AttrDefault *defval2 = constr2->defval;
00388
00389
00390
00391
00392
00393
00394 for (j = 0; j < n; defval2++, j++)
00395 {
00396 if (defval1->adnum == defval2->adnum)
00397 break;
00398 }
00399 if (j >= n)
00400 return false;
00401 if (strcmp(defval1->adbin, defval2->adbin) != 0)
00402 return false;
00403 }
00404 n = constr1->num_check;
00405 if (n != (int) constr2->num_check)
00406 return false;
00407 for (i = 0; i < n; i++)
00408 {
00409 ConstrCheck *check1 = constr1->check + i;
00410 ConstrCheck *check2 = constr2->check;
00411
00412
00413
00414
00415
00416
00417 for (j = 0; j < n; check2++, j++)
00418 {
00419 if (strcmp(check1->ccname, check2->ccname) == 0 &&
00420 strcmp(check1->ccbin, check2->ccbin) == 0)
00421 break;
00422 }
00423 if (j >= n)
00424 return false;
00425 }
00426 }
00427 else if (tupdesc2->constr != NULL)
00428 return false;
00429 return true;
00430 }
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441 void
00442 TupleDescInitEntry(TupleDesc desc,
00443 AttrNumber attributeNumber,
00444 const char *attributeName,
00445 Oid oidtypeid,
00446 int32 typmod,
00447 int attdim)
00448 {
00449 HeapTuple tuple;
00450 Form_pg_type typeForm;
00451 Form_pg_attribute att;
00452
00453
00454
00455
00456 AssertArg(PointerIsValid(desc));
00457 AssertArg(attributeNumber >= 1);
00458 AssertArg(attributeNumber <= desc->natts);
00459
00460
00461
00462
00463 att = desc->attrs[attributeNumber - 1];
00464
00465 att->attrelid = 0;
00466
00467
00468
00469
00470
00471
00472 if (attributeName != NULL)
00473 namestrcpy(&(att->attname), attributeName);
00474 else
00475 MemSet(NameStr(att->attname), 0, NAMEDATALEN);
00476
00477 att->attstattarget = -1;
00478 att->attcacheoff = -1;
00479 att->atttypmod = typmod;
00480
00481 att->attnum = attributeNumber;
00482 att->attndims = attdim;
00483
00484 att->attnotnull = false;
00485 att->atthasdef = false;
00486 att->attisdropped = false;
00487 att->attislocal = true;
00488 att->attinhcount = 0;
00489
00490
00491 tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(oidtypeid));
00492 if (!HeapTupleIsValid(tuple))
00493 elog(ERROR, "cache lookup failed for type %u", oidtypeid);
00494 typeForm = (Form_pg_type) GETSTRUCT(tuple);
00495
00496 att->atttypid = oidtypeid;
00497 att->attlen = typeForm->typlen;
00498 att->attbyval = typeForm->typbyval;
00499 att->attalign = typeForm->typalign;
00500 att->attstorage = typeForm->typstorage;
00501 att->attcollation = typeForm->typcollation;
00502
00503 ReleaseSysCache(tuple);
00504 }
00505
00506
00507
00508
00509
00510
00511
00512 void
00513 TupleDescInitEntryCollation(TupleDesc desc,
00514 AttrNumber attributeNumber,
00515 Oid collationid)
00516 {
00517
00518
00519
00520 AssertArg(PointerIsValid(desc));
00521 AssertArg(attributeNumber >= 1);
00522 AssertArg(attributeNumber <= desc->natts);
00523
00524 desc->attrs[attributeNumber - 1]->attcollation = collationid;
00525 }
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537 TupleDesc
00538 BuildDescForRelation(List *schema)
00539 {
00540 int natts;
00541 AttrNumber attnum;
00542 ListCell *l;
00543 TupleDesc desc;
00544 bool has_not_null;
00545 char *attname;
00546 Oid atttypid;
00547 int32 atttypmod;
00548 Oid attcollation;
00549 int attdim;
00550
00551
00552
00553
00554 natts = list_length(schema);
00555 desc = CreateTemplateTupleDesc(natts, false);
00556 has_not_null = false;
00557
00558 attnum = 0;
00559
00560 foreach(l, schema)
00561 {
00562 ColumnDef *entry = lfirst(l);
00563 AclResult aclresult;
00564
00565
00566
00567
00568
00569
00570 attnum++;
00571
00572 attname = entry->colname;
00573 typenameTypeIdAndMod(NULL, entry->typeName, &atttypid, &atttypmod);
00574
00575 aclresult = pg_type_aclcheck(atttypid, GetUserId(), ACL_USAGE);
00576 if (aclresult != ACLCHECK_OK)
00577 aclcheck_error_type(aclresult, atttypid);
00578
00579 attcollation = GetColumnDefCollation(NULL, entry, atttypid);
00580 attdim = list_length(entry->typeName->arrayBounds);
00581
00582 if (entry->typeName->setof)
00583 ereport(ERROR,
00584 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
00585 errmsg("column \"%s\" cannot be declared SETOF",
00586 attname)));
00587
00588 TupleDescInitEntry(desc, attnum, attname,
00589 atttypid, atttypmod, attdim);
00590
00591
00592 TupleDescInitEntryCollation(desc, attnum, attcollation);
00593 if (entry->storage)
00594 desc->attrs[attnum - 1]->attstorage = entry->storage;
00595
00596
00597 desc->attrs[attnum - 1]->attnotnull = entry->is_not_null;
00598 has_not_null |= entry->is_not_null;
00599 desc->attrs[attnum - 1]->attislocal = entry->is_local;
00600 desc->attrs[attnum - 1]->attinhcount = entry->inhcount;
00601 }
00602
00603 if (has_not_null)
00604 {
00605 TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
00606
00607 constr->has_not_null = true;
00608 constr->defval = NULL;
00609 constr->num_defval = 0;
00610 constr->check = NULL;
00611 constr->num_check = 0;
00612 desc->constr = constr;
00613 }
00614 else
00615 {
00616 desc->constr = NULL;
00617 }
00618
00619 return desc;
00620 }
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633 TupleDesc
00634 BuildDescFromLists(List *names, List *types, List *typmods, List *collations)
00635 {
00636 int natts;
00637 AttrNumber attnum;
00638 ListCell *l1;
00639 ListCell *l2;
00640 ListCell *l3;
00641 ListCell *l4;
00642 TupleDesc desc;
00643
00644 natts = list_length(names);
00645 Assert(natts == list_length(types));
00646 Assert(natts == list_length(typmods));
00647 Assert(natts == list_length(collations));
00648
00649
00650
00651
00652 desc = CreateTemplateTupleDesc(natts, false);
00653
00654 attnum = 0;
00655
00656 l2 = list_head(types);
00657 l3 = list_head(typmods);
00658 l4 = list_head(collations);
00659 foreach(l1, names)
00660 {
00661 char *attname = strVal(lfirst(l1));
00662 Oid atttypid;
00663 int32 atttypmod;
00664 Oid attcollation;
00665
00666 atttypid = lfirst_oid(l2);
00667 l2 = lnext(l2);
00668 atttypmod = lfirst_int(l3);
00669 l3 = lnext(l3);
00670 attcollation = lfirst_oid(l4);
00671 l4 = lnext(l4);
00672
00673 attnum++;
00674
00675 TupleDescInitEntry(desc, attnum, attname, atttypid, atttypmod, 0);
00676 TupleDescInitEntryCollation(desc, attnum, attcollation);
00677 }
00678
00679 return desc;
00680 }