summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/common/heaptuple.c1603
-rw-r--r--src/backend/access/common/heapvalid.c206
-rw-r--r--src/backend/access/common/indextuple.c758
-rw-r--r--src/backend/access/common/indexvalid.c104
-rw-r--r--src/backend/access/common/printtup.c431
-rw-r--r--src/backend/access/common/scankey.c54
-rw-r--r--src/backend/access/common/tupdesc.c890
-rw-r--r--src/backend/access/gist/gist.c2267
-rw-r--r--src/backend/access/gist/gistget.c644
-rw-r--r--src/backend/access/gist/gistscan.c620
-rw-r--r--src/backend/access/gist/giststrat.c123
-rw-r--r--src/backend/access/hash/hash.c767
-rw-r--r--src/backend/access/hash/hashfunc.c411
-rw-r--r--src/backend/access/hash/hashinsert.c386
-rw-r--r--src/backend/access/hash/hashovfl.c1065
-rw-r--r--src/backend/access/hash/hashpage.c1107
-rw-r--r--src/backend/access/hash/hashscan.c229
-rw-r--r--src/backend/access/hash/hashsearch.c758
-rw-r--r--src/backend/access/hash/hashstrat.c69
-rw-r--r--src/backend/access/hash/hashutil.c161
-rw-r--r--src/backend/access/heap/heapam.c2531
-rw-r--r--src/backend/access/heap/hio.c229
-rw-r--r--src/backend/access/heap/stats.c531
-rw-r--r--src/backend/access/index/genam.c328
-rw-r--r--src/backend/access/index/indexam.c474
-rw-r--r--src/backend/access/index/istrat.c1095
-rw-r--r--src/backend/access/nbtree/nbtcompare.c201
-rw-r--r--src/backend/access/nbtree/nbtinsert.c2923
-rw-r--r--src/backend/access/nbtree/nbtpage.c902
-rw-r--r--src/backend/access/nbtree/nbtree.c927
-rw-r--r--src/backend/access/nbtree/nbtscan.c267
-rw-r--r--src/backend/access/nbtree/nbtsearch.c2617
-rw-r--r--src/backend/access/nbtree/nbtsort.c1926
-rw-r--r--src/backend/access/nbtree/nbtstrat.c156
-rw-r--r--src/backend/access/nbtree/nbtutils.c623
-rw-r--r--src/backend/access/rtree/rtget.c544
-rw-r--r--src/backend/access/rtree/rtproc.c209
-rw-r--r--src/backend/access/rtree/rtree.c1753
-rw-r--r--src/backend/access/rtree/rtscan.c626
-rw-r--r--src/backend/access/rtree/rtstrat.c346
-rw-r--r--src/backend/access/transam/transam.c964
-rw-r--r--src/backend/access/transam/transsup.c1065
-rw-r--r--src/backend/access/transam/varsup.c1019
-rw-r--r--src/backend/access/transam/xact.c2014
-rw-r--r--src/backend/access/transam/xid.c94
-rw-r--r--src/backend/bootstrap/bootstrap.c1683
-rw-r--r--src/backend/catalog/catalog.c253
-rw-r--r--src/backend/catalog/heap.c2747
-rw-r--r--src/backend/catalog/index.c3019
-rw-r--r--src/backend/catalog/indexing.c808
-rw-r--r--src/backend/catalog/pg_aggregate.c555
-rw-r--r--src/backend/catalog/pg_operator.c1926
-rw-r--r--src/backend/catalog/pg_proc.c445
-rw-r--r--src/backend/catalog/pg_type.c1013
-rw-r--r--src/backend/commands/_deadcode/version.c369
-rw-r--r--src/backend/commands/async.c831
-rw-r--r--src/backend/commands/cluster.c580
-rw-r--r--src/backend/commands/command.c827
-rw-r--r--src/backend/commands/copy.c1884
-rw-r--r--src/backend/commands/creatinh.c1112
-rw-r--r--src/backend/commands/defind.c899
-rw-r--r--src/backend/commands/define.c1113
-rw-r--r--src/backend/commands/explain.c353
-rw-r--r--src/backend/commands/purge.c271
-rw-r--r--src/backend/commands/recipe.c2130
-rw-r--r--src/backend/commands/remove.c796
-rw-r--r--src/backend/commands/rename.c401
-rw-r--r--src/backend/commands/sequence.c924
-rw-r--r--src/backend/commands/trigger.c1050
-rw-r--r--src/backend/commands/vacuum.c3920
-rw-r--r--src/backend/commands/view.c427
-rw-r--r--src/backend/executor/execAmi.c693
-rw-r--r--src/backend/executor/execFlatten.c372
-rw-r--r--src/backend/executor/execJunk.c638
-rw-r--r--src/backend/executor/execMain.c2324
-rw-r--r--src/backend/executor/execProcnode.c820
-rw-r--r--src/backend/executor/execQual.c2665
-rw-r--r--src/backend/executor/execScan.c208
-rw-r--r--src/backend/executor/execTuples.c1526
-rw-r--r--src/backend/executor/execUtils.c1816
-rw-r--r--src/backend/executor/functions.c695
-rw-r--r--src/backend/executor/nodeAgg.c1055
-rw-r--r--src/backend/executor/nodeAppend.c852
-rw-r--r--src/backend/executor/nodeGroup.c632
-rw-r--r--src/backend/executor/nodeHash.c1420
-rw-r--r--src/backend/executor/nodeHashjoin.c1377
-rw-r--r--src/backend/executor/nodeIndexscan.c1623
-rw-r--r--src/backend/executor/nodeMaterial.c631
-rw-r--r--src/backend/executor/nodeMergejoin.c2165
-rw-r--r--src/backend/executor/nodeNestloop.c632
-rw-r--r--src/backend/executor/nodeResult.c454
-rw-r--r--src/backend/executor/nodeSeqscan.c726
-rw-r--r--src/backend/executor/nodeSort.c632
-rw-r--r--src/backend/executor/nodeTee.c899
-rw-r--r--src/backend/executor/nodeUnique.c532
-rw-r--r--src/backend/executor/spi.c1537
-rw-r--r--src/backend/lib/bit.c27
-rw-r--r--src/backend/lib/dllist.c246
-rw-r--r--src/backend/lib/fstack.c146
-rw-r--r--src/backend/lib/hasht.c48
-rw-r--r--src/backend/lib/lispsort.c67
-rw-r--r--src/backend/lib/qsort.c186
-rw-r--r--src/backend/lib/stringinfo.c142
-rw-r--r--src/backend/libpq/auth.c838
-rw-r--r--src/backend/libpq/be-dumpdata.c448
-rw-r--r--src/backend/libpq/be-fsstubs.c470
-rw-r--r--src/backend/libpq/be-pqexec.c613
-rw-r--r--src/backend/libpq/hba.c1336
-rw-r--r--src/backend/libpq/password.c190
-rw-r--r--src/backend/libpq/portal.c946
-rw-r--r--src/backend/libpq/portalbuf.c609
-rw-r--r--src/backend/libpq/pqcomm.c1016
-rw-r--r--src/backend/libpq/pqcomprim.c230
-rw-r--r--src/backend/libpq/pqpacket.c361
-rw-r--r--src/backend/libpq/pqsignal.c78
-rw-r--r--src/backend/libpq/util.c98
-rw-r--r--src/backend/main/main.c71
-rw-r--r--src/backend/nodes/copyfuncs.c2634
-rw-r--r--src/backend/nodes/equalfuncs.c1149
-rw-r--r--src/backend/nodes/list.c685
-rw-r--r--src/backend/nodes/makefuncs.c139
-rw-r--r--src/backend/nodes/nodeFuncs.c119
-rw-r--r--src/backend/nodes/nodes.c36
-rw-r--r--src/backend/nodes/outfuncs.c2640
-rw-r--r--src/backend/nodes/print.c582
-rw-r--r--src/backend/nodes/read.c421
-rw-r--r--src/backend/nodes/readfuncs.c3199
-rw-r--r--src/backend/optimizer/geqo/geqo_copy.c40
-rw-r--r--src/backend/optimizer/geqo/geqo_cx.c132
-rw-r--r--src/backend/optimizer/geqo/geqo_erx.c567
-rw-r--r--src/backend/optimizer/geqo/geqo_eval.c985
-rw-r--r--src/backend/optimizer/geqo/geqo_main.c249
-rw-r--r--src/backend/optimizer/geqo/geqo_misc.c347
-rw-r--r--src/backend/optimizer/geqo/geqo_mutation.c65
-rw-r--r--src/backend/optimizer/geqo/geqo_ox1.c122
-rw-r--r--src/backend/optimizer/geqo/geqo_ox2.c146
-rw-r--r--src/backend/optimizer/geqo/geqo_params.c268
-rw-r--r--src/backend/optimizer/geqo/geqo_paths.c190
-rw-r--r--src/backend/optimizer/geqo/geqo_pmx.c281
-rw-r--r--src/backend/optimizer/geqo/geqo_pool.c301
-rw-r--r--src/backend/optimizer/geqo/geqo_px.c121
-rw-r--r--src/backend/optimizer/geqo/geqo_recombination.c93
-rw-r--r--src/backend/optimizer/geqo/geqo_selection.c88
-rw-r--r--src/backend/optimizer/geqo/minspantree.c317
-rw-r--r--src/backend/optimizer/path/allpaths.c609
-rw-r--r--src/backend/optimizer/path/clausesel.c536
-rw-r--r--src/backend/optimizer/path/costsize.c624
-rw-r--r--src/backend/optimizer/path/hashutils.c174
-rw-r--r--src/backend/optimizer/path/indxpath.c2113
-rw-r--r--src/backend/optimizer/path/joinpath.c1097
-rw-r--r--src/backend/optimizer/path/joinrels.c884
-rw-r--r--src/backend/optimizer/path/joinutils.c679
-rw-r--r--src/backend/optimizer/path/mergeutils.c170
-rw-r--r--src/backend/optimizer/path/orindxpath.c430
-rw-r--r--src/backend/optimizer/path/predmig.c1064
-rw-r--r--src/backend/optimizer/path/prune.c284
-rw-r--r--src/backend/optimizer/path/xfunc.c2192
-rw-r--r--src/backend/optimizer/plan/createplan.c2005
-rw-r--r--src/backend/optimizer/plan/initsplan.c579
-rw-r--r--src/backend/optimizer/plan/planmain.c952
-rw-r--r--src/backend/optimizer/plan/planner.c635
-rw-r--r--src/backend/optimizer/plan/setrefs.c1148
-rw-r--r--src/backend/optimizer/prep/archive.c61
-rw-r--r--src/backend/optimizer/prep/prepqual.c980
-rw-r--r--src/backend/optimizer/prep/preptlist.c544
-rw-r--r--src/backend/optimizer/prep/prepunion.c628
-rw-r--r--src/backend/optimizer/util/clauseinfo.c259
-rw-r--r--src/backend/optimizer/util/clauses.c1026
-rw-r--r--src/backend/optimizer/util/indexnode.c113
-rw-r--r--src/backend/optimizer/util/internal.c48
-rw-r--r--src/backend/optimizer/util/joininfo.c132
-rw-r--r--src/backend/optimizer/util/keys.c261
-rw-r--r--src/backend/optimizer/util/ordering.c154
-rw-r--r--src/backend/optimizer/util/pathnode.c867
-rw-r--r--src/backend/optimizer/util/plancat.c969
-rw-r--r--src/backend/optimizer/util/relnode.c182
-rw-r--r--src/backend/optimizer/util/tlist.c834
-rw-r--r--src/backend/optimizer/util/var.c308
-rw-r--r--src/backend/parser/analyze.c4324
-rw-r--r--src/backend/parser/catalog_utils.c2457
-rw-r--r--src/backend/parser/dbcommands.c409
-rw-r--r--src/backend/parser/keywords.c366
-rw-r--r--src/backend/parser/parse_query.c1340
-rw-r--r--src/backend/parser/parser.c844
-rw-r--r--src/backend/parser/scansup.c173
-rw-r--r--src/backend/parser/sysfunc.c51
-rw-r--r--src/backend/port/BSD44_derived/dl.c56
-rw-r--r--src/backend/port/BSD44_derived/port-protos.h26
-rw-r--r--src/backend/port/aix/dlfcn.c393
-rw-r--r--src/backend/port/aix/dlfcn.h37
-rw-r--r--src/backend/port/aix/port-protos.h8
-rw-r--r--src/backend/port/alpha/port-protos.h14
-rw-r--r--src/backend/port/alpha/port.c23
-rw-r--r--src/backend/port/bsdi/dynloader.c123
-rw-r--r--src/backend/port/bsdi/port-protos.h24
-rw-r--r--src/backend/port/dgux/dynloader.c120
-rw-r--r--src/backend/port/dgux/port-protos.h18
-rw-r--r--src/backend/port/dgux/port.c4
-rw-r--r--src/backend/port/hpux/dynloader.c36
-rw-r--r--src/backend/port/hpux/fixade.h63
-rw-r--r--src/backend/port/hpux/port-protos.h20
-rw-r--r--src/backend/port/hpux/port.c32
-rw-r--r--src/backend/port/hpux/rusagestub.h23
-rw-r--r--src/backend/port/i386_solaris/port-protos.h20
-rw-r--r--src/backend/port/i386_solaris/port.c76
-rw-r--r--src/backend/port/i386_solaris/rusagestub.h25
-rw-r--r--src/backend/port/inet_aton.c96
-rw-r--r--src/backend/port/inet_aton.h2
-rw-r--r--src/backend/port/irix5/port-protos.h16
-rw-r--r--src/backend/port/irix5/port.c6
-rw-r--r--src/backend/port/linux/dynloader.c128
-rw-r--r--src/backend/port/linux/port-protos.h32
-rw-r--r--src/backend/port/linux/port.c4
-rw-r--r--src/backend/port/linuxalpha/machine.h4
-rw-r--r--src/backend/port/linuxalpha/port-protos.h16
-rw-r--r--src/backend/port/linuxalpha/port.c4
-rw-r--r--src/backend/port/nextstep/dynloader.c97
-rw-r--r--src/backend/port/nextstep/port-protos.h24
-rw-r--r--src/backend/port/nextstep/port.c75
-rw-r--r--src/backend/port/sco/port-protos.h16
-rw-r--r--src/backend/port/sco/port.c73
-rw-r--r--src/backend/port/sco/rusagestub.h23
-rw-r--r--src/backend/port/sparc_solaris/port-protos.h28
-rw-r--r--src/backend/port/sparc_solaris/port.c81
-rw-r--r--src/backend/port/sparc_solaris/rusagestub.h25
-rw-r--r--src/backend/port/strerror.c27
-rw-r--r--src/backend/port/sunos4/float.h26
-rw-r--r--src/backend/port/sunos4/port-protos.h18
-rw-r--r--src/backend/port/sunos4/strtol.c96
-rw-r--r--src/backend/port/svr4/port-protos.h18
-rw-r--r--src/backend/port/svr4/port.c98
-rw-r--r--src/backend/port/svr4/rusagestub.h23
-rw-r--r--src/backend/port/ultrix4/dl.h143
-rw-r--r--src/backend/port/ultrix4/dynloader.c85
-rw-r--r--src/backend/port/ultrix4/port-protos.h24
-rw-r--r--src/backend/port/ultrix4/port.c8
-rw-r--r--src/backend/port/ultrix4/strdup.c14
-rw-r--r--src/backend/port/univel/frontend-port-protos.h12
-rw-r--r--src/backend/port/univel/port-protos.h22
-rw-r--r--src/backend/port/univel/port.c111
-rw-r--r--src/backend/port/univel/rusagestub.h23
-rw-r--r--src/backend/postmaster/postmaster.c1949
-rw-r--r--src/backend/regex/engine.c823
-rw-r--r--src/backend/regex/regcomp.c1114
-rw-r--r--src/backend/regex/regerror.c197
-rw-r--r--src/backend/regex/regexec.c156
-rw-r--r--src/backend/regex/regfree.c47
-rw-r--r--src/backend/rewrite/locks.c173
-rw-r--r--src/backend/rewrite/rewriteDefine.c399
-rw-r--r--src/backend/rewrite/rewriteHandler.c1066
-rw-r--r--src/backend/rewrite/rewriteManip.c707
-rw-r--r--src/backend/rewrite/rewriteRemove.c257
-rw-r--r--src/backend/rewrite/rewriteSupport.c428
-rw-r--r--src/backend/storage/buffer/buf_init.c407
-rw-r--r--src/backend/storage/buffer/buf_table.c217
-rw-r--r--src/backend/storage/buffer/bufmgr.c2695
-rw-r--r--src/backend/storage/buffer/freelist.c373
-rw-r--r--src/backend/storage/buffer/localbuf.c370
-rw-r--r--src/backend/storage/file/fd.c1177
-rw-r--r--src/backend/storage/ipc/ipc.c991
-rw-r--r--src/backend/storage/ipc/ipci.c178
-rw-r--r--src/backend/storage/ipc/s_lock.c384
-rw-r--r--src/backend/storage/ipc/shmem.c951
-rw-r--r--src/backend/storage/ipc/shmqueue.c274
-rw-r--r--src/backend/storage/ipc/sinval.c222
-rw-r--r--src/backend/storage/ipc/sinvaladt.c1129
-rw-r--r--src/backend/storage/ipc/spin.c246
-rw-r--r--src/backend/storage/large_object/inv_api.c1877
-rw-r--r--src/backend/storage/lmgr/lmgr.c1129
-rw-r--r--src/backend/storage/lmgr/lock.c2137
-rw-r--r--src/backend/storage/lmgr/multi.c615
-rw-r--r--src/backend/storage/lmgr/proc.c1117
-rw-r--r--src/backend/storage/lmgr/single.c93
-rw-r--r--src/backend/storage/page/bufpage.c670
-rw-r--r--src/backend/storage/page/itemptr.c25
-rw-r--r--src/backend/storage/smgr/md.c1088
-rw-r--r--src/backend/storage/smgr/mm.c761
-rw-r--r--src/backend/storage/smgr/smgr.c432
-rw-r--r--src/backend/storage/smgr/smgrtype.c66
-rw-r--r--src/backend/tcop/aclchk.c952
-rw-r--r--src/backend/tcop/dest.c502
-rw-r--r--src/backend/tcop/fastpath.c520
-rw-r--r--src/backend/tcop/postgres.c2789
-rw-r--r--src/backend/tcop/pquery.c563
-rw-r--r--src/backend/tcop/utility.c1212
-rw-r--r--src/backend/tcop/variable.c598
-rw-r--r--src/backend/tioga/Arr_TgRecipe.h68
-rw-r--r--src/backend/tioga/Varray.c54
-rw-r--r--src/backend/tioga/Varray.h33
-rw-r--r--src/backend/tioga/tgRecipe.c1172
-rw-r--r--src/backend/tioga/tgRecipe.h181
-rw-r--r--src/backend/utils/adt/acl.c979
-rw-r--r--src/backend/utils/adt/arrayfuncs.c2706
-rw-r--r--src/backend/utils/adt/arrayutils.c123
-rw-r--r--src/backend/utils/adt/bool.c58
-rw-r--r--src/backend/utils/adt/cash.c734
-rw-r--r--src/backend/utils/adt/char.c518
-rw-r--r--src/backend/utils/adt/chunk.c989
-rw-r--r--src/backend/utils/adt/date.c1421
-rw-r--r--src/backend/utils/adt/datetime.c667
-rw-r--r--src/backend/utils/adt/datum.c221
-rw-r--r--src/backend/utils/adt/dt.c6008
-rw-r--r--src/backend/utils/adt/filename.c187
-rw-r--r--src/backend/utils/adt/float.c2140
-rw-r--r--src/backend/utils/adt/geo_ops.c5111
-rw-r--r--src/backend/utils/adt/geo_selfuncs.c142
-rw-r--r--src/backend/utils/adt/int.c641
-rw-r--r--src/backend/utils/adt/like.c287
-rw-r--r--src/backend/utils/adt/misc.c73
-rw-r--r--src/backend/utils/adt/nabstime.c682
-rw-r--r--src/backend/utils/adt/name.c242
-rw-r--r--src/backend/utils/adt/not_in.c148
-rw-r--r--src/backend/utils/adt/numutils.c687
-rw-r--r--src/backend/utils/adt/oid.c153
-rw-r--r--src/backend/utils/adt/oidint2.c110
-rw-r--r--src/backend/utils/adt/oidint4.c139
-rw-r--r--src/backend/utils/adt/oidname.c115
-rw-r--r--src/backend/utils/adt/oracle_compat.c714
-rw-r--r--src/backend/utils/adt/regexp.c398
-rw-r--r--src/backend/utils/adt/regproc.c229
-rw-r--r--src/backend/utils/adt/selfuncs.c962
-rw-r--r--src/backend/utils/adt/sets.c260
-rw-r--r--src/backend/utils/adt/tid.c109
-rw-r--r--src/backend/utils/adt/timestamp.c126
-rw-r--r--src/backend/utils/adt/varchar.c738
-rw-r--r--src/backend/utils/adt/varlena.c819
-rw-r--r--src/backend/utils/cache/catcache.c1786
-rw-r--r--src/backend/utils/cache/fcache.c481
-rw-r--r--src/backend/utils/cache/inval.c840
-rw-r--r--src/backend/utils/cache/lsyscache.c618
-rw-r--r--src/backend/utils/cache/rel.c57
-rw-r--r--src/backend/utils/cache/relcache.c3493
-rw-r--r--src/backend/utils/cache/syscache.c1057
-rw-r--r--src/backend/utils/error/assert.c86
-rw-r--r--src/backend/utils/error/elog.c392
-rw-r--r--src/backend/utils/error/exc.c229
-rw-r--r--src/backend/utils/error/excabort.c20
-rw-r--r--src/backend/utils/error/excid.c40
-rw-r--r--src/backend/utils/error/format.c30
-rw-r--r--src/backend/utils/fmgr/dfmgr.c441
-rw-r--r--src/backend/utils/fmgr/fmgr.c390
-rw-r--r--src/backend/utils/hash/dynahash.c1382
-rw-r--r--src/backend/utils/hash/hashfn.c212
-rw-r--r--src/backend/utils/init/enbl.c21
-rw-r--r--src/backend/utils/init/findbe.c377
-rw-r--r--src/backend/utils/init/globals.c127
-rw-r--r--src/backend/utils/init/miscinit.c268
-rw-r--r--src/backend/utils/init/postinit.c1064
-rw-r--r--src/backend/utils/misc/superuser.c28
-rw-r--r--src/backend/utils/mmgr/aset.c411
-rw-r--r--src/backend/utils/mmgr/mcxt.c517
-rw-r--r--src/backend/utils/mmgr/oset.c126
-rw-r--r--src/backend/utils/mmgr/palloc.c82
-rw-r--r--src/backend/utils/mmgr/portalmem.c1222
-rw-r--r--src/backend/utils/sort/lselect.c525
-rw-r--r--src/backend/utils/sort/psort.c1311
-rw-r--r--src/backend/utils/time/tqual.c1263
-rw-r--r--src/bin/pg_dump/common.c589
-rw-r--r--src/bin/pg_dump/pg_dump.c4050
-rw-r--r--src/bin/pg_dump/pg_dump.h368
-rw-r--r--src/bin/pg_id/pg_id.c62
-rw-r--r--src/bin/pg_passwd/pg_passwd.c553
-rw-r--r--src/bin/pg_version/pg_version.c41
-rw-r--r--src/bin/pgtclsh/pgtclAppInit.c111
-rw-r--r--src/bin/pgtclsh/pgtkAppInit.c117
-rw-r--r--src/bin/psql/psql.c3771
-rw-r--r--src/bin/psql/psqlHelp.h338
-rw-r--r--src/bin/psql/stringutils.c116
-rw-r--r--src/bin/psql/stringutils.h11
-rw-r--r--src/include/access/attnum.h34
-rw-r--r--src/include/access/funcindex.h21
-rw-r--r--src/include/access/genam.h58
-rw-r--r--src/include/access/gist.h231
-rw-r--r--src/include/access/gistscan.h19
-rw-r--r--src/include/access/giststrat.h9
-rw-r--r--src/include/access/hash.h384
-rw-r--r--src/include/access/heapam.h228
-rw-r--r--src/include/access/hio.h15
-rw-r--r--src/include/access/htup.h101
-rw-r--r--src/include/access/ibit.h25
-rw-r--r--src/include/access/iqual.h15
-rw-r--r--src/include/access/istrat.h62
-rw-r--r--src/include/access/itup.h98
-rw-r--r--src/include/access/nbtree.h388
-rw-r--r--src/include/access/printtup.h20
-rw-r--r--src/include/access/relscan.h92
-rw-r--r--src/include/access/rtree.h167
-rw-r--r--src/include/access/rtscan.h8
-rw-r--r--src/include/access/rtstrat.h11
-rw-r--r--src/include/access/sdir.h35
-rw-r--r--src/include/access/skey.h48
-rw-r--r--src/include/access/strat.h99
-rw-r--r--src/include/access/transam.h212
-rw-r--r--src/include/access/tupdesc.h81
-rw-r--r--src/include/access/tupmacs.h20
-rw-r--r--src/include/access/valid.h24
-rw-r--r--src/include/access/xact.h112
-rw-r--r--src/include/bootstrap/bootstrap.h64
-rw-r--r--src/include/c.h537
-rw-r--r--src/include/catalog/catalog.h16
-rw-r--r--src/include/catalog/catname.h10
-rw-r--r--src/include/catalog/heap.h25
-rw-r--r--src/include/catalog/index.h69
-rw-r--r--src/include/catalog/indexing.h110
-rw-r--r--src/include/catalog/pg_aggregate.h175
-rw-r--r--src/include/catalog/pg_am.h133
-rw-r--r--src/include/catalog/pg_amop.h215
-rw-r--r--src/include/catalog/pg_amproc.h61
-rw-r--r--src/include/catalog/pg_attrdef.h47
-rw-r--r--src/include/catalog/pg_attribute.h917
-rw-r--r--src/include/catalog/pg_class.h248
-rw-r--r--src/include/catalog/pg_database.h49
-rw-r--r--src/include/catalog/pg_defaults.h45
-rw-r--r--src/include/catalog/pg_demon.h57
-rw-r--r--src/include/catalog/pg_group.h30
-rw-r--r--src/include/catalog/pg_hosts.h36
-rw-r--r--src/include/catalog/pg_index.h93
-rw-r--r--src/include/catalog/pg_inheritproc.h47
-rw-r--r--src/include/catalog/pg_inherits.h49
-rw-r--r--src/include/catalog/pg_ipl.h47
-rw-r--r--src/include/catalog/pg_language.h52
-rw-r--r--src/include/catalog/pg_listener.h41
-rw-r--r--src/include/catalog/pg_log.h33
-rw-r--r--src/include/catalog/pg_magic.h45
-rw-r--r--src/include/catalog/pg_opclass.h103
-rw-r--r--src/include/catalog/pg_operator.h1104
-rw-r--r--src/include/catalog/pg_parg.h55
-rw-r--r--src/include/catalog/pg_proc.h1886
-rw-r--r--src/include/catalog/pg_relcheck.h47
-rw-r--r--src/include/catalog/pg_rewrite.h63
-rw-r--r--src/include/catalog/pg_server.h49
-rw-r--r--src/include/catalog/pg_statistic.h57
-rw-r--r--src/include/catalog/pg_time.h31
-rw-r--r--src/include/catalog/pg_trigger.h92
-rw-r--r--src/include/catalog/pg_type.h455
-rw-r--r--src/include/catalog/pg_user.h63
-rw-r--r--src/include/catalog/pg_variable.h33
-rw-r--r--src/include/catalog/pg_version.h49
-rw-r--r--src/include/commands/async.h20
-rw-r--r--src/include/commands/cluster.h16
-rw-r--r--src/include/commands/command.h30
-rw-r--r--src/include/commands/copy.h13
-rw-r--r--src/include/commands/creatinh.h12
-rw-r--r--src/include/commands/defrem.h47
-rw-r--r--src/include/commands/explain.h12
-rw-r--r--src/include/commands/purge.h17
-rw-r--r--src/include/commands/recipe.h8
-rw-r--r--src/include/commands/rename.h24
-rw-r--r--src/include/commands/sequence.h36
-rw-r--r--src/include/commands/trigger.h79
-rw-r--r--src/include/commands/vacuum.h169
-rw-r--r--src/include/commands/version.h8
-rw-r--r--src/include/commands/view.h16
-rw-r--r--src/include/executor/execFlatten.h13
-rw-r--r--src/include/executor/execdebug.h360
-rw-r--r--src/include/executor/execdefs.h44
-rw-r--r--src/include/executor/execdesc.h32
-rw-r--r--src/include/executor/executor.h189
-rw-r--r--src/include/executor/functions.h18
-rw-r--r--src/include/executor/hashjoin.h97
-rw-r--r--src/include/executor/nodeAgg.h18
-rw-r--r--src/include/executor/nodeAppend.h18
-rw-r--r--src/include/executor/nodeGroup.h18
-rw-r--r--src/include/executor/nodeHash.h41
-rw-r--r--src/include/executor/nodeHashjoin.h23
-rw-r--r--src/include/executor/nodeIndexscan.h29
-rw-r--r--src/include/executor/nodeMaterial.h22
-rw-r--r--src/include/executor/nodeMergejoin.h18
-rw-r--r--src/include/executor/nodeNestloop.h18
-rw-r--r--src/include/executor/nodeResult.h18
-rw-r--r--src/include/executor/nodeSeqscan.h24
-rw-r--r--src/include/executor/nodeSort.h22
-rw-r--r--src/include/executor/nodeTee.h20
-rw-r--r--src/include/executor/nodeUnique.h18
-rw-r--r--src/include/executor/spi.h81
-rw-r--r--src/include/executor/tuptable.h76
-rw-r--r--src/include/lib/dllist.h98
-rw-r--r--src/include/lib/fstack.h96
-rw-r--r--src/include/lib/hasht.h14
-rw-r--r--src/include/lib/lispsort.h10
-rw-r--r--src/include/lib/qsort.h20
-rw-r--r--src/include/lib/stringinfo.h31
-rw-r--r--src/include/libpq/auth.h38
-rw-r--r--src/include/libpq/be-fsstubs.h36
-rw-r--r--src/include/libpq/hba.h48
-rw-r--r--src/include/libpq/libpq-be.h36
-rw-r--r--src/include/libpq/libpq-fs.h109
-rw-r--r--src/include/libpq/libpq.h328
-rw-r--r--src/include/libpq/password.h5
-rw-r--r--src/include/libpq/pqcomm.h173
-rw-r--r--src/include/libpq/pqsignal.h12
-rw-r--r--src/include/miscadmin.h177
-rw-r--r--src/include/nodes/execnodes.h1022
-rw-r--r--src/include/nodes/makefuncs.h60
-rw-r--r--src/include/nodes/memnodes.h117
-rw-r--r--src/include/nodes/nodeFuncs.h16
-rw-r--r--src/include/nodes/nodes.h450
-rw-r--r--src/include/nodes/params.h103
-rw-r--r--src/include/nodes/parsenodes.h1148
-rw-r--r--src/include/nodes/pg_list.h144
-rw-r--r--src/include/nodes/plannodes.h375
-rw-r--r--src/include/nodes/primnodes.h448
-rw-r--r--src/include/nodes/print.h27
-rw-r--r--src/include/nodes/readfuncs.h20
-rw-r--r--src/include/nodes/relation.h466
-rw-r--r--src/include/optimizer/clauseinfo.h22
-rw-r--r--src/include/optimizer/clauses.h74
-rw-r--r--src/include/optimizer/cost.h77
-rw-r--r--src/include/optimizer/geqo.h55
-rw-r--r--src/include/optimizer/geqo_copy.h18
-rw-r--r--src/include/optimizer/geqo_gene.h44
-rw-r--r--src/include/optimizer/geqo_misc.h28
-rw-r--r--src/include/optimizer/geqo_mutation.h18
-rw-r--r--src/include/optimizer/geqo_paths.h20
-rw-r--r--src/include/optimizer/geqo_pool.h28
-rw-r--r--src/include/optimizer/geqo_random.h18
-rw-r--r--src/include/optimizer/geqo_recombination.h66
-rw-r--r--src/include/optimizer/geqo_selection.h18
-rw-r--r--src/include/optimizer/internal.h81
-rw-r--r--src/include/optimizer/joininfo.h12
-rw-r--r--src/include/optimizer/keys.h14
-rw-r--r--src/include/optimizer/ordering.h22
-rw-r--r--src/include/optimizer/pathnode.h53
-rw-r--r--src/include/optimizer/paths.h92
-rw-r--r--src/include/optimizer/plancat.h73
-rw-r--r--src/include/optimizer/planmain.h60
-rw-r--r--src/include/optimizer/planner.h10
-rw-r--r--src/include/optimizer/prep.h43
-rw-r--r--src/include/optimizer/tlist.h40
-rw-r--r--src/include/optimizer/var.h14
-rw-r--r--src/include/optimizer/xfunc.h81
-rw-r--r--src/include/parser/catalog_utils.h71
-rw-r--r--src/include/parser/dbcommands.h21
-rw-r--r--src/include/parser/gramparse.h14
-rw-r--r--src/include/parser/keywords.h23
-rw-r--r--src/include/parser/parse_query.h81
-rw-r--r--src/include/parser/parse_state.h31
-rw-r--r--src/include/parser/parsetree.h73
-rw-r--r--src/include/parser/scansup.h9
-rw-r--r--src/include/parser/sysfunc.h9
-rw-r--r--src/include/port/BSD44_derived.h30
-rw-r--r--src/include/port/aix.h18
-rw-r--r--src/include/port/alpha.h14
-rw-r--r--src/include/port/bsdi.h18
-rw-r--r--src/include/port/dgux.h17
-rw-r--r--src/include/port/hpux.h28
-rw-r--r--src/include/port/i386_solaris.h54
-rw-r--r--src/include/port/irix5.h14
-rw-r--r--src/include/port/linux.h59
-rw-r--r--src/include/port/nextstep.h36
-rw-r--r--src/include/port/sco.h8
-rw-r--r--src/include/port/sparc_solaris.h28
-rw-r--r--src/include/port/sunos4.h16
-rw-r--r--src/include/port/svr4.h16
-rw-r--r--src/include/port/ultrix4.h79
-rw-r--r--src/include/port/univel.h38
-rw-r--r--src/include/port/win32.h16
-rw-r--r--src/include/postgres.h197
-rw-r--r--src/include/postgres_ext.h30
-rw-r--r--src/include/regex/cclass.h105
-rw-r--r--src/include/regex/cdefs.h112
-rw-r--r--src/include/regex/cname.h417
-rw-r--r--src/include/regex/regex.h123
-rw-r--r--src/include/regex/regex2.h195
-rw-r--r--src/include/regex/regexp.h56
-rw-r--r--src/include/regex/utils.h34
-rw-r--r--src/include/rewrite/locks.h15
-rw-r--r--src/include/rewrite/prs2lock.h40
-rw-r--r--src/include/rewrite/rewriteDefine.h12
-rw-r--r--src/include/rewrite/rewriteHandler.h35
-rw-r--r--src/include/rewrite/rewriteManip.h35
-rw-r--r--src/include/rewrite/rewriteRemove.h16
-rw-r--r--src/include/rewrite/rewriteSupport.h22
-rw-r--r--src/include/storage/backendid.h23
-rw-r--r--src/include/storage/block.h65
-rw-r--r--src/include/storage/buf.h20
-rw-r--r--src/include/storage/buf_internals.h262
-rw-r--r--src/include/storage/bufmgr.h89
-rw-r--r--src/include/storage/bufpage.h196
-rw-r--r--src/include/storage/fd.h74
-rw-r--r--src/include/storage/ipc.h242
-rw-r--r--src/include/storage/item.h10
-rw-r--r--src/include/storage/itemid.h53
-rw-r--r--src/include/storage/itempos.h39
-rw-r--r--src/include/storage/itemptr.h80
-rw-r--r--src/include/storage/large_object.h60
-rw-r--r--src/include/storage/lmgr.h92
-rw-r--r--src/include/storage/lock.h170
-rw-r--r--src/include/storage/multilev.h38
-rw-r--r--src/include/storage/off.h40
-rw-r--r--src/include/storage/page.h14
-rw-r--r--src/include/storage/pagenum.h14
-rw-r--r--src/include/storage/pos.h32
-rw-r--r--src/include/storage/proc.h113
-rw-r--r--src/include/storage/shmem.h86
-rw-r--r--src/include/storage/sinval.h23
-rw-r--r--src/include/storage/sinvaladt.h176
-rw-r--r--src/include/storage/smgr.h124
-rw-r--r--src/include/storage/spin.h20
-rw-r--r--src/include/strdup.h2
-rw-r--r--src/include/tcop/dest.h88
-rw-r--r--src/include/tcop/fastpath.h22
-rw-r--r--src/include/tcop/pquery.h22
-rw-r--r--src/include/tcop/tcopdebug.h22
-rw-r--r--src/include/tcop/tcopprot.h35
-rw-r--r--src/include/tcop/utility.h8
-rw-r--r--src/include/tcop/variable.h25
-rw-r--r--src/include/utils/acl.h197
-rw-r--r--src/include/utils/array.h162
-rw-r--r--src/include/utils/bit.h24
-rw-r--r--src/include/utils/builtins.h817
-rw-r--r--src/include/utils/cash.h34
-rw-r--r--src/include/utils/catcache.h98
-rw-r--r--src/include/utils/datetime.h6
-rw-r--r--src/include/utils/datum.h19
-rw-r--r--src/include/utils/dt.h373
-rw-r--r--src/include/utils/dynahash.h11
-rw-r--r--src/include/utils/dynamic_loader.h31
-rw-r--r--src/include/utils/elog.h38
-rw-r--r--src/include/utils/exc.h107
-rw-r--r--src/include/utils/excid.h16
-rw-r--r--src/include/utils/fcache.h80
-rw-r--r--src/include/utils/fcache2.h8
-rw-r--r--src/include/utils/fmgrtab.h25
-rw-r--r--src/include/utils/geo_decls.h513
-rw-r--r--src/include/utils/hsearch.h190
-rw-r--r--src/include/utils/inval.h37
-rw-r--r--src/include/utils/lselect.h62
-rw-r--r--src/include/utils/lsyscache.h46
-rw-r--r--src/include/utils/mcxt.h39
-rw-r--r--src/include/utils/memutils.h271
-rw-r--r--src/include/utils/module.h18
-rw-r--r--src/include/utils/nabstime.h96
-rw-r--r--src/include/utils/oidcompos.h68
-rw-r--r--src/include/utils/palloc.h17
-rw-r--r--src/include/utils/portal.h85
-rw-r--r--src/include/utils/psort.h104
-rw-r--r--src/include/utils/rel.h155
-rw-r--r--src/include/utils/rel2.h15
-rw-r--r--src/include/utils/relcache.h26
-rw-r--r--src/include/utils/sets.h10
-rw-r--r--src/include/utils/syscache.h129
-rw-r--r--src/include/utils/tqual.h36
-rw-r--r--src/include/version.h16
-rw-r--r--src/interfaces/libpgtcl/libpgtcl.h12
-rw-r--r--src/interfaces/libpgtcl/pgtcl.c277
-rw-r--r--src/interfaces/libpgtcl/pgtclCmds.c2054
-rw-r--r--src/interfaces/libpgtcl/pgtclCmds.h134
-rw-r--r--src/interfaces/libpgtcl/pgtclId.c260
-rw-r--r--src/interfaces/libpgtcl/pgtclId.h24
-rw-r--r--src/interfaces/libpq/fe-auth.c763
-rw-r--r--src/interfaces/libpq/fe-auth.h34
-rw-r--r--src/interfaces/libpq/fe-connect.c1686
-rw-r--r--src/interfaces/libpq/fe-connect.h12
-rw-r--r--src/interfaces/libpq/fe-exec.c3014
-rw-r--r--src/interfaces/libpq/fe-lobj.c939
-rw-r--r--src/interfaces/libpq/fe-misc.c227
-rw-r--r--src/interfaces/libpq/libpq-fe.h503
-rw-r--r--src/interfaces/libpq/pqsignal.c38
-rw-r--r--src/interfaces/libpq/pqsignal.h12
-rw-r--r--src/lextest/lextest.c6
-rw-r--r--src/test/examples/testlibpq.c213
-rw-r--r--src/test/examples/testlibpq2.c142
-rw-r--r--src/test/examples/testlibpq3.c263
-rw-r--r--src/test/examples/testlibpq4.c240
-rw-r--r--src/test/examples/testlo.c392
-rw-r--r--src/test/examples/testlo2.c378
-rw-r--r--src/test/regress/regress.c375
-rw-r--r--src/tools/entab/entab.c153
-rw-r--r--src/tools/entab/halt.c54
-rw-r--r--src/tutorial/C-code/beard.c68
-rw-r--r--src/tutorial/C-code/complex.c175
-rw-r--r--src/tutorial/C-code/funcs.c89
-rw-r--r--src/utils/strdup.c14
-rw-r--r--src/utils/version.c190
675 files changed, 151127 insertions, 137370 deletions
diff --git a/src/backend/access/common/heaptuple.c b/src/backend/access/common/heaptuple.c
index 60ec3e4d3ab..17257690303 100644
--- a/src/backend/access/common/heaptuple.c
+++ b/src/backend/access/common/heaptuple.c
@@ -1,18 +1,18 @@
/*-------------------------------------------------------------------------
*
* heaptuple.c--
- * This file contains heap tuple accessor and mutator routines, as well
- * as a few various tuple utilities.
+ * This file contains heap tuple accessor and mutator routines, as well
+ * as a few various tuple utilities.
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/common/heaptuple.c,v 1.21 1997/08/26 23:31:20 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/common/heaptuple.c,v 1.22 1997/09/07 04:37:30 momjian Exp $
*
* NOTES
- * The old interface functions have been converted to macros
- * and moved to heapam.h
+ * The old interface functions have been converted to macros
+ * and moved to heapam.h
*
*-------------------------------------------------------------------------
*/
@@ -27,9 +27,9 @@
#include <utils/memutils.h>
#ifndef HAVE_MEMMOVE
-# include <regex/utils.h>
+#include <regex/utils.h>
#else
-# include <string.h>
+#include <string.h>
#endif
@@ -37,902 +37,991 @@
#if !defined(NO_ASSERT_CHECKING) && defined(sparc) && defined(sunos4)
#define register
-#endif /* !NO_ASSERT_CHECKING && sparc && sunos4 */
+#endif /* !NO_ASSERT_CHECKING && sparc && sunos4 */
/* ----------------------------------------------------------------
- * misc support routines
+ * misc support routines
* ----------------------------------------------------------------
*/
/* ----------------
- * ComputeDataSize
+ * ComputeDataSize
* ----------------
*/
Size
ComputeDataSize(TupleDesc tupleDesc,
- Datum value[],
- char nulls[])
+ Datum value[],
+ char nulls[])
{
- uint32 data_length;
- int i;
- int numberOfAttributes = tupleDesc->natts;
- AttributeTupleForm *att = tupleDesc->attrs;
-
- for (data_length = 0, i = 0; i < numberOfAttributes; i++) {
- if (nulls[i] != ' ') continue;
-
- switch (att[i]->attlen) {
- case -1:
- /*
- * This is the size of the disk representation and so
- * must include the additional sizeof long.
- */
- if (att[i]->attalign == 'd') {
- data_length = DOUBLEALIGN(data_length)
- + VARSIZE(DatumGetPointer(value[i]));
- } else {
- data_length = INTALIGN(data_length)
- + VARSIZE(DatumGetPointer(value[i]));
- }
- break;
- case sizeof(char):
- data_length++;
- break;
- case sizeof(short):
- data_length = SHORTALIGN(data_length + sizeof(short));
- break;
- case sizeof(int32):
- data_length = INTALIGN(data_length + sizeof(int32));
- break;
- default:
- if (att[i]->attlen < sizeof(int32))
- elog(WARN, "ComputeDataSize: attribute %d has len %d",
- i, att[i]->attlen);
- if (att[i]->attalign == 'd')
- data_length = DOUBLEALIGN(data_length) + att[i]->attlen;
- else
- data_length = LONGALIGN(data_length) + att[i]->attlen;
- break;
+ uint32 data_length;
+ int i;
+ int numberOfAttributes = tupleDesc->natts;
+ AttributeTupleForm *att = tupleDesc->attrs;
+
+ for (data_length = 0, i = 0; i < numberOfAttributes; i++)
+ {
+ if (nulls[i] != ' ')
+ continue;
+
+ switch (att[i]->attlen)
+ {
+ case -1:
+
+ /*
+ * This is the size of the disk representation and so must
+ * include the additional sizeof long.
+ */
+ if (att[i]->attalign == 'd')
+ {
+ data_length = DOUBLEALIGN(data_length)
+ + VARSIZE(DatumGetPointer(value[i]));
+ }
+ else
+ {
+ data_length = INTALIGN(data_length)
+ + VARSIZE(DatumGetPointer(value[i]));
+ }
+ break;
+ case sizeof(char):
+ data_length++;
+ break;
+ case sizeof(short):
+ data_length = SHORTALIGN(data_length + sizeof(short));
+ break;
+ case sizeof(int32):
+ data_length = INTALIGN(data_length + sizeof(int32));
+ break;
+ default:
+ if (att[i]->attlen < sizeof(int32))
+ elog(WARN, "ComputeDataSize: attribute %d has len %d",
+ i, att[i]->attlen);
+ if (att[i]->attalign == 'd')
+ data_length = DOUBLEALIGN(data_length) + att[i]->attlen;
+ else
+ data_length = LONGALIGN(data_length) + att[i]->attlen;
+ break;
+ }
}
- }
-
- return data_length;
+
+ return data_length;
}
/* ----------------
- * DataFill
+ * DataFill
* ----------------
*/
void
DataFill(char *data,
- TupleDesc tupleDesc,
- Datum value[],
- char nulls[],
- char *infomask,
- bits8 *bit)
+ TupleDesc tupleDesc,
+ Datum value[],
+ char nulls[],
+ char *infomask,
+ bits8 * bit)
{
- bits8 *bitP = 0;
- int bitmask = 0;
- uint32 data_length;
- int i;
- int numberOfAttributes = tupleDesc->natts;
- AttributeTupleForm *att = tupleDesc->attrs;
-
- if (bit != NULL) {
- bitP = &bit[-1];
- bitmask = CSIGNBIT;
- }
-
- *infomask = 0;
-
- for (i = 0; i < numberOfAttributes; i++) {
- if (bit != NULL) {
- if (bitmask != CSIGNBIT) {
- bitmask <<= 1;
- } else {
- bitP += 1;
- *bitP = 0x0;
- bitmask = 1;
- }
-
- if (nulls[i] == 'n') {
- *infomask |= HEAP_HASNULL;
- continue;
- }
-
- *bitP |= bitmask;
+ bits8 *bitP = 0;
+ int bitmask = 0;
+ uint32 data_length;
+ int i;
+ int numberOfAttributes = tupleDesc->natts;
+ AttributeTupleForm *att = tupleDesc->attrs;
+
+ if (bit != NULL)
+ {
+ bitP = &bit[-1];
+ bitmask = CSIGNBIT;
}
-
- switch (att[i]->attlen) {
- case -1:
- *infomask |= HEAP_HASVARLENA;
- if (att[i]->attalign=='d') {
- data = (char *) DOUBLEALIGN(data);
- } else {
- data = (char *) INTALIGN(data);
- }
- data_length = VARSIZE(DatumGetPointer(value[i]));
- memmove(data, DatumGetPointer(value[i]),data_length);
- data += data_length;
- break;
- case sizeof(char):
- *data = att[i]->attbyval ?
- DatumGetChar(value[i]) : *((char *) value[i]);
- data += sizeof(char);
- break;
- case sizeof(int16):
- data = (char *) SHORTALIGN(data);
- * (short *) data = (att[i]->attbyval ?
- DatumGetInt16(value[i]) :
- *((short *) value[i]));
- data += sizeof(short);
- break;
- case sizeof(int32):
- data = (char *) INTALIGN(data);
- * (int32 *) data = (att[i]->attbyval ?
- DatumGetInt32(value[i]) :
- *((int32 *) value[i]));
- data += sizeof(int32);
- break;
- default:
- if (att[i]->attlen < sizeof(int32))
- elog(WARN, "DataFill: attribute %d has len %d",
- i, att[i]->attlen);
- if (att[i]->attalign == 'd') {
- data = (char *) DOUBLEALIGN(data);
- memmove(data, DatumGetPointer(value[i]),
- att[i]->attlen);
- data += att[i]->attlen;
- } else {
- data = (char *) LONGALIGN(data);
- memmove(data, DatumGetPointer(value[i]),
- att[i]->attlen);
- data += att[i]->attlen;
- }
- break;
+
+ *infomask = 0;
+
+ for (i = 0; i < numberOfAttributes; i++)
+ {
+ if (bit != NULL)
+ {
+ if (bitmask != CSIGNBIT)
+ {
+ bitmask <<= 1;
+ }
+ else
+ {
+ bitP += 1;
+ *bitP = 0x0;
+ bitmask = 1;
+ }
+
+ if (nulls[i] == 'n')
+ {
+ *infomask |= HEAP_HASNULL;
+ continue;
+ }
+
+ *bitP |= bitmask;
+ }
+
+ switch (att[i]->attlen)
+ {
+ case -1:
+ *infomask |= HEAP_HASVARLENA;
+ if (att[i]->attalign == 'd')
+ {
+ data = (char *) DOUBLEALIGN(data);
+ }
+ else
+ {
+ data = (char *) INTALIGN(data);
+ }
+ data_length = VARSIZE(DatumGetPointer(value[i]));
+ memmove(data, DatumGetPointer(value[i]), data_length);
+ data += data_length;
+ break;
+ case sizeof(char):
+ *data = att[i]->attbyval ?
+ DatumGetChar(value[i]) : *((char *) value[i]);
+ data += sizeof(char);
+ break;
+ case sizeof(int16):
+ data = (char *) SHORTALIGN(data);
+ *(short *) data = (att[i]->attbyval ?
+ DatumGetInt16(value[i]) :
+ *((short *) value[i]));
+ data += sizeof(short);
+ break;
+ case sizeof(int32):
+ data = (char *) INTALIGN(data);
+ *(int32 *) data = (att[i]->attbyval ?
+ DatumGetInt32(value[i]) :
+ *((int32 *) value[i]));
+ data += sizeof(int32);
+ break;
+ default:
+ if (att[i]->attlen < sizeof(int32))
+ elog(WARN, "DataFill: attribute %d has len %d",
+ i, att[i]->attlen);
+ if (att[i]->attalign == 'd')
+ {
+ data = (char *) DOUBLEALIGN(data);
+ memmove(data, DatumGetPointer(value[i]),
+ att[i]->attlen);
+ data += att[i]->attlen;
+ }
+ else
+ {
+ data = (char *) LONGALIGN(data);
+ memmove(data, DatumGetPointer(value[i]),
+ att[i]->attlen);
+ data += att[i]->attlen;
+ }
+ break;
+ }
}
- }
}
/* ----------------------------------------------------------------
- * heap tuple interface
+ * heap tuple interface
* ----------------------------------------------------------------
*/
/* ----------------
- * heap_attisnull - returns 1 iff tuple attribute is not present
+ * heap_attisnull - returns 1 iff tuple attribute is not present
* ----------------
*/
int
heap_attisnull(HeapTuple tup, int attnum)
{
- if (attnum > (int)tup->t_natts)
- return (1);
-
- if (HeapTupleNoNulls(tup)) return(0);
-
- if (attnum > 0) {
- return(att_isnull(attnum - 1, tup->t_bits));
- } else
- switch (attnum) {
- case SelfItemPointerAttributeNumber:
- case ObjectIdAttributeNumber:
- case MinTransactionIdAttributeNumber:
- case MinCommandIdAttributeNumber:
- case MaxTransactionIdAttributeNumber:
- case MaxCommandIdAttributeNumber:
- case ChainItemPointerAttributeNumber:
- case AnchorItemPointerAttributeNumber:
- case MinAbsoluteTimeAttributeNumber:
- case MaxAbsoluteTimeAttributeNumber:
- case VersionTypeAttributeNumber:
- break;
-
- case 0:
- elog(WARN, "heap_attisnull: zero attnum disallowed");
-
- default:
- elog(WARN, "heap_attisnull: undefined negative attnum");
+ if (attnum > (int) tup->t_natts)
+ return (1);
+
+ if (HeapTupleNoNulls(tup))
+ return (0);
+
+ if (attnum > 0)
+ {
+ return (att_isnull(attnum - 1, tup->t_bits));
}
-
- return (0);
+ else
+ switch (attnum)
+ {
+ case SelfItemPointerAttributeNumber:
+ case ObjectIdAttributeNumber:
+ case MinTransactionIdAttributeNumber:
+ case MinCommandIdAttributeNumber:
+ case MaxTransactionIdAttributeNumber:
+ case MaxCommandIdAttributeNumber:
+ case ChainItemPointerAttributeNumber:
+ case AnchorItemPointerAttributeNumber:
+ case MinAbsoluteTimeAttributeNumber:
+ case MaxAbsoluteTimeAttributeNumber:
+ case VersionTypeAttributeNumber:
+ break;
+
+ case 0:
+ elog(WARN, "heap_attisnull: zero attnum disallowed");
+
+ default:
+ elog(WARN, "heap_attisnull: undefined negative attnum");
+ }
+
+ return (0);
}
/* ----------------------------------------------------------------
- * system attribute heap tuple support
+ * system attribute heap tuple support
* ----------------------------------------------------------------
*/
/* ----------------
- * heap_sysattrlen
+ * heap_sysattrlen
*
- * This routine returns the length of a system attribute.
+ * This routine returns the length of a system attribute.
* ----------------
*/
int
heap_sysattrlen(AttrNumber attno)
{
- HeapTupleData *f = NULL;
-
- switch (attno) {
- case SelfItemPointerAttributeNumber: return sizeof f->t_ctid;
- case ObjectIdAttributeNumber: return sizeof f->t_oid;
- case MinTransactionIdAttributeNumber: return sizeof f->t_xmin;
- case MinCommandIdAttributeNumber: return sizeof f->t_cmin;
- case MaxTransactionIdAttributeNumber: return sizeof f->t_xmax;
- case MaxCommandIdAttributeNumber: return sizeof f->t_cmax;
- case ChainItemPointerAttributeNumber: return sizeof f->t_chain;
- case MinAbsoluteTimeAttributeNumber: return sizeof f->t_tmin;
- case MaxAbsoluteTimeAttributeNumber: return sizeof f->t_tmax;
- case VersionTypeAttributeNumber: return sizeof f->t_vtype;
-
- case AnchorItemPointerAttributeNumber:
- elog(WARN, "heap_sysattrlen: field t_anchor does not exist!");
- return 0;
-
- default:
- elog(WARN, "sysattrlen: System attribute number %d unknown.", attno);
- return 0;
- }
+ HeapTupleData *f = NULL;
+
+ switch (attno)
+ {
+ case SelfItemPointerAttributeNumber:
+ return sizeof f->t_ctid;
+ case ObjectIdAttributeNumber:
+ return sizeof f->t_oid;
+ case MinTransactionIdAttributeNumber:
+ return sizeof f->t_xmin;
+ case MinCommandIdAttributeNumber:
+ return sizeof f->t_cmin;
+ case MaxTransactionIdAttributeNumber:
+ return sizeof f->t_xmax;
+ case MaxCommandIdAttributeNumber:
+ return sizeof f->t_cmax;
+ case ChainItemPointerAttributeNumber:
+ return sizeof f->t_chain;
+ case MinAbsoluteTimeAttributeNumber:
+ return sizeof f->t_tmin;
+ case MaxAbsoluteTimeAttributeNumber:
+ return sizeof f->t_tmax;
+ case VersionTypeAttributeNumber:
+ return sizeof f->t_vtype;
+
+ case AnchorItemPointerAttributeNumber:
+ elog(WARN, "heap_sysattrlen: field t_anchor does not exist!");
+ return 0;
+
+ default:
+ elog(WARN, "sysattrlen: System attribute number %d unknown.", attno);
+ return 0;
+ }
}
/* ----------------
- * heap_sysattrbyval
+ * heap_sysattrbyval
*
- * This routine returns the "by-value" property of a system attribute.
+ * This routine returns the "by-value" property of a system attribute.
* ----------------
*/
bool
heap_sysattrbyval(AttrNumber attno)
{
- bool byval;
-
- switch (attno) {
- case SelfItemPointerAttributeNumber:
- byval = false;
- break;
- case ObjectIdAttributeNumber:
- byval = true;
- break;
- case MinTransactionIdAttributeNumber:
- byval = true;
- break;
- case MinCommandIdAttributeNumber:
- byval = true;
- break;
- case MaxTransactionIdAttributeNumber:
- byval = true;
- break;
- case MaxCommandIdAttributeNumber:
- byval = true;
- break;
- case ChainItemPointerAttributeNumber:
- byval = false;
- break;
- case AnchorItemPointerAttributeNumber:
- byval = false;
- break;
- case MinAbsoluteTimeAttributeNumber:
- byval = true;
- break;
- case MaxAbsoluteTimeAttributeNumber:
- byval = true;
- break;
- case VersionTypeAttributeNumber:
- byval = true;
- break;
- default:
- byval = true;
- elog(WARN, "sysattrbyval: System attribute number %d unknown.",
- attno);
- break;
- }
-
- return byval;
+ bool byval;
+
+ switch (attno)
+ {
+ case SelfItemPointerAttributeNumber:
+ byval = false;
+ break;
+ case ObjectIdAttributeNumber:
+ byval = true;
+ break;
+ case MinTransactionIdAttributeNumber:
+ byval = true;
+ break;
+ case MinCommandIdAttributeNumber:
+ byval = true;
+ break;
+ case MaxTransactionIdAttributeNumber:
+ byval = true;
+ break;
+ case MaxCommandIdAttributeNumber:
+ byval = true;
+ break;
+ case ChainItemPointerAttributeNumber:
+ byval = false;
+ break;
+ case AnchorItemPointerAttributeNumber:
+ byval = false;
+ break;
+ case MinAbsoluteTimeAttributeNumber:
+ byval = true;
+ break;
+ case MaxAbsoluteTimeAttributeNumber:
+ byval = true;
+ break;
+ case VersionTypeAttributeNumber:
+ byval = true;
+ break;
+ default:
+ byval = true;
+ elog(WARN, "sysattrbyval: System attribute number %d unknown.",
+ attno);
+ break;
+ }
+
+ return byval;
}
/* ----------------
- * heap_getsysattr
+ * heap_getsysattr
* ----------------
*/
-char *
+char *
heap_getsysattr(HeapTuple tup, Buffer b, int attnum)
{
- switch (attnum) {
- case SelfItemPointerAttributeNumber:
- return ((char *)&tup->t_ctid);
- case ObjectIdAttributeNumber:
- return ((char *) (long) tup->t_oid);
- case MinTransactionIdAttributeNumber:
- return ((char *) (long) tup->t_xmin);
- case MinCommandIdAttributeNumber:
- return ((char *) (long) tup->t_cmin);
- case MaxTransactionIdAttributeNumber:
- return ((char *) (long) tup->t_xmax);
- case MaxCommandIdAttributeNumber:
- return ((char *) (long) tup->t_cmax);
- case ChainItemPointerAttributeNumber:
- return ((char *) &tup->t_chain);
- case AnchorItemPointerAttributeNumber:
- elog(WARN, "heap_getsysattr: t_anchor does not exist!");
- break;
-
- /*
- * For tmin and tmax, we need to do some extra work. These don't
- * get filled in until the vacuum cleaner runs (or we manage to flush
- * a page after setting the value correctly below). If the vacuum
- * cleaner hasn't run yet, then the times stored in the tuple are
- * wrong, and we need to look up the commit time of the transaction.
- * We cache this value in the tuple to avoid doing the work more than
- * once.
- */
-
- case MinAbsoluteTimeAttributeNumber:
- if (!AbsoluteTimeIsBackwardCompatiblyValid(tup->t_tmin) &&
- TransactionIdDidCommit(tup->t_xmin))
- tup->t_tmin = TransactionIdGetCommitTime(tup->t_xmin);
- return ((char *) (long) tup->t_tmin);
- case MaxAbsoluteTimeAttributeNumber:
- if (!AbsoluteTimeIsBackwardCompatiblyReal(tup->t_tmax)) {
- if (TransactionIdDidCommit(tup->t_xmax))
- tup->t_tmax = TransactionIdGetCommitTime(tup->t_xmax);
- else
- tup->t_tmax = CURRENT_ABSTIME;
+ switch (attnum)
+ {
+ case SelfItemPointerAttributeNumber:
+ return ((char *) &tup->t_ctid);
+ case ObjectIdAttributeNumber:
+ return ((char *) (long) tup->t_oid);
+ case MinTransactionIdAttributeNumber:
+ return ((char *) (long) tup->t_xmin);
+ case MinCommandIdAttributeNumber:
+ return ((char *) (long) tup->t_cmin);
+ case MaxTransactionIdAttributeNumber:
+ return ((char *) (long) tup->t_xmax);
+ case MaxCommandIdAttributeNumber:
+ return ((char *) (long) tup->t_cmax);
+ case ChainItemPointerAttributeNumber:
+ return ((char *) &tup->t_chain);
+ case AnchorItemPointerAttributeNumber:
+ elog(WARN, "heap_getsysattr: t_anchor does not exist!");
+ break;
+
+ /*
+ * For tmin and tmax, we need to do some extra work. These don't
+ * get filled in until the vacuum cleaner runs (or we manage to
+ * flush a page after setting the value correctly below). If the
+ * vacuum cleaner hasn't run yet, then the times stored in the
+ * tuple are wrong, and we need to look up the commit time of the
+ * transaction. We cache this value in the tuple to avoid doing
+ * the work more than once.
+ */
+
+ case MinAbsoluteTimeAttributeNumber:
+ if (!AbsoluteTimeIsBackwardCompatiblyValid(tup->t_tmin) &&
+ TransactionIdDidCommit(tup->t_xmin))
+ tup->t_tmin = TransactionIdGetCommitTime(tup->t_xmin);
+ return ((char *) (long) tup->t_tmin);
+ case MaxAbsoluteTimeAttributeNumber:
+ if (!AbsoluteTimeIsBackwardCompatiblyReal(tup->t_tmax))
+ {
+ if (TransactionIdDidCommit(tup->t_xmax))
+ tup->t_tmax = TransactionIdGetCommitTime(tup->t_xmax);
+ else
+ tup->t_tmax = CURRENT_ABSTIME;
+ }
+ return ((char *) (long) tup->t_tmax);
+ case VersionTypeAttributeNumber:
+ return ((char *) (long) tup->t_vtype);
+ default:
+ elog(WARN, "heap_getsysattr: undefined attnum %d", attnum);
}
- return ((char *) (long) tup->t_tmax);
- case VersionTypeAttributeNumber:
- return ((char *) (long) tup->t_vtype);
- default:
- elog(WARN, "heap_getsysattr: undefined attnum %d", attnum);
- }
- return(NULL);
+ return (NULL);
}
/* ----------------
- * fastgetattr
+ * fastgetattr
*
- * This is a newer version of fastgetattr which attempts to be
- * faster by caching attribute offsets in the attribute descriptor.
+ * This is a newer version of fastgetattr which attempts to be
+ * faster by caching attribute offsets in the attribute descriptor.
*
- * an alternate way to speed things up would be to cache offsets
- * with the tuple, but that seems more difficult unless you take
- * the storage hit of actually putting those offsets into the
- * tuple you send to disk. Yuck.
+ * an alternate way to speed things up would be to cache offsets
+ * with the tuple, but that seems more difficult unless you take
+ * the storage hit of actually putting those offsets into the
+ * tuple you send to disk. Yuck.
*
- * This scheme will be slightly slower than that, but should
- * preform well for queries which hit large #'s of tuples. After
- * you cache the offsets once, examining all the other tuples using
- * the same attribute descriptor will go much quicker. -cim 5/4/91
+ * This scheme will be slightly slower than that, but should
+ * preform well for queries which hit large #'s of tuples. After
+ * you cache the offsets once, examining all the other tuples using
+ * the same attribute descriptor will go much quicker. -cim 5/4/91
* ----------------
*/
-char *
+char *
fastgetattr(HeapTuple tup,
- int attnum,
- TupleDesc tupleDesc,
- bool *isnull)
+ int attnum,
+ TupleDesc tupleDesc,
+ bool * isnull)
{
- char *tp; /* ptr to att in tuple */
- bits8 *bp = NULL; /* ptr to att in tuple */
- int slow; /* do we have to walk nulls? */
- AttributeTupleForm *att = tupleDesc->attrs;
-
- /* ----------------
- * sanity checks
- * ----------------
- */
-
- Assert(attnum > 0);
-
- /* ----------------
- * Three cases:
- *
- * 1: No nulls and no variable length attributes.
- * 2: Has a null or a varlena AFTER att.
- * 3: Has nulls or varlenas BEFORE att.
- * ----------------
- */
-
- if (isnull)
- *isnull = false;
-
- if (HeapTupleNoNulls(tup)) {
- attnum--;
- if (att[attnum]->attcacheoff > 0) {
- return (char *)
- fetchatt( &(att[attnum]),
- (char *)tup + tup->t_hoff + att[attnum]->attcacheoff);
- } else if (attnum == 0) {
- /*
- * first attribute is always at position zero
- */
- return((char *) fetchatt(&(att[0]), (char *) tup + tup->t_hoff));
- }
-
- tp = (char *) tup + tup->t_hoff;
-
- slow = 0;
- } else {
- /*
- * there's a null somewhere in the tuple
- */
+ char *tp; /* ptr to att in tuple */
+ bits8 *bp = NULL; /* ptr to att in tuple */
+ int slow; /* do we have to walk nulls? */
+ AttributeTupleForm *att = tupleDesc->attrs;
- bp = tup->t_bits;
- tp = (char *) tup + tup->t_hoff;
- slow = 0;
- attnum--;
-
/* ----------------
- * check to see if desired att is null
+ * sanity checks
* ----------------
*/
-
- if (att_isnull(attnum, bp)) {
- if (isnull)
- *isnull = true;
- return NULL;
- }
+
+ Assert(attnum > 0);
/* ----------------
- * Now check to see if any preceeding bits are null...
+ * Three cases:
+ *
+ * 1: No nulls and no variable length attributes.
+ * 2: Has a null or a varlena AFTER att.
+ * 3: Has nulls or varlenas BEFORE att.
* ----------------
*/
-
+
+ if (isnull)
+ *isnull = false;
+
+ if (HeapTupleNoNulls(tup))
{
- register int i = 0; /* current offset in bp */
-
- for (i = 0; i < attnum && !slow; i++) {
- if (att_isnull(i, bp)) slow = 1;
- }
+ attnum--;
+ if (att[attnum]->attcacheoff > 0)
+ {
+ return (char *)
+ fetchatt(&(att[attnum]),
+ (char *) tup + tup->t_hoff + att[attnum]->attcacheoff);
+ }
+ else if (attnum == 0)
+ {
+
+ /*
+ * first attribute is always at position zero
+ */
+ return ((char *) fetchatt(&(att[0]), (char *) tup + tup->t_hoff));
+ }
+
+ tp = (char *) tup + tup->t_hoff;
+
+ slow = 0;
}
- }
-
- /*
- * now check for any non-fixed length attrs before our attribute
- */
- if (!slow) {
- if (att[attnum]->attcacheoff > 0) {
- return (char *)
- fetchatt(&(att[attnum]),
- tp + att[attnum]->attcacheoff);
- } else if (attnum == 0) {
- return (char *)
- fetchatt(&(att[0]), (char *) tup + tup->t_hoff);
- } else if (!HeapTupleAllFixed(tup)) {
- register int j = 0;
-
- for (j = 0; j < attnum && !slow; j++)
- if (att[j]->attlen < 1) slow = 1;
+ else
+ {
+
+ /*
+ * there's a null somewhere in the tuple
+ */
+
+ bp = tup->t_bits;
+ tp = (char *) tup + tup->t_hoff;
+ slow = 0;
+ attnum--;
+
+ /* ----------------
+ * check to see if desired att is null
+ * ----------------
+ */
+
+ if (att_isnull(attnum, bp))
+ {
+ if (isnull)
+ *isnull = true;
+ return NULL;
+ }
+
+ /* ----------------
+ * Now check to see if any preceeding bits are null...
+ * ----------------
+ */
+
+ {
+ register int i = 0; /* current offset in bp */
+
+ for (i = 0; i < attnum && !slow; i++)
+ {
+ if (att_isnull(i, bp))
+ slow = 1;
+ }
+ }
}
- }
-
- /*
- * if slow is zero, and we got here, we know that we have a tuple with
- * no nulls. We also have to initialize the remainder of
- * the attribute cached offset values.
- */
- if (!slow) {
- register int j = 1;
- register long off;
-
+
/*
- * need to set cache for some atts
+ * now check for any non-fixed length attrs before our attribute
*/
-
- att[0]->attcacheoff = 0;
-
- while (att[j]->attcacheoff > 0) j++;
-
- off = att[j-1]->attcacheoff + att[j-1]->attlen;
-
- for (; j < attnum + 1; j++) {
- switch(att[j]->attlen) {
- case -1:
- off = (att[j]->attalign=='d') ?
- DOUBLEALIGN(off) : INTALIGN(off);
- break;
- case sizeof(char):
- break;
- case sizeof(short):
- off = SHORTALIGN(off);
- break;
- case sizeof(int32):
- off = INTALIGN(off);
- break;
- default:
- if (att[j]->attlen < sizeof(int32)) {
- elog(WARN,
- "fastgetattr: attribute %d has len %d",
- j, att[j]->attlen);
+ if (!slow)
+ {
+ if (att[attnum]->attcacheoff > 0)
+ {
+ return (char *)
+ fetchatt(&(att[attnum]),
+ tp + att[attnum]->attcacheoff);
+ }
+ else if (attnum == 0)
+ {
+ return (char *)
+ fetchatt(&(att[0]), (char *) tup + tup->t_hoff);
+ }
+ else if (!HeapTupleAllFixed(tup))
+ {
+ register int j = 0;
+
+ for (j = 0; j < attnum && !slow; j++)
+ if (att[j]->attlen < 1)
+ slow = 1;
}
- if (att[j]->attalign == 'd')
- off = DOUBLEALIGN(off);
- else
- off = LONGALIGN(off);
- break;
- }
-
- att[j]->attcacheoff = off;
- off += att[j]->attlen;
}
-
- return
- (char *)fetchatt(&(att[attnum]), tp + att[attnum]->attcacheoff);
- } else {
- register bool usecache = true;
- register int off = 0;
- register int i;
-
+
/*
- * Now we know that we have to walk the tuple CAREFULLY.
- *
- * Note - This loop is a little tricky. On iteration i we
- * first set the offset for attribute i and figure out how much
- * the offset should be incremented. Finally, we need to align the
- * offset based on the size of attribute i+1 (for which the offset
- * has been computed). -mer 12 Dec 1991
+ * if slow is zero, and we got here, we know that we have a tuple with
+ * no nulls. We also have to initialize the remainder of the
+ * attribute cached offset values.
*/
-
- for (i = 0; i < attnum; i++) {
- if (!HeapTupleNoNulls(tup)) {
- if (att_isnull(i, bp)) {
- usecache = false;
- continue;
- }
- }
- switch (att[i]->attlen) {
- case -1:
- off = (att[i]->attalign=='d') ?
- DOUBLEALIGN(off) : INTALIGN(off);
- break;
- case sizeof(char):
- break;
- case sizeof(short):
- off = SHORTALIGN(off);
- break;
- case sizeof(int32):
- off = INTALIGN(off);
- break;
- default:
- if (att[i]->attlen < sizeof(int32))
- elog(WARN,
- "fastgetattr2: attribute %d has len %d",
- i, att[i]->attlen);
- if (att[i]->attalign == 'd')
- off = DOUBLEALIGN(off);
- else
- off = LONGALIGN(off);
- break;
- }
- if (usecache && att[i]->attcacheoff > 0) {
- off = att[i]->attcacheoff;
- if (att[i]->attlen == -1) {
- usecache = false;
+ if (!slow)
+ {
+ register int j = 1;
+ register long off;
+
+ /*
+ * need to set cache for some atts
+ */
+
+ att[0]->attcacheoff = 0;
+
+ while (att[j]->attcacheoff > 0)
+ j++;
+
+ off = att[j - 1]->attcacheoff + att[j - 1]->attlen;
+
+ for (; j < attnum + 1; j++)
+ {
+ switch (att[j]->attlen)
+ {
+ case -1:
+ off = (att[j]->attalign == 'd') ?
+ DOUBLEALIGN(off) : INTALIGN(off);
+ break;
+ case sizeof(char):
+ break;
+ case sizeof(short):
+ off = SHORTALIGN(off);
+ break;
+ case sizeof(int32):
+ off = INTALIGN(off);
+ break;
+ default:
+ if (att[j]->attlen < sizeof(int32))
+ {
+ elog(WARN,
+ "fastgetattr: attribute %d has len %d",
+ j, att[j]->attlen);
+ }
+ if (att[j]->attalign == 'd')
+ off = DOUBLEALIGN(off);
+ else
+ off = LONGALIGN(off);
+ break;
+ }
+
+ att[j]->attcacheoff = off;
+ off += att[j]->attlen;
}
- } else {
- if (usecache) att[i]->attcacheoff = off;
- }
-
- switch(att[i]->attlen) {
- case sizeof(char):
- off++;
- break;
- case sizeof(int16):
- off += sizeof(int16);
- break;
- case sizeof(int32):
- off += sizeof(int32);
- break;
- case -1:
- usecache = false;
- off += VARSIZE(tp + off);
- break;
- default:
- off += att[i]->attlen;
- break;
- }
+
+ return
+ (char *) fetchatt(&(att[attnum]), tp + att[attnum]->attcacheoff);
}
- switch (att[attnum]->attlen) {
- case -1:
- off = (att[attnum]->attalign=='d')?
- DOUBLEALIGN(off) : INTALIGN(off);
- break;
- case sizeof(char):
- break;
- case sizeof(short):
- off = SHORTALIGN(off);
- break;
- case sizeof(int32):
- off = INTALIGN(off);
- break;
- default:
- if (att[attnum]->attlen < sizeof(int32))
- elog(WARN, "fastgetattr3: attribute %d has len %d",
- attnum, att[attnum]->attlen);
- if (att[attnum]->attalign == 'd')
- off = DOUBLEALIGN(off);
- else
- off = LONGALIGN(off);
- break;
+ else
+ {
+ register bool usecache = true;
+ register int off = 0;
+ register int i;
+
+ /*
+ * Now we know that we have to walk the tuple CAREFULLY.
+ *
+ * Note - This loop is a little tricky. On iteration i we first set
+ * the offset for attribute i and figure out how much the offset
+ * should be incremented. Finally, we need to align the offset
+ * based on the size of attribute i+1 (for which the offset has
+ * been computed). -mer 12 Dec 1991
+ */
+
+ for (i = 0; i < attnum; i++)
+ {
+ if (!HeapTupleNoNulls(tup))
+ {
+ if (att_isnull(i, bp))
+ {
+ usecache = false;
+ continue;
+ }
+ }
+ switch (att[i]->attlen)
+ {
+ case -1:
+ off = (att[i]->attalign == 'd') ?
+ DOUBLEALIGN(off) : INTALIGN(off);
+ break;
+ case sizeof(char):
+ break;
+ case sizeof(short):
+ off = SHORTALIGN(off);
+ break;
+ case sizeof(int32):
+ off = INTALIGN(off);
+ break;
+ default:
+ if (att[i]->attlen < sizeof(int32))
+ elog(WARN,
+ "fastgetattr2: attribute %d has len %d",
+ i, att[i]->attlen);
+ if (att[i]->attalign == 'd')
+ off = DOUBLEALIGN(off);
+ else
+ off = LONGALIGN(off);
+ break;
+ }
+ if (usecache && att[i]->attcacheoff > 0)
+ {
+ off = att[i]->attcacheoff;
+ if (att[i]->attlen == -1)
+ {
+ usecache = false;
+ }
+ }
+ else
+ {
+ if (usecache)
+ att[i]->attcacheoff = off;
+ }
+
+ switch (att[i]->attlen)
+ {
+ case sizeof(char):
+ off++;
+ break;
+ case sizeof(int16):
+ off += sizeof(int16);
+ break;
+ case sizeof(int32):
+ off += sizeof(int32);
+ break;
+ case -1:
+ usecache = false;
+ off += VARSIZE(tp + off);
+ break;
+ default:
+ off += att[i]->attlen;
+ break;
+ }
+ }
+ switch (att[attnum]->attlen)
+ {
+ case -1:
+ off = (att[attnum]->attalign == 'd') ?
+ DOUBLEALIGN(off) : INTALIGN(off);
+ break;
+ case sizeof(char):
+ break;
+ case sizeof(short):
+ off = SHORTALIGN(off);
+ break;
+ case sizeof(int32):
+ off = INTALIGN(off);
+ break;
+ default:
+ if (att[attnum]->attlen < sizeof(int32))
+ elog(WARN, "fastgetattr3: attribute %d has len %d",
+ attnum, att[attnum]->attlen);
+ if (att[attnum]->attalign == 'd')
+ off = DOUBLEALIGN(off);
+ else
+ off = LONGALIGN(off);
+ break;
+ }
+ return ((char *) fetchatt(&(att[attnum]), tp + off));
}
- return((char *) fetchatt(&(att[attnum]), tp + off));
- }
}
/* ----------------
- * heap_copytuple
+ * heap_copytuple
*
- * returns a copy of an entire tuple
+ * returns a copy of an entire tuple
* ----------------
*/
HeapTuple
heap_copytuple(HeapTuple tuple)
{
- HeapTuple newTuple;
+ HeapTuple newTuple;
- if (! HeapTupleIsValid(tuple))
- return (NULL);
-
- /* XXX For now, just prevent an undetectable executor related error */
- if (tuple->t_len > MAXTUPLEN) {
- elog(WARN, "palloctup: cannot handle length %d tuples",
- tuple->t_len);
- }
-
- newTuple = (HeapTuple) palloc(tuple->t_len);
- memmove((char *) newTuple, (char *) tuple, (int) tuple->t_len);
- return(newTuple);
+ if (!HeapTupleIsValid(tuple))
+ return (NULL);
+
+ /* XXX For now, just prevent an undetectable executor related error */
+ if (tuple->t_len > MAXTUPLEN)
+ {
+ elog(WARN, "palloctup: cannot handle length %d tuples",
+ tuple->t_len);
+ }
+
+ newTuple = (HeapTuple) palloc(tuple->t_len);
+ memmove((char *) newTuple, (char *) tuple, (int) tuple->t_len);
+ return (newTuple);
}
#ifdef NOT_USED
/* ----------------
- * heap_deformtuple
+ * heap_deformtuple
*
- * the inverse of heap_formtuple (see below)
+ * the inverse of heap_formtuple (see below)
* ----------------
*/
void
heap_deformtuple(HeapTuple tuple,
- TupleDesc tdesc,
- Datum values[],
- char nulls[])
+ TupleDesc tdesc,
+ Datum values[],
+ char nulls[])
{
- int i;
- int natts;
-
- Assert(HeapTupleIsValid(tuple));
-
- natts = tuple->t_natts;
- for (i = 0; i<natts; i++) {
- bool isnull;
-
- values[i] = (Datum)heap_getattr(tuple,
- InvalidBuffer,
- i+1,
- tdesc,
- &isnull);
- if (isnull)
- nulls[i] = 'n';
- else
- nulls[i] = ' ';
- }
+ int i;
+ int natts;
+
+ Assert(HeapTupleIsValid(tuple));
+
+ natts = tuple->t_natts;
+ for (i = 0; i < natts; i++)
+ {
+ bool isnull;
+
+ values[i] = (Datum) heap_getattr(tuple,
+ InvalidBuffer,
+ i + 1,
+ tdesc,
+ &isnull);
+ if (isnull)
+ nulls[i] = 'n';
+ else
+ nulls[i] = ' ';
+ }
}
+
#endif
/* ----------------
- * heap_formtuple
+ * heap_formtuple
*
- * constructs a tuple from the given value[] and null[] arrays
+ * constructs a tuple from the given value[] and null[] arrays
*
* old comments
- * Handles alignment by aligning 2 byte attributes on short boundries
- * and 3 or 4 byte attributes on long word boundries on a vax; and
- * aligning non-byte attributes on short boundries on a sun. Does
- * not properly align fixed length arrays of 1 or 2 byte types (yet).
+ * Handles alignment by aligning 2 byte attributes on short boundries
+ * and 3 or 4 byte attributes on long word boundries on a vax; and
+ * aligning non-byte attributes on short boundries on a sun. Does
+ * not properly align fixed length arrays of 1 or 2 byte types (yet).
*
- * Null attributes are indicated by a 'n' in the appropriate byte
- * of the null[]. Non-null attributes are indicated by a ' ' (space).
+ * Null attributes are indicated by a 'n' in the appropriate byte
+ * of the null[]. Non-null attributes are indicated by a ' ' (space).
*
- * Fix me. (Figure that must keep context if debug--allow give oid.)
- * Assumes in order.
+ * Fix me. (Figure that must keep context if debug--allow give oid.)
+ * Assumes in order.
* ----------------
*/
HeapTuple
heap_formtuple(TupleDesc tupleDescriptor,
- Datum value[],
- char nulls[])
+ Datum value[],
+ char nulls[])
{
- char *tp; /* tuple pointer */
- HeapTuple tuple; /* return tuple */
- int bitmaplen;
- long len;
- int hoff;
- bool hasnull = false;
- int i;
- int numberOfAttributes = tupleDescriptor->natts;
-
- len = sizeof *tuple - sizeof tuple->t_bits;
-
- for (i = 0; i < numberOfAttributes && !hasnull; i++) {
- if (nulls[i] != ' ') hasnull = true;
- }
-
- if (numberOfAttributes > MaxHeapAttributeNumber)
- elog(WARN, "heap_formtuple: numberOfAttributes of %d > %d",
- numberOfAttributes, MaxHeapAttributeNumber);
-
- if (hasnull) {
- bitmaplen = BITMAPLEN(numberOfAttributes);
- len += bitmaplen;
- }
-
- hoff = len = DOUBLEALIGN(len); /* be conservative here */
-
- len += ComputeDataSize(tupleDescriptor, value, nulls);
-
- tp = (char *) palloc(len);
- tuple = (HeapTuple) tp;
-
- memset(tp, 0, (int)len);
-
- tuple->t_len = len;
- tuple->t_natts = numberOfAttributes;
- tuple->t_hoff = hoff;
- tuple->t_tmin = INVALID_ABSTIME;
- tuple->t_tmax = CURRENT_ABSTIME;
-
- DataFill((char *)tuple + tuple->t_hoff,
- tupleDescriptor,
- value,
- nulls,
- &tuple->t_infomask,
- (hasnull ? tuple->t_bits : NULL));
-
- return (tuple);
+ char *tp; /* tuple pointer */
+ HeapTuple tuple; /* return tuple */
+ int bitmaplen;
+ long len;
+ int hoff;
+ bool hasnull = false;
+ int i;
+ int numberOfAttributes = tupleDescriptor->natts;
+
+ len = sizeof *tuple - sizeof tuple->t_bits;
+
+ for (i = 0; i < numberOfAttributes && !hasnull; i++)
+ {
+ if (nulls[i] != ' ')
+ hasnull = true;
+ }
+
+ if (numberOfAttributes > MaxHeapAttributeNumber)
+ elog(WARN, "heap_formtuple: numberOfAttributes of %d > %d",
+ numberOfAttributes, MaxHeapAttributeNumber);
+
+ if (hasnull)
+ {
+ bitmaplen = BITMAPLEN(numberOfAttributes);
+ len += bitmaplen;
+ }
+
+ hoff = len = DOUBLEALIGN(len); /* be conservative here */
+
+ len += ComputeDataSize(tupleDescriptor, value, nulls);
+
+ tp = (char *) palloc(len);
+ tuple = (HeapTuple) tp;
+
+ memset(tp, 0, (int) len);
+
+ tuple->t_len = len;
+ tuple->t_natts = numberOfAttributes;
+ tuple->t_hoff = hoff;
+ tuple->t_tmin = INVALID_ABSTIME;
+ tuple->t_tmax = CURRENT_ABSTIME;
+
+ DataFill((char *) tuple + tuple->t_hoff,
+ tupleDescriptor,
+ value,
+ nulls,
+ &tuple->t_infomask,
+ (hasnull ? tuple->t_bits : NULL));
+
+ return (tuple);
}
/* ----------------
- * heap_modifytuple
+ * heap_modifytuple
*
- * forms a new tuple from an old tuple and a set of replacement values.
+ * forms a new tuple from an old tuple and a set of replacement values.
* ----------------
*/
HeapTuple
heap_modifytuple(HeapTuple tuple,
- Buffer buffer,
- Relation relation,
- Datum replValue[],
- char replNull[],
- char repl[])
+ Buffer buffer,
+ Relation relation,
+ Datum replValue[],
+ char replNull[],
+ char repl[])
{
- int attoff;
- int numberOfAttributes;
- Datum *value;
- char *nulls;
- bool isNull;
- HeapTuple newTuple;
- int madecopy;
- uint8 infomask;
-
- /* ----------------
- * sanity checks
- * ----------------
- */
- Assert(HeapTupleIsValid(tuple));
- Assert(BufferIsValid(buffer) || RelationIsValid(relation));
- Assert(HeapTupleIsValid(tuple));
- Assert(PointerIsValid(replValue));
- Assert(PointerIsValid(replNull));
- Assert(PointerIsValid(repl));
-
- /* ----------------
- * if we're pointing to a disk page, then first
- * make a copy of our tuple so that all the attributes
- * are available. XXX this is inefficient -cim
- * ----------------
- */
- madecopy = 0;
- if (BufferIsValid(buffer) == true) {
- relation = (Relation) BufferGetRelation(buffer);
- tuple = heap_copytuple(tuple);
- madecopy = 1;
- }
-
- numberOfAttributes = RelationGetRelationTupleForm(relation)->relnatts;
-
- /* ----------------
- * allocate and fill value[] and nulls[] arrays from either
- * the tuple or the repl information, as appropriate.
- * ----------------
- */
- value = (Datum *) palloc(numberOfAttributes * sizeof *value);
- nulls = (char *) palloc(numberOfAttributes * sizeof *nulls);
-
- for (attoff = 0;
- attoff < numberOfAttributes;
- attoff += 1) {
-
- if (repl[attoff] == ' ') {
- char *attr;
-
- attr =
- heap_getattr(tuple,
- InvalidBuffer,
- AttrOffsetGetAttrNumber(attoff),
- RelationGetTupleDescriptor(relation),
- &isNull) ;
- value[attoff] = PointerGetDatum(attr);
- nulls[attoff] = (isNull) ? 'n' : ' ';
-
- } else if (repl[attoff] != 'r') {
- elog(WARN, "heap_modifytuple: repl is \\%3d", repl[attoff]);
-
- } else { /* == 'r' */
- value[attoff] = replValue[attoff];
- nulls[attoff] = replNull[attoff];
+ int attoff;
+ int numberOfAttributes;
+ Datum *value;
+ char *nulls;
+ bool isNull;
+ HeapTuple newTuple;
+ int madecopy;
+ uint8 infomask;
+
+ /* ----------------
+ * sanity checks
+ * ----------------
+ */
+ Assert(HeapTupleIsValid(tuple));
+ Assert(BufferIsValid(buffer) || RelationIsValid(relation));
+ Assert(HeapTupleIsValid(tuple));
+ Assert(PointerIsValid(replValue));
+ Assert(PointerIsValid(replNull));
+ Assert(PointerIsValid(repl));
+
+ /* ----------------
+ * if we're pointing to a disk page, then first
+ * make a copy of our tuple so that all the attributes
+ * are available. XXX this is inefficient -cim
+ * ----------------
+ */
+ madecopy = 0;
+ if (BufferIsValid(buffer) == true)
+ {
+ relation = (Relation) BufferGetRelation(buffer);
+ tuple = heap_copytuple(tuple);
+ madecopy = 1;
+ }
+
+ numberOfAttributes = RelationGetRelationTupleForm(relation)->relnatts;
+
+ /* ----------------
+ * allocate and fill value[] and nulls[] arrays from either
+ * the tuple or the repl information, as appropriate.
+ * ----------------
+ */
+ value = (Datum *) palloc(numberOfAttributes * sizeof *value);
+ nulls = (char *) palloc(numberOfAttributes * sizeof *nulls);
+
+ for (attoff = 0;
+ attoff < numberOfAttributes;
+ attoff += 1)
+ {
+
+ if (repl[attoff] == ' ')
+ {
+ char *attr;
+
+ attr =
+ heap_getattr(tuple,
+ InvalidBuffer,
+ AttrOffsetGetAttrNumber(attoff),
+ RelationGetTupleDescriptor(relation),
+ &isNull);
+ value[attoff] = PointerGetDatum(attr);
+ nulls[attoff] = (isNull) ? 'n' : ' ';
+
+ }
+ else if (repl[attoff] != 'r')
+ {
+ elog(WARN, "heap_modifytuple: repl is \\%3d", repl[attoff]);
+
+ }
+ else
+ { /* == 'r' */
+ value[attoff] = replValue[attoff];
+ nulls[attoff] = replNull[attoff];
+ }
}
- }
-
- /* ----------------
- * create a new tuple from the values[] and nulls[] arrays
- * ----------------
- */
- newTuple = heap_formtuple(RelationGetTupleDescriptor(relation),
- value,
- nulls);
-
- /* ----------------
- * copy the header except for t_len, t_natts, t_hoff, t_bits, t_infomask
- * ----------------
- */
- infomask = newTuple->t_infomask;
- memmove((char *) &newTuple->t_ctid, /*XXX*/
- (char *) &tuple->t_ctid,
- ((char *) &tuple->t_hoff - (char *) &tuple->t_ctid)); /*XXX*/
- newTuple->t_infomask = infomask;
- newTuple->t_natts = numberOfAttributes; /* fix t_natts just in case */
-
- /* ----------------
- * if we made a copy of the tuple, then free it.
- * ----------------
- */
- if (madecopy)
- pfree(tuple);
-
- return
- newTuple;
+
+ /* ----------------
+ * create a new tuple from the values[] and nulls[] arrays
+ * ----------------
+ */
+ newTuple = heap_formtuple(RelationGetTupleDescriptor(relation),
+ value,
+ nulls);
+
+ /* ----------------
+ * copy the header except for t_len, t_natts, t_hoff, t_bits, t_infomask
+ * ----------------
+ */
+ infomask = newTuple->t_infomask;
+ memmove((char *) &newTuple->t_ctid, /* XXX */
+ (char *) &tuple->t_ctid,
+ ((char *) &tuple->t_hoff - (char *) &tuple->t_ctid)); /* XXX */
+ newTuple->t_infomask = infomask;
+ newTuple->t_natts = numberOfAttributes; /* fix t_natts just in
+ * case */
+
+ /* ----------------
+ * if we made a copy of the tuple, then free it.
+ * ----------------
+ */
+ if (madecopy)
+ pfree(tuple);
+
+ return
+ newTuple;
}
/* ----------------------------------------------------------------
- * other misc functions
+ * other misc functions
* ----------------------------------------------------------------
*/
HeapTuple
heap_addheader(uint32 natts, /* max domain index */
- int structlen, /* its length */
- char *structure) /* pointer to the struct */
+ int structlen, /* its length */
+ char *structure) /* pointer to the struct */
{
- register char *tp; /* tuple data pointer */
- HeapTuple tup;
- long len;
- int hoff;
-
- AssertArg(natts > 0);
-
- len = sizeof (HeapTupleData) - sizeof (tup->t_bits);
-
- hoff = len = DOUBLEALIGN(len); /* be conservative */
- len += structlen;
- tp = (char *) palloc(len);
- tup = (HeapTuple) tp;
- memset((char*)tup, 0, len);
-
- tup->t_len = (short) len; /* XXX */
- tp += tup->t_hoff = hoff;
- tup->t_natts = natts;
- tup->t_infomask = 0;
-
- memmove(tp, structure, structlen);
-
- return (tup);
+ register char *tp; /* tuple data pointer */
+ HeapTuple tup;
+ long len;
+ int hoff;
+
+ AssertArg(natts > 0);
+
+ len = sizeof(HeapTupleData) - sizeof(tup->t_bits);
+
+ hoff = len = DOUBLEALIGN(len); /* be conservative */
+ len += structlen;
+ tp = (char *) palloc(len);
+ tup = (HeapTuple) tp;
+ memset((char *) tup, 0, len);
+
+ tup->t_len = (short) len; /* XXX */
+ tp += tup->t_hoff = hoff;
+ tup->t_natts = natts;
+ tup->t_infomask = 0;
+
+ memmove(tp, structure, structlen);
+
+ return (tup);
}
diff --git a/src/backend/access/common/heapvalid.c b/src/backend/access/common/heapvalid.c
index 186ee654b32..0caeb54e17c 100644
--- a/src/backend/access/common/heapvalid.c
+++ b/src/backend/access/common/heapvalid.c
@@ -1,13 +1,13 @@
/*-------------------------------------------------------------------------
*
* heapvalid.c--
- * heap tuple qualification validity checking code
+ * heap tuple qualification validity checking code
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/common/Attic/heapvalid.c,v 1.16 1997/08/29 09:12:20 vadim Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/common/Attic/heapvalid.c,v 1.17 1997/09/07 04:37:36 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -25,128 +25,138 @@
#include <utils/builtins.h>
/* ----------------
- * heap_keytest
+ * heap_keytest
*
- * Test a heap tuple with respect to a scan key.
+ * Test a heap tuple with respect to a scan key.
* ----------------
*/
bool
heap_keytest(HeapTuple t,
- TupleDesc tupdesc,
- int nkeys,
- ScanKey keys)
+ TupleDesc tupdesc,
+ int nkeys,
+ ScanKey keys)
{
- bool isnull;
- Datum atp;
- int test;
-
- for (; nkeys--; keys++) {
- atp = (Datum)heap_getattr(t, InvalidBuffer,
- keys->sk_attno,
- tupdesc,
- &isnull);
-
- if (isnull)
- /* XXX eventually should check if SK_ISNULL */
- return false;
-
- if (keys->sk_flags & SK_ISNULL) {
- return (false);
+ bool isnull;
+ Datum atp;
+ int test;
+
+ for (; nkeys--; keys++)
+ {
+ atp = (Datum) heap_getattr(t, InvalidBuffer,
+ keys->sk_attno,
+ tupdesc,
+ &isnull);
+
+ if (isnull)
+ /* XXX eventually should check if SK_ISNULL */
+ return false;
+
+ if (keys->sk_flags & SK_ISNULL)
+ {
+ return (false);
+ }
+
+ if (keys->sk_func == (func_ptr) oideq) /* optimization */
+ test = (keys->sk_argument == atp);
+ else if (keys->sk_flags & SK_COMMUTE)
+ test = (long) FMGR_PTR2(keys->sk_func, keys->sk_procedure,
+ keys->sk_argument, atp);
+ else
+ test = (long) FMGR_PTR2(keys->sk_func, keys->sk_procedure,
+ atp, keys->sk_argument);
+
+ if (!test == !(keys->sk_flags & SK_NEGATE))
+ return false;
}
- if (keys->sk_func == (func_ptr)oideq) /* optimization */
- test = (keys->sk_argument == atp);
- else if (keys->sk_flags & SK_COMMUTE)
- test = (long) FMGR_PTR2(keys->sk_func, keys->sk_procedure,
- keys->sk_argument, atp);
- else
- test = (long) FMGR_PTR2(keys->sk_func, keys->sk_procedure,
- atp, keys->sk_argument);
-
- if (!test == !(keys->sk_flags & SK_NEGATE))
- return false;
- }
-
- return true;
+ return true;
}
/* ----------------
- * heap_tuple_satisfies
+ * heap_tuple_satisfies
*
- * Returns a valid HeapTuple if it satisfies the timequal and keytest.
- * Returns NULL otherwise. Used to be heap_satisifies (sic) which
- * returned a boolean. It now returns a tuple so that we can avoid doing two
- * PageGetItem's per tuple.
+ * Returns a valid HeapTuple if it satisfies the timequal and keytest.
+ * Returns NULL otherwise. Used to be heap_satisifies (sic) which
+ * returned a boolean. It now returns a tuple so that we can avoid doing two
+ * PageGetItem's per tuple.
*
- * Complete check of validity including LP_CTUP and keytest.
- * This should perhaps be combined with valid somehow in the
- * future. (Also, additional rule tests/time range tests.)
+ * Complete check of validity including LP_CTUP and keytest.
+ * This should perhaps be combined with valid somehow in the
+ * future. (Also, additional rule tests/time range tests.)
*
- * on 8/21/92 mao says: i rearranged the tests here to do keytest before
- * SatisfiesTimeQual. profiling indicated that even for vacuumed relations,
- * time qual checking was more expensive than key testing. time qual is
- * least likely to fail, too. we should really add the time qual test to
- * the restriction and optimize it in the normal way. this has interactions
- * with joey's expensive function work.
+ * on 8/21/92 mao says: i rearranged the tests here to do keytest before
+ * SatisfiesTimeQual. profiling indicated that even for vacuumed relations,
+ * time qual checking was more expensive than key testing. time qual is
+ * least likely to fail, too. we should really add the time qual test to
+ * the restriction and optimize it in the normal way. this has interactions
+ * with joey's expensive function work.
* ----------------
*/
HeapTuple
heap_tuple_satisfies(ItemId itemId,
- Relation relation,
- Buffer buffer,
- PageHeader disk_page,
- TimeQual qual,
- int nKeys,
- ScanKey key)
+ Relation relation,
+ Buffer buffer,
+ PageHeader disk_page,
+ TimeQual qual,
+ int nKeys,
+ ScanKey key)
{
- HeapTuple tuple, result;
- bool res;
- TransactionId old_tmin, old_tmax;
-
- if (! ItemIdIsUsed(itemId))
- return NULL;
-
- tuple = (HeapTuple) PageGetItem((Page) disk_page, itemId);
-
- if (key != NULL)
- res = heap_keytest(tuple, RelationGetTupleDescriptor(relation),
- nKeys, key);
- else
- res = TRUE;
-
- result = (HeapTuple)NULL;
- if (res) {
- if(relation->rd_rel->relkind == RELKIND_UNCATALOGED) {
- result = tuple;
- } else {
- old_tmin = tuple->t_tmin;
- old_tmax = tuple->t_tmax;
- res = HeapTupleSatisfiesTimeQual(tuple,qual);
- if(tuple->t_tmin != old_tmin ||
- tuple->t_tmax != old_tmax) {
- SetBufferCommitInfoNeedsSave(buffer);
- }
- if(res) {
- result = tuple;
- }
+ HeapTuple tuple,
+ result;
+ bool res;
+ TransactionId old_tmin,
+ old_tmax;
+
+ if (!ItemIdIsUsed(itemId))
+ return NULL;
+
+ tuple = (HeapTuple) PageGetItem((Page) disk_page, itemId);
+
+ if (key != NULL)
+ res = heap_keytest(tuple, RelationGetTupleDescriptor(relation),
+ nKeys, key);
+ else
+ res = TRUE;
+
+ result = (HeapTuple) NULL;
+ if (res)
+ {
+ if (relation->rd_rel->relkind == RELKIND_UNCATALOGED)
+ {
+ result = tuple;
+ }
+ else
+ {
+ old_tmin = tuple->t_tmin;
+ old_tmax = tuple->t_tmax;
+ res = HeapTupleSatisfiesTimeQual(tuple, qual);
+ if (tuple->t_tmin != old_tmin ||
+ tuple->t_tmax != old_tmax)
+ {
+ SetBufferCommitInfoNeedsSave(buffer);
+ }
+ if (res)
+ {
+ result = tuple;
+ }
+ }
}
- }
- return result;
+ return result;
}
/*
- * TupleUpdatedByCurXactAndCmd() -- Returns true if this tuple has
- * already been updated once by the current transaction/command
- * pair.
+ * TupleUpdatedByCurXactAndCmd() -- Returns true if this tuple has
+ * already been updated once by the current transaction/command
+ * pair.
*/
bool
TupleUpdatedByCurXactAndCmd(HeapTuple t)
{
- if (TransactionIdEquals(t->t_xmax,
- GetCurrentTransactionId()) &&
- CommandIdGEScanCommandId (t->t_cmax))
- return true;
-
- return false;
+ if (TransactionIdEquals(t->t_xmax,
+ GetCurrentTransactionId()) &&
+ CommandIdGEScanCommandId(t->t_cmax))
+ return true;
+
+ return false;
}
diff --git a/src/backend/access/common/indextuple.c b/src/backend/access/common/indextuple.c
index a71fc46dc98..c133693801b 100644
--- a/src/backend/access/common/indextuple.c
+++ b/src/backend/access/common/indextuple.c
@@ -1,14 +1,14 @@
/*-------------------------------------------------------------------------
*
* indextuple.c--
- * This file contains index tuple accessor and mutator routines,
- * as well as a few various tuple utilities.
+ * This file contains index tuple accessor and mutator routines,
+ * as well as a few various tuple utilities.
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/common/indextuple.c,v 1.15 1997/08/19 21:28:50 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/common/indextuple.c,v 1.16 1997/09/07 04:37:37 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -21,402 +21,438 @@
#include <access/tupmacs.h>
#ifndef HAVE_MEMMOVE
-# include <regex/utils.h>
+#include <regex/utils.h>
#else
-# include <string.h>
+#include <string.h>
#endif
-static Size IndexInfoFindDataOffset(unsigned short t_info);
-static char *fastgetiattr(IndexTuple tup, int attnum,
- TupleDesc att, bool *isnull);
+static Size IndexInfoFindDataOffset(unsigned short t_info);
+static char *
+fastgetiattr(IndexTuple tup, int attnum,
+ TupleDesc att, bool * isnull);
/* ----------------------------------------------------------------
- * index_ tuple interface routines
+ * index_ tuple interface routines
* ----------------------------------------------------------------
*/
/* ----------------
- * index_formtuple
+ * index_formtuple
* ----------------
*/
IndexTuple
index_formtuple(TupleDesc tupleDescriptor,
- Datum value[],
- char null[])
+ Datum value[],
+ char null[])
{
- register char *tp; /* tuple pointer */
- IndexTuple tuple; /* return tuple */
- Size size, hoff;
- int i;
- unsigned short infomask = 0;
- bool hasnull = false;
- char tupmask = 0;
- int numberOfAttributes = tupleDescriptor->natts;
-
- if (numberOfAttributes > MaxIndexAttributeNumber)
- elog(WARN, "index_formtuple: numberOfAttributes of %d > %d",
- numberOfAttributes, MaxIndexAttributeNumber);
-
-
- for (i = 0; i < numberOfAttributes && !hasnull; i++) {
- if (null[i] != ' ') hasnull = true;
- }
-
- if (hasnull) infomask |= INDEX_NULL_MASK;
-
- hoff = IndexInfoFindDataOffset(infomask);
- size = hoff
- + ComputeDataSize(tupleDescriptor,
- value, null);
- size = DOUBLEALIGN(size); /* be conservative */
-
- tp = (char *) palloc(size);
- tuple = (IndexTuple) tp;
- memset(tp,0,(int)size);
-
- DataFill((char *)tp + hoff,
- tupleDescriptor,
- value,
- null,
- &tupmask,
- (hasnull ? (bits8*)tp + sizeof(*tuple) : NULL));
-
- /*
- * We do this because DataFill wants to initialize a "tupmask" which
- * is used for HeapTuples, but we want an indextuple infomask. The only
- * "relevent" info is the "has variable attributes" field, which is in
- * mask position 0x02. We have already set the null mask above.
- */
-
- if (tupmask & 0x02) infomask |= INDEX_VAR_MASK;
-
- /*
- * Here we make sure that we can actually hold the size. We also want
- * to make sure that size is not aligned oddly. This actually is a
- * rather odd way to make sure the size is not too large overall.
- */
-
- if (size & 0xE000)
- elog(WARN, "index_formtuple: data takes %d bytes: too big", size);
-
-
- infomask |= size;
-
- /* ----------------
- * initialize metadata
- * ----------------
- */
- tuple->t_info = infomask;
- return (tuple);
+ register char *tp; /* tuple pointer */
+ IndexTuple tuple; /* return tuple */
+ Size size,
+ hoff;
+ int i;
+ unsigned short infomask = 0;
+ bool hasnull = false;
+ char tupmask = 0;
+ int numberOfAttributes = tupleDescriptor->natts;
+
+ if (numberOfAttributes > MaxIndexAttributeNumber)
+ elog(WARN, "index_formtuple: numberOfAttributes of %d > %d",
+ numberOfAttributes, MaxIndexAttributeNumber);
+
+
+ for (i = 0; i < numberOfAttributes && !hasnull; i++)
+ {
+ if (null[i] != ' ')
+ hasnull = true;
+ }
+
+ if (hasnull)
+ infomask |= INDEX_NULL_MASK;
+
+ hoff = IndexInfoFindDataOffset(infomask);
+ size = hoff
+ + ComputeDataSize(tupleDescriptor,
+ value, null);
+ size = DOUBLEALIGN(size); /* be conservative */
+
+ tp = (char *) palloc(size);
+ tuple = (IndexTuple) tp;
+ memset(tp, 0, (int) size);
+
+ DataFill((char *) tp + hoff,
+ tupleDescriptor,
+ value,
+ null,
+ &tupmask,
+ (hasnull ? (bits8 *) tp + sizeof(*tuple) : NULL));
+
+ /*
+ * We do this because DataFill wants to initialize a "tupmask" which
+ * is used for HeapTuples, but we want an indextuple infomask. The
+ * only "relevent" info is the "has variable attributes" field, which
+ * is in mask position 0x02. We have already set the null mask above.
+ */
+
+ if (tupmask & 0x02)
+ infomask |= INDEX_VAR_MASK;
+
+ /*
+ * Here we make sure that we can actually hold the size. We also want
+ * to make sure that size is not aligned oddly. This actually is a
+ * rather odd way to make sure the size is not too large overall.
+ */
+
+ if (size & 0xE000)
+ elog(WARN, "index_formtuple: data takes %d bytes: too big", size);
+
+
+ infomask |= size;
+
+ /* ----------------
+ * initialize metadata
+ * ----------------
+ */
+ tuple->t_info = infomask;
+ return (tuple);
}
/* ----------------
- * fastgetiattr
+ * fastgetiattr
*
- * This is a newer version of fastgetiattr which attempts to be
- * faster by caching attribute offsets in the attribute descriptor.
+ * This is a newer version of fastgetiattr which attempts to be
+ * faster by caching attribute offsets in the attribute descriptor.
*
- * an alternate way to speed things up would be to cache offsets
- * with the tuple, but that seems more difficult unless you take
- * the storage hit of actually putting those offsets into the
- * tuple you send to disk. Yuck.
+ * an alternate way to speed things up would be to cache offsets
+ * with the tuple, but that seems more difficult unless you take
+ * the storage hit of actually putting those offsets into the
+ * tuple you send to disk. Yuck.
*
- * This scheme will be slightly slower than that, but should
- * preform well for queries which hit large #'s of tuples. After
- * you cache the offsets once, examining all the other tuples using
- * the same attribute descriptor will go much quicker. -cim 5/4/91
+ * This scheme will be slightly slower than that, but should
+ * preform well for queries which hit large #'s of tuples. After
+ * you cache the offsets once, examining all the other tuples using
+ * the same attribute descriptor will go much quicker. -cim 5/4/91
* ----------------
*/
-static char *
+static char *
fastgetiattr(IndexTuple tup,
- int attnum,
- TupleDesc tupleDesc,
- bool *isnull)
+ int attnum,
+ TupleDesc tupleDesc,
+ bool * isnull)
{
- register char *tp; /* ptr to att in tuple */
- register char *bp = NULL; /* ptr to att in tuple */
- int slow; /* do we have to walk nulls? */
- register int data_off; /* tuple data offset */
- AttributeTupleForm *att = tupleDesc->attrs;
-
- /* ----------------
- * sanity checks
- * ----------------
- */
-
- Assert(PointerIsValid(isnull));
- Assert(attnum > 0);
-
- /* ----------------
- * Three cases:
- *
- * 1: No nulls and no variable length attributes.
- * 2: Has a null or a varlena AFTER att.
- * 3: Has nulls or varlenas BEFORE att.
- * ----------------
- */
-
- *isnull = false;
- data_off = IndexTupleHasMinHeader(tup) ? sizeof *tup :
- IndexInfoFindDataOffset(tup->t_info);
-
- if (IndexTupleNoNulls(tup)) {
-
- /* first attribute is always at position zero */
-
- if (attnum == 1) {
- return(fetchatt(&(att[0]), (char *) tup + data_off));
- }
- attnum--;
-
- if (att[attnum]->attcacheoff > 0) {
- return(fetchatt(&(att[attnum]),
- (char *) tup + data_off +
- att[attnum]->attcacheoff));
- }
-
- tp = (char *) tup + data_off;
-
- slow = 0;
- }else { /* there's a null somewhere in the tuple */
-
- bp = (char *) tup + sizeof(*tup); /* "knows" t_bits are here! */
- slow = 0;
+ register char *tp; /* ptr to att in tuple */
+ register char *bp = NULL; /* ptr to att in tuple */
+ int slow; /* do we have to walk nulls? */
+ register int data_off; /* tuple data offset */
+ AttributeTupleForm *att = tupleDesc->attrs;
+
/* ----------------
- * check to see if desired att is null
+ * sanity checks
* ----------------
*/
-
- attnum--;
- {
- if (att_isnull(attnum, bp)) {
- *isnull = true;
- return NULL;
- }
- }
+
+ Assert(PointerIsValid(isnull));
+ Assert(attnum > 0);
+
/* ----------------
- * Now check to see if any preceeding bits are null...
+ * Three cases:
+ *
+ * 1: No nulls and no variable length attributes.
+ * 2: Has a null or a varlena AFTER att.
+ * 3: Has nulls or varlenas BEFORE att.
* ----------------
*/
+
+ *isnull = false;
+ data_off = IndexTupleHasMinHeader(tup) ? sizeof *tup :
+ IndexInfoFindDataOffset(tup->t_info);
+
+ if (IndexTupleNoNulls(tup))
{
- register int i = 0; /* current offset in bp */
- register int mask; /* bit in byte we're looking at */
- register char n; /* current byte in bp */
- register int byte, finalbit;
-
- byte = attnum >> 3;
- finalbit = attnum & 0x07;
-
- for (; i <= byte; i++) {
- n = bp[i];
- if (i < byte) {
- /* check for nulls in any "earlier" bytes */
- if ((~n) != 0) {
- slow++;
- break;
- }
- } else {
- /* check for nulls "before" final bit of last byte*/
- mask = (finalbit << 1) - 1;
- if ((~n) & mask)
- slow++;
+
+ /* first attribute is always at position zero */
+
+ if (attnum == 1)
+ {
+ return (fetchatt(&(att[0]), (char *) tup + data_off));
+ }
+ attnum--;
+
+ if (att[attnum]->attcacheoff > 0)
+ {
+ return (fetchatt(&(att[attnum]),
+ (char *) tup + data_off +
+ att[attnum]->attcacheoff));
}
- }
+
+ tp = (char *) tup + data_off;
+
+ slow = 0;
}
- tp = (char *) tup + data_off;
- }
-
- /* now check for any non-fixed length attrs before our attribute */
-
- if (!slow) {
- if (att[attnum]->attcacheoff > 0) {
- return(fetchatt(&(att[attnum]),
- tp + att[attnum]->attcacheoff));
- }else if (!IndexTupleAllFixed(tup)) {
- register int j = 0;
-
- for (j = 0; j < attnum && !slow; j++)
- if (att[j]->attlen < 1) slow = 1;
+ else
+ { /* there's a null somewhere in the tuple */
+
+ bp = (char *) tup + sizeof(*tup); /* "knows" t_bits are
+ * here! */
+ slow = 0;
+ /* ----------------
+ * check to see if desired att is null
+ * ----------------
+ */
+
+ attnum--;
+ {
+ if (att_isnull(attnum, bp))
+ {
+ *isnull = true;
+ return NULL;
+ }
+ }
+ /* ----------------
+ * Now check to see if any preceeding bits are null...
+ * ----------------
+ */
+ {
+ register int i = 0; /* current offset in bp */
+ register int mask; /* bit in byte we're looking at */
+ register char n; /* current byte in bp */
+ register int byte,
+ finalbit;
+
+ byte = attnum >> 3;
+ finalbit = attnum & 0x07;
+
+ for (; i <= byte; i++)
+ {
+ n = bp[i];
+ if (i < byte)
+ {
+ /* check for nulls in any "earlier" bytes */
+ if ((~n) != 0)
+ {
+ slow++;
+ break;
+ }
+ }
+ else
+ {
+ /* check for nulls "before" final bit of last byte */
+ mask = (finalbit << 1) - 1;
+ if ((~n) & mask)
+ slow++;
+ }
+ }
+ }
+ tp = (char *) tup + data_off;
}
- }
-
- /*
- * if slow is zero, and we got here, we know that we have a tuple with
- * no nulls. We also know that we have to initialize the remainder of
- * the attribute cached offset values.
- */
-
- if (!slow) {
- register int j = 1;
- register long off;
-
- /*
- * need to set cache for some atts
- */
-
- att[0]->attcacheoff = 0;
-
- while (att[j]->attcacheoff > 0) j++;
-
- off = att[j-1]->attcacheoff +
- att[j-1]->attlen;
-
- for (; j < attnum + 1; j++) {
- /*
- * Fix me when going to a machine with more than a four-byte
- * word!
- */
-
- switch(att[j]->attlen)
+
+ /* now check for any non-fixed length attrs before our attribute */
+
+ if (!slow)
+ {
+ if (att[attnum]->attcacheoff > 0)
{
- case -1:
- off = (att[j]->attalign=='d')?
- DOUBLEALIGN(off):INTALIGN(off);
- break;
- case sizeof(char):
- break;
- case sizeof(short):
- off = SHORTALIGN(off);
- break;
- case sizeof(int32):
- off = INTALIGN(off);
- break;
- default:
- if (att[j]->attlen > sizeof(int32))
- off = (att[j]->attalign=='d')?
- DOUBLEALIGN(off) : LONGALIGN(off);
- else
- elog(WARN, "fastgetiattr: attribute %d has len %d",
- j, att[j]->attlen);
- break;
-
+ return (fetchatt(&(att[attnum]),
+ tp + att[attnum]->attcacheoff));
+ }
+ else if (!IndexTupleAllFixed(tup))
+ {
+ register int j = 0;
+
+ for (j = 0; j < attnum && !slow; j++)
+ if (att[j]->attlen < 1)
+ slow = 1;
}
-
- att[j]->attcacheoff = off;
- off += att[j]->attlen;
}
-
- return(fetchatt( &(att[attnum]),
- tp + att[attnum]->attcacheoff));
- }else {
- register bool usecache = true;
- register int off = 0;
- register int i;
-
+
/*
- * Now we know that we have to walk the tuple CAREFULLY.
+ * if slow is zero, and we got here, we know that we have a tuple with
+ * no nulls. We also know that we have to initialize the remainder of
+ * the attribute cached offset values.
*/
-
- for (i = 0; i < attnum; i++) {
- if (!IndexTupleNoNulls(tup)) {
- if (att_isnull(i, bp)) {
- usecache = false;
- continue;
+
+ if (!slow)
+ {
+ register int j = 1;
+ register long off;
+
+ /*
+ * need to set cache for some atts
+ */
+
+ att[0]->attcacheoff = 0;
+
+ while (att[j]->attcacheoff > 0)
+ j++;
+
+ off = att[j - 1]->attcacheoff +
+ att[j - 1]->attlen;
+
+ for (; j < attnum + 1; j++)
+ {
+
+ /*
+ * Fix me when going to a machine with more than a four-byte
+ * word!
+ */
+
+ switch (att[j]->attlen)
+ {
+ case -1:
+ off = (att[j]->attalign == 'd') ?
+ DOUBLEALIGN(off) : INTALIGN(off);
+ break;
+ case sizeof(char):
+ break;
+ case sizeof(short):
+ off = SHORTALIGN(off);
+ break;
+ case sizeof(int32):
+ off = INTALIGN(off);
+ break;
+ default:
+ if (att[j]->attlen > sizeof(int32))
+ off = (att[j]->attalign == 'd') ?
+ DOUBLEALIGN(off) : LONGALIGN(off);
+ else
+ elog(WARN, "fastgetiattr: attribute %d has len %d",
+ j, att[j]->attlen);
+ break;
+
+ }
+
+ att[j]->attcacheoff = off;
+ off += att[j]->attlen;
}
- }
-
- if (usecache && att[i]->attcacheoff > 0) {
- off = att[i]->attcacheoff;
- if (att[i]->attlen == -1)
- usecache = false;
- else
- continue;
- }
-
- if (usecache) att[i]->attcacheoff = off;
- switch(att[i]->attlen)
+
+ return (fetchatt(&(att[attnum]),
+ tp + att[attnum]->attcacheoff));
+ }
+ else
+ {
+ register bool usecache = true;
+ register int off = 0;
+ register int i;
+
+ /*
+ * Now we know that we have to walk the tuple CAREFULLY.
+ */
+
+ for (i = 0; i < attnum; i++)
{
+ if (!IndexTupleNoNulls(tup))
+ {
+ if (att_isnull(i, bp))
+ {
+ usecache = false;
+ continue;
+ }
+ }
+
+ if (usecache && att[i]->attcacheoff > 0)
+ {
+ off = att[i]->attcacheoff;
+ if (att[i]->attlen == -1)
+ usecache = false;
+ else
+ continue;
+ }
+
+ if (usecache)
+ att[i]->attcacheoff = off;
+ switch (att[i]->attlen)
+ {
+ case sizeof(char):
+ off++;
+ break;
+ case sizeof(short):
+ off = SHORTALIGN(off) +sizeof(short);
+ break;
+ case sizeof(int32):
+ off = INTALIGN(off) + sizeof(int32);
+ break;
+ case -1:
+ usecache = false;
+ off = (att[i]->attalign == 'd') ?
+ DOUBLEALIGN(off) : INTALIGN(off);
+ off += VARSIZE(tp + off);
+ break;
+ default:
+ if (att[i]->attlen > sizeof(int32))
+ off = (att[i]->attalign == 'd') ?
+ DOUBLEALIGN(off) + att[i]->attlen :
+ LONGALIGN(off) + att[i]->attlen;
+ else
+ elog(WARN, "fastgetiattr2: attribute %d has len %d",
+ i, att[i]->attlen);
+
+ break;
+ }
+ }
+
+ /*
+ * I don't know why this code was missed here! I've got it from
+ * heaptuple.c:fastgetattr(). - vadim 06/12/97
+ */
+ switch (att[attnum]->attlen)
+ {
+ case -1:
+ off = (att[attnum]->attalign == 'd') ?
+ DOUBLEALIGN(off) : INTALIGN(off);
+ break;
case sizeof(char):
- off++;
- break;
+ break;
case sizeof(short):
- off = SHORTALIGN(off) + sizeof(short);
- break;
+ off = SHORTALIGN(off);
+ break;
case sizeof(int32):
- off = INTALIGN(off) + sizeof(int32);
- break;
- case -1:
- usecache = false;
- off = (att[i]->attalign=='d')?
- DOUBLEALIGN(off):INTALIGN(off);
- off += VARSIZE(tp + off);
- break;
+ off = INTALIGN(off);
+ break;
default:
- if (att[i]->attlen > sizeof(int32))
- off = (att[i]->attalign=='d') ?
- DOUBLEALIGN(off) + att[i]->attlen :
- LONGALIGN(off) + att[i]->attlen;
- else
- elog(WARN, "fastgetiattr2: attribute %d has len %d",
- i, att[i]->attlen);
-
- break;
+ if (att[attnum]->attlen < sizeof(int32))
+ elog(WARN, "fastgetattr3: attribute %d has len %d",
+ attnum, att[attnum]->attlen);
+ if (att[attnum]->attalign == 'd')
+ off = DOUBLEALIGN(off);
+ else
+ off = LONGALIGN(off);
+ break;
}
+
+ return (fetchatt(&att[attnum], tp + off));
}
- /*
- * I don't know why this code was missed here!
- * I've got it from heaptuple.c:fastgetattr().
- * - vadim 06/12/97
- */
- switch (att[attnum]->attlen) {
- case -1:
- off = (att[attnum]->attalign=='d')?
- DOUBLEALIGN(off) : INTALIGN(off);
- break;
- case sizeof(char):
- break;
- case sizeof(short):
- off = SHORTALIGN(off);
- break;
- case sizeof(int32):
- off = INTALIGN(off);
- break;
- default:
- if (att[attnum]->attlen < sizeof(int32))
- elog(WARN, "fastgetattr3: attribute %d has len %d",
- attnum, att[attnum]->attlen);
- if (att[attnum]->attalign == 'd')
- off = DOUBLEALIGN(off);
- else
- off = LONGALIGN(off);
- break;
- }
-
- return(fetchatt(&att[attnum], tp + off));
- }
}
/* ----------------
- * index_getattr
+ * index_getattr
* ----------------
*/
Datum
index_getattr(IndexTuple tuple,
- AttrNumber attNum,
- TupleDesc tupDesc,
- bool *isNullOutP)
+ AttrNumber attNum,
+ TupleDesc tupDesc,
+ bool * isNullOutP)
{
- Assert (attNum > 0);
+ Assert(attNum > 0);
- return (Datum)
- fastgetiattr(tuple, attNum, tupDesc, isNullOutP);
+ return (Datum)
+ fastgetiattr(tuple, attNum, tupDesc, isNullOutP);
}
RetrieveIndexResult
FormRetrieveIndexResult(ItemPointer indexItemPointer,
- ItemPointer heapItemPointer)
+ ItemPointer heapItemPointer)
{
- RetrieveIndexResult result;
-
- Assert(ItemPointerIsValid(indexItemPointer));
- Assert(ItemPointerIsValid(heapItemPointer));
-
- result = (RetrieveIndexResult) palloc(sizeof *result);
-
- result->index_iptr = *indexItemPointer;
- result->heap_iptr = *heapItemPointer;
-
- return (result);
+ RetrieveIndexResult result;
+
+ Assert(ItemPointerIsValid(indexItemPointer));
+ Assert(ItemPointerIsValid(heapItemPointer));
+
+ result = (RetrieveIndexResult) palloc(sizeof *result);
+
+ result->index_iptr = *indexItemPointer;
+ result->heap_iptr = *heapItemPointer;
+
+ return (result);
}
/*
@@ -425,19 +461,21 @@ FormRetrieveIndexResult(ItemPointer indexItemPointer,
*
* Change me if adding an attribute to IndexTuples!!!!!!!!!!!
*/
-static Size
+static Size
IndexInfoFindDataOffset(unsigned short t_info)
{
- if (!(t_info & INDEX_NULL_MASK))
- return((Size) sizeof(IndexTupleData));
- else {
- Size size = sizeof(IndexTupleData);
-
- if (t_info & INDEX_NULL_MASK) {
- size += sizeof(IndexAttributeBitMapData);
+ if (!(t_info & INDEX_NULL_MASK))
+ return ((Size) sizeof(IndexTupleData));
+ else
+ {
+ Size size = sizeof(IndexTupleData);
+
+ if (t_info & INDEX_NULL_MASK)
+ {
+ size += sizeof(IndexAttributeBitMapData);
+ }
+ return DOUBLEALIGN(size); /* be conservative */
}
- return DOUBLEALIGN(size); /* be conservative */
- }
}
/*
@@ -445,17 +483,17 @@ IndexInfoFindDataOffset(unsigned short t_info)
* we assume we have space that is already palloc'ed.
*/
void
-CopyIndexTuple(IndexTuple source, IndexTuple *target)
+CopyIndexTuple(IndexTuple source, IndexTuple * target)
{
- Size size;
- IndexTuple ret;
-
- size = IndexTupleSize(source);
- if (*target == NULL) {
- *target = (IndexTuple) palloc(size);
- }
-
- ret = *target;
- memmove((char*)ret, (char*)source, size);
-}
+ Size size;
+ IndexTuple ret;
+
+ size = IndexTupleSize(source);
+ if (*target == NULL)
+ {
+ *target = (IndexTuple) palloc(size);
+ }
+ ret = *target;
+ memmove((char *) ret, (char *) source, size);
+}
diff --git a/src/backend/access/common/indexvalid.c b/src/backend/access/common/indexvalid.c
index aff9af42f8d..9f8501beb2e 100644
--- a/src/backend/access/common/indexvalid.c
+++ b/src/backend/access/common/indexvalid.c
@@ -1,13 +1,13 @@
/*-------------------------------------------------------------------------
*
* indexvalid.c--
- * index tuple qualification validity checking code
+ * index tuple qualification validity checking code
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/common/Attic/indexvalid.c,v 1.14 1997/03/18 18:38:19 scrappy Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/common/Attic/indexvalid.c,v 1.15 1997/09/07 04:37:38 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -21,64 +21,70 @@
#include <executor/execdebug.h>
/* ----------------------------------------------------------------
- * index scan key qualification code
+ * index scan key qualification code
* ----------------------------------------------------------------
*/
-int NIndexTupleProcessed;
+int NIndexTupleProcessed;
/* ----------------
- * index_keytest
+ * index_keytest
*
* old comments
- * May eventually combine with other tests (like timeranges)?
- * Should have Buffer buffer; as an argument and pass it to amgetattr.
+ * May eventually combine with other tests (like timeranges)?
+ * Should have Buffer buffer; as an argument and pass it to amgetattr.
* ----------------
*/
bool
index_keytest(IndexTuple tuple,
- TupleDesc tupdesc,
- int scanKeySize,
- ScanKey key)
+ TupleDesc tupdesc,
+ int scanKeySize,
+ ScanKey key)
{
- bool isNull;
- Datum datum;
- int test;
-
- IncrIndexProcessed();
-
- while (scanKeySize > 0) {
- datum = index_getattr(tuple,
- key[0].sk_attno,
- tupdesc,
- &isNull);
-
- if (isNull) {
- /* XXX eventually should check if SK_ISNULL */
- return (false);
- }
-
- if (key[0].sk_flags & SK_ISNULL) {
- return (false);
- }
+ bool isNull;
+ Datum datum;
+ int test;
- if (key[0].sk_flags & SK_COMMUTE) {
- test = (*(key[0].sk_func))
- (DatumGetPointer(key[0].sk_argument),
- datum) ? 1 : 0;
- } else {
- test = (*(key[0].sk_func))
- (datum,
- DatumGetPointer(key[0].sk_argument)) ? 1 : 0;
- }
-
- if (!test == !(key[0].sk_flags & SK_NEGATE)) {
- return (false);
+ IncrIndexProcessed();
+
+ while (scanKeySize > 0)
+ {
+ datum = index_getattr(tuple,
+ key[0].sk_attno,
+ tupdesc,
+ &isNull);
+
+ if (isNull)
+ {
+ /* XXX eventually should check if SK_ISNULL */
+ return (false);
+ }
+
+ if (key[0].sk_flags & SK_ISNULL)
+ {
+ return (false);
+ }
+
+ if (key[0].sk_flags & SK_COMMUTE)
+ {
+ test = (*(key[0].sk_func))
+ (DatumGetPointer(key[0].sk_argument),
+ datum) ? 1 : 0;
+ }
+ else
+ {
+ test = (*(key[0].sk_func))
+ (datum,
+ DatumGetPointer(key[0].sk_argument)) ? 1 : 0;
+ }
+
+ if (!test == !(key[0].sk_flags & SK_NEGATE))
+ {
+ return (false);
+ }
+
+ scanKeySize -= 1;
+ key++;
}
-
- scanKeySize -= 1;
- key++;
- }
-
- return (true);
-}
+ return (true);
+}
diff --git a/src/backend/access/common/printtup.c b/src/backend/access/common/printtup.c
index 98fbddc639d..599ac59a455 100644
--- a/src/backend/access/common/printtup.c
+++ b/src/backend/access/common/printtup.c
@@ -1,14 +1,14 @@
/*-------------------------------------------------------------------------
*
* printtup.c--
- * Routines to print out tuples to the destination (binary or non-binary
- * portals, frontend/interactive backend, etc.).
+ * Routines to print out tuples to the destination (binary or non-binary
+ * portals, frontend/interactive backend, etc.).
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.15 1997/08/26 23:31:23 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.16 1997/09/07 04:37:39 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -16,279 +16,304 @@
#include <string.h>
#include <postgres.h>
-#include <fmgr.h>
-#include <access/heapam.h>
-#include <access/printtup.h>
+#include <fmgr.h>
+#include <access/heapam.h>
+#include <access/printtup.h>
#include <catalog/pg_type.h>
#include <libpq/libpq.h>
#include <utils/syscache.h>
/* ----------------------------------------------------------------
- * printtup / debugtup support
+ * printtup / debugtup support
* ----------------------------------------------------------------
*/
/* ----------------
- * typtoout - used by printtup and debugtup
+ * typtoout - used by printtup and debugtup
* ----------------
*/
Oid
typtoout(Oid type)
{
- HeapTuple typeTuple;
-
- typeTuple = SearchSysCacheTuple(TYPOID,
- ObjectIdGetDatum(type),
- 0, 0, 0);
-
- if (HeapTupleIsValid(typeTuple))
- return((Oid)
- ((TypeTupleForm) GETSTRUCT(typeTuple))->typoutput);
-
- elog(WARN, "typtoout: Cache lookup of type %d failed", type);
- return(InvalidOid);
+ HeapTuple typeTuple;
+
+ typeTuple = SearchSysCacheTuple(TYPOID,
+ ObjectIdGetDatum(type),
+ 0, 0, 0);
+
+ if (HeapTupleIsValid(typeTuple))
+ return ((Oid)
+ ((TypeTupleForm) GETSTRUCT(typeTuple))->typoutput);
+
+ elog(WARN, "typtoout: Cache lookup of type %d failed", type);
+ return (InvalidOid);
}
Oid
gettypelem(Oid type)
{
- HeapTuple typeTuple;
-
- typeTuple = SearchSysCacheTuple(TYPOID,
- ObjectIdGetDatum(type),
- 0,0,0);
-
- if (HeapTupleIsValid(typeTuple))
- return((Oid)
- ((TypeTupleForm) GETSTRUCT(typeTuple))->typelem);
-
- elog(WARN, "typtoout: Cache lookup of type %d failed", type);
- return(InvalidOid);
+ HeapTuple typeTuple;
+
+ typeTuple = SearchSysCacheTuple(TYPOID,
+ ObjectIdGetDatum(type),
+ 0, 0, 0);
+
+ if (HeapTupleIsValid(typeTuple))
+ return ((Oid)
+ ((TypeTupleForm) GETSTRUCT(typeTuple))->typelem);
+
+ elog(WARN, "typtoout: Cache lookup of type %d failed", type);
+ return (InvalidOid);
}
/* ----------------
- * printtup
+ * printtup
* ----------------
*/
void
printtup(HeapTuple tuple, TupleDesc typeinfo)
{
- int i, j, k;
- char *outputstr, *attr;
- bool isnull;
- Oid typoutput;
-
- /* ----------------
- * tell the frontend to expect new tuple data
- * ----------------
- */
- pq_putnchar("D", 1);
-
- /* ----------------
- * send a bitmap of which attributes are null
- * ----------------
- */
- j = 0;
- k = 1 << 7;
- for (i = 0; i < tuple->t_natts; ) {
- i++; /* heap_getattr is a macro, so no increment */
- attr = heap_getattr(tuple, InvalidBuffer, i, typeinfo, &isnull);
- if (!isnull)
- j |= k;
- k >>= 1;
- if (!(i & 7)) {
- pq_putint(j, 1);
- j = 0;
- k = 1 << 7;
+ int i,
+ j,
+ k;
+ char *outputstr,
+ *attr;
+ bool isnull;
+ Oid typoutput;
+
+ /* ----------------
+ * tell the frontend to expect new tuple data
+ * ----------------
+ */
+ pq_putnchar("D", 1);
+
+ /* ----------------
+ * send a bitmap of which attributes are null
+ * ----------------
+ */
+ j = 0;
+ k = 1 << 7;
+ for (i = 0; i < tuple->t_natts;)
+ {
+ i++; /* heap_getattr is a macro, so no
+ * increment */
+ attr = heap_getattr(tuple, InvalidBuffer, i, typeinfo, &isnull);
+ if (!isnull)
+ j |= k;
+ k >>= 1;
+ if (!(i & 7))
+ {
+ pq_putint(j, 1);
+ j = 0;
+ k = 1 << 7;
+ }
}
- }
- if (i & 7)
- pq_putint(j, 1);
-
- /* ----------------
- * send the attributes of this tuple
- * ----------------
- */
- for (i = 0; i < tuple->t_natts; ++i) {
- attr = heap_getattr(tuple, InvalidBuffer, i+1, typeinfo, &isnull);
- typoutput = typtoout((Oid) typeinfo->attrs[i]->atttypid);
-
- if (!isnull && OidIsValid(typoutput)) {
- outputstr = fmgr(typoutput, attr,
- gettypelem(typeinfo->attrs[i]->atttypid));
- pq_putint(strlen(outputstr)+4, 4);
- pq_putnchar(outputstr, strlen(outputstr));
- pfree(outputstr);
+ if (i & 7)
+ pq_putint(j, 1);
+
+ /* ----------------
+ * send the attributes of this tuple
+ * ----------------
+ */
+ for (i = 0; i < tuple->t_natts; ++i)
+ {
+ attr = heap_getattr(tuple, InvalidBuffer, i + 1, typeinfo, &isnull);
+ typoutput = typtoout((Oid) typeinfo->attrs[i]->atttypid);
+
+ if (!isnull && OidIsValid(typoutput))
+ {
+ outputstr = fmgr(typoutput, attr,
+ gettypelem(typeinfo->attrs[i]->atttypid));
+ pq_putint(strlen(outputstr) + 4, 4);
+ pq_putnchar(outputstr, strlen(outputstr));
+ pfree(outputstr);
+ }
}
- }
}
/* ----------------
- * printatt
+ * printatt
* ----------------
*/
static void
printatt(unsigned attributeId,
- AttributeTupleForm attributeP,
- char *value)
+ AttributeTupleForm attributeP,
+ char *value)
{
- printf("\t%2d: %s%s%s%s\t(typeid = %u, len = %d, byval = %c)\n",
- attributeId,
- attributeP->attname.data,
- value != NULL ? " = \"" : "",
- value != NULL ? value : "",
- value != NULL ? "\"" : "",
- (unsigned int) (attributeP->atttypid),
- attributeP->attlen,
- attributeP->attbyval ? 't' : 'f');
+ printf("\t%2d: %s%s%s%s\t(typeid = %u, len = %d, byval = %c)\n",
+ attributeId,
+ attributeP->attname.data,
+ value != NULL ? " = \"" : "",
+ value != NULL ? value : "",
+ value != NULL ? "\"" : "",
+ (unsigned int) (attributeP->atttypid),
+ attributeP->attlen,
+ attributeP->attbyval ? 't' : 'f');
}
/* ----------------
- * showatts
+ * showatts
* ----------------
*/
void
showatts(char *name, TupleDesc tupleDesc)
{
- int i;
- int natts = tupleDesc->natts;
- AttributeTupleForm *attinfo = tupleDesc->attrs;
+ int i;
+ int natts = tupleDesc->natts;
+ AttributeTupleForm *attinfo = tupleDesc->attrs;
- puts(name);
- for (i = 0; i < natts; ++i)
- printatt((unsigned) i+1, attinfo[i], (char *) NULL);
- printf("\t----\n");
+ puts(name);
+ for (i = 0; i < natts; ++i)
+ printatt((unsigned) i + 1, attinfo[i], (char *) NULL);
+ printf("\t----\n");
}
/* ----------------
- * debugtup
+ * debugtup
* ----------------
*/
void
debugtup(HeapTuple tuple, TupleDesc typeinfo)
{
- register int i;
- char *attr, *value;
- bool isnull;
- Oid typoutput;
-
- for (i = 0; i < tuple->t_natts; ++i) {
- attr = heap_getattr(tuple, InvalidBuffer, i+1, typeinfo, &isnull);
- typoutput = typtoout((Oid) typeinfo->attrs[i]->atttypid);
-
- if (!isnull && OidIsValid(typoutput)) {
- value = fmgr(typoutput, attr,
- gettypelem(typeinfo->attrs[i]->atttypid));
- printatt((unsigned) i+1, typeinfo->attrs[i], value);
- pfree(value);
+ register int i;
+ char *attr,
+ *value;
+ bool isnull;
+ Oid typoutput;
+
+ for (i = 0; i < tuple->t_natts; ++i)
+ {
+ attr = heap_getattr(tuple, InvalidBuffer, i + 1, typeinfo, &isnull);
+ typoutput = typtoout((Oid) typeinfo->attrs[i]->atttypid);
+
+ if (!isnull && OidIsValid(typoutput))
+ {
+ value = fmgr(typoutput, attr,
+ gettypelem(typeinfo->attrs[i]->atttypid));
+ printatt((unsigned) i + 1, typeinfo->attrs[i], value);
+ pfree(value);
+ }
}
- }
- printf("\t----\n");
+ printf("\t----\n");
}
/* ----------------
- * printtup_internal
- * Protocol expects either T, D, C, E, or N.
- * We use a different data prefix, e.g. 'B' instead of 'D' to
- * indicate a tuple in internal (binary) form.
+ * printtup_internal
+ * Protocol expects either T, D, C, E, or N.
+ * We use a different data prefix, e.g. 'B' instead of 'D' to
+ * indicate a tuple in internal (binary) form.
*
- * This is same as printtup, except we don't use the typout func.
+ * This is same as printtup, except we don't use the typout func.
* ----------------
*/
void
printtup_internal(HeapTuple tuple, TupleDesc typeinfo)
{
- int i, j, k;
- char *attr;
- bool isnull;
-
- /* ----------------
- * tell the frontend to expect new tuple data
- * ----------------
- */
- pq_putnchar("B", 1);
-
- /* ----------------
- * send a bitmap of which attributes are null
- * ----------------
- */
- j = 0;
- k = 1 << 7;
- for (i = 0; i < tuple->t_natts; ) {
- i++; /* heap_getattr is a macro, so no increment */
- attr = heap_getattr(tuple, InvalidBuffer, i, typeinfo, &isnull);
- if (!isnull)
- j |= k;
- k >>= 1;
- if (!(i & 7)) {
- pq_putint(j, 1);
- j = 0;
- k = 1 << 7;
+ int i,
+ j,
+ k;
+ char *attr;
+ bool isnull;
+
+ /* ----------------
+ * tell the frontend to expect new tuple data
+ * ----------------
+ */
+ pq_putnchar("B", 1);
+
+ /* ----------------
+ * send a bitmap of which attributes are null
+ * ----------------
+ */
+ j = 0;
+ k = 1 << 7;
+ for (i = 0; i < tuple->t_natts;)
+ {
+ i++; /* heap_getattr is a macro, so no
+ * increment */
+ attr = heap_getattr(tuple, InvalidBuffer, i, typeinfo, &isnull);
+ if (!isnull)
+ j |= k;
+ k >>= 1;
+ if (!(i & 7))
+ {
+ pq_putint(j, 1);
+ j = 0;
+ k = 1 << 7;
+ }
}
- }
- if (i & 7)
- pq_putint(j, 1);
-
- /* ----------------
- * send the attributes of this tuple
- * ----------------
- */
+ if (i & 7)
+ pq_putint(j, 1);
+
+ /* ----------------
+ * send the attributes of this tuple
+ * ----------------
+ */
#ifdef IPORTAL_DEBUG
- fprintf(stderr, "sending tuple with %d atts\n", tuple->t_natts);
+ fprintf(stderr, "sending tuple with %d atts\n", tuple->t_natts);
#endif
- for (i = 0; i < tuple->t_natts; ++i) {
- int32 len = typeinfo->attrs[i]->attlen;
-
- attr = heap_getattr(tuple, InvalidBuffer, i+1, typeinfo, &isnull);
- if (!isnull) {
- /* # of bytes, and opaque data */
- if (len == -1) {
- /* variable length, assume a varlena structure */
- len = VARSIZE(attr) - VARHDRSZ;
-
- pq_putint(len, sizeof(int32));
- pq_putnchar(VARDATA(attr), len);
-#ifdef IPORTAL_DEBUG
+ for (i = 0; i < tuple->t_natts; ++i)
+ {
+ int32 len = typeinfo->attrs[i]->attlen;
+
+ attr = heap_getattr(tuple, InvalidBuffer, i + 1, typeinfo, &isnull);
+ if (!isnull)
{
- char *d = VARDATA(attr);
-
- fprintf(stderr, "length %d data %x%x%x%x\n",
- len, *d, *(d+1), *(d+2), *(d+3));
- }
+ /* # of bytes, and opaque data */
+ if (len == -1)
+ {
+ /* variable length, assume a varlena structure */
+ len = VARSIZE(attr) - VARHDRSZ;
+
+ pq_putint(len, sizeof(int32));
+ pq_putnchar(VARDATA(attr), len);
+#ifdef IPORTAL_DEBUG
+ {
+ char *d = VARDATA(attr);
+
+ fprintf(stderr, "length %d data %x%x%x%x\n",
+ len, *d, *(d + 1), *(d + 2), *(d + 3));
+ }
#endif
- } else {
- /* fixed size */
- if (typeinfo->attrs[i]->attbyval) {
- int8 i8;
- int16 i16;
- int32 i32;
-
- pq_putint(len, sizeof(int32));
- switch (len) {
- case sizeof(int8):
- i8 = DatumGetChar(attr);
- pq_putnchar((char *) &i8, len);
- break;
- case sizeof(int16):
- i16 = DatumGetInt16(attr);
- pq_putnchar((char *) &i16, len);
- break;
- case sizeof(int32):
- i32 = DatumGetInt32(attr);
- pq_putnchar((char *) &i32, len);
- break;
- }
+ }
+ else
+ {
+ /* fixed size */
+ if (typeinfo->attrs[i]->attbyval)
+ {
+ int8 i8;
+ int16 i16;
+ int32 i32;
+
+ pq_putint(len, sizeof(int32));
+ switch (len)
+ {
+ case sizeof(int8):
+ i8 = DatumGetChar(attr);
+ pq_putnchar((char *) &i8, len);
+ break;
+ case sizeof(int16):
+ i16 = DatumGetInt16(attr);
+ pq_putnchar((char *) &i16, len);
+ break;
+ case sizeof(int32):
+ i32 = DatumGetInt32(attr);
+ pq_putnchar((char *) &i32, len);
+ break;
+ }
#ifdef IPORTAL_DEBUG
- fprintf(stderr, "byval length %d data %d\n", len, attr);
+ fprintf(stderr, "byval length %d data %d\n", len, attr);
#endif
- } else {
- pq_putint(len, sizeof(int32));
- pq_putnchar(attr, len);
+ }
+ else
+ {
+ pq_putint(len, sizeof(int32));
+ pq_putnchar(attr, len);
#ifdef IPORTAL_DEBUG
- fprintf(stderr, "byref length %d data %x\n", len, attr);
+ fprintf(stderr, "byref length %d data %x\n", len, attr);
#endif
+ }
+ }
}
- }
}
- }
}
diff --git a/src/backend/access/common/scankey.c b/src/backend/access/common/scankey.c
index fb242497ebc..9fbe264ae5c 100644
--- a/src/backend/access/common/scankey.c
+++ b/src/backend/access/common/scankey.c
@@ -1,13 +1,13 @@
/*-------------------------------------------------------------------------
*
* scan.c--
- * scan direction and key code
+ * scan direction and key code
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/common/scankey.c,v 1.9 1996/11/05 07:42:45 scrappy Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/common/scankey.c,v 1.10 1997/09/07 04:37:39 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -19,49 +19,49 @@
/*
* ScanKeyEntryIsLegal --
- * True iff the scan key entry is legal.
+ * True iff the scan key entry is legal.
*/
#define ScanKeyEntryIsLegal(entry) \
- ((bool) (AssertMacro(PointerIsValid(entry)) && \
- AttributeNumberIsValid(entry->sk_attno)))
+ ((bool) (AssertMacro(PointerIsValid(entry)) && \
+ AttributeNumberIsValid(entry->sk_attno)))
/*
* ScanKeyEntrySetIllegal --
- * Marks a scan key entry as illegal.
+ * Marks a scan key entry as illegal.
*/
void
ScanKeyEntrySetIllegal(ScanKey entry)
{
- Assert(PointerIsValid(entry));
-
- entry->sk_flags = 0; /* just in case... */
- entry->sk_attno = InvalidAttrNumber;
- entry->sk_procedure = 0; /* should be InvalidRegProcedure */
+ Assert(PointerIsValid(entry));
+
+ entry->sk_flags = 0; /* just in case... */
+ entry->sk_attno = InvalidAttrNumber;
+ entry->sk_procedure = 0; /* should be InvalidRegProcedure */
}
/*
* ScanKeyEntryInitialize --
- * Initializes an scan key entry.
+ * Initializes an scan key entry.
*
* Note:
- * Assumes the scan key entry is valid.
- * Assumes the intialized scan key entry will be legal.
+ * Assumes the scan key entry is valid.
+ * Assumes the intialized scan key entry will be legal.
*/
void
ScanKeyEntryInitialize(ScanKey entry,
- bits16 flags,
- AttrNumber attributeNumber,
- RegProcedure procedure,
- Datum argument)
+ bits16 flags,
+ AttrNumber attributeNumber,
+ RegProcedure procedure,
+ Datum argument)
{
- Assert(PointerIsValid(entry));
-
- entry->sk_flags = flags;
- entry->sk_attno = attributeNumber;
- entry->sk_procedure = procedure;
- entry->sk_argument = argument;
- fmgr_info(procedure, &entry->sk_func, &entry->sk_nargs);
-
- Assert(ScanKeyEntryIsLegal(entry));
+ Assert(PointerIsValid(entry));
+
+ entry->sk_flags = flags;
+ entry->sk_attno = attributeNumber;
+ entry->sk_procedure = procedure;
+ entry->sk_argument = argument;
+ fmgr_info(procedure, &entry->sk_func, &entry->sk_nargs);
+
+ Assert(ScanKeyEntryIsLegal(entry));
}
diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c
index a38a5229f28..e616702a8ea 100644
--- a/src/backend/access/common/tupdesc.c
+++ b/src/backend/access/common/tupdesc.c
@@ -1,17 +1,17 @@
/*-------------------------------------------------------------------------
*
* tupdesc.c--
- * POSTGRES tuple descriptor support code
+ * POSTGRES tuple descriptor support code
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.19 1997/08/22 02:55:39 vadim Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.20 1997/09/07 04:37:41 momjian Exp $
*
* NOTES
- * some of the executor utility code such as "ExecTypeFromTL" should be
- * moved here.
+ * some of the executor utility code such as "ExecTypeFromTL" should be
+ * moved here.
*
*-------------------------------------------------------------------------
*/
@@ -28,518 +28,534 @@
#include <utils/syscache.h>
#ifndef HAVE_MEMMOVE
-# include <regex/utils.h>
+#include <regex/utils.h>
#else
-# include <string.h>
+#include <string.h>
#endif
/* ----------------------------------------------------------------
- * CreateTemplateTupleDesc
+ * CreateTemplateTupleDesc
*
- * This function allocates and zeros a tuple descriptor structure.
+ * This function allocates and zeros a tuple descriptor structure.
* ----------------------------------------------------------------
*/
TupleDesc
CreateTemplateTupleDesc(int natts)
{
- uint32 size;
- TupleDesc desc;
-
- /* ----------------
- * sanity checks
- * ----------------
- */
- AssertArg(natts >= 1);
-
- /* ----------------
- * allocate enough memory for the tuple descriptor and
- * zero it as TupleDescInitEntry assumes that the descriptor
- * is filled with NULL pointers.
- * ----------------
- */
- size = natts * sizeof (AttributeTupleForm);
- desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
- desc->attrs = (AttributeTupleForm*) palloc(size);
- desc->constr = NULL;
- memset(desc->attrs, 0, size);
-
- desc->natts = natts;
-
- return (desc);
+ uint32 size;
+ TupleDesc desc;
+
+ /* ----------------
+ * sanity checks
+ * ----------------
+ */
+ AssertArg(natts >= 1);
+
+ /* ----------------
+ * allocate enough memory for the tuple descriptor and
+ * zero it as TupleDescInitEntry assumes that the descriptor
+ * is filled with NULL pointers.
+ * ----------------
+ */
+ size = natts * sizeof(AttributeTupleForm);
+ desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
+ desc->attrs = (AttributeTupleForm *) palloc(size);
+ desc->constr = NULL;
+ memset(desc->attrs, 0, size);
+
+ desc->natts = natts;
+
+ return (desc);
}
/* ----------------------------------------------------------------
- * CreateTupleDesc
+ * CreateTupleDesc
*
- * This function allocates a new TupleDesc from AttributeTupleForm array
+ * This function allocates a new TupleDesc from AttributeTupleForm array
* ----------------------------------------------------------------
*/
TupleDesc
-CreateTupleDesc(int natts, AttributeTupleForm* attrs)
+CreateTupleDesc(int natts, AttributeTupleForm * attrs)
{
- TupleDesc desc;
-
- /* ----------------
- * sanity checks
- * ----------------
- */
- AssertArg(natts >= 1);
-
- desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
- desc->attrs = attrs;
- desc->natts = natts;
- desc->constr = NULL;
-
- return (desc);
+ TupleDesc desc;
+
+ /* ----------------
+ * sanity checks
+ * ----------------
+ */
+ AssertArg(natts >= 1);
+
+ desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
+ desc->attrs = attrs;
+ desc->natts = natts;
+ desc->constr = NULL;
+
+ return (desc);
}
/* ----------------------------------------------------------------
- * CreateTupleDescCopy
+ * CreateTupleDescCopy
*
- * This function creates a new TupleDesc by copying from an existing
- * TupleDesc
- *
- * !!! Constraints are not copied !!!
+ * This function creates a new TupleDesc by copying from an existing
+ * TupleDesc
+ *
+ * !!! Constraints are not copied !!!
* ----------------------------------------------------------------
*/
TupleDesc
CreateTupleDescCopy(TupleDesc tupdesc)
{
- TupleDesc desc;
- int i, size;
-
- desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
- desc->natts = tupdesc->natts;
- size = desc->natts * sizeof (AttributeTupleForm);
- desc->attrs = (AttributeTupleForm*) palloc(size);
- for (i=0;i<desc->natts;i++) {
- desc->attrs[i] =
- (AttributeTupleForm)palloc(ATTRIBUTE_TUPLE_SIZE);
- memmove(desc->attrs[i],
- tupdesc->attrs[i],
- ATTRIBUTE_TUPLE_SIZE);
- desc->attrs[i]->attnotnull = false;
- desc->attrs[i]->atthasdef = false;
- }
- desc->constr = NULL;
-
- return desc;
+ TupleDesc desc;
+ int i,
+ size;
+
+ desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
+ desc->natts = tupdesc->natts;
+ size = desc->natts * sizeof(AttributeTupleForm);
+ desc->attrs = (AttributeTupleForm *) palloc(size);
+ for (i = 0; i < desc->natts; i++)
+ {
+ desc->attrs[i] =
+ (AttributeTupleForm) palloc(ATTRIBUTE_TUPLE_SIZE);
+ memmove(desc->attrs[i],
+ tupdesc->attrs[i],
+ ATTRIBUTE_TUPLE_SIZE);
+ desc->attrs[i]->attnotnull = false;
+ desc->attrs[i]->atthasdef = false;
+ }
+ desc->constr = NULL;
+
+ return desc;
}
/* ----------------------------------------------------------------
- * CreateTupleDescCopyConstr
+ * CreateTupleDescCopyConstr
+ *
+ * This function creates a new TupleDesc by copying from an existing
+ * TupleDesc (with Constraints)
*
- * This function creates a new TupleDesc by copying from an existing
- * TupleDesc (with Constraints)
- *
* ----------------------------------------------------------------
*/
TupleDesc
CreateTupleDescCopyConstr(TupleDesc tupdesc)
{
- TupleDesc desc;
- TupleConstr *constr = tupdesc->constr;
- int i, size;
-
- desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
- desc->natts = tupdesc->natts;
- size = desc->natts * sizeof (AttributeTupleForm);
- desc->attrs = (AttributeTupleForm*) palloc(size);
- for (i=0;i<desc->natts;i++) {
- desc->attrs[i] =
- (AttributeTupleForm)palloc(ATTRIBUTE_TUPLE_SIZE);
- memmove(desc->attrs[i],
- tupdesc->attrs[i],
- ATTRIBUTE_TUPLE_SIZE);
- }
- if (constr)
- {
- TupleConstr *cpy = (TupleConstr *) palloc(sizeof(TupleConstr));
-
- cpy->has_not_null = constr->has_not_null;
-
- if ( ( cpy->num_defval = constr->num_defval ) > 0 )
- {
- cpy->defval = (AttrDefault *) palloc (cpy->num_defval * sizeof (AttrDefault));
- memcpy (cpy->defval, constr->defval, cpy->num_defval * sizeof (AttrDefault));
- for (i = cpy->num_defval - 1; i >= 0; i--)
- {
- if ( constr->defval[i].adbin )
- cpy->defval[i].adbin = pstrdup (constr->defval[i].adbin);
- if ( constr->defval[i].adsrc )
- cpy->defval[i].adsrc = pstrdup (constr->defval[i].adsrc);
- }
- }
-
- if ( ( cpy->num_check = constr->num_check ) > 0 )
- {
- cpy->check = (ConstrCheck *) palloc (cpy->num_check * sizeof (ConstrCheck));
- memcpy (cpy->check, constr->check, cpy->num_check * sizeof (ConstrCheck));
- for (i = cpy->num_check - 1; i >= 0; i--)
- {
- if ( constr->check[i].ccname )
- cpy->check[i].ccname = pstrdup (constr->check[i].ccname);
- if ( constr->check[i].ccbin )
- cpy->check[i].ccbin = pstrdup (constr->check[i].ccbin);
- if ( constr->check[i].ccsrc )
- cpy->check[i].ccsrc = pstrdup (constr->check[i].ccsrc);
- }
- }
-
- desc->constr = cpy;
- }
- else
- desc->constr = NULL;
-
- return desc;
+ TupleDesc desc;
+ TupleConstr *constr = tupdesc->constr;
+ int i,
+ size;
+
+ desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
+ desc->natts = tupdesc->natts;
+ size = desc->natts * sizeof(AttributeTupleForm);
+ desc->attrs = (AttributeTupleForm *) palloc(size);
+ for (i = 0; i < desc->natts; i++)
+ {
+ desc->attrs[i] =
+ (AttributeTupleForm) palloc(ATTRIBUTE_TUPLE_SIZE);
+ memmove(desc->attrs[i],
+ tupdesc->attrs[i],
+ ATTRIBUTE_TUPLE_SIZE);
+ }
+ if (constr)
+ {
+ TupleConstr *cpy = (TupleConstr *) palloc(sizeof(TupleConstr));
+
+ cpy->has_not_null = constr->has_not_null;
+
+ if ((cpy->num_defval = constr->num_defval) > 0)
+ {
+ cpy->defval = (AttrDefault *) palloc(cpy->num_defval * sizeof(AttrDefault));
+ memcpy(cpy->defval, constr->defval, cpy->num_defval * sizeof(AttrDefault));
+ for (i = cpy->num_defval - 1; i >= 0; i--)
+ {
+ if (constr->defval[i].adbin)
+ cpy->defval[i].adbin = pstrdup(constr->defval[i].adbin);
+ if (constr->defval[i].adsrc)
+ cpy->defval[i].adsrc = pstrdup(constr->defval[i].adsrc);
+ }
+ }
+
+ if ((cpy->num_check = constr->num_check) > 0)
+ {
+ cpy->check = (ConstrCheck *) palloc(cpy->num_check * sizeof(ConstrCheck));
+ memcpy(cpy->check, constr->check, cpy->num_check * sizeof(ConstrCheck));
+ for (i = cpy->num_check - 1; i >= 0; i--)
+ {
+ if (constr->check[i].ccname)
+ cpy->check[i].ccname = pstrdup(constr->check[i].ccname);
+ if (constr->check[i].ccbin)
+ cpy->check[i].ccbin = pstrdup(constr->check[i].ccbin);
+ if (constr->check[i].ccsrc)
+ cpy->check[i].ccsrc = pstrdup(constr->check[i].ccsrc);
+ }
+ }
+
+ desc->constr = cpy;
+ }
+ else
+ desc->constr = NULL;
+
+ return desc;
}
void
-FreeTupleDesc (TupleDesc tupdesc)
+FreeTupleDesc(TupleDesc tupdesc)
{
- int i;
-
- for (i = 0; i < tupdesc->natts; i++)
- pfree (tupdesc->attrs[i]);
- pfree (tupdesc->attrs);
- if ( tupdesc->constr )
- {
- if ( tupdesc->constr->num_defval > 0 )
- {
- AttrDefault *attrdef = tupdesc->constr->defval;
-
- for (i = tupdesc->constr->num_defval - 1; i >= 0; i--)
- {
- if ( attrdef[i].adbin )
- pfree (attrdef[i].adbin);
- if ( attrdef[i].adsrc )
- pfree (attrdef[i].adsrc);
- }
- pfree (attrdef);
- }
- if ( tupdesc->constr->num_check > 0 )
- {
- ConstrCheck *check = tupdesc->constr->check;
-
- for (i = tupdesc->constr->num_check - 1; i >= 0; i--)
- {
- if ( check[i].ccname )
- pfree (check[i].ccname);
- if ( check[i].ccbin )
- pfree (check[i].ccbin);
- if ( check[i].ccsrc )
- pfree (check[i].ccsrc);
- }
- pfree (check);
- }
- pfree (tupdesc->constr);
- }
-
- pfree (tupdesc);
+ int i;
+
+ for (i = 0; i < tupdesc->natts; i++)
+ pfree(tupdesc->attrs[i]);
+ pfree(tupdesc->attrs);
+ if (tupdesc->constr)
+ {
+ if (tupdesc->constr->num_defval > 0)
+ {
+ AttrDefault *attrdef = tupdesc->constr->defval;
+
+ for (i = tupdesc->constr->num_defval - 1; i >= 0; i--)
+ {
+ if (attrdef[i].adbin)
+ pfree(attrdef[i].adbin);
+ if (attrdef[i].adsrc)
+ pfree(attrdef[i].adsrc);
+ }
+ pfree(attrdef);
+ }
+ if (tupdesc->constr->num_check > 0)
+ {
+ ConstrCheck *check = tupdesc->constr->check;
+
+ for (i = tupdesc->constr->num_check - 1; i >= 0; i--)
+ {
+ if (check[i].ccname)
+ pfree(check[i].ccname);
+ if (check[i].ccbin)
+ pfree(check[i].ccbin);
+ if (check[i].ccsrc)
+ pfree(check[i].ccsrc);
+ }
+ pfree(check);
+ }
+ pfree(tupdesc->constr);
+ }
+
+ pfree(tupdesc);
}
/* ----------------------------------------------------------------
- * TupleDescInitEntry
+ * TupleDescInitEntry
*
- * This function initializes a single attribute structure in
- * a preallocated tuple descriptor.
+ * This function initializes a single attribute structure in
+ * a preallocated tuple descriptor.
* ----------------------------------------------------------------
*/
bool
TupleDescInitEntry(TupleDesc desc,
- AttrNumber attributeNumber,
- char *attributeName,
- char *typeName,
- int attdim,
- bool attisset)
+ AttrNumber attributeNumber,
+ char *attributeName,
+ char *typeName,
+ int attdim,
+ bool attisset)
{
- HeapTuple tuple;
- TypeTupleForm typeForm;
- AttributeTupleForm att;
-
- /* ----------------
- * sanity checks
- * ----------------
- */
- AssertArg(PointerIsValid(desc));
- AssertArg(attributeNumber >= 1);
- /* attributeName's are sometimes NULL,
- from resdom's. I don't know why that is, though -- Jolly */
-/* AssertArg(NameIsValid(attributeName));*/
-/* AssertArg(NameIsValid(typeName));*/
-
- AssertArg(!PointerIsValid(desc->attrs[attributeNumber - 1]));
-
-
- /* ----------------
- * allocate storage for this attribute
- * ----------------
- */
-
- att = (AttributeTupleForm) palloc(ATTRIBUTE_TUPLE_SIZE);
- desc->attrs[attributeNumber - 1] = att;
-
- /* ----------------
- * initialize some of the attribute fields
- * ----------------
- */
- att->attrelid = 0; /* dummy value */
-
- if (attributeName != NULL)
- namestrcpy(&(att->attname), attributeName);
- else
- memset(att->attname.data,0,NAMEDATALEN);
-
-
- att->attdisbursion = 0; /* dummy value */
- att->attcacheoff = -1;
-
- att->attnum = attributeNumber;
- att->attnelems = attdim;
- att->attisset = attisset;
-
- att->attnotnull = false;
- att->atthasdef = false;
-
- /* ----------------
- * search the system cache for the type tuple of the attribute
- * we are creating so that we can get the typeid and some other
- * stuff.
- *
- * Note: in the special case of
- *
- * create EMP (name = char16, manager = EMP)
- *
- * RelationNameCreateHeapRelation() calls BuildDesc() which
- * calls this routine and since EMP does not exist yet, the
- * system cache lookup below fails. That's fine, but rather
- * then doing a elog(WARN) we just leave that information
- * uninitialized, return false, then fix things up later.
- * -cim 6/14/90
- * ----------------
- */
- tuple = SearchSysCacheTuple(TYPNAME, PointerGetDatum(typeName),
- 0,0,0);
- if (! HeapTupleIsValid(tuple)) {
+ HeapTuple tuple;
+ TypeTupleForm typeForm;
+ AttributeTupleForm att;
+
/* ----------------
- * here type info does not exist yet so we just fill
- * the attribute with dummy information and return false.
+ * sanity checks
* ----------------
*/
- att->atttypid = InvalidOid;
- att->attlen = (int16) 0;
- att->attbyval = (bool) 0;
- att->attalign = 'i';
- return false;
- }
-
- /* ----------------
- * type info exists so we initialize our attribute
- * information from the type tuple we found..
- * ----------------
- */
- typeForm = (TypeTupleForm) GETSTRUCT(tuple);
-
- att->atttypid = tuple->t_oid;
- att->attalign = typeForm->typalign;
-
- /* ------------------------
- If this attribute is a set, what is really stored in the
- attribute is the OID of a tuple in the pg_proc catalog.
- The pg_proc tuple contains the query string which defines
- this set - i.e., the query to run to get the set.
- So the atttypid (just assigned above) refers to the type returned
- by this query, but the actual length of this attribute is the
- length (size) of an OID.
-
- Why not just make the atttypid point to the OID type, instead
- of the type the query returns? Because the executor uses the atttypid
- to tell the front end what type will be returned (in BeginCommand),
- and in the end the type returned will be the result of the query, not
- an OID.
-
- Why not wait until the return type of the set is known (i.e., the
- recursive call to the executor to execute the set has returned)
- before telling the front end what the return type will be? Because
- the executor is a delicate thing, and making sure that the correct
- order of front-end commands is maintained is messy, especially
- considering that target lists may change as inherited attributes
- are considered, etc. Ugh.
- -----------------------------------------
- */
- if (attisset) {
- Type t = type("oid");
- att->attlen = tlen(t);
- att->attbyval = tbyval(t);
- } else {
- att->attlen = typeForm->typlen;
- att->attbyval = typeForm->typbyval;
- }
-
-
- return true;
+ AssertArg(PointerIsValid(desc));
+ AssertArg(attributeNumber >= 1);
+
+ /*
+ * attributeName's are sometimes NULL, from resdom's. I don't know
+ * why that is, though -- Jolly
+ */
+/* AssertArg(NameIsValid(attributeName));*/
+/* AssertArg(NameIsValid(typeName));*/
+
+ AssertArg(!PointerIsValid(desc->attrs[attributeNumber - 1]));
+
+
+ /* ----------------
+ * allocate storage for this attribute
+ * ----------------
+ */
+
+ att = (AttributeTupleForm) palloc(ATTRIBUTE_TUPLE_SIZE);
+ desc->attrs[attributeNumber - 1] = att;
+
+ /* ----------------
+ * initialize some of the attribute fields
+ * ----------------
+ */
+ att->attrelid = 0; /* dummy value */
+
+ if (attributeName != NULL)
+ namestrcpy(&(att->attname), attributeName);
+ else
+ memset(att->attname.data, 0, NAMEDATALEN);
+
+
+ att->attdisbursion = 0; /* dummy value */
+ att->attcacheoff = -1;
+
+ att->attnum = attributeNumber;
+ att->attnelems = attdim;
+ att->attisset = attisset;
+
+ att->attnotnull = false;
+ att->atthasdef = false;
+
+ /* ----------------
+ * search the system cache for the type tuple of the attribute
+ * we are creating so that we can get the typeid and some other
+ * stuff.
+ *
+ * Note: in the special case of
+ *
+ * create EMP (name = char16, manager = EMP)
+ *
+ * RelationNameCreateHeapRelation() calls BuildDesc() which
+ * calls this routine and since EMP does not exist yet, the
+ * system cache lookup below fails. That's fine, but rather
+ * then doing a elog(WARN) we just leave that information
+ * uninitialized, return false, then fix things up later.
+ * -cim 6/14/90
+ * ----------------
+ */
+ tuple = SearchSysCacheTuple(TYPNAME, PointerGetDatum(typeName),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tuple))
+ {
+ /* ----------------
+ * here type info does not exist yet so we just fill
+ * the attribute with dummy information and return false.
+ * ----------------
+ */
+ att->atttypid = InvalidOid;
+ att->attlen = (int16) 0;
+ att->attbyval = (bool) 0;
+ att->attalign = 'i';
+ return false;
+ }
+
+ /* ----------------
+ * type info exists so we initialize our attribute
+ * information from the type tuple we found..
+ * ----------------
+ */
+ typeForm = (TypeTupleForm) GETSTRUCT(tuple);
+
+ att->atttypid = tuple->t_oid;
+ att->attalign = typeForm->typalign;
+
+ /* ------------------------
+ If this attribute is a set, what is really stored in the
+ attribute is the OID of a tuple in the pg_proc catalog.
+ The pg_proc tuple contains the query string which defines
+ this set - i.e., the query to run to get the set.
+ So the atttypid (just assigned above) refers to the type returned
+ by this query, but the actual length of this attribute is the
+ length (size) of an OID.
+
+ Why not just make the atttypid point to the OID type, instead
+ of the type the query returns? Because the executor uses the atttypid
+ to tell the front end what type will be returned (in BeginCommand),
+ and in the end the type returned will be the result of the query, not
+ an OID.
+
+ Why not wait until the return type of the set is known (i.e., the
+ recursive call to the executor to execute the set has returned)
+ before telling the front end what the return type will be? Because
+ the executor is a delicate thing, and making sure that the correct
+ order of front-end commands is maintained is messy, especially
+ considering that target lists may change as inherited attributes
+ are considered, etc. Ugh.
+ -----------------------------------------
+ */
+ if (attisset)
+ {
+ Type t = type("oid");
+
+ att->attlen = tlen(t);
+ att->attbyval = tbyval(t);
+ }
+ else
+ {
+ att->attlen = typeForm->typlen;
+ att->attbyval = typeForm->typbyval;
+ }
+
+
+ return true;
}
/* ----------------------------------------------------------------
- * TupleDescMakeSelfReference
+ * TupleDescMakeSelfReference
*
- * This function initializes a "self-referential" attribute like
- * manager in "create EMP (name=text, manager = EMP)".
- * It calls TypeShellMake() which inserts a "shell" type
- * tuple into pg_type. A self-reference is one kind of set, so
- * its size and byval are the same as for a set. See the comments
- * above in TupleDescInitEntry.
+ * This function initializes a "self-referential" attribute like
+ * manager in "create EMP (name=text, manager = EMP)".
+ * It calls TypeShellMake() which inserts a "shell" type
+ * tuple into pg_type. A self-reference is one kind of set, so
+ * its size and byval are the same as for a set. See the comments
+ * above in TupleDescInitEntry.
* ----------------------------------------------------------------
*/
static void
TupleDescMakeSelfReference(TupleDesc desc,
- AttrNumber attnum,
- char *relname)
+ AttrNumber attnum,
+ char *relname)
{
- AttributeTupleForm att;
- Type t = type("oid");
-
- att = desc->attrs[attnum-1];
- att->atttypid = TypeShellMake(relname);
- att->attlen = tlen(t);
- att->attbyval = tbyval(t);
- att->attnelems = 0;
+ AttributeTupleForm att;
+ Type t = type("oid");
+
+ att = desc->attrs[attnum - 1];
+ att->atttypid = TypeShellMake(relname);
+ att->attlen = tlen(t);
+ att->attbyval = tbyval(t);
+ att->attnelems = 0;
}
/* ----------------------------------------------------------------
- * BuildDescForRelation
+ * BuildDescForRelation
*
- * This is a general purpose function identical to BuildDesc
- * but is used by the DefineRelation() code to catch the
- * special case where you
+ * This is a general purpose function identical to BuildDesc
+ * but is used by the DefineRelation() code to catch the
+ * special case where you
*
- * create FOO ( ..., x = FOO )
+ * create FOO ( ..., x = FOO )
*
- * here, the initial type lookup for "x = FOO" will fail
- * because FOO isn't in the catalogs yet. But since we
- * are creating FOO, instead of doing an elog() we add
- * a shell type tuple to pg_type and fix things later
- * in amcreate().
+ * here, the initial type lookup for "x = FOO" will fail
+ * because FOO isn't in the catalogs yet. But since we
+ * are creating FOO, instead of doing an elog() we add
+ * a shell type tuple to pg_type and fix things later
+ * in amcreate().
* ----------------------------------------------------------------
*/
TupleDesc
-BuildDescForRelation(List *schema, char *relname)
+BuildDescForRelation(List * schema, char *relname)
{
- int natts;
- AttrNumber attnum;
- List *p;
- TupleDesc desc;
- AttrDefault *attrdef = NULL;
- TupleConstr *constr = (TupleConstr *) palloc(sizeof(TupleConstr));
- char *attname;
- char *typename;
- int attdim;
- int ndef = 0;
- bool attisset;
-
- /* ----------------
- * allocate a new tuple descriptor
- * ----------------
- */
- natts = length(schema);
- desc = CreateTemplateTupleDesc(natts);
- constr->has_not_null = false;
-
- attnum = 0;
-
- typename = palloc(NAMEDATALEN);
-
- foreach(p, schema) {
- ColumnDef *entry;
- List *arry;
+ int natts;
+ AttrNumber attnum;
+ List *p;
+ TupleDesc desc;
+ AttrDefault *attrdef = NULL;
+ TupleConstr *constr = (TupleConstr *) palloc(sizeof(TupleConstr));
+ char *attname;
+ char *typename;
+ int attdim;
+ int ndef = 0;
+ bool attisset;
/* ----------------
- * for each entry in the list, get the name and type
- * information from the list and have TupleDescInitEntry
- * fill in the attribute information we need.
+ * allocate a new tuple descriptor
* ----------------
- */
- attnum++;
-
- entry = lfirst(p);
- attname = entry->colname;
- arry = entry->typename->arrayBounds;
- attisset = entry->typename->setof;
-
- strNcpy(typename, entry->typename->name,NAMEDATALEN-1);
- if (arry != NIL)
- attdim = length(arry);
- else
- attdim = 0;
-
- if (! TupleDescInitEntry(desc, attnum, attname,
- typename, attdim, attisset)) {
- /* ----------------
- * if TupleDescInitEntry() fails, it means there is
- * no type in the system catalogs. So now we check if
- * the type name equals the relation name. If so we
- * have a self reference, otherwise it's an error.
- * ----------------
- */
- if (!strcmp(typename, relname)) {
- TupleDescMakeSelfReference(desc, attnum, relname);
- } else
- elog(WARN, "DefineRelation: no such type %s",
- typename);
- }
-
- /*
- * this is for char() and varchar(). When an entry is of type
- * char() or varchar(), typlen is set to the appropriate length,
- * which we'll use here instead. (The catalog lookup only returns
- * the length of bpchar and varchar which is not what we want!)
- * - ay 6/95
*/
- if (entry->typename->typlen > 0) {
- desc->attrs[attnum - 1]->attlen = entry->typename->typlen;
- }
+ natts = length(schema);
+ desc = CreateTemplateTupleDesc(natts);
+ constr->has_not_null = false;
- /* This is for constraints */
- if (entry->is_not_null)
- constr->has_not_null = true;
- desc->attrs[attnum-1]->attnotnull = entry->is_not_null;
-
- if ( entry->defval != NULL )
+ attnum = 0;
+
+ typename = palloc(NAMEDATALEN);
+
+ foreach(p, schema)
{
- if ( attrdef == NULL )
- attrdef = (AttrDefault*) palloc (natts * sizeof (AttrDefault));
- attrdef[ndef].adnum = attnum;
- attrdef[ndef].adbin = NULL;
- attrdef[ndef].adsrc = entry->defval;
- ndef++;
- desc->attrs[attnum-1]->atthasdef = true;
+ ColumnDef *entry;
+ List *arry;
+
+ /* ----------------
+ * for each entry in the list, get the name and type
+ * information from the list and have TupleDescInitEntry
+ * fill in the attribute information we need.
+ * ----------------
+ */
+ attnum++;
+
+ entry = lfirst(p);
+ attname = entry->colname;
+ arry = entry->typename->arrayBounds;
+ attisset = entry->typename->setof;
+
+ strNcpy(typename, entry->typename->name, NAMEDATALEN - 1);
+ if (arry != NIL)
+ attdim = length(arry);
+ else
+ attdim = 0;
+
+ if (!TupleDescInitEntry(desc, attnum, attname,
+ typename, attdim, attisset))
+ {
+ /* ----------------
+ * if TupleDescInitEntry() fails, it means there is
+ * no type in the system catalogs. So now we check if
+ * the type name equals the relation name. If so we
+ * have a self reference, otherwise it's an error.
+ * ----------------
+ */
+ if (!strcmp(typename, relname))
+ {
+ TupleDescMakeSelfReference(desc, attnum, relname);
+ }
+ else
+ elog(WARN, "DefineRelation: no such type %s",
+ typename);
+ }
+
+ /*
+ * this is for char() and varchar(). When an entry is of type
+ * char() or varchar(), typlen is set to the appropriate length,
+ * which we'll use here instead. (The catalog lookup only returns
+ * the length of bpchar and varchar which is not what we want!) -
+ * ay 6/95
+ */
+ if (entry->typename->typlen > 0)
+ {
+ desc->attrs[attnum - 1]->attlen = entry->typename->typlen;
+ }
+
+ /* This is for constraints */
+ if (entry->is_not_null)
+ constr->has_not_null = true;
+ desc->attrs[attnum - 1]->attnotnull = entry->is_not_null;
+
+ if (entry->defval != NULL)
+ {
+ if (attrdef == NULL)
+ attrdef = (AttrDefault *) palloc(natts * sizeof(AttrDefault));
+ attrdef[ndef].adnum = attnum;
+ attrdef[ndef].adbin = NULL;
+ attrdef[ndef].adsrc = entry->defval;
+ ndef++;
+ desc->attrs[attnum - 1]->atthasdef = true;
+ }
+
}
+ if (constr->has_not_null || ndef > 0)
+ {
+ desc->constr = constr;
- }
- if ( constr->has_not_null || ndef > 0 )
- {
- desc->constr = constr;
-
- if ( ndef > 0 ) /* DEFAULTs */
- {
- if ( ndef < natts )
- constr->defval = (AttrDefault*)
- repalloc (attrdef, ndef * sizeof (AttrDefault));
- else
- constr->defval = attrdef;
- constr->num_defval = ndef;
- }
- else
- constr->num_defval = 0;
- constr->num_check = 0;
- }
- else
- {
- pfree (constr);
- desc->constr = NULL;
- }
- return desc;
+ if (ndef > 0) /* DEFAULTs */
+ {
+ if (ndef < natts)
+ constr->defval = (AttrDefault *)
+ repalloc(attrdef, ndef * sizeof(AttrDefault));
+ else
+ constr->defval = attrdef;
+ constr->num_defval = ndef;
+ }
+ else
+ constr->num_defval = 0;
+ constr->num_check = 0;
+ }
+ else
+ {
+ pfree(constr);
+ desc->constr = NULL;
+ }
+ return desc;
}
-
diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c
index 1d36f340ed6..598f9ed8f02 100644
--- a/src/backend/access/gist/gist.c
+++ b/src/backend/access/gist/gist.c
@@ -1,7 +1,7 @@
/*-------------------------------------------------------------------------
*
* gist.c--
- * interface routines for the postgres GiST index access method.
+ * interface routines for the postgres GiST index access method.
*
*
*
@@ -26,308 +26,345 @@
#include <utils/syscache.h>
#ifndef HAVE_MEMMOVE
-# include <regex/utils.h>
+#include <regex/utils.h>
#else
-# include <string.h>
+#include <string.h>
#endif
/* non-export function prototypes */
-static InsertIndexResult gistdoinsert(Relation r, IndexTuple itup,
- GISTSTATE *GISTstate);
-static InsertIndexResult gistentryinsert(Relation r, GISTSTACK *stk,
- IndexTuple tup,
- GISTSTATE *giststate);
-static void gistentryinserttwo(Relation r, GISTSTACK *stk, IndexTuple ltup,
- IndexTuple rtup, GISTSTATE *giststate);
-static void gistAdjustKeys(Relation r, GISTSTACK *stk, BlockNumber blk,
- char *datum, int att_size, GISTSTATE *giststate);
-static void gistintinsert(Relation r, GISTSTACK *stk, IndexTuple ltup,
- IndexTuple rtup, GISTSTATE *giststate);
-static InsertIndexResult gistSplit(Relation r, Buffer buffer,
- GISTSTACK *stack, IndexTuple itup,
- GISTSTATE *giststate);
-static void gistnewroot(GISTSTATE *giststate, Relation r, IndexTuple lt,
+static InsertIndexResult
+gistdoinsert(Relation r, IndexTuple itup,
+ GISTSTATE * GISTstate);
+static InsertIndexResult
+gistentryinsert(Relation r, GISTSTACK * stk,
+ IndexTuple tup,
+ GISTSTATE * giststate);
+static void
+gistentryinserttwo(Relation r, GISTSTACK * stk, IndexTuple ltup,
+ IndexTuple rtup, GISTSTATE * giststate);
+static void
+gistAdjustKeys(Relation r, GISTSTACK * stk, BlockNumber blk,
+ char *datum, int att_size, GISTSTATE * giststate);
+static void
+gistintinsert(Relation r, GISTSTACK * stk, IndexTuple ltup,
+ IndexTuple rtup, GISTSTATE * giststate);
+static InsertIndexResult
+gistSplit(Relation r, Buffer buffer,
+ GISTSTACK * stack, IndexTuple itup,
+ GISTSTATE * giststate);
+static void
+gistnewroot(GISTSTATE * giststate, Relation r, IndexTuple lt,
IndexTuple rt);
-static void GISTInitBuffer(Buffer b, uint32 f);
-static BlockNumber gistChooseSubtree(Relation r, IndexTuple itup, int level,
- GISTSTATE *giststate,
- GISTSTACK **retstack, Buffer *leafbuf);
-static OffsetNumber gistchoose(Relation r, Page p, IndexTuple it,
- GISTSTATE *giststate);
-static int gistnospace(Page p, IndexTuple it);
-void gistdelete(Relation r, ItemPointer tid);
+static void GISTInitBuffer(Buffer b, uint32 f);
+static BlockNumber
+gistChooseSubtree(Relation r, IndexTuple itup, int level,
+ GISTSTATE * giststate,
+ GISTSTACK ** retstack, Buffer * leafbuf);
+static OffsetNumber
+gistchoose(Relation r, Page p, IndexTuple it,
+ GISTSTATE * giststate);
+static int gistnospace(Page p, IndexTuple it);
+void gistdelete(Relation r, ItemPointer tid);
static IndexTuple gist_tuple_replacekey(Relation r, GISTENTRY entry, IndexTuple t);
-static void gistcentryinit(GISTSTATE *giststate, GISTENTRY *e, char *pr,
- Relation r, Page pg, OffsetNumber o, int b, bool l) ;
-static char *int_range_out(INTRANGE *r);
+static void
+gistcentryinit(GISTSTATE * giststate, GISTENTRY * e, char *pr,
+ Relation r, Page pg, OffsetNumber o, int b, bool l);
+static char *int_range_out(INTRANGE * r);
/*
** routine to build an index. Basically calls insert over and over
*/
void
gistbuild(Relation heap,
- Relation index,
- int natts,
- AttrNumber *attnum,
- IndexStrategy istrat,
- uint16 pint,
- Datum *params,
- FuncIndexInfo *finfo,
- PredInfo *predInfo)
+ Relation index,
+ int natts,
+ AttrNumber * attnum,
+ IndexStrategy istrat,
+ uint16 pint,
+ Datum * params,
+ FuncIndexInfo * finfo,
+ PredInfo * predInfo)
{
- HeapScanDesc scan;
- Buffer buffer;
- AttrNumber i;
- HeapTuple htup;
- IndexTuple itup;
- TupleDesc hd, id;
- InsertIndexResult res;
- Datum *d;
- bool *nulls;
- int nb, nh, ni;
+ HeapScanDesc scan;
+ Buffer buffer;
+ AttrNumber i;
+ HeapTuple htup;
+ IndexTuple itup;
+ TupleDesc hd,
+ id;
+ InsertIndexResult res;
+ Datum *d;
+ bool *nulls;
+ int nb,
+ nh,
+ ni;
+
#ifndef OMIT_PARTIAL_INDEX
- ExprContext *econtext;
- TupleTable tupleTable;
- TupleTableSlot *slot;
+ ExprContext *econtext;
+ TupleTable tupleTable;
+ TupleTableSlot *slot;
+
#endif
- Oid hrelid, irelid;
- Node *pred, *oldPred;
- GISTSTATE giststate;
- GISTENTRY tmpcentry;
- bool *compvec;
-
- /* GiSTs only know how to do stupid locking now */
- RelationSetLockForWrite(index);
-
- setheapoverride(TRUE); /* so we can see the new pg_index tuple */
- initGISTstate(&giststate, index);
- setheapoverride(FALSE);
-
- pred = predInfo->pred;
- oldPred = predInfo->oldPred;
-
- /*
- * We expect to be called exactly once for any index relation.
- * If that's not the case, big trouble's what we have.
- */
-
- if (oldPred == NULL && (nb = RelationGetNumberOfBlocks(index)) != 0)
- elog(WARN, "%.16s already contains data", &(index->rd_rel->relname.data[0]));
-
- /* initialize the root page (if this is a new index) */
- if (oldPred == NULL) {
- buffer = ReadBuffer(index, P_NEW);
- GISTInitBuffer(buffer, F_LEAF);
- WriteBuffer(buffer);
- }
-
- /* init the tuple descriptors and get set for a heap scan */
- hd = RelationGetTupleDescriptor(heap);
- id = RelationGetTupleDescriptor(index);
- d = (Datum *)palloc(natts * sizeof (*d));
- nulls = (bool *)palloc(natts * sizeof (*nulls));
-
- /*
- * If this is a predicate (partial) index, we will need to evaluate the
- * predicate using ExecQual, which requires the current tuple to be in a
- * slot of a TupleTable. In addition, ExecQual must have an ExprContext
- * referring to that slot. Here, we initialize dummy TupleTable and
- * ExprContext objects for this purpose. --Nels, Feb '92
- */
+ Oid hrelid,
+ irelid;
+ Node *pred,
+ *oldPred;
+ GISTSTATE giststate;
+ GISTENTRY tmpcentry;
+ bool *compvec;
+
+ /* GiSTs only know how to do stupid locking now */
+ RelationSetLockForWrite(index);
+
+ setheapoverride(TRUE); /* so we can see the new pg_index tuple */
+ initGISTstate(&giststate, index);
+ setheapoverride(FALSE);
+
+ pred = predInfo->pred;
+ oldPred = predInfo->oldPred;
+
+ /*
+ * We expect to be called exactly once for any index relation. If
+ * that's not the case, big trouble's what we have.
+ */
+
+ if (oldPred == NULL && (nb = RelationGetNumberOfBlocks(index)) != 0)
+ elog(WARN, "%.16s already contains data", &(index->rd_rel->relname.data[0]));
+
+ /* initialize the root page (if this is a new index) */
+ if (oldPred == NULL)
+ {
+ buffer = ReadBuffer(index, P_NEW);
+ GISTInitBuffer(buffer, F_LEAF);
+ WriteBuffer(buffer);
+ }
+
+ /* init the tuple descriptors and get set for a heap scan */
+ hd = RelationGetTupleDescriptor(heap);
+ id = RelationGetTupleDescriptor(index);
+ d = (Datum *) palloc(natts * sizeof(*d));
+ nulls = (bool *) palloc(natts * sizeof(*nulls));
+
+ /*
+ * If this is a predicate (partial) index, we will need to evaluate
+ * the predicate using ExecQual, which requires the current tuple to
+ * be in a slot of a TupleTable. In addition, ExecQual must have an
+ * ExprContext referring to that slot. Here, we initialize dummy
+ * TupleTable and ExprContext objects for this purpose. --Nels, Feb
+ * '92
+ */
#ifndef OMIT_PARTIAL_INDEX
- if (pred != NULL || oldPred != NULL) {
- tupleTable = ExecCreateTupleTable(1);
- slot = ExecAllocTableSlot(tupleTable);
- econtext = makeNode(ExprContext);
- FillDummyExprContext(econtext, slot, hd, buffer);
- }
- else /* shut the compiler up */
+ if (pred != NULL || oldPred != NULL)
+ {
+ tupleTable = ExecCreateTupleTable(1);
+ slot = ExecAllocTableSlot(tupleTable);
+ econtext = makeNode(ExprContext);
+ FillDummyExprContext(econtext, slot, hd, buffer);
+ }
+ else
+/* shut the compiler up */
{
tupleTable = NULL;
slot = NULL;
econtext = NULL;
}
-#endif /* OMIT_PARTIAL_INDEX */
- scan = heap_beginscan(heap, 0, NowTimeQual, 0, (ScanKey) NULL);
- htup = heap_getnext(scan, 0, &buffer);
-
- /* int the tuples as we insert them */
- nh = ni = 0;
-
- for (; HeapTupleIsValid(htup); htup = heap_getnext(scan, 0, &buffer)) {
-
- nh++;
-
- /*
- * If oldPred != NULL, this is an EXTEND INDEX command, so skip
- * this tuple if it was already in the existing partial index
- */
- if (oldPred != NULL) {
+#endif /* OMIT_PARTIAL_INDEX */
+ scan = heap_beginscan(heap, 0, NowTimeQual, 0, (ScanKey) NULL);
+ htup = heap_getnext(scan, 0, &buffer);
+
+ /* int the tuples as we insert them */
+ nh = ni = 0;
+
+ for (; HeapTupleIsValid(htup); htup = heap_getnext(scan, 0, &buffer))
+ {
+
+ nh++;
+
+ /*
+ * If oldPred != NULL, this is an EXTEND INDEX command, so skip
+ * this tuple if it was already in the existing partial index
+ */
+ if (oldPred != NULL)
+ {
#ifndef OMIT_PARTIAL_INDEX
- /*SetSlotContents(slot, htup); */
- slot->val = htup;
- if (ExecQual((List*)oldPred, econtext) == true) {
+ /* SetSlotContents(slot, htup); */
+ slot->val = htup;
+ if (ExecQual((List *) oldPred, econtext) == true)
+ {
+ ni++;
+ continue;
+ }
+#endif /* OMIT_PARTIAL_INDEX */
+ }
+
+ /*
+ * Skip this tuple if it doesn't satisfy the partial-index
+ * predicate
+ */
+ if (pred != NULL)
+ {
+#ifndef OMIT_PARTIAL_INDEX
+ /* SetSlotContents(slot, htup); */
+ slot->val = htup;
+ if (ExecQual((List *) pred, econtext) == false)
+ continue;
+#endif /* OMIT_PARTIAL_INDEX */
+ }
+
ni++;
- continue;
- }
-#endif /* OMIT_PARTIAL_INDEX */
+
+ /*
+ * For the current heap tuple, extract all the attributes we use
+ * in this index, and note which are null.
+ */
+
+ for (i = 1; i <= natts; i++)
+ {
+ int attoff;
+ bool attnull;
+
+ /*
+ * Offsets are from the start of the tuple, and are
+ * zero-based; indices are one-based. The next call returns i
+ * - 1. That's data hiding for you.
+ */
+
+ attoff = AttrNumberGetAttrOffset(i);
+
+ /*
+ * d[attoff] = HeapTupleGetAttributeValue(htup, buffer,
+ */
+ d[attoff] = GetIndexValue(htup,
+ hd,
+ attoff,
+ attnum,
+ finfo,
+ &attnull,
+ buffer);
+ nulls[attoff] = (attnull ? 'n' : ' ');
+ }
+
+ /* immediately compress keys to normalize */
+ compvec = (bool *) palloc(sizeof(bool) * natts);
+ for (i = 0; i < natts; i++)
+ {
+ gistcentryinit(&giststate, &tmpcentry, (char *) d[i],
+ (Relation) NULL, (Page) NULL, (OffsetNumber) 0,
+ -1 /* size is currently bogus */ , TRUE);
+ if (d[i] != (Datum) tmpcentry.pred && !(giststate.keytypbyval))
+ compvec[i] = TRUE;
+ else
+ compvec[i] = FALSE;
+ d[i] = (Datum) tmpcentry.pred;
+ }
+
+ /* form an index tuple and point it at the heap tuple */
+ itup = index_formtuple(id, &d[0], nulls);
+ itup->t_tid = htup->t_ctid;
+
+ /*
+ * Since we already have the index relation locked, we call
+ * gistdoinsert directly. Normal access method calls dispatch
+ * through gistinsert, which locks the relation for write. This
+ * is the right thing to do if you're inserting single tups, but
+ * not when you're initializing the whole index at once.
+ */
+
+ res = gistdoinsert(index, itup, &giststate);
+ for (i = 0; i < natts; i++)
+ if (compvec[i] == TRUE)
+ pfree((char *) d[i]);
+ pfree(itup);
+ pfree(res);
+ pfree(compvec);
}
-
- /* Skip this tuple if it doesn't satisfy the partial-index predicate */
- if (pred != NULL) {
+
+ /* okay, all heap tuples are indexed */
+ heap_endscan(scan);
+ RelationUnsetLockForWrite(index);
+
+ if (pred != NULL || oldPred != NULL)
+ {
#ifndef OMIT_PARTIAL_INDEX
- /*SetSlotContents(slot, htup); */
- slot->val = htup;
- if (ExecQual((List*)pred, econtext) == false)
- continue;
-#endif /* OMIT_PARTIAL_INDEX */
+ ExecDestroyTupleTable(tupleTable, true);
+ pfree(econtext);
+#endif /* OMIT_PARTIAL_INDEX */
}
-
- ni++;
-
+
/*
- * For the current heap tuple, extract all the attributes
- * we use in this index, and note which are null.
+ * Since we just inted the tuples in the heap, we update its stats in
+ * pg_relation to guarantee that the planner takes advantage of the
+ * index we just created. UpdateStats() does a
+ * CommandinterIncrement(), which flushes changed entries from the
+ * system relcache. The act of constructing an index changes these
+ * heap and index tuples in the system catalogs, so they need to be
+ * flushed. We close them to guarantee that they will be.
*/
-
- for (i = 1; i <= natts; i++) {
- int attoff;
- bool attnull;
-
- /*
- * Offsets are from the start of the tuple, and are
- * zero-based; indices are one-based. The next call
- * returns i - 1. That's data hiding for you.
- */
-
- attoff = AttrNumberGetAttrOffset(i);
- /*
- d[attoff] = HeapTupleGetAttributeValue(htup, buffer,
- */
- d[attoff] = GetIndexValue(htup,
- hd,
- attoff,
- attnum,
- finfo,
- &attnull,
- buffer);
- nulls[attoff] = (attnull ? 'n' : ' ');
- }
-
- /* immediately compress keys to normalize */
- compvec = (bool *)palloc(sizeof(bool) * natts);
- for (i = 0; i < natts; i++) {
- gistcentryinit(&giststate, &tmpcentry, (char *)d[i],
- (Relation) NULL, (Page) NULL, (OffsetNumber) 0,
- -1 /* size is currently bogus */, TRUE);
- if (d[i] != (Datum)tmpcentry.pred && !(giststate.keytypbyval))
- compvec[i] = TRUE;
- else compvec[i] = FALSE;
- d[i] = (Datum)tmpcentry.pred;
+
+ hrelid = heap->rd_id;
+ irelid = index->rd_id;
+ heap_close(heap);
+ index_close(index);
+
+ UpdateStats(hrelid, nh, true);
+ UpdateStats(irelid, ni, false);
+
+ if (oldPred != NULL)
+ {
+ if (ni == nh)
+ pred = NULL;
+ UpdateIndexPredicate(irelid, oldPred, pred);
}
- /* form an index tuple and point it at the heap tuple */
- itup = index_formtuple(id, &d[0], nulls);
- itup->t_tid = htup->t_ctid;
-
- /*
- * Since we already have the index relation locked, we
- * call gistdoinsert directly. Normal access method calls
- * dispatch through gistinsert, which locks the relation
- * for write. This is the right thing to do if you're
- * inserting single tups, but not when you're initializing
- * the whole index at once.
- */
-
- res = gistdoinsert(index, itup, &giststate);
- for (i = 0; i < natts; i++)
- if (compvec[i] == TRUE) pfree((char *)d[i]);
- pfree(itup);
- pfree(res);
- pfree(compvec);
- }
-
- /* okay, all heap tuples are indexed */
- heap_endscan(scan);
- RelationUnsetLockForWrite(index);
-
- if (pred != NULL || oldPred != NULL) {
-#ifndef OMIT_PARTIAL_INDEX
- ExecDestroyTupleTable(tupleTable, true);
- pfree(econtext);
-#endif /* OMIT_PARTIAL_INDEX */
- }
-
- /*
- * Since we just inted the tuples in the heap, we update its
- * stats in pg_relation to guarantee that the planner takes
- * advantage of the index we just created. UpdateStats() does a
- * CommandinterIncrement(), which flushes changed entries from
- * the system relcache. The act of constructing an index changes
- * these heap and index tuples in the system catalogs, so they
- * need to be flushed. We close them to guarantee that they
- * will be.
- */
-
- hrelid = heap->rd_id;
- irelid = index->rd_id;
- heap_close(heap);
- index_close(index);
-
- UpdateStats(hrelid, nh, true);
- UpdateStats(irelid, ni, false);
-
- if (oldPred != NULL) {
- if (ni == nh) pred = NULL;
- UpdateIndexPredicate(irelid, oldPred, pred);
- }
-
- /* be tidy */
- pfree(nulls);
- pfree(d);
+ /* be tidy */
+ pfree(nulls);
+ pfree(d);
}
/*
- * gistinsert -- wrapper for GiST tuple insertion.
+ * gistinsert -- wrapper for GiST tuple insertion.
*
- * This is the public interface routine for tuple insertion in GiSTs.
- * It doesn't do any work; just locks the relation and passes the buck.
+ * This is the public interface routine for tuple insertion in GiSTs.
+ * It doesn't do any work; just locks the relation and passes the buck.
*/
InsertIndexResult
-gistinsert(Relation r, Datum *datum, char *nulls, ItemPointer ht_ctid, Relation heapRel)
+gistinsert(Relation r, Datum * datum, char *nulls, ItemPointer ht_ctid, Relation heapRel)
{
- InsertIndexResult res;
- IndexTuple itup;
- GISTSTATE giststate;
- GISTENTRY tmpentry;
- int i;
- bool *compvec;
-
- initGISTstate(&giststate, r);
-
- /* immediately compress keys to normalize */
- compvec = (bool *)palloc(sizeof(bool) * r->rd_att->natts);
- for (i = 0; i < r->rd_att->natts; i++) {
- gistcentryinit(&giststate, &tmpentry, (char *)datum[i],
- (Relation) NULL, (Page) NULL, (OffsetNumber) 0,
- -1 /* size is currently bogus */, TRUE);
- if (datum[i] != (Datum)tmpentry.pred && !(giststate.keytypbyval))
- compvec[i] = TRUE;
- else compvec[i] = FALSE;
- datum[i] = (Datum)tmpentry.pred;
- }
- itup = index_formtuple(RelationGetTupleDescriptor(r), datum, nulls);
- itup->t_tid = *ht_ctid;
-
- RelationSetLockForWrite(r);
- res = gistdoinsert(r, itup, &giststate);
- for (i = 0; i < r->rd_att->natts; i++)
- if (compvec[i] == TRUE) pfree((char *)datum[i]);
- pfree(itup);
- pfree(compvec);
-
- /* XXX two-phase locking -- don't unlock the relation until EOT */
- return (res);
+ InsertIndexResult res;
+ IndexTuple itup;
+ GISTSTATE giststate;
+ GISTENTRY tmpentry;
+ int i;
+ bool *compvec;
+
+ initGISTstate(&giststate, r);
+
+ /* immediately compress keys to normalize */
+ compvec = (bool *) palloc(sizeof(bool) * r->rd_att->natts);
+ for (i = 0; i < r->rd_att->natts; i++)
+ {
+ gistcentryinit(&giststate, &tmpentry, (char *) datum[i],
+ (Relation) NULL, (Page) NULL, (OffsetNumber) 0,
+ -1 /* size is currently bogus */ , TRUE);
+ if (datum[i] != (Datum) tmpentry.pred && !(giststate.keytypbyval))
+ compvec[i] = TRUE;
+ else
+ compvec[i] = FALSE;
+ datum[i] = (Datum) tmpentry.pred;
+ }
+ itup = index_formtuple(RelationGetTupleDescriptor(r), datum, nulls);
+ itup->t_tid = *ht_ctid;
+
+ RelationSetLockForWrite(r);
+ res = gistdoinsert(r, itup, &giststate);
+ for (i = 0; i < r->rd_att->natts; i++)
+ if (compvec[i] == TRUE)
+ pfree((char *) datum[i]);
+ pfree(itup);
+ pfree(compvec);
+
+ /* XXX two-phase locking -- don't unlock the relation until EOT */
+ return (res);
}
/*
@@ -336,475 +373,509 @@ gistinsert(Relation r, Datum *datum, char *nulls, ItemPointer ht_ctid, Relation
** that knowledge (some compression routines may want to fish around
** on the page, for example, or do something special for leaf nodes.)
*/
-static OffsetNumber
-gistPageAddItem(GISTSTATE *giststate,
- Relation r,
- Page page,
- Item item,
- Size size,
- OffsetNumber offsetNumber,
- ItemIdFlags flags,
- GISTENTRY *dentry,
- IndexTuple *newtup)
+static OffsetNumber
+gistPageAddItem(GISTSTATE * giststate,
+ Relation r,
+ Page page,
+ Item item,
+ Size size,
+ OffsetNumber offsetNumber,
+ ItemIdFlags flags,
+ GISTENTRY * dentry,
+ IndexTuple * newtup)
{
- GISTENTRY tmpcentry;
- IndexTuple itup = (IndexTuple)item;
-
- /* recompress the item given that we now know the exact page and
- offset for insertion */
- gistdentryinit(giststate, dentry,
- (((char *) itup) + sizeof(IndexTupleData)),
- (Relation)0, (Page)0, (OffsetNumber)InvalidOffsetNumber,
- IndexTupleSize(itup) - sizeof(IndexTupleData), FALSE);
- gistcentryinit(giststate, &tmpcentry, dentry->pred, r, page,
- offsetNumber, dentry->bytes, FALSE);
- *newtup = gist_tuple_replacekey(r, *dentry, itup);
- /* be tidy */
- if (tmpcentry.pred != dentry->pred
- && tmpcentry.pred != (((char *) itup) + sizeof(IndexTupleData)))
- pfree(tmpcentry.pred);
-
- return(PageAddItem(page, (Item) *newtup, IndexTupleSize(*newtup),
- offsetNumber, flags));
+ GISTENTRY tmpcentry;
+ IndexTuple itup = (IndexTuple) item;
+
+ /*
+ * recompress the item given that we now know the exact page and
+ * offset for insertion
+ */
+ gistdentryinit(giststate, dentry,
+ (((char *) itup) + sizeof(IndexTupleData)),
+ (Relation) 0, (Page) 0, (OffsetNumber) InvalidOffsetNumber,
+ IndexTupleSize(itup) - sizeof(IndexTupleData), FALSE);
+ gistcentryinit(giststate, &tmpcentry, dentry->pred, r, page,
+ offsetNumber, dentry->bytes, FALSE);
+ *newtup = gist_tuple_replacekey(r, *dentry, itup);
+ /* be tidy */
+ if (tmpcentry.pred != dentry->pred
+ && tmpcentry.pred != (((char *) itup) + sizeof(IndexTupleData)))
+ pfree(tmpcentry.pred);
+
+ return (PageAddItem(page, (Item) * newtup, IndexTupleSize(*newtup),
+ offsetNumber, flags));
}
-static InsertIndexResult
-gistdoinsert(Relation r,
- IndexTuple itup, /* itup contains compressed entry */
- GISTSTATE *giststate)
+static InsertIndexResult
+gistdoinsert(Relation r,
+ IndexTuple itup, /* itup contains compressed entry */
+ GISTSTATE * giststate)
{
- GISTENTRY tmpdentry;
- InsertIndexResult res;
- OffsetNumber l;
- GISTSTACK *stack;
- Buffer buffer;
- BlockNumber blk;
- Page page;
- OffsetNumber off;
- IndexTuple newtup;
-
- /* 3rd arg is ignored for now */
- blk = gistChooseSubtree(r, itup, 0, giststate, &stack, &buffer);
- page = (Page) BufferGetPage(buffer);
-
- if (gistnospace(page, itup)) {
- /* need to do a split */
- res = gistSplit(r, buffer, stack, itup, giststate);
+ GISTENTRY tmpdentry;
+ InsertIndexResult res;
+ OffsetNumber l;
+ GISTSTACK *stack;
+ Buffer buffer;
+ BlockNumber blk;
+ Page page;
+ OffsetNumber off;
+ IndexTuple newtup;
+
+ /* 3rd arg is ignored for now */
+ blk = gistChooseSubtree(r, itup, 0, giststate, &stack, &buffer);
+ page = (Page) BufferGetPage(buffer);
+
+ if (gistnospace(page, itup))
+ {
+ /* need to do a split */
+ res = gistSplit(r, buffer, stack, itup, giststate);
+ gistfreestack(stack);
+ WriteBuffer(buffer); /* don't forget to release buffer! */
+ return (res);
+ }
+
+ if (PageIsEmpty(page))
+ off = FirstOffsetNumber;
+ else
+ off = OffsetNumberNext(PageGetMaxOffsetNumber(page));
+
+ /* add the item and write the buffer */
+ l = gistPageAddItem(giststate, r, page, (Item) itup, IndexTupleSize(itup),
+ off, LP_USED, &tmpdentry, &newtup);
+ WriteBuffer(buffer);
+
+ /* now expand the page boundary in the parent to include the new child */
+ gistAdjustKeys(r, stack, blk, tmpdentry.pred, tmpdentry.bytes, giststate);
gistfreestack(stack);
- WriteBuffer(buffer); /* don't forget to release buffer! */
+
+ /* be tidy */
+ if (itup != newtup)
+ pfree(newtup);
+ if (tmpdentry.pred != (((char *) itup) + sizeof(IndexTupleData)))
+ pfree(tmpdentry.pred);
+
+ /* build and return an InsertIndexResult for this insertion */
+ res = (InsertIndexResult) palloc(sizeof(InsertIndexResultData));
+ ItemPointerSet(&(res->pointerData), blk, l);
+
return (res);
- }
-
- if (PageIsEmpty(page))
- off = FirstOffsetNumber;
- else
- off = OffsetNumberNext(PageGetMaxOffsetNumber(page));
-
- /* add the item and write the buffer */
- l = gistPageAddItem(giststate, r, page, (Item) itup, IndexTupleSize(itup),
- off, LP_USED, &tmpdentry, &newtup);
- WriteBuffer(buffer);
-
- /* now expand the page boundary in the parent to include the new child */
- gistAdjustKeys(r, stack, blk, tmpdentry.pred, tmpdentry.bytes, giststate);
- gistfreestack(stack);
-
- /* be tidy */
- if (itup != newtup)
- pfree(newtup);
- if (tmpdentry.pred != (((char *) itup) + sizeof(IndexTupleData)))
- pfree(tmpdentry.pred);
-
- /* build and return an InsertIndexResult for this insertion */
- res = (InsertIndexResult) palloc(sizeof(InsertIndexResultData));
- ItemPointerSet(&(res->pointerData), blk, l);
-
- return (res);
}
-static BlockNumber
-gistChooseSubtree(Relation r, IndexTuple itup, /* itup has compressed entry */
- int level,
- GISTSTATE *giststate,
- GISTSTACK **retstack /*out*/,
- Buffer *leafbuf /*out*/)
+static BlockNumber
+gistChooseSubtree(Relation r, IndexTuple itup, /* itup has compressed
+ * entry */
+ int level,
+ GISTSTATE * giststate,
+ GISTSTACK ** retstack /* out */ ,
+ Buffer * leafbuf /* out */ )
{
- Buffer buffer;
- BlockNumber blk;
- GISTSTACK *stack;
- Page page;
- GISTPageOpaque opaque;
- IndexTuple which;
-
- blk = GISTP_ROOT;
- buffer = InvalidBuffer;
- stack = (GISTSTACK *) NULL;
-
- do {
- /* let go of current buffer before getting next */
- if (buffer != InvalidBuffer)
- ReleaseBuffer(buffer);
-
- /* get next buffer */
- buffer = ReadBuffer(r, blk);
- page = (Page) BufferGetPage(buffer);
-
- opaque = (GISTPageOpaque) PageGetSpecialPointer(page);
- if (!(opaque->flags & F_LEAF)) {
- GISTSTACK *n;
- ItemId iid;
-
- n = (GISTSTACK *) palloc(sizeof(GISTSTACK));
- n->gs_parent = stack;
- n->gs_blk = blk;
- n->gs_child = gistchoose(r, page, itup, giststate);
- stack = n;
-
- iid = PageGetItemId(page, n->gs_child);
- which = (IndexTuple) PageGetItem(page, iid);
- blk = ItemPointerGetBlockNumber(&(which->t_tid));
- }
- } while (!(opaque->flags & F_LEAF));
-
- *retstack = stack;
- *leafbuf = buffer;
-
- return(blk);
+ Buffer buffer;
+ BlockNumber blk;
+ GISTSTACK *stack;
+ Page page;
+ GISTPageOpaque opaque;
+ IndexTuple which;
+
+ blk = GISTP_ROOT;
+ buffer = InvalidBuffer;
+ stack = (GISTSTACK *) NULL;
+
+ do
+ {
+ /* let go of current buffer before getting next */
+ if (buffer != InvalidBuffer)
+ ReleaseBuffer(buffer);
+
+ /* get next buffer */
+ buffer = ReadBuffer(r, blk);
+ page = (Page) BufferGetPage(buffer);
+
+ opaque = (GISTPageOpaque) PageGetSpecialPointer(page);
+ if (!(opaque->flags & F_LEAF))
+ {
+ GISTSTACK *n;
+ ItemId iid;
+
+ n = (GISTSTACK *) palloc(sizeof(GISTSTACK));
+ n->gs_parent = stack;
+ n->gs_blk = blk;
+ n->gs_child = gistchoose(r, page, itup, giststate);
+ stack = n;
+
+ iid = PageGetItemId(page, n->gs_child);
+ which = (IndexTuple) PageGetItem(page, iid);
+ blk = ItemPointerGetBlockNumber(&(which->t_tid));
+ }
+ } while (!(opaque->flags & F_LEAF));
+
+ *retstack = stack;
+ *leafbuf = buffer;
+
+ return (blk);
}
static void
gistAdjustKeys(Relation r,
- GISTSTACK *stk,
- BlockNumber blk,
- char *datum, /* datum is uncompressed */
- int att_size,
- GISTSTATE *giststate)
+ GISTSTACK * stk,
+ BlockNumber blk,
+ char *datum, /* datum is uncompressed */
+ int att_size,
+ GISTSTATE * giststate)
{
- char *oldud;
- Page p;
- Buffer b;
- bool result;
- bytea *evec;
- GISTENTRY centry, *ev0p, *ev1p;
- int size, datumsize;
- IndexTuple tid;
-
- if (stk == (GISTSTACK *) NULL)
- return;
-
- b = ReadBuffer(r, stk->gs_blk);
- p = BufferGetPage(b);
-
- oldud = (char *) PageGetItem(p, PageGetItemId(p, stk->gs_child));
- tid = (IndexTuple) oldud;
- size = IndexTupleSize((IndexTuple)oldud) - sizeof(IndexTupleData);
- oldud += sizeof(IndexTupleData);
-
- evec = (bytea *) palloc(2*sizeof(GISTENTRY) + VARHDRSZ);
- VARSIZE(evec) = 2*sizeof(GISTENTRY) + VARHDRSZ;
-
- /* insert decompressed oldud into entry vector */
- gistdentryinit(giststate, &((GISTENTRY *)VARDATA(evec))[0],
- oldud, r, p, stk->gs_child,
- size, FALSE);
- ev0p = &((GISTENTRY *)VARDATA(evec))[0];
-
- /* insert datum entry into entry vector */
- gistentryinit(((GISTENTRY *)VARDATA(evec))[1], datum,
- (Relation)NULL,(Page)NULL,(OffsetNumber)0, att_size, FALSE);
- ev1p = &((GISTENTRY *)VARDATA(evec))[1];
-
- /* form union of decompressed entries */
- datum = (char *) (giststate->unionFn)(evec, &datumsize);
-
- /* did union leave decompressed version of oldud unchanged? */
- (giststate->equalFn)(ev0p->pred, datum, &result);
- if (!result) {
- TupleDesc td = RelationGetTupleDescriptor(r);
-
- /* compress datum for storage on page */
- gistcentryinit(giststate, &centry, datum, ev0p->rel, ev0p->page,
- ev0p->offset, datumsize, FALSE);
- if (td->attrs[0]->attlen >= 0) {
- memmove(oldud, centry.pred, att_size);
- gistAdjustKeys(r, stk->gs_parent, stk->gs_blk, datum, att_size,
- giststate);
+ char *oldud;
+ Page p;
+ Buffer b;
+ bool result;
+ bytea *evec;
+ GISTENTRY centry,
+ *ev0p,
+ *ev1p;
+ int size,
+ datumsize;
+ IndexTuple tid;
+
+ if (stk == (GISTSTACK *) NULL)
+ return;
+
+ b = ReadBuffer(r, stk->gs_blk);
+ p = BufferGetPage(b);
+
+ oldud = (char *) PageGetItem(p, PageGetItemId(p, stk->gs_child));
+ tid = (IndexTuple) oldud;
+ size = IndexTupleSize((IndexTuple) oldud) - sizeof(IndexTupleData);
+ oldud += sizeof(IndexTupleData);
+
+ evec = (bytea *) palloc(2 * sizeof(GISTENTRY) + VARHDRSZ);
+ VARSIZE(evec) = 2 * sizeof(GISTENTRY) + VARHDRSZ;
+
+ /* insert decompressed oldud into entry vector */
+ gistdentryinit(giststate, &((GISTENTRY *) VARDATA(evec))[0],
+ oldud, r, p, stk->gs_child,
+ size, FALSE);
+ ev0p = &((GISTENTRY *) VARDATA(evec))[0];
+
+ /* insert datum entry into entry vector */
+ gistentryinit(((GISTENTRY *) VARDATA(evec))[1], datum,
+ (Relation) NULL, (Page) NULL, (OffsetNumber) 0, att_size, FALSE);
+ ev1p = &((GISTENTRY *) VARDATA(evec))[1];
+
+ /* form union of decompressed entries */
+ datum = (char *) (giststate->unionFn) (evec, &datumsize);
+
+ /* did union leave decompressed version of oldud unchanged? */
+ (giststate->equalFn) (ev0p->pred, datum, &result);
+ if (!result)
+ {
+ TupleDesc td = RelationGetTupleDescriptor(r);
+
+ /* compress datum for storage on page */
+ gistcentryinit(giststate, &centry, datum, ev0p->rel, ev0p->page,
+ ev0p->offset, datumsize, FALSE);
+ if (td->attrs[0]->attlen >= 0)
+ {
+ memmove(oldud, centry.pred, att_size);
+ gistAdjustKeys(r, stk->gs_parent, stk->gs_blk, datum, att_size,
+ giststate);
+ }
+ else if (VARSIZE(centry.pred) == VARSIZE(oldud))
+ {
+ memmove(oldud, centry.pred, VARSIZE(centry.pred));
+ gistAdjustKeys(r, stk->gs_parent, stk->gs_blk, datum, att_size,
+ giststate);
+ }
+ else
+ {
+
+ /*
+ * * new datum is not the same size as the old. * We have to
+ * delete the old entry and insert the new * one. Note that
+ * this may cause a split here!
+ */
+ IndexTuple newtup;
+ ItemPointerData oldtid;
+ char *isnull;
+ TupleDesc tupDesc;
+ InsertIndexResult res;
+
+ /* delete old tuple */
+ ItemPointerSet(&oldtid, stk->gs_blk, stk->gs_child);
+ gistdelete(r, (ItemPointer) & oldtid);
+
+ /* generate and insert new tuple */
+ tupDesc = r->rd_att;
+ isnull = (char *) palloc(r->rd_rel->relnatts);
+ memset(isnull, ' ', r->rd_rel->relnatts);
+ newtup = (IndexTuple) index_formtuple(tupDesc,
+ (Datum *) & centry.pred, isnull);
+ pfree(isnull);
+ /* set pointer in new tuple to point to current child */
+ ItemPointerSet(&oldtid, blk, 1);
+ newtup->t_tid = oldtid;
+
+ /* inserting the new entry also adjust keys above */
+ res = gistentryinsert(r, stk, newtup, giststate);
+
+ /* in stack, set info to point to new tuple */
+ stk->gs_blk = ItemPointerGetBlockNumber(&(res->pointerData));
+ stk->gs_child = ItemPointerGetOffsetNumber(&(res->pointerData));
+
+ pfree(res);
+ }
+ WriteBuffer(b);
+
+ if (centry.pred != datum)
+ pfree(datum);
}
- else if (VARSIZE(centry.pred) == VARSIZE(oldud)) {
- memmove(oldud, centry.pred, VARSIZE(centry.pred));
- gistAdjustKeys(r, stk->gs_parent, stk->gs_blk, datum, att_size,
- giststate);
+ else
+ {
+ ReleaseBuffer(b);
}
- else {
- /*
- ** new datum is not the same size as the old.
- ** We have to delete the old entry and insert the new
- ** one. Note that this may cause a split here!
- */
- IndexTuple newtup;
- ItemPointerData oldtid;
- char *isnull;
- TupleDesc tupDesc;
- InsertIndexResult res;
-
- /* delete old tuple */
- ItemPointerSet(&oldtid, stk->gs_blk, stk->gs_child);
- gistdelete(r, (ItemPointer)&oldtid);
-
- /* generate and insert new tuple */
- tupDesc = r->rd_att;
- isnull = (char *) palloc(r->rd_rel->relnatts);
- memset(isnull, ' ', r->rd_rel->relnatts);
- newtup = (IndexTuple) index_formtuple(tupDesc,
- (Datum *) &centry.pred, isnull);
- pfree(isnull);
- /* set pointer in new tuple to point to current child */
- ItemPointerSet(&oldtid, blk, 1);
- newtup->t_tid = oldtid;
-
- /* inserting the new entry also adjust keys above */
- res = gistentryinsert(r, stk, newtup, giststate);
-
- /* in stack, set info to point to new tuple */
- stk->gs_blk = ItemPointerGetBlockNumber(&(res->pointerData));
- stk->gs_child = ItemPointerGetOffsetNumber(&(res->pointerData));
-
- pfree(res);
- }
- WriteBuffer(b);
-
- if (centry.pred != datum)
- pfree(datum);
- }
- else {
- ReleaseBuffer(b);
- }
- pfree(evec);
+ pfree(evec);
}
/*
- * gistSplit -- split a page in the tree.
+ * gistSplit -- split a page in the tree.
*
*/
-static InsertIndexResult
+static InsertIndexResult
gistSplit(Relation r,
- Buffer buffer,
- GISTSTACK *stack,
- IndexTuple itup, /* contains compressed entry */
- GISTSTATE *giststate)
+ Buffer buffer,
+ GISTSTACK * stack,
+ IndexTuple itup, /* contains compressed entry */
+ GISTSTATE * giststate)
{
- Page p;
- Buffer leftbuf, rightbuf;
- Page left, right;
- ItemId itemid;
- IndexTuple item;
- IndexTuple ltup, rtup, newtup;
- OffsetNumber maxoff;
- OffsetNumber i;
- OffsetNumber leftoff, rightoff;
- BlockNumber lbknum, rbknum;
- BlockNumber bufblock;
- GISTPageOpaque opaque;
- int blank;
- InsertIndexResult res;
- char *isnull;
- GIST_SPLITVEC v;
- TupleDesc tupDesc;
- bytea *entryvec;
- bool *decompvec;
- IndexTuple item_1;
- GISTENTRY tmpdentry, tmpentry;
-
- isnull = (char *) palloc(r->rd_rel->relnatts);
- for (blank = 0; blank < r->rd_rel->relnatts; blank++)
- isnull[blank] = ' ';
- p = (Page) BufferGetPage(buffer);
- opaque = (GISTPageOpaque) PageGetSpecialPointer(p);
-
-
- /*
- * The root of the tree is the first block in the relation. If
- * we're about to split the root, we need to do some hocus-pocus
- * to enforce this guarantee.
- */
-
- if (BufferGetBlockNumber(buffer) == GISTP_ROOT) {
- leftbuf = ReadBuffer(r, P_NEW);
- GISTInitBuffer(leftbuf, opaque->flags);
- lbknum = BufferGetBlockNumber(leftbuf);
- left = (Page) BufferGetPage(leftbuf);
- } else {
- leftbuf = buffer;
- IncrBufferRefCount(buffer);
- lbknum = BufferGetBlockNumber(buffer);
- left = (Page) PageGetTempPage(p, sizeof(GISTPageOpaqueData));
- }
-
- rightbuf = ReadBuffer(r, P_NEW);
- GISTInitBuffer(rightbuf, opaque->flags);
- rbknum = BufferGetBlockNumber(rightbuf);
- right = (Page) BufferGetPage(rightbuf);
-
- /* generate the item array */
- maxoff = PageGetMaxOffsetNumber(p);
- entryvec = (bytea *)palloc(VARHDRSZ + (maxoff + 2) * sizeof(GISTENTRY));
- decompvec = (bool *)palloc(VARHDRSZ + (maxoff + 2) * sizeof(bool));
- for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) {
- item_1 = (IndexTuple) PageGetItem(p, PageGetItemId(p, i));
- gistdentryinit(giststate, &((GISTENTRY *)VARDATA(entryvec))[i],
- (((char *) item_1) + sizeof(IndexTupleData)),
- r, p, i,
- IndexTupleSize(item_1) - sizeof(IndexTupleData), FALSE);
- if ((char *)(((GISTENTRY *)VARDATA(entryvec))[i].pred)
- == (((char *) item_1) + sizeof(IndexTupleData)))
- decompvec[i] = FALSE;
- else decompvec[i] = TRUE;
- }
-
- /* add the new datum as the last entry */
- gistdentryinit(giststate, &(((GISTENTRY *)VARDATA(entryvec))[maxoff+1]),
- (((char *) itup) + sizeof(IndexTupleData)),
- (Relation)NULL, (Page)NULL,
- (OffsetNumber)0, tmpentry.bytes, FALSE);
- if ((char *)(((GISTENTRY *)VARDATA(entryvec))[maxoff+1]).pred !=
- (((char *) itup) + sizeof(IndexTupleData)))
- decompvec[maxoff+1] = TRUE;
- else decompvec[maxoff+1] = FALSE;
-
- VARSIZE(entryvec) = (maxoff + 2) * sizeof(GISTENTRY) + VARHDRSZ;
-
- /* now let the user-defined picksplit function set up the split vector */
- (giststate->picksplitFn)(entryvec, &v);
-
- /* compress ldatum and rdatum */
- gistcentryinit(giststate, &tmpentry, v.spl_ldatum, (Relation)NULL,
- (Page)NULL, (OffsetNumber)0,
- ((GISTENTRY *)VARDATA(entryvec))[i].bytes, FALSE);
- if (v.spl_ldatum != tmpentry.pred)
- pfree(v.spl_ldatum);
- v.spl_ldatum = tmpentry.pred;
-
- gistcentryinit(giststate, &tmpentry, v.spl_rdatum, (Relation)NULL,
- (Page)NULL, (OffsetNumber)0,
- ((GISTENTRY *)VARDATA(entryvec))[i].bytes, FALSE);
- if (v.spl_rdatum != tmpentry.pred)
- pfree(v.spl_rdatum);
- v.spl_rdatum = tmpentry.pred;
-
- /* clean up the entry vector: its preds need to be deleted, too */
- for (i = FirstOffsetNumber; i <= maxoff+1; i = OffsetNumberNext(i))
- if (decompvec[i])
- pfree(((GISTENTRY *)VARDATA(entryvec))[i].pred);
- pfree(entryvec);
- pfree(decompvec);
-
- leftoff = rightoff = FirstOffsetNumber;
- maxoff = PageGetMaxOffsetNumber(p);
- for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) {
- itemid = PageGetItemId(p, i);
- item = (IndexTuple) PageGetItem(p, itemid);
-
- if (i == *(v.spl_left)) {
- gistPageAddItem(giststate, r, left, (Item) item,
- IndexTupleSize(item),
- leftoff, LP_USED, &tmpdentry, &newtup);
- leftoff = OffsetNumberNext(leftoff);
- v.spl_left++; /* advance in left split vector */
- /* be tidy */
- if (tmpdentry.pred != (((char *) item) + sizeof(IndexTupleData)))
- pfree(tmpdentry.pred);
- if ((IndexTuple)item != newtup)
- pfree(newtup);
- }
- else {
- gistPageAddItem(giststate, r, right, (Item) item,
- IndexTupleSize(item),
- rightoff, LP_USED, &tmpdentry, &newtup);
- rightoff = OffsetNumberNext(rightoff);
- v.spl_right++; /* advance in right split vector */
- /* be tidy */
- if (tmpdentry.pred != (((char *) item) + sizeof(IndexTupleData)))
- pfree(tmpdentry.pred);
- if (item != newtup)
- pfree(newtup);
+ Page p;
+ Buffer leftbuf,
+ rightbuf;
+ Page left,
+ right;
+ ItemId itemid;
+ IndexTuple item;
+ IndexTuple ltup,
+ rtup,
+ newtup;
+ OffsetNumber maxoff;
+ OffsetNumber i;
+ OffsetNumber leftoff,
+ rightoff;
+ BlockNumber lbknum,
+ rbknum;
+ BlockNumber bufblock;
+ GISTPageOpaque opaque;
+ int blank;
+ InsertIndexResult res;
+ char *isnull;
+ GIST_SPLITVEC v;
+ TupleDesc tupDesc;
+ bytea *entryvec;
+ bool *decompvec;
+ IndexTuple item_1;
+ GISTENTRY tmpdentry,
+ tmpentry;
+
+ isnull = (char *) palloc(r->rd_rel->relnatts);
+ for (blank = 0; blank < r->rd_rel->relnatts; blank++)
+ isnull[blank] = ' ';
+ p = (Page) BufferGetPage(buffer);
+ opaque = (GISTPageOpaque) PageGetSpecialPointer(p);
+
+
+ /*
+ * The root of the tree is the first block in the relation. If we're
+ * about to split the root, we need to do some hocus-pocus to enforce
+ * this guarantee.
+ */
+
+ if (BufferGetBlockNumber(buffer) == GISTP_ROOT)
+ {
+ leftbuf = ReadBuffer(r, P_NEW);
+ GISTInitBuffer(leftbuf, opaque->flags);
+ lbknum = BufferGetBlockNumber(leftbuf);
+ left = (Page) BufferGetPage(leftbuf);
}
- }
-
- /* build an InsertIndexResult for this insertion */
- res = (InsertIndexResult) palloc(sizeof(InsertIndexResultData));
-
- /* now insert the new index tuple */
- if (*(v.spl_left) != FirstOffsetNumber) {
- gistPageAddItem(giststate, r, left, (Item) itup,
- IndexTupleSize(itup),
- leftoff, LP_USED, &tmpdentry, &newtup);
- leftoff = OffsetNumberNext(leftoff);
- ItemPointerSet(&(res->pointerData), lbknum, leftoff);
- /* be tidy */
- if (tmpdentry.pred != (((char *) itup) + sizeof(IndexTupleData)))
- pfree(tmpdentry.pred);
- if (itup != newtup)
- pfree(newtup);
- } else {
- gistPageAddItem(giststate, r, right, (Item) itup,
- IndexTupleSize(itup),
- rightoff, LP_USED, &tmpdentry, &newtup);
- rightoff = OffsetNumberNext(rightoff);
- ItemPointerSet(&(res->pointerData), rbknum, rightoff);
- /* be tidy */
- if (tmpdentry.pred != (((char *) itup) + sizeof(IndexTupleData)))
- pfree(tmpdentry.pred);
- if (itup != newtup)
- pfree(newtup);
- }
-
- if ((bufblock = BufferGetBlockNumber(buffer)) != GISTP_ROOT) {
- PageRestoreTempPage(left, p);
- }
- WriteBuffer(leftbuf);
- WriteBuffer(rightbuf);
-
- /*
- * Okay, the page is split. We have three things left to do:
- *
- * 1) Adjust any active scans on this index to cope with changes
- * we introduced in its structure by splitting this page.
- *
- * 2) "Tighten" the bounding box of the pointer to the left
- * page in the parent node in the tree, if any. Since we
- * moved a bunch of stuff off the left page, we expect it
- * to get smaller. This happens in the internal insertion
- * routine.
- *
- * 3) Insert a pointer to the right page in the parent. This
- * may cause the parent to split. If it does, we need to
- * repeat steps one and two for each split node in the tree.
- */
-
- /* adjust active scans */
- gistadjscans(r, GISTOP_SPLIT, bufblock, FirstOffsetNumber);
-
- tupDesc = r->rd_att;
-
- ltup = (IndexTuple) index_formtuple(tupDesc,
- (Datum *) &(v.spl_ldatum), isnull);
- rtup = (IndexTuple) index_formtuple(tupDesc,
- (Datum *) &(v.spl_rdatum), isnull);
- pfree(isnull);
-
- /* set pointers to new child pages in the internal index tuples */
- ItemPointerSet(&(ltup->t_tid), lbknum, 1);
- ItemPointerSet(&(rtup->t_tid), rbknum, 1);
-
- gistintinsert(r, stack, ltup, rtup, giststate);
-
- pfree(ltup);
- pfree(rtup);
-
- return (res);
+ else
+ {
+ leftbuf = buffer;
+ IncrBufferRefCount(buffer);
+ lbknum = BufferGetBlockNumber(buffer);
+ left = (Page) PageGetTempPage(p, sizeof(GISTPageOpaqueData));
+ }
+
+ rightbuf = ReadBuffer(r, P_NEW);
+ GISTInitBuffer(rightbuf, opaque->flags);
+ rbknum = BufferGetBlockNumber(rightbuf);
+ right = (Page) BufferGetPage(rightbuf);
+
+ /* generate the item array */
+ maxoff = PageGetMaxOffsetNumber(p);
+ entryvec = (bytea *) palloc(VARHDRSZ + (maxoff + 2) * sizeof(GISTENTRY));
+ decompvec = (bool *) palloc(VARHDRSZ + (maxoff + 2) * sizeof(bool));
+ for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
+ {
+ item_1 = (IndexTuple) PageGetItem(p, PageGetItemId(p, i));
+ gistdentryinit(giststate, &((GISTENTRY *) VARDATA(entryvec))[i],
+ (((char *) item_1) + sizeof(IndexTupleData)),
+ r, p, i,
+ IndexTupleSize(item_1) - sizeof(IndexTupleData), FALSE);
+ if ((char *) (((GISTENTRY *) VARDATA(entryvec))[i].pred)
+ == (((char *) item_1) + sizeof(IndexTupleData)))
+ decompvec[i] = FALSE;
+ else
+ decompvec[i] = TRUE;
+ }
+
+ /* add the new datum as the last entry */
+ gistdentryinit(giststate, &(((GISTENTRY *) VARDATA(entryvec))[maxoff + 1]),
+ (((char *) itup) + sizeof(IndexTupleData)),
+ (Relation) NULL, (Page) NULL,
+ (OffsetNumber) 0, tmpentry.bytes, FALSE);
+ if ((char *) (((GISTENTRY *) VARDATA(entryvec))[maxoff + 1]).pred !=
+ (((char *) itup) + sizeof(IndexTupleData)))
+ decompvec[maxoff + 1] = TRUE;
+ else
+ decompvec[maxoff + 1] = FALSE;
+
+ VARSIZE(entryvec) = (maxoff + 2) * sizeof(GISTENTRY) + VARHDRSZ;
+
+ /* now let the user-defined picksplit function set up the split vector */
+ (giststate->picksplitFn) (entryvec, &v);
+
+ /* compress ldatum and rdatum */
+ gistcentryinit(giststate, &tmpentry, v.spl_ldatum, (Relation) NULL,
+ (Page) NULL, (OffsetNumber) 0,
+ ((GISTENTRY *) VARDATA(entryvec))[i].bytes, FALSE);
+ if (v.spl_ldatum != tmpentry.pred)
+ pfree(v.spl_ldatum);
+ v.spl_ldatum = tmpentry.pred;
+
+ gistcentryinit(giststate, &tmpentry, v.spl_rdatum, (Relation) NULL,
+ (Page) NULL, (OffsetNumber) 0,
+ ((GISTENTRY *) VARDATA(entryvec))[i].bytes, FALSE);
+ if (v.spl_rdatum != tmpentry.pred)
+ pfree(v.spl_rdatum);
+ v.spl_rdatum = tmpentry.pred;
+
+ /* clean up the entry vector: its preds need to be deleted, too */
+ for (i = FirstOffsetNumber; i <= maxoff + 1; i = OffsetNumberNext(i))
+ if (decompvec[i])
+ pfree(((GISTENTRY *) VARDATA(entryvec))[i].pred);
+ pfree(entryvec);
+ pfree(decompvec);
+
+ leftoff = rightoff = FirstOffsetNumber;
+ maxoff = PageGetMaxOffsetNumber(p);
+ for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
+ {
+ itemid = PageGetItemId(p, i);
+ item = (IndexTuple) PageGetItem(p, itemid);
+
+ if (i == *(v.spl_left))
+ {
+ gistPageAddItem(giststate, r, left, (Item) item,
+ IndexTupleSize(item),
+ leftoff, LP_USED, &tmpdentry, &newtup);
+ leftoff = OffsetNumberNext(leftoff);
+ v.spl_left++; /* advance in left split vector */
+ /* be tidy */
+ if (tmpdentry.pred != (((char *) item) + sizeof(IndexTupleData)))
+ pfree(tmpdentry.pred);
+ if ((IndexTuple) item != newtup)
+ pfree(newtup);
+ }
+ else
+ {
+ gistPageAddItem(giststate, r, right, (Item) item,
+ IndexTupleSize(item),
+ rightoff, LP_USED, &tmpdentry, &newtup);
+ rightoff = OffsetNumberNext(rightoff);
+ v.spl_right++; /* advance in right split vector */
+ /* be tidy */
+ if (tmpdentry.pred != (((char *) item) + sizeof(IndexTupleData)))
+ pfree(tmpdentry.pred);
+ if (item != newtup)
+ pfree(newtup);
+ }
+ }
+
+ /* build an InsertIndexResult for this insertion */
+ res = (InsertIndexResult) palloc(sizeof(InsertIndexResultData));
+
+ /* now insert the new index tuple */
+ if (*(v.spl_left) != FirstOffsetNumber)
+ {
+ gistPageAddItem(giststate, r, left, (Item) itup,
+ IndexTupleSize(itup),
+ leftoff, LP_USED, &tmpdentry, &newtup);
+ leftoff = OffsetNumberNext(leftoff);
+ ItemPointerSet(&(res->pointerData), lbknum, leftoff);
+ /* be tidy */
+ if (tmpdentry.pred != (((char *) itup) + sizeof(IndexTupleData)))
+ pfree(tmpdentry.pred);
+ if (itup != newtup)
+ pfree(newtup);
+ }
+ else
+ {
+ gistPageAddItem(giststate, r, right, (Item) itup,
+ IndexTupleSize(itup),
+ rightoff, LP_USED, &tmpdentry, &newtup);
+ rightoff = OffsetNumberNext(rightoff);
+ ItemPointerSet(&(res->pointerData), rbknum, rightoff);
+ /* be tidy */
+ if (tmpdentry.pred != (((char *) itup) + sizeof(IndexTupleData)))
+ pfree(tmpdentry.pred);
+ if (itup != newtup)
+ pfree(newtup);
+ }
+
+ if ((bufblock = BufferGetBlockNumber(buffer)) != GISTP_ROOT)
+ {
+ PageRestoreTempPage(left, p);
+ }
+ WriteBuffer(leftbuf);
+ WriteBuffer(rightbuf);
+
+ /*
+ * Okay, the page is split. We have three things left to do:
+ *
+ * 1) Adjust any active scans on this index to cope with changes we
+ * introduced in its structure by splitting this page.
+ *
+ * 2) "Tighten" the bounding box of the pointer to the left page in the
+ * parent node in the tree, if any. Since we moved a bunch of stuff
+ * off the left page, we expect it to get smaller. This happens in
+ * the internal insertion routine.
+ *
+ * 3) Insert a pointer to the right page in the parent. This may cause
+ * the parent to split. If it does, we need to repeat steps one and
+ * two for each split node in the tree.
+ */
+
+ /* adjust active scans */
+ gistadjscans(r, GISTOP_SPLIT, bufblock, FirstOffsetNumber);
+
+ tupDesc = r->rd_att;
+
+ ltup = (IndexTuple) index_formtuple(tupDesc,
+ (Datum *) & (v.spl_ldatum), isnull);
+ rtup = (IndexTuple) index_formtuple(tupDesc,
+ (Datum *) & (v.spl_rdatum), isnull);
+ pfree(isnull);
+
+ /* set pointers to new child pages in the internal index tuples */
+ ItemPointerSet(&(ltup->t_tid), lbknum, 1);
+ ItemPointerSet(&(rtup->t_tid), rbknum, 1);
+
+ gistintinsert(r, stack, ltup, rtup, giststate);
+
+ pfree(ltup);
+ pfree(rtup);
+
+ return (res);
}
/*
@@ -813,22 +884,23 @@ gistSplit(Relation r,
*/
static void
gistintinsert(Relation r,
- GISTSTACK *stk,
- IndexTuple ltup, /* new version of entry for old page */
- IndexTuple rtup, /* entry for new page */
- GISTSTATE *giststate)
+ GISTSTACK * stk,
+ IndexTuple ltup, /* new version of entry for old page */
+ IndexTuple rtup, /* entry for new page */
+ GISTSTATE * giststate)
{
- ItemPointerData ltid;
+ ItemPointerData ltid;
- if (stk == (GISTSTACK *) NULL) {
- gistnewroot(giststate, r, ltup, rtup);
- return;
- }
-
- /* remove old left pointer, insert the 2 new entries */
- ItemPointerSet(&ltid, stk->gs_blk, stk->gs_child);
- gistdelete(r, (ItemPointer)&ltid);
- gistentryinserttwo(r, stk, ltup, rtup, giststate);
+ if (stk == (GISTSTACK *) NULL)
+ {
+ gistnewroot(giststate, r, ltup, rtup);
+ return;
+ }
+
+ /* remove old left pointer, insert the 2 new entries */
+ ItemPointerSet(&ltid, stk->gs_blk, stk->gs_child);
+ gistdelete(r, (ItemPointer) & ltid);
+ gistentryinserttwo(r, stk, ltup, rtup, giststate);
}
@@ -836,280 +908,299 @@ gistintinsert(Relation r,
** Insert two entries onto one page, handling a split for either one!
*/
static void
-gistentryinserttwo(Relation r, GISTSTACK *stk, IndexTuple ltup,
- IndexTuple rtup, GISTSTATE *giststate)
+gistentryinserttwo(Relation r, GISTSTACK * stk, IndexTuple ltup,
+ IndexTuple rtup, GISTSTATE * giststate)
{
- Buffer b;
- Page p;
- InsertIndexResult res;
- GISTENTRY tmpentry;
- IndexTuple newtup;
-
- b = ReadBuffer(r, stk->gs_blk);
- p = BufferGetPage(b);
-
- if (gistnospace(p, ltup)) {
- res = gistSplit(r, b, stk->gs_parent, ltup, giststate);
- WriteBuffer(b); /* don't forget to release buffer! - 01/31/94 */
- pfree(res);
- gistdoinsert(r, rtup, giststate);
- } else {
- gistPageAddItem(giststate, r, p, (Item)ltup,
- IndexTupleSize(ltup), InvalidOffsetNumber,
- LP_USED, &tmpentry, &newtup);
- WriteBuffer(b);
- gistAdjustKeys(r, stk->gs_parent, stk->gs_blk, tmpentry.pred,
- tmpentry.bytes, giststate);
- /* be tidy */
- if (tmpentry.pred != (((char *) ltup) + sizeof(IndexTupleData)))
- pfree(tmpentry.pred);
- if (ltup != newtup)
- pfree(newtup);
- gistentryinsert(r, stk, rtup, giststate);
- }
-}
+ Buffer b;
+ Page p;
+ InsertIndexResult res;
+ GISTENTRY tmpentry;
+ IndexTuple newtup;
+
+ b = ReadBuffer(r, stk->gs_blk);
+ p = BufferGetPage(b);
+
+ if (gistnospace(p, ltup))
+ {
+ res = gistSplit(r, b, stk->gs_parent, ltup, giststate);
+ WriteBuffer(b); /* don't forget to release buffer! -
+ * 01/31/94 */
+ pfree(res);
+ gistdoinsert(r, rtup, giststate);
+ }
+ else
+ {
+ gistPageAddItem(giststate, r, p, (Item) ltup,
+ IndexTupleSize(ltup), InvalidOffsetNumber,
+ LP_USED, &tmpentry, &newtup);
+ WriteBuffer(b);
+ gistAdjustKeys(r, stk->gs_parent, stk->gs_blk, tmpentry.pred,
+ tmpentry.bytes, giststate);
+ /* be tidy */
+ if (tmpentry.pred != (((char *) ltup) + sizeof(IndexTupleData)))
+ pfree(tmpentry.pred);
+ if (ltup != newtup)
+ pfree(newtup);
+ gistentryinsert(r, stk, rtup, giststate);
+ }
+}
/*
** Insert an entry onto a page
*/
-static InsertIndexResult
-gistentryinsert(Relation r, GISTSTACK *stk, IndexTuple tup,
- GISTSTATE *giststate)
+static InsertIndexResult
+gistentryinsert(Relation r, GISTSTACK * stk, IndexTuple tup,
+ GISTSTATE * giststate)
{
- Buffer b;
- Page p;
- InsertIndexResult res;
- OffsetNumber off;
- GISTENTRY tmpentry;
- IndexTuple newtup;
-
- b = ReadBuffer(r, stk->gs_blk);
- p = BufferGetPage(b);
-
- if (gistnospace(p, tup)) {
- res = gistSplit(r, b, stk->gs_parent, tup, giststate);
- WriteBuffer(b); /* don't forget to release buffer! - 01/31/94 */
- return(res);
- }
- else {
- res = (InsertIndexResult) palloc(sizeof(InsertIndexResultData));
- off = gistPageAddItem(giststate, r, p, (Item) tup, IndexTupleSize(tup),
- InvalidOffsetNumber, LP_USED, &tmpentry, &newtup);
- WriteBuffer(b);
- ItemPointerSet(&(res->pointerData), stk->gs_blk, off);
- gistAdjustKeys(r, stk->gs_parent, stk->gs_blk, tmpentry.pred,
- tmpentry.bytes, giststate);
- /* be tidy */
- if (tmpentry.pred != (((char *) tup) + sizeof(IndexTupleData)))
- pfree(tmpentry.pred);
- if (tup != newtup)
- pfree(newtup);
- return(res);
- }
-}
+ Buffer b;
+ Page p;
+ InsertIndexResult res;
+ OffsetNumber off;
+ GISTENTRY tmpentry;
+ IndexTuple newtup;
+
+ b = ReadBuffer(r, stk->gs_blk);
+ p = BufferGetPage(b);
+
+ if (gistnospace(p, tup))
+ {
+ res = gistSplit(r, b, stk->gs_parent, tup, giststate);
+ WriteBuffer(b); /* don't forget to release buffer! -
+ * 01/31/94 */
+ return (res);
+ }
+ else
+ {
+ res = (InsertIndexResult) palloc(sizeof(InsertIndexResultData));
+ off = gistPageAddItem(giststate, r, p, (Item) tup, IndexTupleSize(tup),
+ InvalidOffsetNumber, LP_USED, &tmpentry, &newtup);
+ WriteBuffer(b);
+ ItemPointerSet(&(res->pointerData), stk->gs_blk, off);
+ gistAdjustKeys(r, stk->gs_parent, stk->gs_blk, tmpentry.pred,
+ tmpentry.bytes, giststate);
+ /* be tidy */
+ if (tmpentry.pred != (((char *) tup) + sizeof(IndexTupleData)))
+ pfree(tmpentry.pred);
+ if (tup != newtup)
+ pfree(newtup);
+ return (res);
+ }
+}
static void
-gistnewroot(GISTSTATE *giststate, Relation r, IndexTuple lt, IndexTuple rt)
+gistnewroot(GISTSTATE * giststate, Relation r, IndexTuple lt, IndexTuple rt)
{
- Buffer b;
- Page p;
- GISTENTRY tmpentry;
- IndexTuple newtup;
-
- b = ReadBuffer(r, GISTP_ROOT);
- GISTInitBuffer(b, 0);
- p = BufferGetPage(b);
- gistPageAddItem(giststate, r, p, (Item) lt, IndexTupleSize(lt),
- FirstOffsetNumber,
- LP_USED, &tmpentry, &newtup);
- /* be tidy */
- if (tmpentry.pred != (((char *) lt) + sizeof(IndexTupleData)))
- pfree(tmpentry.pred);
- if (lt != newtup)
- pfree(newtup);
- gistPageAddItem(giststate, r, p, (Item) rt, IndexTupleSize(rt),
- OffsetNumberNext(FirstOffsetNumber), LP_USED,
- &tmpentry, &newtup);
- /* be tidy */
- if (tmpentry.pred != (((char *) rt) + sizeof(IndexTupleData)))
- pfree(tmpentry.pred);
- if (rt != newtup)
- pfree(newtup);
- WriteBuffer(b);
+ Buffer b;
+ Page p;
+ GISTENTRY tmpentry;
+ IndexTuple newtup;
+
+ b = ReadBuffer(r, GISTP_ROOT);
+ GISTInitBuffer(b, 0);
+ p = BufferGetPage(b);
+ gistPageAddItem(giststate, r, p, (Item) lt, IndexTupleSize(lt),
+ FirstOffsetNumber,
+ LP_USED, &tmpentry, &newtup);
+ /* be tidy */
+ if (tmpentry.pred != (((char *) lt) + sizeof(IndexTupleData)))
+ pfree(tmpentry.pred);
+ if (lt != newtup)
+ pfree(newtup);
+ gistPageAddItem(giststate, r, p, (Item) rt, IndexTupleSize(rt),
+ OffsetNumberNext(FirstOffsetNumber), LP_USED,
+ &tmpentry, &newtup);
+ /* be tidy */
+ if (tmpentry.pred != (((char *) rt) + sizeof(IndexTupleData)))
+ pfree(tmpentry.pred);
+ if (rt != newtup)
+ pfree(newtup);
+ WriteBuffer(b);
}
static void
GISTInitBuffer(Buffer b, uint32 f)
{
- GISTPageOpaque opaque;
- Page page;
- Size pageSize;
-
- pageSize = BufferGetPageSize(b);
-
- page = BufferGetPage(b);
- memset(page, 0, (int) pageSize);
- PageInit(page, pageSize, sizeof(GISTPageOpaqueData));
-
- opaque = (GISTPageOpaque) PageGetSpecialPointer(page);
- opaque->flags = f;
+ GISTPageOpaque opaque;
+ Page page;
+ Size pageSize;
+
+ pageSize = BufferGetPageSize(b);
+
+ page = BufferGetPage(b);
+ memset(page, 0, (int) pageSize);
+ PageInit(page, pageSize, sizeof(GISTPageOpaqueData));
+
+ opaque = (GISTPageOpaque) PageGetSpecialPointer(page);
+ opaque->flags = f;
}
/*
** find entry with lowest penalty
*/
-static OffsetNumber
-gistchoose(Relation r, Page p, IndexTuple it, /* it has compressed entry */
- GISTSTATE *giststate)
+static OffsetNumber
+gistchoose(Relation r, Page p, IndexTuple it, /* it has compressed entry */
+ GISTSTATE * giststate)
{
- OffsetNumber maxoff;
- OffsetNumber i;
- char *id;
- char *datum;
- float usize;
- OffsetNumber which;
- float which_grow;
- GISTENTRY entry, identry;
- int size, idsize;
-
- idsize = IndexTupleSize(it) - sizeof(IndexTupleData);
- id = ((char *) it) + sizeof(IndexTupleData);
- maxoff = PageGetMaxOffsetNumber(p);
- which_grow = -1.0;
- which = -1;
-
- gistdentryinit(giststate,&identry,id,(Relation)NULL,(Page)NULL,
- (OffsetNumber)0, idsize, FALSE);
-
- for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) {
- datum = (char *) PageGetItem(p, PageGetItemId(p, i));
- size = IndexTupleSize(datum) - sizeof(IndexTupleData);
- datum += sizeof(IndexTupleData);
- gistdentryinit(giststate,&entry,datum,r,p,i,size,FALSE);
- (giststate->penaltyFn)(&entry, &identry, &usize);
- if (which_grow < 0 || usize < which_grow) {
- which = i;
- which_grow = usize;
- if (which_grow == 0)
- break;
+ OffsetNumber maxoff;
+ OffsetNumber i;
+ char *id;
+ char *datum;
+ float usize;
+ OffsetNumber which;
+ float which_grow;
+ GISTENTRY entry,
+ identry;
+ int size,
+ idsize;
+
+ idsize = IndexTupleSize(it) - sizeof(IndexTupleData);
+ id = ((char *) it) + sizeof(IndexTupleData);
+ maxoff = PageGetMaxOffsetNumber(p);
+ which_grow = -1.0;
+ which = -1;
+
+ gistdentryinit(giststate, &identry, id, (Relation) NULL, (Page) NULL,
+ (OffsetNumber) 0, idsize, FALSE);
+
+ for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
+ {
+ datum = (char *) PageGetItem(p, PageGetItemId(p, i));
+ size = IndexTupleSize(datum) - sizeof(IndexTupleData);
+ datum += sizeof(IndexTupleData);
+ gistdentryinit(giststate, &entry, datum, r, p, i, size, FALSE);
+ (giststate->penaltyFn) (&entry, &identry, &usize);
+ if (which_grow < 0 || usize < which_grow)
+ {
+ which = i;
+ which_grow = usize;
+ if (which_grow == 0)
+ break;
+ }
+ if (entry.pred != datum)
+ pfree(entry.pred);
}
- if (entry.pred != datum)
- pfree(entry.pred);
- }
- if (identry.pred != id)
- pfree(identry.pred);
-
- return (which);
+ if (identry.pred != id)
+ pfree(identry.pred);
+
+ return (which);
}
static int
gistnospace(Page p, IndexTuple it)
{
- return (PageGetFreeSpace(p) < IndexTupleSize(it));
+ return (PageGetFreeSpace(p) < IndexTupleSize(it));
}
void
-gistfreestack(GISTSTACK *s)
+gistfreestack(GISTSTACK * s)
{
- GISTSTACK *p;
-
- while (s != (GISTSTACK *) NULL) {
- p = s->gs_parent;
- pfree(s);
- s = p;
- }
+ GISTSTACK *p;
+
+ while (s != (GISTSTACK *) NULL)
+ {
+ p = s->gs_parent;
+ pfree(s);
+ s = p;
+ }
}
-/*
-** remove an entry from a page
+/*
+** remove an entry from a page
*/
void
gistdelete(Relation r, ItemPointer tid)
{
- BlockNumber blkno;
- OffsetNumber offnum;
- Buffer buf;
- Page page;
-
- /* must write-lock on delete */
- RelationSetLockForWrite(r);
-
- blkno = ItemPointerGetBlockNumber(tid);
- offnum = ItemPointerGetOffsetNumber(tid);
-
- /* adjust any scans that will be affected by this deletion */
- gistadjscans(r, GISTOP_DEL, blkno, offnum);
-
- /* delete the index tuple */
- buf = ReadBuffer(r, blkno);
- page = BufferGetPage(buf);
-
- PageIndexTupleDelete(page, offnum);
-
- WriteBuffer(buf);
-
- /* XXX -- two-phase locking, don't release the write lock */
+ BlockNumber blkno;
+ OffsetNumber offnum;
+ Buffer buf;
+ Page page;
+
+ /* must write-lock on delete */
+ RelationSetLockForWrite(r);
+
+ blkno = ItemPointerGetBlockNumber(tid);
+ offnum = ItemPointerGetOffsetNumber(tid);
+
+ /* adjust any scans that will be affected by this deletion */
+ gistadjscans(r, GISTOP_DEL, blkno, offnum);
+
+ /* delete the index tuple */
+ buf = ReadBuffer(r, blkno);
+ page = BufferGetPage(buf);
+
+ PageIndexTupleDelete(page, offnum);
+
+ WriteBuffer(buf);
+
+ /* XXX -- two-phase locking, don't release the write lock */
}
-void
-initGISTstate(GISTSTATE *giststate, Relation index)
+void
+initGISTstate(GISTSTATE * giststate, Relation index)
{
- RegProcedure consistent_proc, union_proc, compress_proc, decompress_proc;
- RegProcedure penalty_proc, picksplit_proc, equal_proc;
- func_ptr user_fn;
- int pronargs;
- HeapTuple htup;
- IndexTupleForm itupform;
-
- consistent_proc = index_getprocid(index, 1, GIST_CONSISTENT_PROC);
- union_proc = index_getprocid(index, 1, GIST_UNION_PROC);
- compress_proc = index_getprocid(index, 1, GIST_COMPRESS_PROC);
- decompress_proc = index_getprocid(index, 1, GIST_DECOMPRESS_PROC);
- penalty_proc = index_getprocid(index, 1, GIST_PENALTY_PROC);
- picksplit_proc = index_getprocid(index, 1, GIST_PICKSPLIT_PROC);
- equal_proc = index_getprocid(index, 1, GIST_EQUAL_PROC);
- fmgr_info(consistent_proc, &user_fn, &pronargs);
- giststate->consistentFn = user_fn;
- fmgr_info(union_proc, &user_fn, &pronargs);
- giststate->unionFn = user_fn;
- fmgr_info(compress_proc, &user_fn, &pronargs);
- giststate->compressFn = user_fn;
- fmgr_info(decompress_proc, &user_fn, &pronargs);
- giststate->decompressFn = user_fn;
- fmgr_info(penalty_proc, &user_fn, &pronargs);
- giststate->penaltyFn = user_fn;
- fmgr_info(picksplit_proc, &user_fn, &pronargs);
- giststate->picksplitFn = user_fn;
- fmgr_info(equal_proc, &user_fn, &pronargs);
- giststate->equalFn = user_fn;
-
- /* see if key type is different from type of attribute being indexed */
- htup = SearchSysCacheTuple(INDEXRELID, ObjectIdGetDatum(index->rd_id),
- 0,0,0);
- itupform = (IndexTupleForm)GETSTRUCT(htup);
- if (!HeapTupleIsValid(htup))
- elog(WARN, "initGISTstate: index %d not found", index->rd_id);
- giststate->haskeytype = itupform->indhaskeytype;
- if (giststate->haskeytype) {
- /* key type is different -- is it byval? */
- htup = SearchSysCacheTuple(ATTNUM,
- ObjectIdGetDatum(itupform->indexrelid),
- UInt16GetDatum(FirstOffsetNumber),
- 0,0);
- if (!HeapTupleIsValid(htup)) {
- elog(WARN, "initGISTstate: no attribute tuple %d %d",
- itupform->indexrelid, FirstOffsetNumber);
- return;
+ RegProcedure consistent_proc,
+ union_proc,
+ compress_proc,
+ decompress_proc;
+ RegProcedure penalty_proc,
+ picksplit_proc,
+ equal_proc;
+ func_ptr user_fn;
+ int pronargs;
+ HeapTuple htup;
+ IndexTupleForm itupform;
+
+ consistent_proc = index_getprocid(index, 1, GIST_CONSISTENT_PROC);
+ union_proc = index_getprocid(index, 1, GIST_UNION_PROC);
+ compress_proc = index_getprocid(index, 1, GIST_COMPRESS_PROC);
+ decompress_proc = index_getprocid(index, 1, GIST_DECOMPRESS_PROC);
+ penalty_proc = index_getprocid(index, 1, GIST_PENALTY_PROC);
+ picksplit_proc = index_getprocid(index, 1, GIST_PICKSPLIT_PROC);
+ equal_proc = index_getprocid(index, 1, GIST_EQUAL_PROC);
+ fmgr_info(consistent_proc, &user_fn, &pronargs);
+ giststate->consistentFn = user_fn;
+ fmgr_info(union_proc, &user_fn, &pronargs);
+ giststate->unionFn = user_fn;
+ fmgr_info(compress_proc, &user_fn, &pronargs);
+ giststate->compressFn = user_fn;
+ fmgr_info(decompress_proc, &user_fn, &pronargs);
+ giststate->decompressFn = user_fn;
+ fmgr_info(penalty_proc, &user_fn, &pronargs);
+ giststate->penaltyFn = user_fn;
+ fmgr_info(picksplit_proc, &user_fn, &pronargs);
+ giststate->picksplitFn = user_fn;
+ fmgr_info(equal_proc, &user_fn, &pronargs);
+ giststate->equalFn = user_fn;
+
+ /* see if key type is different from type of attribute being indexed */
+ htup = SearchSysCacheTuple(INDEXRELID, ObjectIdGetDatum(index->rd_id),
+ 0, 0, 0);
+ itupform = (IndexTupleForm) GETSTRUCT(htup);
+ if (!HeapTupleIsValid(htup))
+ elog(WARN, "initGISTstate: index %d not found", index->rd_id);
+ giststate->haskeytype = itupform->indhaskeytype;
+ if (giststate->haskeytype)
+ {
+ /* key type is different -- is it byval? */
+ htup = SearchSysCacheTuple(ATTNUM,
+ ObjectIdGetDatum(itupform->indexrelid),
+ UInt16GetDatum(FirstOffsetNumber),
+ 0, 0);
+ if (!HeapTupleIsValid(htup))
+ {
+ elog(WARN, "initGISTstate: no attribute tuple %d %d",
+ itupform->indexrelid, FirstOffsetNumber);
+ return;
+ }
+ giststate->keytypbyval = (((AttributeTupleForm) htup)->attbyval);
}
- giststate->keytypbyval = (((AttributeTupleForm)htup)->attbyval);
- }
- else
- giststate->keytypbyval = FALSE;
- return;
+ else
+ giststate->keytypbyval = FALSE;
+ return;
}
@@ -1118,56 +1209,61 @@ initGISTstate(GISTSTATE *giststate, Relation index)
** the key with another key, which may involve generating a new IndexTuple
** if the sizes don't match
*/
-static IndexTuple
+static IndexTuple
gist_tuple_replacekey(Relation r, GISTENTRY entry, IndexTuple t)
{
- char * datum = (((char *) t) + sizeof(IndexTupleData));
-
- /* if new entry fits in index tuple, copy it in */
- if (entry.bytes < IndexTupleSize(t) - sizeof(IndexTupleData)) {
- memcpy(datum, entry.pred, entry.bytes);
- /* clear out old size */
- t->t_info &= 0xe000;
- /* or in new size */
- t->t_info |= MAXALIGN(entry.bytes + sizeof(IndexTupleData));
-
- return(t);
- }
- else {
- /* generate a new index tuple for the compressed entry */
- TupleDesc tupDesc = r->rd_att;
- IndexTuple newtup;
- char *isnull;
- int blank;
-
- isnull = (char *) palloc(r->rd_rel->relnatts);
- for (blank = 0; blank < r->rd_rel->relnatts; blank++)
- isnull[blank] = ' ';
- newtup = (IndexTuple) index_formtuple(tupDesc,
- (Datum *)&(entry.pred),
- isnull);
- newtup->t_tid = t->t_tid;
- pfree(isnull);
- return(newtup);
- }
+ char *datum = (((char *) t) + sizeof(IndexTupleData));
+
+ /* if new entry fits in index tuple, copy it in */
+ if (entry.bytes < IndexTupleSize(t) - sizeof(IndexTupleData))
+ {
+ memcpy(datum, entry.pred, entry.bytes);
+ /* clear out old size */
+ t->t_info &= 0xe000;
+ /* or in new size */
+ t->t_info |= MAXALIGN(entry.bytes + sizeof(IndexTupleData));
+
+ return (t);
+ }
+ else
+ {
+ /* generate a new index tuple for the compressed entry */
+ TupleDesc tupDesc = r->rd_att;
+ IndexTuple newtup;
+ char *isnull;
+ int blank;
+
+ isnull = (char *) palloc(r->rd_rel->relnatts);
+ for (blank = 0; blank < r->rd_rel->relnatts; blank++)
+ isnull[blank] = ' ';
+ newtup = (IndexTuple) index_formtuple(tupDesc,
+ (Datum *) & (entry.pred),
+ isnull);
+ newtup->t_tid = t->t_tid;
+ pfree(isnull);
+ return (newtup);
+ }
}
-
+
/*
** initialize a GiST entry with a decompressed version of pred
*/
void
-gistdentryinit(GISTSTATE *giststate, GISTENTRY *e, char *pr, Relation r,
- Page pg, OffsetNumber o, int b, bool l)
-{
- GISTENTRY *dep;
- gistentryinit(*e, pr, r, pg, o, b, l);
- if (giststate->haskeytype) {
- dep = (GISTENTRY *)((giststate->decompressFn)(e));
- gistentryinit(*e, dep->pred, dep->rel, dep->page, dep->offset, dep->bytes,
- dep->leafkey);
- if (dep != e) pfree(dep);
- }
+gistdentryinit(GISTSTATE * giststate, GISTENTRY * e, char *pr, Relation r,
+ Page pg, OffsetNumber o, int b, bool l)
+{
+ GISTENTRY *dep;
+
+ gistentryinit(*e, pr, r, pg, o, b, l);
+ if (giststate->haskeytype)
+ {
+ dep = (GISTENTRY *) ((giststate->decompressFn) (e));
+ gistentryinit(*e, dep->pred, dep->rel, dep->page, dep->offset, dep->bytes,
+ dep->leafkey);
+ if (dep != e)
+ pfree(dep);
+ }
}
@@ -1175,19 +1271,22 @@ gistdentryinit(GISTSTATE *giststate, GISTENTRY *e, char *pr, Relation r,
** initialize a GiST entry with a compressed version of pred
*/
static void
-gistcentryinit(GISTSTATE *giststate, GISTENTRY *e, char *pr, Relation r,
- Page pg, OffsetNumber o, int b, bool l)
-{
- GISTENTRY *cep;
- gistentryinit(*e, pr, r, pg, o, b, l);
- if (giststate->haskeytype) {
- cep = (GISTENTRY *)((giststate->compressFn)(e));
- gistentryinit(*e, cep->pred, cep->rel, cep->page, cep->offset, cep->bytes,
- cep->leafkey);
- if (cep != e) pfree(cep);
- }
+gistcentryinit(GISTSTATE * giststate, GISTENTRY * e, char *pr, Relation r,
+ Page pg, OffsetNumber o, int b, bool l)
+{
+ GISTENTRY *cep;
+
+ gistentryinit(*e, pr, r, pg, o, b, l);
+ if (giststate->haskeytype)
+ {
+ cep = (GISTENTRY *) ((giststate->compressFn) (e));
+ gistentryinit(*e, cep->pred, cep->rel, cep->page, cep->offset, cep->bytes,
+ cep->leafkey);
+ if (cep != e)
+ pfree(cep);
+ }
}
-
+
#ifdef GISTDEBUG
@@ -1200,89 +1299,95 @@ gistcentryinit(GISTSTATE *giststate, GISTENTRY *e, char *pr, Relation r,
void
_gistdump(Relation r)
{
- Buffer buf;
- Page page;
- OffsetNumber offnum, maxoff;
- BlockNumber blkno;
- BlockNumber nblocks;
- GISTPageOpaque po;
- IndexTuple itup;
- BlockNumber itblkno;
- OffsetNumber itoffno;
- char *datum;
- char *itkey;
-
- nblocks = RelationGetNumberOfBlocks(r);
- for (blkno = 0; blkno < nblocks; blkno++) {
- buf = ReadBuffer(r, blkno);
- page = BufferGetPage(buf);
- po = (GISTPageOpaque) PageGetSpecialPointer(page);
- maxoff = PageGetMaxOffsetNumber(page);
- printf("Page %d maxoff %d <%s>\n", blkno, maxoff,
- (po->flags & F_LEAF ? "LEAF" : "INTERNAL"));
-
- if (PageIsEmpty(page)) {
- ReleaseBuffer(buf);
- continue;
- }
-
- for (offnum = FirstOffsetNumber;
- offnum <= maxoff;
- offnum = OffsetNumberNext(offnum)) {
- itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, offnum));
- itblkno = ItemPointerGetBlockNumber(&(itup->t_tid));
- itoffno = ItemPointerGetOffsetNumber(&(itup->t_tid));
- datum = ((char *) itup);
- datum += sizeof(IndexTupleData);
- /* get out function for type of key, and out it! */
- itkey = (char *) int_range_out((INTRANGE *)datum);
- /* itkey = " unable to print"; */
- printf("\t[%d] size %d heap <%d,%d> key:%s\n",
- offnum, IndexTupleSize(itup), itblkno, itoffno, itkey);
- pfree(itkey);
+ Buffer buf;
+ Page page;
+ OffsetNumber offnum,
+ maxoff;
+ BlockNumber blkno;
+ BlockNumber nblocks;
+ GISTPageOpaque po;
+ IndexTuple itup;
+ BlockNumber itblkno;
+ OffsetNumber itoffno;
+ char *datum;
+ char *itkey;
+
+ nblocks = RelationGetNumberOfBlocks(r);
+ for (blkno = 0; blkno < nblocks; blkno++)
+ {
+ buf = ReadBuffer(r, blkno);
+ page = BufferGetPage(buf);
+ po = (GISTPageOpaque) PageGetSpecialPointer(page);
+ maxoff = PageGetMaxOffsetNumber(page);
+ printf("Page %d maxoff %d <%s>\n", blkno, maxoff,
+ (po->flags & F_LEAF ? "LEAF" : "INTERNAL"));
+
+ if (PageIsEmpty(page))
+ {
+ ReleaseBuffer(buf);
+ continue;
+ }
+
+ for (offnum = FirstOffsetNumber;
+ offnum <= maxoff;
+ offnum = OffsetNumberNext(offnum))
+ {
+ itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, offnum));
+ itblkno = ItemPointerGetBlockNumber(&(itup->t_tid));
+ itoffno = ItemPointerGetOffsetNumber(&(itup->t_tid));
+ datum = ((char *) itup);
+ datum += sizeof(IndexTupleData);
+ /* get out function for type of key, and out it! */
+ itkey = (char *) int_range_out((INTRANGE *) datum);
+ /* itkey = " unable to print"; */
+ printf("\t[%d] size %d heap <%d,%d> key:%s\n",
+ offnum, IndexTupleSize(itup), itblkno, itoffno, itkey);
+ pfree(itkey);
+ }
+
+ ReleaseBuffer(buf);
}
-
- ReleaseBuffer(buf);
- }
}
#ifdef NOT_USED
-static char *text_range_out(TXTRANGE *r)
+static char *
+text_range_out(TXTRANGE * r)
{
- char *result;
- char *lower, *upper;
-
- if (r == NULL)
- return(NULL);
- result = (char *)palloc(16 + VARSIZE(TRLOWER(r)) + VARSIZE(TRUPPER(r))
- - 2*VARHDRSZ);
-
- lower = (char *)palloc(VARSIZE(TRLOWER(r)) + 1 - VARHDRSZ);
- memcpy(lower, VARDATA(TRLOWER(r)), VARSIZE(TRLOWER(r)) - VARHDRSZ);
- lower[VARSIZE(TRLOWER(r)) - VARHDRSZ] = '\0';
- upper = (char *)palloc(VARSIZE(TRUPPER(r)) + 1 - VARHDRSZ);
- memcpy(upper, VARDATA(TRUPPER(r)), VARSIZE(TRUPPER(r)) - VARHDRSZ);
- upper[VARSIZE(TRUPPER(r)) - VARHDRSZ] = '\0';
-
- sprintf(result, "[%s,%s): %d", lower, upper, r->flag);
- pfree(lower);
- pfree(upper);
- return(result);
+ char *result;
+ char *lower,
+ *upper;
+
+ if (r == NULL)
+ return (NULL);
+ result = (char *) palloc(16 + VARSIZE(TRLOWER(r)) + VARSIZE(TRUPPER(r))
+ - 2 * VARHDRSZ);
+
+ lower = (char *) palloc(VARSIZE(TRLOWER(r)) + 1 - VARHDRSZ);
+ memcpy(lower, VARDATA(TRLOWER(r)), VARSIZE(TRLOWER(r)) - VARHDRSZ);
+ lower[VARSIZE(TRLOWER(r)) - VARHDRSZ] = '\0';
+ upper = (char *) palloc(VARSIZE(TRUPPER(r)) + 1 - VARHDRSZ);
+ memcpy(upper, VARDATA(TRUPPER(r)), VARSIZE(TRUPPER(r)) - VARHDRSZ);
+ upper[VARSIZE(TRUPPER(r)) - VARHDRSZ] = '\0';
+
+ sprintf(result, "[%s,%s): %d", lower, upper, r->flag);
+ pfree(lower);
+ pfree(upper);
+ return (result);
}
+
#endif
-static char *
-int_range_out(INTRANGE *r)
+static char *
+int_range_out(INTRANGE * r)
{
- char *result;
-
- if (r == NULL)
- return(NULL);
- result = (char *)palloc(80);
- sprintf(result, "[%d,%d): %d",r->lower, r->upper, r->flag);
-
- return(result);
-}
+ char *result;
+
+ if (r == NULL)
+ return (NULL);
+ result = (char *) palloc(80);
+ sprintf(result, "[%d,%d): %d", r->lower, r->upper, r->flag);
-#endif /* defined GISTDEBUG */
+ return (result);
+}
+#endif /* defined GISTDEBUG */
diff --git a/src/backend/access/gist/gistget.c b/src/backend/access/gist/gistget.c
index ac1697e5ed2..cad4cef267e 100644
--- a/src/backend/access/gist/gistget.c
+++ b/src/backend/access/gist/gistget.c
@@ -1,12 +1,12 @@
/*-------------------------------------------------------------------------
*
* gistget.c--
- * fetch tuples from a GiST scan.
+ * fetch tuples from a GiST scan.
*
*
*
* IDENTIFICATION
- * /usr/local/devel/pglite/cvs/src/backend/access/gisr/gistget.c,v 1.9.1 1996/11/21 01:00:00 vadim Exp
+ * /usr/local/devel/pglite/cvs/src/backend/access/gisr/gistget.c,v 1.9.1 1996/11/21 01:00:00 vadim Exp
*
*-------------------------------------------------------------------------
*/
@@ -22,350 +22,392 @@
#include <storage/bufmgr.h>
#ifndef HAVE_MEMMOVE
-# include <regex/utils.h>
+#include <regex/utils.h>
#else
-# include <string.h>
+#include <string.h>
#endif
-static OffsetNumber gistfindnext(IndexScanDesc s, Page p, OffsetNumber n,
- ScanDirection dir);
+static OffsetNumber
+gistfindnext(IndexScanDesc s, Page p, OffsetNumber n,
+ ScanDirection dir);
static RetrieveIndexResult gistscancache(IndexScanDesc s, ScanDirection dir);
static RetrieveIndexResult gistfirst(IndexScanDesc s, ScanDirection dir);
static RetrieveIndexResult gistnext(IndexScanDesc s, ScanDirection dir);
static ItemPointer gistheapptr(Relation r, ItemPointer itemp);
-static bool gistindex_keytest(IndexTuple tuple, TupleDesc tupdesc,
- int scanKeySize, ScanKey key, GISTSTATE *giststate,
- Relation r, Page p, OffsetNumber offset);
+static bool
+gistindex_keytest(IndexTuple tuple, TupleDesc tupdesc,
+ int scanKeySize, ScanKey key, GISTSTATE * giststate,
+ Relation r, Page p, OffsetNumber offset);
RetrieveIndexResult
gistgettuple(IndexScanDesc s, ScanDirection dir)
{
- RetrieveIndexResult res;
-
- /* if we have it cached in the scan desc, just return the value */
- if ((res = gistscancache(s, dir)) != (RetrieveIndexResult) NULL)
+ RetrieveIndexResult res;
+
+ /* if we have it cached in the scan desc, just return the value */
+ if ((res = gistscancache(s, dir)) != (RetrieveIndexResult) NULL)
+ return (res);
+
+ /* not cached, so we'll have to do some work */
+ if (ItemPointerIsValid(&(s->currentItemData)))
+ {
+ res = gistnext(s, dir);
+ }
+ else
+ {
+ res = gistfirst(s, dir);
+ }
return (res);
-
- /* not cached, so we'll have to do some work */
- if (ItemPointerIsValid(&(s->currentItemData))) {
- res = gistnext(s, dir);
- } else {
- res = gistfirst(s, dir);
- }
- return (res);
}
-static RetrieveIndexResult
+static RetrieveIndexResult
gistfirst(IndexScanDesc s, ScanDirection dir)
{
- Buffer b;
- Page p;
- OffsetNumber n;
- OffsetNumber maxoff;
- RetrieveIndexResult res;
- GISTPageOpaque po;
- GISTScanOpaque so;
- GISTSTACK *stk;
- BlockNumber blk;
- IndexTuple it;
-
- b = ReadBuffer(s->relation, GISTP_ROOT);
- p = BufferGetPage(b);
- po = (GISTPageOpaque) PageGetSpecialPointer(p);
- so = (GISTScanOpaque) s->opaque;
-
- for (;;) {
- maxoff = PageGetMaxOffsetNumber(p);
- if (ScanDirectionIsBackward(dir))
- n = gistfindnext(s, p, maxoff, dir);
- else
- n = gistfindnext(s, p, FirstOffsetNumber, dir);
-
- while (n < FirstOffsetNumber || n > maxoff) {
-
- ReleaseBuffer(b);
- if (so->s_stack == (GISTSTACK *) NULL)
- return ((RetrieveIndexResult) NULL);
-
- stk = so->s_stack;
- b = ReadBuffer(s->relation, stk->gs_blk);
- p = BufferGetPage(b);
- po = (GISTPageOpaque) PageGetSpecialPointer(p);
- maxoff = PageGetMaxOffsetNumber(p);
-
- if (ScanDirectionIsBackward(dir)) {
- n = OffsetNumberPrev(stk->gs_child);
- } else {
- n = OffsetNumberNext(stk->gs_child);
- }
- so->s_stack = stk->gs_parent;
- pfree(stk);
-
- n = gistfindnext(s, p, n, dir);
- }
- if (po->flags & F_LEAF) {
- ItemPointerSet(&(s->currentItemData), BufferGetBlockNumber(b), n);
-
- it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));
-
- res = FormRetrieveIndexResult(&(s->currentItemData), &(it->t_tid));
-
- ReleaseBuffer(b);
- return (res);
- } else {
- stk = (GISTSTACK *) palloc(sizeof(GISTSTACK));
- stk->gs_child = n;
- stk->gs_blk = BufferGetBlockNumber(b);
- stk->gs_parent = so->s_stack;
- so->s_stack = stk;
-
- it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));
- blk = ItemPointerGetBlockNumber(&(it->t_tid));
-
- ReleaseBuffer(b);
- b = ReadBuffer(s->relation, blk);
- p = BufferGetPage(b);
- po = (GISTPageOpaque) PageGetSpecialPointer(p);
+ Buffer b;
+ Page p;
+ OffsetNumber n;
+ OffsetNumber maxoff;
+ RetrieveIndexResult res;
+ GISTPageOpaque po;
+ GISTScanOpaque so;
+ GISTSTACK *stk;
+ BlockNumber blk;
+ IndexTuple it;
+
+ b = ReadBuffer(s->relation, GISTP_ROOT);
+ p = BufferGetPage(b);
+ po = (GISTPageOpaque) PageGetSpecialPointer(p);
+ so = (GISTScanOpaque) s->opaque;
+
+ for (;;)
+ {
+ maxoff = PageGetMaxOffsetNumber(p);
+ if (ScanDirectionIsBackward(dir))
+ n = gistfindnext(s, p, maxoff, dir);
+ else
+ n = gistfindnext(s, p, FirstOffsetNumber, dir);
+
+ while (n < FirstOffsetNumber || n > maxoff)
+ {
+
+ ReleaseBuffer(b);
+ if (so->s_stack == (GISTSTACK *) NULL)
+ return ((RetrieveIndexResult) NULL);
+
+ stk = so->s_stack;
+ b = ReadBuffer(s->relation, stk->gs_blk);
+ p = BufferGetPage(b);
+ po = (GISTPageOpaque) PageGetSpecialPointer(p);
+ maxoff = PageGetMaxOffsetNumber(p);
+
+ if (ScanDirectionIsBackward(dir))
+ {
+ n = OffsetNumberPrev(stk->gs_child);
+ }
+ else
+ {
+ n = OffsetNumberNext(stk->gs_child);
+ }
+ so->s_stack = stk->gs_parent;
+ pfree(stk);
+
+ n = gistfindnext(s, p, n, dir);
+ }
+ if (po->flags & F_LEAF)
+ {
+ ItemPointerSet(&(s->currentItemData), BufferGetBlockNumber(b), n);
+
+ it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));
+
+ res = FormRetrieveIndexResult(&(s->currentItemData), &(it->t_tid));
+
+ ReleaseBuffer(b);
+ return (res);
+ }
+ else
+ {
+ stk = (GISTSTACK *) palloc(sizeof(GISTSTACK));
+ stk->gs_child = n;
+ stk->gs_blk = BufferGetBlockNumber(b);
+ stk->gs_parent = so->s_stack;
+ so->s_stack = stk;
+
+ it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));
+ blk = ItemPointerGetBlockNumber(&(it->t_tid));
+
+ ReleaseBuffer(b);
+ b = ReadBuffer(s->relation, blk);
+ p = BufferGetPage(b);
+ po = (GISTPageOpaque) PageGetSpecialPointer(p);
+ }
}
- }
}
-static RetrieveIndexResult
+static RetrieveIndexResult
gistnext(IndexScanDesc s, ScanDirection dir)
{
- Buffer b;
- Page p;
- OffsetNumber n;
- OffsetNumber maxoff;
- RetrieveIndexResult res;
- GISTPageOpaque po;
- GISTScanOpaque so;
- GISTSTACK *stk;
- BlockNumber blk;
- IndexTuple it;
-
- blk = ItemPointerGetBlockNumber(&(s->currentItemData));
- n = ItemPointerGetOffsetNumber(&(s->currentItemData));
-
- if (ScanDirectionIsForward(dir)) {
- n = OffsetNumberNext(n);
- } else {
- n = OffsetNumberPrev(n);
- }
-
- b = ReadBuffer(s->relation, blk);
- p = BufferGetPage(b);
- po = (GISTPageOpaque) PageGetSpecialPointer(p);
- so = (GISTScanOpaque) s->opaque;
-
- for (;;) {
- maxoff = PageGetMaxOffsetNumber(p);
- n = gistfindnext(s, p, n, dir);
-
- while (n < FirstOffsetNumber || n > maxoff) {
-
- ReleaseBuffer(b);
- if (so->s_stack == (GISTSTACK *) NULL)
- return ((RetrieveIndexResult) NULL);
-
- stk = so->s_stack;
- b = ReadBuffer(s->relation, stk->gs_blk);
- p = BufferGetPage(b);
- maxoff = PageGetMaxOffsetNumber(p);
- po = (GISTPageOpaque) PageGetSpecialPointer(p);
-
- if (ScanDirectionIsBackward(dir)) {
- n = OffsetNumberPrev(stk->gs_child);
- } else {
- n = OffsetNumberNext(stk->gs_child);
- }
- so->s_stack = stk->gs_parent;
- pfree(stk);
-
- n = gistfindnext(s, p, n, dir);
+ Buffer b;
+ Page p;
+ OffsetNumber n;
+ OffsetNumber maxoff;
+ RetrieveIndexResult res;
+ GISTPageOpaque po;
+ GISTScanOpaque so;
+ GISTSTACK *stk;
+ BlockNumber blk;
+ IndexTuple it;
+
+ blk = ItemPointerGetBlockNumber(&(s->currentItemData));
+ n = ItemPointerGetOffsetNumber(&(s->currentItemData));
+
+ if (ScanDirectionIsForward(dir))
+ {
+ n = OffsetNumberNext(n);
+ }
+ else
+ {
+ n = OffsetNumberPrev(n);
}
- if (po->flags & F_LEAF) {
- ItemPointerSet(&(s->currentItemData), BufferGetBlockNumber(b), n);
-
- it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));
-
- res = FormRetrieveIndexResult(&(s->currentItemData), &(it->t_tid));
-
- ReleaseBuffer(b);
- return (res);
- } else {
- stk = (GISTSTACK *) palloc(sizeof(GISTSTACK));
- stk->gs_child = n;
- stk->gs_blk = BufferGetBlockNumber(b);
- stk->gs_parent = so->s_stack;
- so->s_stack = stk;
-
- it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));
- blk = ItemPointerGetBlockNumber(&(it->t_tid));
-
- ReleaseBuffer(b);
- b = ReadBuffer(s->relation, blk);
- p = BufferGetPage(b);
- po = (GISTPageOpaque) PageGetSpecialPointer(p);
-
- if (ScanDirectionIsBackward(dir)) {
- n = PageGetMaxOffsetNumber(p);
- } else {
- n = FirstOffsetNumber;
- }
+
+ b = ReadBuffer(s->relation, blk);
+ p = BufferGetPage(b);
+ po = (GISTPageOpaque) PageGetSpecialPointer(p);
+ so = (GISTScanOpaque) s->opaque;
+
+ for (;;)
+ {
+ maxoff = PageGetMaxOffsetNumber(p);
+ n = gistfindnext(s, p, n, dir);
+
+ while (n < FirstOffsetNumber || n > maxoff)
+ {
+
+ ReleaseBuffer(b);
+ if (so->s_stack == (GISTSTACK *) NULL)
+ return ((RetrieveIndexResult) NULL);
+
+ stk = so->s_stack;
+ b = ReadBuffer(s->relation, stk->gs_blk);
+ p = BufferGetPage(b);
+ maxoff = PageGetMaxOffsetNumber(p);
+ po = (GISTPageOpaque) PageGetSpecialPointer(p);
+
+ if (ScanDirectionIsBackward(dir))
+ {
+ n = OffsetNumberPrev(stk->gs_child);
+ }
+ else
+ {
+ n = OffsetNumberNext(stk->gs_child);
+ }
+ so->s_stack = stk->gs_parent;
+ pfree(stk);
+
+ n = gistfindnext(s, p, n, dir);
+ }
+ if (po->flags & F_LEAF)
+ {
+ ItemPointerSet(&(s->currentItemData), BufferGetBlockNumber(b), n);
+
+ it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));
+
+ res = FormRetrieveIndexResult(&(s->currentItemData), &(it->t_tid));
+
+ ReleaseBuffer(b);
+ return (res);
+ }
+ else
+ {
+ stk = (GISTSTACK *) palloc(sizeof(GISTSTACK));
+ stk->gs_child = n;
+ stk->gs_blk = BufferGetBlockNumber(b);
+ stk->gs_parent = so->s_stack;
+ so->s_stack = stk;
+
+ it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));
+ blk = ItemPointerGetBlockNumber(&(it->t_tid));
+
+ ReleaseBuffer(b);
+ b = ReadBuffer(s->relation, blk);
+ p = BufferGetPage(b);
+ po = (GISTPageOpaque) PageGetSpecialPointer(p);
+
+ if (ScanDirectionIsBackward(dir))
+ {
+ n = PageGetMaxOffsetNumber(p);
+ }
+ else
+ {
+ n = FirstOffsetNumber;
+ }
+ }
}
- }
}
/* Similar to index_keytest, but decompresses the key in the IndexTuple */
-static bool
+static bool
gistindex_keytest(IndexTuple tuple,
- TupleDesc tupdesc,
- int scanKeySize,
- ScanKey key,
- GISTSTATE *giststate,
- Relation r,
- Page p,
- OffsetNumber offset)
+ TupleDesc tupdesc,
+ int scanKeySize,
+ ScanKey key,
+ GISTSTATE * giststate,
+ Relation r,
+ Page p,
+ OffsetNumber offset)
{
- bool isNull;
- Datum datum;
- int test;
- GISTENTRY de;
-
- IncrIndexProcessed();
-
-
- while (scanKeySize > 0) {
- datum = index_getattr(tuple,
- 1,
- tupdesc,
- &isNull);
- gistdentryinit(giststate, &de, (char *)datum, r, p, offset,
- IndexTupleSize(tuple) - sizeof(IndexTupleData),
- FALSE);
-
- if (isNull) {
- /* XXX eventually should check if SK_ISNULL */
- return (false);
- }
-
- if (key[0].sk_flags & SK_COMMUTE) {
- test = (*(key[0].sk_func))
- (DatumGetPointer(key[0].sk_argument),
- &de, key[0].sk_procedure) ? 1 : 0;
- } else {
- test = (*(key[0].sk_func))
- (&de,
- DatumGetPointer(key[0].sk_argument),
- key[0].sk_procedure) ? 1 : 0;
- }
-
- if (!test == !(key[0].sk_flags & SK_NEGATE)) {
- return (false);
+ bool isNull;
+ Datum datum;
+ int test;
+ GISTENTRY de;
+
+ IncrIndexProcessed();
+
+
+ while (scanKeySize > 0)
+ {
+ datum = index_getattr(tuple,
+ 1,
+ tupdesc,
+ &isNull);
+ gistdentryinit(giststate, &de, (char *) datum, r, p, offset,
+ IndexTupleSize(tuple) - sizeof(IndexTupleData),
+ FALSE);
+
+ if (isNull)
+ {
+ /* XXX eventually should check if SK_ISNULL */
+ return (false);
+ }
+
+ if (key[0].sk_flags & SK_COMMUTE)
+ {
+ test = (*(key[0].sk_func))
+ (DatumGetPointer(key[0].sk_argument),
+ &de, key[0].sk_procedure) ? 1 : 0;
+ }
+ else
+ {
+ test = (*(key[0].sk_func))
+ (&de,
+ DatumGetPointer(key[0].sk_argument),
+ key[0].sk_procedure) ? 1 : 0;
+ }
+
+ if (!test == !(key[0].sk_flags & SK_NEGATE))
+ {
+ return (false);
+ }
+
+ scanKeySize -= 1;
+ key++;
}
-
- scanKeySize -= 1;
- key++;
- }
-
- return (true);
+
+ return (true);
}
-static OffsetNumber
+static OffsetNumber
gistfindnext(IndexScanDesc s, Page p, OffsetNumber n, ScanDirection dir)
{
- OffsetNumber maxoff;
- char *it;
- GISTPageOpaque po;
- GISTScanOpaque so;
- GISTSTATE *giststate;
-
- maxoff = PageGetMaxOffsetNumber(p);
- po = (GISTPageOpaque) PageGetSpecialPointer(p);
- so = (GISTScanOpaque) s->opaque;
- giststate = so->giststate;
-
- /*
- * If we modified the index during the scan, we may have a pointer to
- * a ghost tuple, before the scan. If this is the case, back up one.
- */
-
- if (so->s_flags & GS_CURBEFORE) {
- so->s_flags &= ~GS_CURBEFORE;
- n = OffsetNumberPrev(n);
- }
-
- while (n >= FirstOffsetNumber && n <= maxoff) {
- it = (char *) PageGetItem(p, PageGetItemId(p, n));
- if (gistindex_keytest((IndexTuple) it,
- RelationGetTupleDescriptor(s->relation),
- s->numberOfKeys, s->keyData, giststate,
- s->relation, p, n))
- break;
-
- if (ScanDirectionIsBackward(dir)) {
- n = OffsetNumberPrev(n);
- } else {
- n = OffsetNumberNext(n);
+ OffsetNumber maxoff;
+ char *it;
+ GISTPageOpaque po;
+ GISTScanOpaque so;
+ GISTSTATE *giststate;
+
+ maxoff = PageGetMaxOffsetNumber(p);
+ po = (GISTPageOpaque) PageGetSpecialPointer(p);
+ so = (GISTScanOpaque) s->opaque;
+ giststate = so->giststate;
+
+ /*
+ * If we modified the index during the scan, we may have a pointer to
+ * a ghost tuple, before the scan. If this is the case, back up one.
+ */
+
+ if (so->s_flags & GS_CURBEFORE)
+ {
+ so->s_flags &= ~GS_CURBEFORE;
+ n = OffsetNumberPrev(n);
}
- }
-
- return (n);
+
+ while (n >= FirstOffsetNumber && n <= maxoff)
+ {
+ it = (char *) PageGetItem(p, PageGetItemId(p, n));
+ if (gistindex_keytest((IndexTuple) it,
+ RelationGetTupleDescriptor(s->relation),
+ s->numberOfKeys, s->keyData, giststate,
+ s->relation, p, n))
+ break;
+
+ if (ScanDirectionIsBackward(dir))
+ {
+ n = OffsetNumberPrev(n);
+ }
+ else
+ {
+ n = OffsetNumberNext(n);
+ }
+ }
+
+ return (n);
}
-static RetrieveIndexResult
+static RetrieveIndexResult
gistscancache(IndexScanDesc s, ScanDirection dir)
{
- RetrieveIndexResult res;
- ItemPointer ip;
-
- if (!(ScanDirectionIsNoMovement(dir)
- && ItemPointerIsValid(&(s->currentItemData)))) {
-
- return ((RetrieveIndexResult) NULL);
- }
-
- ip = gistheapptr(s->relation, &(s->currentItemData));
-
- if (ItemPointerIsValid(ip))
- res = FormRetrieveIndexResult(&(s->currentItemData), ip);
- else
- res = (RetrieveIndexResult) NULL;
-
- pfree (ip);
-
- return (res);
+ RetrieveIndexResult res;
+ ItemPointer ip;
+
+ if (!(ScanDirectionIsNoMovement(dir)
+ && ItemPointerIsValid(&(s->currentItemData))))
+ {
+
+ return ((RetrieveIndexResult) NULL);
+ }
+
+ ip = gistheapptr(s->relation, &(s->currentItemData));
+
+ if (ItemPointerIsValid(ip))
+ res = FormRetrieveIndexResult(&(s->currentItemData), ip);
+ else
+ res = (RetrieveIndexResult) NULL;
+
+ pfree(ip);
+
+ return (res);
}
/*
- * gistheapptr returns the item pointer to the tuple in the heap relation
- * for which itemp is the index relation item pointer.
+ * gistheapptr returns the item pointer to the tuple in the heap relation
+ * for which itemp is the index relation item pointer.
*/
-static ItemPointer
+static ItemPointer
gistheapptr(Relation r, ItemPointer itemp)
{
- Buffer b;
- Page p;
- IndexTuple it;
- ItemPointer ip;
- OffsetNumber n;
-
- ip = (ItemPointer) palloc(sizeof(ItemPointerData));
- if (ItemPointerIsValid(itemp)) {
- b = ReadBuffer(r, ItemPointerGetBlockNumber(itemp));
- p = BufferGetPage(b);
- n = ItemPointerGetOffsetNumber(itemp);
- it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));
- memmove((char *) ip, (char *) &(it->t_tid),
- sizeof(ItemPointerData));
- ReleaseBuffer(b);
- } else {
- ItemPointerSetInvalid(ip);
- }
-
- return (ip);
+ Buffer b;
+ Page p;
+ IndexTuple it;
+ ItemPointer ip;
+ OffsetNumber n;
+
+ ip = (ItemPointer) palloc(sizeof(ItemPointerData));
+ if (ItemPointerIsValid(itemp))
+ {
+ b = ReadBuffer(r, ItemPointerGetBlockNumber(itemp));
+ p = BufferGetPage(b);
+ n = ItemPointerGetOffsetNumber(itemp);
+ it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));
+ memmove((char *) ip, (char *) &(it->t_tid),
+ sizeof(ItemPointerData));
+ ReleaseBuffer(b);
+ }
+ else
+ {
+ ItemPointerSetInvalid(ip);
+ }
+
+ return (ip);
}
diff --git a/src/backend/access/gist/gistscan.c b/src/backend/access/gist/gistscan.c
index c877538472c..ec680558d88 100644
--- a/src/backend/access/gist/gistscan.c
+++ b/src/backend/access/gist/gistscan.c
@@ -1,11 +1,11 @@
/*-------------------------------------------------------------------------
*
* gistscan.c--
- * routines to manage scans on index relations
+ * routines to manage scans on index relations
*
*
* IDENTIFICATION
- * /usr/local/devel/pglite/cvs/src/backend/access/gist/gistscan.c,v 1.7 1995/06/14 00:10:05 jolly Exp
+ * /usr/local/devel/pglite/cvs/src/backend/access/gist/gistscan.c,v 1.7 1995/06/14 00:10:05 jolly Exp
*
*-------------------------------------------------------------------------
*/
@@ -18,375 +18,411 @@
#include <access/rtree.h>
#include <storage/bufmgr.h>
#include <access/giststrat.h>
-#include <storage/lmgr.h>
+#include <storage/lmgr.h>
#ifndef HAVE_MEMMOVE
-# include <regex/utils.h>
+#include <regex/utils.h>
#else
-# include <string.h>
+#include <string.h>
#endif
/* routines defined and used here */
-static void gistregscan(IndexScanDesc s);
-static void gistdropscan(IndexScanDesc s);
-static void gistadjone(IndexScanDesc s, int op, BlockNumber blkno,
- OffsetNumber offnum);
-static void adjuststack(GISTSTACK *stk, BlockNumber blkno,
+static void gistregscan(IndexScanDesc s);
+static void gistdropscan(IndexScanDesc s);
+static void
+gistadjone(IndexScanDesc s, int op, BlockNumber blkno,
+ OffsetNumber offnum);
+static void
+adjuststack(GISTSTACK * stk, BlockNumber blkno,
OffsetNumber offnum);
-static void adjustiptr(IndexScanDesc s, ItemPointer iptr,
- int op, BlockNumber blkno, OffsetNumber offnum);
+static void
+adjustiptr(IndexScanDesc s, ItemPointer iptr,
+ int op, BlockNumber blkno, OffsetNumber offnum);
/*
- * Whenever we start a GiST scan in a backend, we register it in private
- * space. Then if the GiST index gets updated, we check all registered
- * scans and adjust them if the tuple they point at got moved by the
- * update. We only need to do this in private space, because when we update
- * an GiST we have a write lock on the tree, so no other process can have
- * any locks at all on it. A single transaction can have write and read
- * locks on the same object, so that's why we need to handle this case.
+ * Whenever we start a GiST scan in a backend, we register it in private
+ * space. Then if the GiST index gets updated, we check all registered
+ * scans and adjust them if the tuple they point at got moved by the
+ * update. We only need to do this in private space, because when we update
+ * an GiST we have a write lock on the tree, so no other process can have
+ * any locks at all on it. A single transaction can have write and read
+ * locks on the same object, so that's why we need to handle this case.
*/
-typedef struct GISTScanListData {
- IndexScanDesc gsl_scan;
- struct GISTScanListData *gsl_next;
-} GISTScanListData;
+typedef struct GISTScanListData
+{
+ IndexScanDesc gsl_scan;
+ struct GISTScanListData *gsl_next;
+} GISTScanListData;
-typedef GISTScanListData *GISTScanList;
+typedef GISTScanListData *GISTScanList;
/* pointer to list of local scans on GiSTs */
static GISTScanList GISTScans = (GISTScanList) NULL;
-
+
IndexScanDesc
gistbeginscan(Relation r,
- bool fromEnd,
- uint16 nkeys,
- ScanKey key)
+ bool fromEnd,
+ uint16 nkeys,
+ ScanKey key)
{
- IndexScanDesc s;
-
- RelationSetLockForRead(r);
- s = RelationGetIndexScan(r, fromEnd, nkeys, key);
- gistregscan(s);
-
- return (s);
+ IndexScanDesc s;
+
+ RelationSetLockForRead(r);
+ s = RelationGetIndexScan(r, fromEnd, nkeys, key);
+ gistregscan(s);
+
+ return (s);
}
void
gistrescan(IndexScanDesc s, bool fromEnd, ScanKey key)
{
- GISTScanOpaque p;
- int i;
-
- if (!IndexScanIsValid(s)) {
- elog(WARN, "gistrescan: invalid scan.");
- return;
- }
-
- /*
- * Clear all the pointers.
- */
-
- ItemPointerSetInvalid(&s->previousItemData);
- ItemPointerSetInvalid(&s->currentItemData);
- ItemPointerSetInvalid(&s->nextItemData);
- ItemPointerSetInvalid(&s->previousMarkData);
- ItemPointerSetInvalid(&s->currentMarkData);
- ItemPointerSetInvalid(&s->nextMarkData);
-
- /*
- * Set flags.
- */
- if (RelationGetNumberOfBlocks(s->relation) == 0) {
- s->flags = ScanUnmarked;
- } else if (fromEnd) {
- s->flags = ScanUnmarked | ScanUncheckedPrevious;
- } else {
- s->flags = ScanUnmarked | ScanUncheckedNext;
- }
-
- s->scanFromEnd = fromEnd;
-
- if (s->numberOfKeys > 0) {
- memmove(s->keyData,
- key,
- s->numberOfKeys * sizeof(ScanKeyData));
- }
-
- p = (GISTScanOpaque) s->opaque;
- if (p != (GISTScanOpaque) NULL) {
- gistfreestack(p->s_stack);
- gistfreestack(p->s_markstk);
- p->s_stack = p->s_markstk = (GISTSTACK *) NULL;
- p->s_flags = 0x0;
- for (i = 0; i < s->numberOfKeys; i++)
+ GISTScanOpaque p;
+ int i;
+
+ if (!IndexScanIsValid(s))
{
- s->keyData[i].sk_procedure
- = RelationGetGISTStrategy(s->relation, s->keyData[i].sk_attno,
- s->keyData[i].sk_procedure);
- s->keyData[i].sk_func = p->giststate->consistentFn;
+ elog(WARN, "gistrescan: invalid scan.");
+ return;
+ }
+
+ /*
+ * Clear all the pointers.
+ */
+
+ ItemPointerSetInvalid(&s->previousItemData);
+ ItemPointerSetInvalid(&s->currentItemData);
+ ItemPointerSetInvalid(&s->nextItemData);
+ ItemPointerSetInvalid(&s->previousMarkData);
+ ItemPointerSetInvalid(&s->currentMarkData);
+ ItemPointerSetInvalid(&s->nextMarkData);
+
+ /*
+ * Set flags.
+ */
+ if (RelationGetNumberOfBlocks(s->relation) == 0)
+ {
+ s->flags = ScanUnmarked;
+ }
+ else if (fromEnd)
+ {
+ s->flags = ScanUnmarked | ScanUncheckedPrevious;
+ }
+ else
+ {
+ s->flags = ScanUnmarked | ScanUncheckedNext;
+ }
+
+ s->scanFromEnd = fromEnd;
+
+ if (s->numberOfKeys > 0)
+ {
+ memmove(s->keyData,
+ key,
+ s->numberOfKeys * sizeof(ScanKeyData));
+ }
+
+ p = (GISTScanOpaque) s->opaque;
+ if (p != (GISTScanOpaque) NULL)
+ {
+ gistfreestack(p->s_stack);
+ gistfreestack(p->s_markstk);
+ p->s_stack = p->s_markstk = (GISTSTACK *) NULL;
+ p->s_flags = 0x0;
+ for (i = 0; i < s->numberOfKeys; i++)
+ {
+ s->keyData[i].sk_procedure
+ = RelationGetGISTStrategy(s->relation, s->keyData[i].sk_attno,
+ s->keyData[i].sk_procedure);
+ s->keyData[i].sk_func = p->giststate->consistentFn;
+ }
+ }
+ else
+ {
+ /* initialize opaque data */
+ p = (GISTScanOpaque) palloc(sizeof(GISTScanOpaqueData));
+ p->s_stack = p->s_markstk = (GISTSTACK *) NULL;
+ p->s_flags = 0x0;
+ s->opaque = p;
+ p->giststate = (GISTSTATE *) palloc(sizeof(GISTSTATE));
+ initGISTstate(p->giststate, s->relation);
+ if (s->numberOfKeys > 0)
+
+ /*
+ * * Play games here with the scan key to use the Consistent *
+ * function for all comparisons: * 1) the sk_procedure field
+ * will now be used to hold the * strategy number * 2) the
+ * sk_func field will point to the Consistent function
+ */
+ for (i = 0; i < s->numberOfKeys; i++)
+ {
+
+ /*
+ * s->keyData[i].sk_procedure =
+ * index_getprocid(s->relation, 1, GIST_CONSISTENT_PROC);
+ */
+ s->keyData[i].sk_procedure
+ = RelationGetGISTStrategy(s->relation, s->keyData[i].sk_attno,
+ s->keyData[i].sk_procedure);
+ s->keyData[i].sk_func = p->giststate->consistentFn;
+ }
}
- } else {
- /* initialize opaque data */
- p = (GISTScanOpaque) palloc(sizeof(GISTScanOpaqueData));
- p->s_stack = p->s_markstk = (GISTSTACK *) NULL;
- p->s_flags = 0x0;
- s->opaque = p;
- p->giststate = (GISTSTATE *)palloc(sizeof(GISTSTATE));
- initGISTstate(p->giststate, s->relation);
- if (s->numberOfKeys > 0)
- /*
- ** Play games here with the scan key to use the Consistent
- ** function for all comparisons:
- ** 1) the sk_procedure field will now be used to hold the
- ** strategy number
- ** 2) the sk_func field will point to the Consistent function
- */
- for (i = 0; i < s->numberOfKeys; i++) {
- /* s->keyData[i].sk_procedure
- = index_getprocid(s->relation, 1, GIST_CONSISTENT_PROC); */
- s->keyData[i].sk_procedure
- = RelationGetGISTStrategy(s->relation, s->keyData[i].sk_attno,
- s->keyData[i].sk_procedure);
- s->keyData[i].sk_func = p->giststate->consistentFn;
- }
- }
}
void
gistmarkpos(IndexScanDesc s)
{
- GISTScanOpaque p;
- GISTSTACK *o, *n, *tmp;
-
- s->currentMarkData = s->currentItemData;
- p = (GISTScanOpaque) s->opaque;
- if (p->s_flags & GS_CURBEFORE)
- p->s_flags |= GS_MRKBEFORE;
- else
- p->s_flags &= ~GS_MRKBEFORE;
-
- o = (GISTSTACK *) NULL;
- n = p->s_stack;
-
- /* copy the parent stack from the current item data */
- while (n != (GISTSTACK *) NULL) {
- tmp = (GISTSTACK *) palloc(sizeof(GISTSTACK));
- tmp->gs_child = n->gs_child;
- tmp->gs_blk = n->gs_blk;
- tmp->gs_parent = o;
- o = tmp;
- n = n->gs_parent;
- }
-
- gistfreestack(p->s_markstk);
- p->s_markstk = o;
+ GISTScanOpaque p;
+ GISTSTACK *o,
+ *n,
+ *tmp;
+
+ s->currentMarkData = s->currentItemData;
+ p = (GISTScanOpaque) s->opaque;
+ if (p->s_flags & GS_CURBEFORE)
+ p->s_flags |= GS_MRKBEFORE;
+ else
+ p->s_flags &= ~GS_MRKBEFORE;
+
+ o = (GISTSTACK *) NULL;
+ n = p->s_stack;
+
+ /* copy the parent stack from the current item data */
+ while (n != (GISTSTACK *) NULL)
+ {
+ tmp = (GISTSTACK *) palloc(sizeof(GISTSTACK));
+ tmp->gs_child = n->gs_child;
+ tmp->gs_blk = n->gs_blk;
+ tmp->gs_parent = o;
+ o = tmp;
+ n = n->gs_parent;
+ }
+
+ gistfreestack(p->s_markstk);
+ p->s_markstk = o;
}
void
gistrestrpos(IndexScanDesc s)
{
- GISTScanOpaque p;
- GISTSTACK *o, *n, *tmp;
-
- s->currentItemData = s->currentMarkData;
- p = (GISTScanOpaque) s->opaque;
- if (p->s_flags & GS_MRKBEFORE)
- p->s_flags |= GS_CURBEFORE;
- else
- p->s_flags &= ~GS_CURBEFORE;
-
- o = (GISTSTACK *) NULL;
- n = p->s_markstk;
-
- /* copy the parent stack from the current item data */
- while (n != (GISTSTACK *) NULL) {
- tmp = (GISTSTACK *) palloc(sizeof(GISTSTACK));
- tmp->gs_child = n->gs_child;
- tmp->gs_blk = n->gs_blk;
- tmp->gs_parent = o;
- o = tmp;
- n = n->gs_parent;
- }
-
- gistfreestack(p->s_stack);
- p->s_stack = o;
+ GISTScanOpaque p;
+ GISTSTACK *o,
+ *n,
+ *tmp;
+
+ s->currentItemData = s->currentMarkData;
+ p = (GISTScanOpaque) s->opaque;
+ if (p->s_flags & GS_MRKBEFORE)
+ p->s_flags |= GS_CURBEFORE;
+ else
+ p->s_flags &= ~GS_CURBEFORE;
+
+ o = (GISTSTACK *) NULL;
+ n = p->s_markstk;
+
+ /* copy the parent stack from the current item data */
+ while (n != (GISTSTACK *) NULL)
+ {
+ tmp = (GISTSTACK *) palloc(sizeof(GISTSTACK));
+ tmp->gs_child = n->gs_child;
+ tmp->gs_blk = n->gs_blk;
+ tmp->gs_parent = o;
+ o = tmp;
+ n = n->gs_parent;
+ }
+
+ gistfreestack(p->s_stack);
+ p->s_stack = o;
}
void
gistendscan(IndexScanDesc s)
{
- GISTScanOpaque p;
-
- p = (GISTScanOpaque) s->opaque;
-
- if (p != (GISTScanOpaque) NULL) {
- gistfreestack(p->s_stack);
- gistfreestack(p->s_markstk);
- pfree (s->opaque);
- }
-
- gistdropscan(s);
- /* XXX don't unset read lock -- two-phase locking */
+ GISTScanOpaque p;
+
+ p = (GISTScanOpaque) s->opaque;
+
+ if (p != (GISTScanOpaque) NULL)
+ {
+ gistfreestack(p->s_stack);
+ gistfreestack(p->s_markstk);
+ pfree(s->opaque);
+ }
+
+ gistdropscan(s);
+ /* XXX don't unset read lock -- two-phase locking */
}
static void
gistregscan(IndexScanDesc s)
{
- GISTScanList l;
-
- l = (GISTScanList) palloc(sizeof(GISTScanListData));
- l->gsl_scan = s;
- l->gsl_next = GISTScans;
- GISTScans = l;
+ GISTScanList l;
+
+ l = (GISTScanList) palloc(sizeof(GISTScanListData));
+ l->gsl_scan = s;
+ l->gsl_next = GISTScans;
+ GISTScans = l;
}
static void
gistdropscan(IndexScanDesc s)
{
- GISTScanList l;
- GISTScanList prev;
-
- prev = (GISTScanList) NULL;
-
- for (l = GISTScans;
- l != (GISTScanList) NULL && l->gsl_scan != s;
- l = l->gsl_next) {
- prev = l;
- }
-
- if (l == (GISTScanList) NULL)
- elog(WARN, "GiST scan list corrupted -- cannot find 0x%lx", s);
-
- if (prev == (GISTScanList) NULL)
- GISTScans = l->gsl_next;
- else
- prev->gsl_next = l->gsl_next;
-
- pfree(l);
+ GISTScanList l;
+ GISTScanList prev;
+
+ prev = (GISTScanList) NULL;
+
+ for (l = GISTScans;
+ l != (GISTScanList) NULL && l->gsl_scan != s;
+ l = l->gsl_next)
+ {
+ prev = l;
+ }
+
+ if (l == (GISTScanList) NULL)
+ elog(WARN, "GiST scan list corrupted -- cannot find 0x%lx", s);
+
+ if (prev == (GISTScanList) NULL)
+ GISTScans = l->gsl_next;
+ else
+ prev->gsl_next = l->gsl_next;
+
+ pfree(l);
}
void
gistadjscans(Relation r, int op, BlockNumber blkno, OffsetNumber offnum)
{
- GISTScanList l;
- Oid relid;
-
- relid = r->rd_id;
- for (l = GISTScans; l != (GISTScanList) NULL; l = l->gsl_next) {
- if (l->gsl_scan->relation->rd_id == relid)
- gistadjone(l->gsl_scan, op, blkno, offnum);
- }
+ GISTScanList l;
+ Oid relid;
+
+ relid = r->rd_id;
+ for (l = GISTScans; l != (GISTScanList) NULL; l = l->gsl_next)
+ {
+ if (l->gsl_scan->relation->rd_id == relid)
+ gistadjone(l->gsl_scan, op, blkno, offnum);
+ }
}
/*
- * gistadjone() -- adjust one scan for update.
+ * gistadjone() -- adjust one scan for update.
*
- * By here, the scan passed in is on a modified relation. Op tells
- * us what the modification is, and blkno and offind tell us what
- * block and offset index were affected. This routine checks the
- * current and marked positions, and the current and marked stacks,
- * to see if any stored location needs to be changed because of the
- * update. If so, we make the change here.
+ * By here, the scan passed in is on a modified relation. Op tells
+ * us what the modification is, and blkno and offind tell us what
+ * block and offset index were affected. This routine checks the
+ * current and marked positions, and the current and marked stacks,
+ * to see if any stored location needs to be changed because of the
+ * update. If so, we make the change here.
*/
static void
gistadjone(IndexScanDesc s,
- int op,
- BlockNumber blkno,
- OffsetNumber offnum)
+ int op,
+ BlockNumber blkno,
+ OffsetNumber offnum)
{
- GISTScanOpaque so;
-
- adjustiptr(s, &(s->currentItemData), op, blkno, offnum);
- adjustiptr(s, &(s->currentMarkData), op, blkno, offnum);
-
- so = (GISTScanOpaque) s->opaque;
-
- if (op == GISTOP_SPLIT) {
- adjuststack(so->s_stack, blkno, offnum);
- adjuststack(so->s_markstk, blkno, offnum);
- }
+ GISTScanOpaque so;
+
+ adjustiptr(s, &(s->currentItemData), op, blkno, offnum);
+ adjustiptr(s, &(s->currentMarkData), op, blkno, offnum);
+
+ so = (GISTScanOpaque) s->opaque;
+
+ if (op == GISTOP_SPLIT)
+ {
+ adjuststack(so->s_stack, blkno, offnum);
+ adjuststack(so->s_markstk, blkno, offnum);
+ }
}
/*
- * adjustiptr() -- adjust current and marked item pointers in the scan
+ * adjustiptr() -- adjust current and marked item pointers in the scan
*
- * Depending on the type of update and the place it happened, we
- * need to do nothing, to back up one record, or to start over on
- * the same page.
+ * Depending on the type of update and the place it happened, we
+ * need to do nothing, to back up one record, or to start over on
+ * the same page.
*/
static void
adjustiptr(IndexScanDesc s,
- ItemPointer iptr,
- int op,
- BlockNumber blkno,
- OffsetNumber offnum)
+ ItemPointer iptr,
+ int op,
+ BlockNumber blkno,
+ OffsetNumber offnum)
{
- OffsetNumber curoff;
- GISTScanOpaque so;
-
- if (ItemPointerIsValid(iptr)) {
- if (ItemPointerGetBlockNumber(iptr) == blkno) {
- curoff = ItemPointerGetOffsetNumber(iptr);
- so = (GISTScanOpaque) s->opaque;
-
- switch (op) {
- case GISTOP_DEL:
- /* back up one if we need to */
- if (curoff >= offnum) {
-
- if (curoff > FirstOffsetNumber) {
- /* just adjust the item pointer */
- ItemPointerSet(iptr, blkno, OffsetNumberPrev(curoff));
- } else {
- /* remember that we're before the current tuple */
- ItemPointerSet(iptr, blkno, FirstOffsetNumber);
- if (iptr == &(s->currentItemData))
- so->s_flags |= GS_CURBEFORE;
- else
- so->s_flags |= GS_MRKBEFORE;
- }
+ OffsetNumber curoff;
+ GISTScanOpaque so;
+
+ if (ItemPointerIsValid(iptr))
+ {
+ if (ItemPointerGetBlockNumber(iptr) == blkno)
+ {
+ curoff = ItemPointerGetOffsetNumber(iptr);
+ so = (GISTScanOpaque) s->opaque;
+
+ switch (op)
+ {
+ case GISTOP_DEL:
+ /* back up one if we need to */
+ if (curoff >= offnum)
+ {
+
+ if (curoff > FirstOffsetNumber)
+ {
+ /* just adjust the item pointer */
+ ItemPointerSet(iptr, blkno, OffsetNumberPrev(curoff));
+ }
+ else
+ {
+ /* remember that we're before the current tuple */
+ ItemPointerSet(iptr, blkno, FirstOffsetNumber);
+ if (iptr == &(s->currentItemData))
+ so->s_flags |= GS_CURBEFORE;
+ else
+ so->s_flags |= GS_MRKBEFORE;
+ }
+ }
+ break;
+
+ case GISTOP_SPLIT:
+ /* back to start of page on split */
+ ItemPointerSet(iptr, blkno, FirstOffsetNumber);
+ if (iptr == &(s->currentItemData))
+ so->s_flags &= ~GS_CURBEFORE;
+ else
+ so->s_flags &= ~GS_MRKBEFORE;
+ break;
+
+ default:
+ elog(WARN, "Bad operation in GiST scan adjust: %d", op);
+ }
}
- break;
-
- case GISTOP_SPLIT:
- /* back to start of page on split */
- ItemPointerSet(iptr, blkno, FirstOffsetNumber);
- if (iptr == &(s->currentItemData))
- so->s_flags &= ~GS_CURBEFORE;
- else
- so->s_flags &= ~GS_MRKBEFORE;
- break;
-
- default:
- elog(WARN, "Bad operation in GiST scan adjust: %d", op);
- }
}
- }
}
/*
- * adjuststack() -- adjust the supplied stack for a split on a page in
- * the index we're scanning.
+ * adjuststack() -- adjust the supplied stack for a split on a page in
+ * the index we're scanning.
*
- * If a page on our parent stack has split, we need to back up to the
- * beginning of the page and rescan it. The reason for this is that
- * the split algorithm for GiSTs doesn't order tuples in any useful
- * way on a single page. This means on that a split, we may wind up
- * looking at some heap tuples more than once. This is handled in the
- * access method update code for heaps; if we've modified the tuple we
- * are looking at already in this transaction, we ignore the update
- * request.
+ * If a page on our parent stack has split, we need to back up to the
+ * beginning of the page and rescan it. The reason for this is that
+ * the split algorithm for GiSTs doesn't order tuples in any useful
+ * way on a single page. This means on that a split, we may wind up
+ * looking at some heap tuples more than once. This is handled in the
+ * access method update code for heaps; if we've modified the tuple we
+ * are looking at already in this transaction, we ignore the update
+ * request.
*/
/*ARGSUSED*/
static void
-adjuststack(GISTSTACK *stk,
- BlockNumber blkno,
- OffsetNumber offnum)
+adjuststack(GISTSTACK * stk,
+ BlockNumber blkno,
+ OffsetNumber offnum)
{
- while (stk != (GISTSTACK *) NULL) {
- if (stk->gs_blk == blkno)
- stk->gs_child = FirstOffsetNumber;
-
- stk = stk->gs_parent;
- }
+ while (stk != (GISTSTACK *) NULL)
+ {
+ if (stk->gs_blk == blkno)
+ stk->gs_child = FirstOffsetNumber;
+
+ stk = stk->gs_parent;
+ }
}
diff --git a/src/backend/access/gist/giststrat.c b/src/backend/access/gist/giststrat.c
index 8c78ccec3ae..c7a6f9ff784 100644
--- a/src/backend/access/gist/giststrat.c
+++ b/src/backend/access/gist/giststrat.c
@@ -1,116 +1,117 @@
/*-------------------------------------------------------------------------
*
* giststrat.c--
- * strategy map data for GiSTs.
+ * strategy map data for GiSTs.
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * /usr/local/devel/pglite/cvs/src/backend/access/gist/giststrat.c,v 1.4 1995/06/14 00:10:05 jolly Exp
+ * /usr/local/devel/pglite/cvs/src/backend/access/gist/giststrat.c,v 1.4 1995/06/14 00:10:05 jolly Exp
*
*-------------------------------------------------------------------------
*/
#include <postgres.h>
-
+
#include <access/gist.h>
#include <access/istrat.h>
/*
- * Note: negate, commute, and negatecommute all assume that operators are
- * ordered as follows in the strategy map:
+ * Note: negate, commute, and negatecommute all assume that operators are
+ * ordered as follows in the strategy map:
*
- * contains, contained-by
+ * contains, contained-by
*
- * The negate, commute, and negatecommute arrays are used by the planner
- * to plan indexed scans over data that appears in the qualificiation in
- * a boolean negation, or whose operands appear in the wrong order. For
- * example, if the operator "<%" means "contains", and the user says
+ * The negate, commute, and negatecommute arrays are used by the planner
+ * to plan indexed scans over data that appears in the qualificiation in
+ * a boolean negation, or whose operands appear in the wrong order. For
+ * example, if the operator "<%" means "contains", and the user says
*
- * where not rel.box <% "(10,10,20,20)"::box
+ * where not rel.box <% "(10,10,20,20)"::box
*
- * the planner can plan an index scan by noting that GiST indices have
- * an operator in their operator class for negating <%.
+ * the planner can plan an index scan by noting that GiST indices have
+ * an operator in their operator class for negating <%.
*
- * Similarly, if the user says something like
+ * Similarly, if the user says something like
*
- * where "(10,10,20,20)"::box <% rel.box
+ * where "(10,10,20,20)"::box <% rel.box
*
- * the planner can see that the GiST index on rel.box has an operator in
- * its opclass for commuting <%, and plan the scan using that operator.
- * This added complexity in the access methods makes the planner a lot easier
- * to write.
+ * the planner can see that the GiST index on rel.box has an operator in
+ * its opclass for commuting <%, and plan the scan using that operator.
+ * This added complexity in the access methods makes the planner a lot easier
+ * to write.
*/
/* if a op b, what operator tells us if (not a op b)? */
-static StrategyNumber GISTNegate[GISTNStrategies] = {
- InvalidStrategy,
- InvalidStrategy,
- InvalidStrategy
- };
+static StrategyNumber GISTNegate[GISTNStrategies] = {
+ InvalidStrategy,
+ InvalidStrategy,
+ InvalidStrategy
+};
/* if a op_1 b, what is the operator op_2 such that b op_2 a? */
-static StrategyNumber GISTCommute[GISTNStrategies] = {
- InvalidStrategy,
- InvalidStrategy,
- InvalidStrategy
- };
+static StrategyNumber GISTCommute[GISTNStrategies] = {
+ InvalidStrategy,
+ InvalidStrategy,
+ InvalidStrategy
+};
/* if a op_1 b, what is the operator op_2 such that (b !op_2 a)? */
-static StrategyNumber GISTNegateCommute[GISTNStrategies] = {
- InvalidStrategy,
- InvalidStrategy,
- InvalidStrategy
- };
+static StrategyNumber GISTNegateCommute[GISTNStrategies] = {
+ InvalidStrategy,
+ InvalidStrategy,
+ InvalidStrategy
+};
/*
- * GiSTs do not currently support TermData (see rtree/rtstrat.c for
+ * GiSTs do not currently support TermData (see rtree/rtstrat.c for
* discussion of
* TermData) -- such logic must be encoded in the user's Consistent function.
*/
/*
- * If you were sufficiently attentive to detail, you would go through
- * the ExpressionData pain above for every one of the strategies
- * we defined. I am not. Now we declare the StrategyEvaluationData
- * structure that gets shipped around to help the planner and the access
- * method decide what sort of scan it should do, based on (a) what the
- * user asked for, (b) what operators are defined for a particular opclass,
- * and (c) the reams of information we supplied above.
+ * If you were sufficiently attentive to detail, you would go through
+ * the ExpressionData pain above for every one of the strategies
+ * we defined. I am not. Now we declare the StrategyEvaluationData
+ * structure that gets shipped around to help the planner and the access
+ * method decide what sort of scan it should do, based on (a) what the
+ * user asked for, (b) what operators are defined for a particular opclass,
+ * and (c) the reams of information we supplied above.
*
- * The idea of all of this initialized data is to make life easier on the
- * user when he defines a new operator class to use this access method.
- * By filling in all the data, we let him get away with leaving holes in his
- * operator class, and still let him use the index. The added complexity
- * in the access methods just isn't worth the trouble, though.
+ * The idea of all of this initialized data is to make life easier on the
+ * user when he defines a new operator class to use this access method.
+ * By filling in all the data, we let him get away with leaving holes in his
+ * operator class, and still let him use the index. The added complexity
+ * in the access methods just isn't worth the trouble, though.
*/
static StrategyEvaluationData GISTEvaluationData = {
- GISTNStrategies, /* # of strategies */
- (StrategyTransformMap) GISTNegate, /* how to do (not qual) */
- (StrategyTransformMap) GISTCommute, /* how to swap operands */
- (StrategyTransformMap) GISTNegateCommute, /* how to do both */
- { NULL }
+ GISTNStrategies, /* # of strategies */
+ (StrategyTransformMap) GISTNegate, /* how to do (not qual) */
+ (StrategyTransformMap) GISTCommute, /* how to swap operands */
+ (StrategyTransformMap) GISTNegateCommute, /* how to do both */
+ {NULL}
};
StrategyNumber
RelationGetGISTStrategy(Relation r,
- AttrNumber attnum,
- RegProcedure proc)
+ AttrNumber attnum,
+ RegProcedure proc)
{
- return (RelationGetStrategy(r, attnum, &GISTEvaluationData, proc));
+ return (RelationGetStrategy(r, attnum, &GISTEvaluationData, proc));
}
#ifdef NOT_USED
bool
RelationInvokeGISTStrategy(Relation r,
- AttrNumber attnum,
- StrategyNumber s,
- Datum left,
- Datum right)
+ AttrNumber attnum,
+ StrategyNumber s,
+ Datum left,
+ Datum right)
{
- return (RelationInvokeStrategy(r, &GISTEvaluationData, attnum, s,
- left, right));
+ return (RelationInvokeStrategy(r, &GISTEvaluationData, attnum, s,
+ left, right));
}
+
#endif
diff --git a/src/backend/access/hash/hash.c b/src/backend/access/hash/hash.c
index 89f81fc56a5..e13539c4ad9 100644
--- a/src/backend/access/hash/hash.c
+++ b/src/backend/access/hash/hash.c
@@ -1,16 +1,16 @@
/*-------------------------------------------------------------------------
*
* hash.c--
- * Implementation of Margo Seltzer's Hashing package for postgres.
+ * Implementation of Margo Seltzer's Hashing package for postgres.
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/hash/hash.c,v 1.12 1997/01/10 09:46:13 vadim Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/hash/hash.c,v 1.13 1997/09/07 04:37:49 momjian Exp $
*
* NOTES
- * This file contains only the public interface routines.
+ * This file contains only the public interface routines.
*
*-------------------------------------------------------------------------
*/
@@ -26,452 +26,483 @@
#include <miscadmin.h>
#ifndef HAVE_MEMMOVE
-# include <regex/utils.h>
+#include <regex/utils.h>
#else
-# include <string.h>
+#include <string.h>
#endif
-bool BuildingHash = false;
+bool BuildingHash = false;
/*
- * hashbuild() -- build a new hash index.
+ * hashbuild() -- build a new hash index.
*
- * We use a global variable to record the fact that we're creating
- * a new index. This is used to avoid high-concurrency locking,
- * since the index won't be visible until this transaction commits
- * and since building is guaranteed to be single-threaded.
+ * We use a global variable to record the fact that we're creating
+ * a new index. This is used to avoid high-concurrency locking,
+ * since the index won't be visible until this transaction commits
+ * and since building is guaranteed to be single-threaded.
*/
void
hashbuild(Relation heap,
- Relation index,
- int natts,
- AttrNumber *attnum,
- IndexStrategy istrat,
- uint16 pcount,
- Datum *params,
- FuncIndexInfo *finfo,
- PredInfo *predInfo)
+ Relation index,
+ int natts,
+ AttrNumber * attnum,
+ IndexStrategy istrat,
+ uint16 pcount,
+ Datum * params,
+ FuncIndexInfo * finfo,
+ PredInfo * predInfo)
{
- HeapScanDesc hscan;
- Buffer buffer;
- HeapTuple htup;
- IndexTuple itup;
- TupleDesc htupdesc, itupdesc;
- Datum *attdata;
- bool *nulls;
- InsertIndexResult res;
- int nhtups, nitups;
- int i;
- HashItem hitem;
+ HeapScanDesc hscan;
+ Buffer buffer;
+ HeapTuple htup;
+ IndexTuple itup;
+ TupleDesc htupdesc,
+ itupdesc;
+ Datum *attdata;
+ bool *nulls;
+ InsertIndexResult res;
+ int nhtups,
+ nitups;
+ int i;
+ HashItem hitem;
+
#ifndef OMIT_PARTIAL_INDEX
- ExprContext *econtext;
- TupleTable tupleTable;
- TupleTableSlot *slot;
+ ExprContext *econtext;
+ TupleTable tupleTable;
+ TupleTableSlot *slot;
+
#endif
- Oid hrelid, irelid;
- Node *pred, *oldPred;
-
- /* note that this is a new btree */
- BuildingHash = true;
-
- pred = predInfo->pred;
- oldPred = predInfo->oldPred;
-
- /* initialize the hash index metadata page (if this is a new index) */
- if (oldPred == NULL)
- _hash_metapinit(index);
-
- /* get tuple descriptors for heap and index relations */
- htupdesc = RelationGetTupleDescriptor(heap);
- itupdesc = RelationGetTupleDescriptor(index);
-
- /* get space for data items that'll appear in the index tuple */
- attdata = (Datum *) palloc(natts * sizeof(Datum));
- nulls = (bool *) palloc(natts * sizeof(bool));
-
- /*
- * If this is a predicate (partial) index, we will need to evaluate the
- * predicate using ExecQual, which requires the current tuple to be in a
- * slot of a TupleTable. In addition, ExecQual must have an ExprContext
- * referring to that slot. Here, we initialize dummy TupleTable and
- * ExprContext objects for this purpose. --Nels, Feb '92
- */
+ Oid hrelid,
+ irelid;
+ Node *pred,
+ *oldPred;
+
+ /* note that this is a new btree */
+ BuildingHash = true;
+
+ pred = predInfo->pred;
+ oldPred = predInfo->oldPred;
+
+ /* initialize the hash index metadata page (if this is a new index) */
+ if (oldPred == NULL)
+ _hash_metapinit(index);
+
+ /* get tuple descriptors for heap and index relations */
+ htupdesc = RelationGetTupleDescriptor(heap);
+ itupdesc = RelationGetTupleDescriptor(index);
+
+ /* get space for data items that'll appear in the index tuple */
+ attdata = (Datum *) palloc(natts * sizeof(Datum));
+ nulls = (bool *) palloc(natts * sizeof(bool));
+
+ /*
+ * If this is a predicate (partial) index, we will need to evaluate
+ * the predicate using ExecQual, which requires the current tuple to
+ * be in a slot of a TupleTable. In addition, ExecQual must have an
+ * ExprContext referring to that slot. Here, we initialize dummy
+ * TupleTable and ExprContext objects for this purpose. --Nels, Feb
+ * '92
+ */
#ifndef OMIT_PARTIAL_INDEX
- if (pred != NULL || oldPred != NULL) {
- tupleTable = ExecCreateTupleTable(1);
- slot = ExecAllocTableSlot(tupleTable);
- econtext = makeNode(ExprContext);
- FillDummyExprContext(econtext, slot, htupdesc, buffer);
- }
- else /* quiet the compiler */
+ if (pred != NULL || oldPred != NULL)
+ {
+ tupleTable = ExecCreateTupleTable(1);
+ slot = ExecAllocTableSlot(tupleTable);
+ econtext = makeNode(ExprContext);
+ FillDummyExprContext(econtext, slot, htupdesc, buffer);
+ }
+ else
+/* quiet the compiler */
{
econtext = NULL;
tupleTable = 0;
slot = 0;
}
-#endif /* OMIT_PARTIAL_INDEX */
-
- /* start a heap scan */
- hscan = heap_beginscan(heap, 0, NowTimeQual, 0, (ScanKey) NULL);
- htup = heap_getnext(hscan, 0, &buffer);
-
- /* build the index */
- nhtups = nitups = 0;
-
- for (; HeapTupleIsValid(htup); htup = heap_getnext(hscan, 0, &buffer)) {
-
- nhtups++;
-
- /*
- * If oldPred != NULL, this is an EXTEND INDEX command, so skip
- * this tuple if it was already in the existing partial index
- */
- if (oldPred != NULL) {
- /*SetSlotContents(slot, htup); */
+#endif /* OMIT_PARTIAL_INDEX */
+
+ /* start a heap scan */
+ hscan = heap_beginscan(heap, 0, NowTimeQual, 0, (ScanKey) NULL);
+ htup = heap_getnext(hscan, 0, &buffer);
+
+ /* build the index */
+ nhtups = nitups = 0;
+
+ for (; HeapTupleIsValid(htup); htup = heap_getnext(hscan, 0, &buffer))
+ {
+
+ nhtups++;
+
+ /*
+ * If oldPred != NULL, this is an EXTEND INDEX command, so skip
+ * this tuple if it was already in the existing partial index
+ */
+ if (oldPred != NULL)
+ {
+ /* SetSlotContents(slot, htup); */
#ifndef OMIT_PARTIAL_INDEX
- slot->val = htup;
- if (ExecQual((List*)oldPred, econtext) == true) {
+ slot->val = htup;
+ if (ExecQual((List *) oldPred, econtext) == true)
+ {
+ nitups++;
+ continue;
+ }
+#endif /* OMIT_PARTIAL_INDEX */
+ }
+
+ /*
+ * Skip this tuple if it doesn't satisfy the partial-index
+ * predicate
+ */
+ if (pred != NULL)
+ {
+#ifndef OMIT_PARTIAL_INDEX
+ /* SetSlotContents(slot, htup); */
+ slot->val = htup;
+ if (ExecQual((List *) pred, econtext) == false)
+ continue;
+#endif /* OMIT_PARTIAL_INDEX */
+ }
+
nitups++;
- continue;
- }
-#endif /* OMIT_PARTIAL_INDEX */
+
+ /*
+ * For the current heap tuple, extract all the attributes we use
+ * in this index, and note which are null.
+ */
+ for (i = 1; i <= natts; i++)
+ {
+ int attoff;
+ bool attnull;
+
+ /*
+ * Offsets are from the start of the tuple, and are
+ * zero-based; indices are one-based. The next call returns i
+ * - 1. That's data hiding for you.
+ */
+
+ /* attoff = i - 1 */
+ attoff = AttrNumberGetAttrOffset(i);
+
+ /*
+ * below, attdata[attoff] set to equal some datum & attnull is
+ * changed to indicate whether or not the attribute is null
+ * for this tuple
+ */
+ attdata[attoff] = GetIndexValue(htup,
+ htupdesc,
+ attoff,
+ attnum,
+ finfo,
+ &attnull,
+ buffer);
+ nulls[attoff] = (attnull ? 'n' : ' ');
+ }
+
+ /* form an index tuple and point it at the heap tuple */
+ itup = index_formtuple(itupdesc, attdata, nulls);
+
+ /*
+ * If the single index key is null, we don't insert it into the
+ * index. Hash tables support scans on '='. Relational algebra
+ * says that A = B returns null if either A or B is null. This
+ * means that no qualification used in an index scan could ever
+ * return true on a null attribute. It also means that indices
+ * can't be used by ISNULL or NOTNULL scans, but that's an
+ * artifact of the strategy map architecture chosen in 1986, not
+ * of the way nulls are handled here.
+ */
+
+ if (itup->t_info & INDEX_NULL_MASK)
+ {
+ pfree(itup);
+ continue;
+ }
+
+ itup->t_tid = htup->t_ctid;
+ hitem = _hash_formitem(itup);
+ res = _hash_doinsert(index, hitem);
+ pfree(hitem);
+ pfree(itup);
+ pfree(res);
}
-
- /* Skip this tuple if it doesn't satisfy the partial-index predicate */
- if (pred != NULL) {
+
+ /* okay, all heap tuples are indexed */
+ heap_endscan(hscan);
+
+ if (pred != NULL || oldPred != NULL)
+ {
#ifndef OMIT_PARTIAL_INDEX
- /*SetSlotContents(slot, htup); */
- slot->val = htup;
- if (ExecQual((List*)pred, econtext) == false)
- continue;
-#endif /* OMIT_PARTIAL_INDEX */
-}
-
- nitups++;
-
- /*
- * For the current heap tuple, extract all the attributes
- * we use in this index, and note which are null.
- */
- for (i = 1; i <= natts; i++) {
- int attoff;
- bool attnull;
-
- /*
- * Offsets are from the start of the tuple, and are
- * zero-based; indices are one-based. The next call
- * returns i - 1. That's data hiding for you.
- */
-
- /* attoff = i - 1 */
- attoff = AttrNumberGetAttrOffset(i);
-
- /* below, attdata[attoff] set to equal some datum &
- * attnull is changed to indicate whether or not the attribute
- * is null for this tuple
- */
- attdata[attoff] = GetIndexValue(htup,
- htupdesc,
- attoff,
- attnum,
- finfo,
- &attnull,
- buffer);
- nulls[attoff] = (attnull ? 'n' : ' ');
+ ExecDestroyTupleTable(tupleTable, true);
+ pfree(econtext);
+#endif /* OMIT_PARTIAL_INDEX */
}
-
- /* form an index tuple and point it at the heap tuple */
- itup = index_formtuple(itupdesc, attdata, nulls);
-
+
/*
- * If the single index key is null, we don't insert it into
- * the index. Hash tables support scans on '='.
- * Relational algebra says that A = B
- * returns null if either A or B is null. This
- * means that no qualification used in an index scan could ever
- * return true on a null attribute. It also means that indices
- * can't be used by ISNULL or NOTNULL scans, but that's an
- * artifact of the strategy map architecture chosen in 1986, not
- * of the way nulls are handled here.
+ * Since we just counted the tuples in the heap, we update its stats
+ * in pg_class to guarantee that the planner takes advantage of the
+ * index we just created. Finally, only update statistics during
+ * normal index definitions, not for indices on system catalogs
+ * created during bootstrap processing. We must close the relations
+ * before updatings statistics to guarantee that the relcache entries
+ * are flushed when we increment the command counter in UpdateStats().
*/
-
- if (itup->t_info & INDEX_NULL_MASK) {
- pfree(itup);
- continue;
- }
-
- itup->t_tid = htup->t_ctid;
- hitem = _hash_formitem(itup);
- res = _hash_doinsert(index, hitem);
- pfree(hitem);
- pfree(itup);
- pfree(res);
- }
-
- /* okay, all heap tuples are indexed */
- heap_endscan(hscan);
-
- if (pred != NULL || oldPred != NULL) {
-#ifndef OMIT_PARTIAL_INDEX
- ExecDestroyTupleTable(tupleTable, true);
- pfree(econtext);
-#endif /* OMIT_PARTIAL_INDEX */
- }
-
- /*
- * Since we just counted the tuples in the heap, we update its
- * stats in pg_class to guarantee that the planner takes advantage
- * of the index we just created. Finally, only update statistics
- * during normal index definitions, not for indices on system catalogs
- * created during bootstrap processing. We must close the relations
- * before updatings statistics to guarantee that the relcache entries
- * are flushed when we increment the command counter in UpdateStats().
- */
- if (IsNormalProcessingMode())
+ if (IsNormalProcessingMode())
{
- hrelid = heap->rd_id;
- irelid = index->rd_id;
- heap_close(heap);
- index_close(index);
- UpdateStats(hrelid, nhtups, true);
- UpdateStats(irelid, nitups, false);
- if (oldPred != NULL) {
- if (nitups == nhtups) pred = NULL;
- UpdateIndexPredicate(irelid, oldPred, pred);
- }
+ hrelid = heap->rd_id;
+ irelid = index->rd_id;
+ heap_close(heap);
+ index_close(index);
+ UpdateStats(hrelid, nhtups, true);
+ UpdateStats(irelid, nitups, false);
+ if (oldPred != NULL)
+ {
+ if (nitups == nhtups)
+ pred = NULL;
+ UpdateIndexPredicate(irelid, oldPred, pred);
+ }
}
-
- /* be tidy */
- pfree(nulls);
- pfree(attdata);
-
- /* all done */
- BuildingHash = false;
+
+ /* be tidy */
+ pfree(nulls);
+ pfree(attdata);
+
+ /* all done */
+ BuildingHash = false;
}
/*
- * hashinsert() -- insert an index tuple into a hash table.
+ * hashinsert() -- insert an index tuple into a hash table.
*
- * Hash on the index tuple's key, find the appropriate location
- * for the new tuple, put it there, and return an InsertIndexResult
- * to the caller.
+ * Hash on the index tuple's key, find the appropriate location
+ * for the new tuple, put it there, and return an InsertIndexResult
+ * to the caller.
*/
InsertIndexResult
-hashinsert(Relation rel, Datum *datum, char *nulls, ItemPointer ht_ctid, Relation heapRel)
+hashinsert(Relation rel, Datum * datum, char *nulls, ItemPointer ht_ctid, Relation heapRel)
{
- HashItem hitem;
- IndexTuple itup;
- InsertIndexResult res;
-
-
- /* generate an index tuple */
- itup = index_formtuple(RelationGetTupleDescriptor(rel), datum, nulls);
- itup->t_tid = *ht_ctid;
-
- if (itup->t_info & INDEX_NULL_MASK)
- return ((InsertIndexResult) NULL);
-
- hitem = _hash_formitem(itup);
-
- res = _hash_doinsert(rel, hitem);
-
- pfree(hitem);
- pfree(itup);
-
- return (res);
+ HashItem hitem;
+ IndexTuple itup;
+ InsertIndexResult res;
+
+
+ /* generate an index tuple */
+ itup = index_formtuple(RelationGetTupleDescriptor(rel), datum, nulls);
+ itup->t_tid = *ht_ctid;
+
+ if (itup->t_info & INDEX_NULL_MASK)
+ return ((InsertIndexResult) NULL);
+
+ hitem = _hash_formitem(itup);
+
+ res = _hash_doinsert(rel, hitem);
+
+ pfree(hitem);
+ pfree(itup);
+
+ return (res);
}
/*
- * hashgettuple() -- Get the next tuple in the scan.
+ * hashgettuple() -- Get the next tuple in the scan.
*/
-char *
+char *
hashgettuple(IndexScanDesc scan, ScanDirection dir)
{
- RetrieveIndexResult res;
-
- /*
- * If we've already initialized this scan, we can just advance it
- * in the appropriate direction. If we haven't done so yet, we
- * call a routine to get the first item in the scan.
- */
-
- if (ItemPointerIsValid(&(scan->currentItemData)))
- res = _hash_next(scan, dir);
- else
- res = _hash_first(scan, dir);
-
- return ((char *) res);
+ RetrieveIndexResult res;
+
+ /*
+ * If we've already initialized this scan, we can just advance it in
+ * the appropriate direction. If we haven't done so yet, we call a
+ * routine to get the first item in the scan.
+ */
+
+ if (ItemPointerIsValid(&(scan->currentItemData)))
+ res = _hash_next(scan, dir);
+ else
+ res = _hash_first(scan, dir);
+
+ return ((char *) res);
}
/*
- * hashbeginscan() -- start a scan on a hash index
+ * hashbeginscan() -- start a scan on a hash index
*/
-char *
+char *
hashbeginscan(Relation rel,
- bool fromEnd,
- uint16 keysz,
- ScanKey scankey)
+ bool fromEnd,
+ uint16 keysz,
+ ScanKey scankey)
{
- IndexScanDesc scan;
- HashScanOpaque so;
-
- scan = RelationGetIndexScan(rel, fromEnd, keysz, scankey);
- so = (HashScanOpaque) palloc(sizeof(HashScanOpaqueData));
- so->hashso_curbuf = so->hashso_mrkbuf = InvalidBuffer;
- scan->opaque = so;
- scan->flags = 0x0;
-
- /* register scan in case we change pages it's using */
- _hash_regscan(scan);
-
- return ((char *) scan);
+ IndexScanDesc scan;
+ HashScanOpaque so;
+
+ scan = RelationGetIndexScan(rel, fromEnd, keysz, scankey);
+ so = (HashScanOpaque) palloc(sizeof(HashScanOpaqueData));
+ so->hashso_curbuf = so->hashso_mrkbuf = InvalidBuffer;
+ scan->opaque = so;
+ scan->flags = 0x0;
+
+ /* register scan in case we change pages it's using */
+ _hash_regscan(scan);
+
+ return ((char *) scan);
}
/*
- * hashrescan() -- rescan an index relation
+ * hashrescan() -- rescan an index relation
*/
void
hashrescan(IndexScanDesc scan, bool fromEnd, ScanKey scankey)
{
- ItemPointer iptr;
- HashScanOpaque so;
-
- so = (HashScanOpaque) scan->opaque;
-
- /* we hold a read lock on the current page in the scan */
- if (ItemPointerIsValid(iptr = &(scan->currentItemData))) {
- _hash_relbuf(scan->relation, so->hashso_curbuf, HASH_READ);
- so->hashso_curbuf = InvalidBuffer;
- ItemPointerSetInvalid(iptr);
- }
- if (ItemPointerIsValid(iptr = &(scan->currentMarkData))) {
- _hash_relbuf(scan->relation, so->hashso_mrkbuf, HASH_READ);
- so->hashso_mrkbuf = InvalidBuffer;
- ItemPointerSetInvalid(iptr);
- }
-
- /* reset the scan key */
- if (scan->numberOfKeys > 0) {
- memmove(scan->keyData,
- scankey,
- scan->numberOfKeys * sizeof(ScanKeyData));
- }
+ ItemPointer iptr;
+ HashScanOpaque so;
+
+ so = (HashScanOpaque) scan->opaque;
+
+ /* we hold a read lock on the current page in the scan */
+ if (ItemPointerIsValid(iptr = &(scan->currentItemData)))
+ {
+ _hash_relbuf(scan->relation, so->hashso_curbuf, HASH_READ);
+ so->hashso_curbuf = InvalidBuffer;
+ ItemPointerSetInvalid(iptr);
+ }
+ if (ItemPointerIsValid(iptr = &(scan->currentMarkData)))
+ {
+ _hash_relbuf(scan->relation, so->hashso_mrkbuf, HASH_READ);
+ so->hashso_mrkbuf = InvalidBuffer;
+ ItemPointerSetInvalid(iptr);
+ }
+
+ /* reset the scan key */
+ if (scan->numberOfKeys > 0)
+ {
+ memmove(scan->keyData,
+ scankey,
+ scan->numberOfKeys * sizeof(ScanKeyData));
+ }
}
/*
- * hashendscan() -- close down a scan
+ * hashendscan() -- close down a scan
*/
void
hashendscan(IndexScanDesc scan)
{
-
- ItemPointer iptr;
- HashScanOpaque so;
-
- so = (HashScanOpaque) scan->opaque;
-
- /* release any locks we still hold */
- if (ItemPointerIsValid(iptr = &(scan->currentItemData))) {
- _hash_relbuf(scan->relation, so->hashso_curbuf, HASH_READ);
- so->hashso_curbuf = InvalidBuffer;
- ItemPointerSetInvalid(iptr);
- }
-
- if (ItemPointerIsValid(iptr = &(scan->currentMarkData))) {
- if (BufferIsValid(so->hashso_mrkbuf))
- _hash_relbuf(scan->relation, so->hashso_mrkbuf, HASH_READ);
- so->hashso_mrkbuf = InvalidBuffer;
- ItemPointerSetInvalid(iptr);
- }
-
- /* don't need scan registered anymore */
- _hash_dropscan(scan);
-
- /* be tidy */
- pfree (scan->opaque);
+
+ ItemPointer iptr;
+ HashScanOpaque so;
+
+ so = (HashScanOpaque) scan->opaque;
+
+ /* release any locks we still hold */
+ if (ItemPointerIsValid(iptr = &(scan->currentItemData)))
+ {
+ _hash_relbuf(scan->relation, so->hashso_curbuf, HASH_READ);
+ so->hashso_curbuf = InvalidBuffer;
+ ItemPointerSetInvalid(iptr);
+ }
+
+ if (ItemPointerIsValid(iptr = &(scan->currentMarkData)))
+ {
+ if (BufferIsValid(so->hashso_mrkbuf))
+ _hash_relbuf(scan->relation, so->hashso_mrkbuf, HASH_READ);
+ so->hashso_mrkbuf = InvalidBuffer;
+ ItemPointerSetInvalid(iptr);
+ }
+
+ /* don't need scan registered anymore */
+ _hash_dropscan(scan);
+
+ /* be tidy */
+ pfree(scan->opaque);
}
/*
- * hashmarkpos() -- save current scan position
+ * hashmarkpos() -- save current scan position
*
*/
void
hashmarkpos(IndexScanDesc scan)
{
- ItemPointer iptr;
- HashScanOpaque so;
-
- /* see if we ever call this code. if we do, then so_mrkbuf a
- * useful element in the scan->opaque structure. if this procedure
- * is never called, so_mrkbuf should be removed from the scan->opaque
- * structure.
- */
- elog(NOTICE, "Hashmarkpos() called.");
-
- so = (HashScanOpaque) scan->opaque;
-
- /* release lock on old marked data, if any */
- if (ItemPointerIsValid(iptr = &(scan->currentMarkData))) {
- _hash_relbuf(scan->relation, so->hashso_mrkbuf, HASH_READ);
- so->hashso_mrkbuf = InvalidBuffer;
- ItemPointerSetInvalid(iptr);
- }
-
- /* bump lock on currentItemData and copy to currentMarkData */
- if (ItemPointerIsValid(&(scan->currentItemData))) {
- so->hashso_mrkbuf = _hash_getbuf(scan->relation,
- BufferGetBlockNumber(so->hashso_curbuf),
- HASH_READ);
- scan->currentMarkData = scan->currentItemData;
- }
+ ItemPointer iptr;
+ HashScanOpaque so;
+
+ /*
+ * see if we ever call this code. if we do, then so_mrkbuf a useful
+ * element in the scan->opaque structure. if this procedure is never
+ * called, so_mrkbuf should be removed from the scan->opaque
+ * structure.
+ */
+ elog(NOTICE, "Hashmarkpos() called.");
+
+ so = (HashScanOpaque) scan->opaque;
+
+ /* release lock on old marked data, if any */
+ if (ItemPointerIsValid(iptr = &(scan->currentMarkData)))
+ {
+ _hash_relbuf(scan->relation, so->hashso_mrkbuf, HASH_READ);
+ so->hashso_mrkbuf = InvalidBuffer;
+ ItemPointerSetInvalid(iptr);
+ }
+
+ /* bump lock on currentItemData and copy to currentMarkData */
+ if (ItemPointerIsValid(&(scan->currentItemData)))
+ {
+ so->hashso_mrkbuf = _hash_getbuf(scan->relation,
+ BufferGetBlockNumber(so->hashso_curbuf),
+ HASH_READ);
+ scan->currentMarkData = scan->currentItemData;
+ }
}
/*
- * hashrestrpos() -- restore scan to last saved position
+ * hashrestrpos() -- restore scan to last saved position
*/
void
hashrestrpos(IndexScanDesc scan)
{
- ItemPointer iptr;
- HashScanOpaque so;
-
- /* see if we ever call this code. if we do, then so_mrkbuf a
- * useful element in the scan->opaque structure. if this procedure
- * is never called, so_mrkbuf should be removed from the scan->opaque
- * structure.
- */
- elog(NOTICE, "Hashrestrpos() called.");
-
- so = (HashScanOpaque) scan->opaque;
-
- /* release lock on current data, if any */
- if (ItemPointerIsValid(iptr = &(scan->currentItemData))) {
- _hash_relbuf(scan->relation, so->hashso_curbuf, HASH_READ);
- so->hashso_curbuf = InvalidBuffer;
- ItemPointerSetInvalid(iptr);
- }
-
- /* bump lock on currentMarkData and copy to currentItemData */
- if (ItemPointerIsValid(&(scan->currentMarkData))) {
- so->hashso_curbuf =
- _hash_getbuf(scan->relation,
- BufferGetBlockNumber(so->hashso_mrkbuf),
- HASH_READ);
-
- scan->currentItemData = scan->currentMarkData;
- }
+ ItemPointer iptr;
+ HashScanOpaque so;
+
+ /*
+ * see if we ever call this code. if we do, then so_mrkbuf a useful
+ * element in the scan->opaque structure. if this procedure is never
+ * called, so_mrkbuf should be removed from the scan->opaque
+ * structure.
+ */
+ elog(NOTICE, "Hashrestrpos() called.");
+
+ so = (HashScanOpaque) scan->opaque;
+
+ /* release lock on current data, if any */
+ if (ItemPointerIsValid(iptr = &(scan->currentItemData)))
+ {
+ _hash_relbuf(scan->relation, so->hashso_curbuf, HASH_READ);
+ so->hashso_curbuf = InvalidBuffer;
+ ItemPointerSetInvalid(iptr);
+ }
+
+ /* bump lock on currentMarkData and copy to currentItemData */
+ if (ItemPointerIsValid(&(scan->currentMarkData)))
+ {
+ so->hashso_curbuf =
+ _hash_getbuf(scan->relation,
+ BufferGetBlockNumber(so->hashso_mrkbuf),
+ HASH_READ);
+
+ scan->currentItemData = scan->currentMarkData;
+ }
}
/* stubs */
void
hashdelete(Relation rel, ItemPointer tid)
{
- /* adjust any active scans that will be affected by this deletion */
- _hash_adjscans(rel, tid);
-
- /* delete the data from the page */
- _hash_pagedel(rel, tid);
-}
+ /* adjust any active scans that will be affected by this deletion */
+ _hash_adjscans(rel, tid);
+ /* delete the data from the page */
+ _hash_pagedel(rel, tid);
+}
diff --git a/src/backend/access/hash/hashfunc.c b/src/backend/access/hash/hashfunc.c
index 5862800b21d..a3cbaa1a94c 100644
--- a/src/backend/access/hash/hashfunc.c
+++ b/src/backend/access/hash/hashfunc.c
@@ -1,17 +1,17 @@
/*-------------------------------------------------------------------------
*
* hashfunc.c--
- * Comparison functions for hash access method.
+ * Comparison functions for hash access method.
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/hash/hashfunc.c,v 1.3 1996/11/10 02:57:40 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/hash/hashfunc.c,v 1.4 1997/09/07 04:37:53 momjian Exp $
*
* NOTES
- * These functions are stored in pg_amproc. For each operator class
- * defined on hash tables, they compute the hash value of the argument.
+ * These functions are stored in pg_amproc. For each operator class
+ * defined on hash tables, they compute the hash value of the argument.
*
*-------------------------------------------------------------------------
*/
@@ -20,206 +20,223 @@
#include "access/hash.h"
-uint32 hashint2(int16 key)
+uint32
+hashint2(int16 key)
{
- return ((uint32) ~key);
+ return ((uint32) ~ key);
}
-uint32 hashint4(uint32 key)
+uint32
+hashint4(uint32 key)
{
- return (~key);
+ return (~key);
}
/* Hash function from Chris Torek. */
-uint32 hashfloat4(float32 keyp)
+uint32
+hashfloat4(float32 keyp)
{
- int len;
- int loop;
- uint32 h;
- char *kp = (char *) keyp;
+ int len;
+ int loop;
+ uint32 h;
+ char *kp = (char *) keyp;
- len = sizeof(float32data);
+ len = sizeof(float32data);
-#define HASH4a h = (h << 5) - h + *kp++;
-#define HASH4b h = (h << 5) + h + *kp++;
+#define HASH4a h = (h << 5) - h + *kp++;
+#define HASH4b h = (h << 5) + h + *kp++;
#define HASH4 HASH4b
- h = 0;
- if (len > 0) {
- loop = (len + 8 - 1) >> 3;
-
- switch (len & (8 - 1)) {
- case 0:
- do { /* All fall throughs */
- HASH4;
- case 7:
- HASH4;
- case 6:
- HASH4;
- case 5:
- HASH4;
- case 4:
- HASH4;
- case 3:
- HASH4;
- case 2:
- HASH4;
- case 1:
- HASH4;
- } while (--loop);
+ h = 0;
+ if (len > 0)
+ {
+ loop = (len + 8 - 1) >> 3;
+
+ switch (len & (8 - 1))
+ {
+ case 0:
+ do
+ { /* All fall throughs */
+ HASH4;
+ case 7:
+ HASH4;
+ case 6:
+ HASH4;
+ case 5:
+ HASH4;
+ case 4:
+ HASH4;
+ case 3:
+ HASH4;
+ case 2:
+ HASH4;
+ case 1:
+ HASH4;
+ } while (--loop);
+ }
}
- }
- return (h);
-}
+ return (h);
+}
-uint32 hashfloat8(float64 keyp)
+uint32
+hashfloat8(float64 keyp)
{
- int len;
- int loop;
- uint32 h;
- char *kp = (char *) keyp;
+ int len;
+ int loop;
+ uint32 h;
+ char *kp = (char *) keyp;
- len = sizeof(float64data);
+ len = sizeof(float64data);
-#define HASH4a h = (h << 5) - h + *kp++;
-#define HASH4b h = (h << 5) + h + *kp++;
+#define HASH4a h = (h << 5) - h + *kp++;
+#define HASH4b h = (h << 5) + h + *kp++;
#define HASH4 HASH4b
- h = 0;
- if (len > 0) {
- loop = (len + 8 - 1) >> 3;
-
- switch (len & (8 - 1)) {
- case 0:
- do { /* All fall throughs */
- HASH4;
- case 7:
- HASH4;
- case 6:
- HASH4;
- case 5:
- HASH4;
- case 4:
- HASH4;
- case 3:
- HASH4;
- case 2:
- HASH4;
- case 1:
- HASH4;
- } while (--loop);
+ h = 0;
+ if (len > 0)
+ {
+ loop = (len + 8 - 1) >> 3;
+
+ switch (len & (8 - 1))
+ {
+ case 0:
+ do
+ { /* All fall throughs */
+ HASH4;
+ case 7:
+ HASH4;
+ case 6:
+ HASH4;
+ case 5:
+ HASH4;
+ case 4:
+ HASH4;
+ case 3:
+ HASH4;
+ case 2:
+ HASH4;
+ case 1:
+ HASH4;
+ } while (--loop);
+ }
}
- }
- return (h);
-}
+ return (h);
+}
-uint32 hashoid(Oid key)
+uint32
+hashoid(Oid key)
{
- return ((uint32) ~key);
+ return ((uint32) ~ key);
}
-uint32 hashchar(char key)
+uint32
+hashchar(char key)
{
- int len;
- uint32 h;
+ int len;
+ uint32 h;
+
+ len = sizeof(char);
- len = sizeof(char);
+#define PRIME1 37
+#define PRIME2 1048583
-#define PRIME1 37
-#define PRIME2 1048583
+ h = 0;
+ /* Convert char to integer */
+ h = h * PRIME1 ^ (key - ' ');
+ h %= PRIME2;
- h = 0;
- /* Convert char to integer */
- h = h * PRIME1 ^ (key - ' ');
- h %= PRIME2;
-
- return (h);
+ return (h);
}
-uint32 hashchar2(uint16 intkey)
+uint32
+hashchar2(uint16 intkey)
{
- uint32 h;
- int len;
- char *key = (char *) &intkey;
-
- h = 0;
- len = sizeof(uint16);
- /* Convert string to integer */
- while (len--)
- h = h * PRIME1 ^ (*key++ - ' ');
- h %= PRIME2;
-
- return (h);
+ uint32 h;
+ int len;
+ char *key = (char *) &intkey;
+
+ h = 0;
+ len = sizeof(uint16);
+ /* Convert string to integer */
+ while (len--)
+ h = h * PRIME1 ^ (*key++ - ' ');
+ h %= PRIME2;
+
+ return (h);
}
-uint32 hashchar4(uint32 intkey)
+uint32
+hashchar4(uint32 intkey)
{
- uint32 h;
- int len;
- char *key = (char *) &intkey;
-
- h = 0;
- len = sizeof(uint32);
- /* Convert string to integer */
- while (len--)
- h = h * PRIME1 ^ (*key++ - ' ');
- h %= PRIME2;
-
- return (h);
+ uint32 h;
+ int len;
+ char *key = (char *) &intkey;
+
+ h = 0;
+ len = sizeof(uint32);
+ /* Convert string to integer */
+ while (len--)
+ h = h * PRIME1 ^ (*key++ - ' ');
+ h %= PRIME2;
+
+ return (h);
}
-uint32 hashchar8(char *key)
+uint32
+hashchar8(char *key)
{
- uint32 h;
- int len;
-
- h = 0;
- len = sizeof(char8);
- /* Convert string to integer */
- while (len--)
- h = h * PRIME1 ^ (*key++ - ' ');
- h %= PRIME2;
-
- return (h);
+ uint32 h;
+ int len;
+
+ h = 0;
+ len = sizeof(char8);
+ /* Convert string to integer */
+ while (len--)
+ h = h * PRIME1 ^ (*key++ - ' ');
+ h %= PRIME2;
+
+ return (h);
}
-uint32 hashname(NameData *n)
+uint32
+hashname(NameData * n)
{
- uint32 h;
- int len;
- char *key;
-
- key = n->data;
-
- h = 0;
- len = NAMEDATALEN;
- /* Convert string to integer */
- while (len--)
- h = h * PRIME1 ^ (*key++ - ' ');
- h %= PRIME2;
-
- return (h);
+ uint32 h;
+ int len;
+ char *key;
+
+ key = n->data;
+
+ h = 0;
+ len = NAMEDATALEN;
+ /* Convert string to integer */
+ while (len--)
+ h = h * PRIME1 ^ (*key++ - ' ');
+ h %= PRIME2;
+
+ return (h);
}
-uint32 hashchar16(char *key)
+uint32
+hashchar16(char *key)
{
- uint32 h;
- int len;
-
- h = 0;
- len = sizeof(char16);
- /* Convert string to integer */
- while (len--)
- h = h * PRIME1 ^ (*key++ - ' ');
- h %= PRIME2;
-
- return (h);
+ uint32 h;
+ int len;
+
+ h = 0;
+ len = sizeof(char16);
+ /* Convert string to integer */
+ while (len--)
+ h = h * PRIME1 ^ (*key++ - ' ');
+ h %= PRIME2;
+
+ return (h);
}
@@ -234,45 +251,49 @@ uint32 hashchar16(char *key)
*
* "OZ's original sdbm hash"
*/
-uint32 hashtext(struct varlena *key)
+uint32
+hashtext(struct varlena * key)
{
- int keylen;
- char *keydata;
- uint32 n;
- int loop;
-
- keydata = VARDATA(key);
- keylen = VARSIZE(key);
-
- /* keylen includes the four bytes in which string keylength is stored */
- keylen -= sizeof(VARSIZE(key));
-
-#define HASHC n = *keydata++ + 65599 * n
-
- n = 0;
- if (keylen > 0) {
- loop = (keylen + 8 - 1) >> 3;
-
- switch (keylen & (8 - 1)) {
- case 0:
- do { /* All fall throughs */
- HASHC;
- case 7:
- HASHC;
- case 6:
- HASHC;
- case 5:
- HASHC;
- case 4:
- HASHC;
- case 3:
- HASHC;
- case 2:
- HASHC;
- case 1:
- HASHC;
- } while (--loop);
+ int keylen;
+ char *keydata;
+ uint32 n;
+ int loop;
+
+ keydata = VARDATA(key);
+ keylen = VARSIZE(key);
+
+ /* keylen includes the four bytes in which string keylength is stored */
+ keylen -= sizeof(VARSIZE(key));
+
+#define HASHC n = *keydata++ + 65599 * n
+
+ n = 0;
+ if (keylen > 0)
+ {
+ loop = (keylen + 8 - 1) >> 3;
+
+ switch (keylen & (8 - 1))
+ {
+ case 0:
+ do
+ { /* All fall throughs */
+ HASHC;
+ case 7:
+ HASHC;
+ case 6:
+ HASHC;
+ case 5:
+ HASHC;
+ case 4:
+ HASHC;
+ case 3:
+ HASHC;
+ case 2:
+ HASHC;
+ case 1:
+ HASHC;
+ } while (--loop);
+ }
}
- }
- return (n);
-}
+ return (n);
+}
diff --git a/src/backend/access/hash/hashinsert.c b/src/backend/access/hash/hashinsert.c
index f1233c68b2d..4829093589a 100644
--- a/src/backend/access/hash/hashinsert.c
+++ b/src/backend/access/hash/hashinsert.c
@@ -1,19 +1,19 @@
/*-------------------------------------------------------------------------
*
* hashinsert.c--
- * Item insertion in hash tables for Postgres.
+ * Item insertion in hash tables for Postgres.
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/hash/hashinsert.c,v 1.8 1997/08/12 22:51:30 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/hash/hashinsert.c,v 1.9 1997/09/07 04:37:56 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#include <postgres.h>
-
+
#include <access/hash.h>
#include <storage/bufmgr.h>
#include <utils/memutils.h>
@@ -22,211 +22,221 @@ static InsertIndexResult _hash_insertonpg(Relation rel, Buffer buf, int keysz, S
static OffsetNumber _hash_pgaddtup(Relation rel, Buffer buf, int keysz, ScanKey itup_scankey, Size itemsize, HashItem hitem);
/*
- * _hash_doinsert() -- Handle insertion of a single HashItem in the table.
+ * _hash_doinsert() -- Handle insertion of a single HashItem in the table.
*
- * This routine is called by the public interface routines, hashbuild
- * and hashinsert. By here, hashitem is filled in, and has a unique
- * (xid, seqno) pair. The datum to be used as a "key" is in the
- * hashitem.
+ * This routine is called by the public interface routines, hashbuild
+ * and hashinsert. By here, hashitem is filled in, and has a unique
+ * (xid, seqno) pair. The datum to be used as a "key" is in the
+ * hashitem.
*/
InsertIndexResult
_hash_doinsert(Relation rel, HashItem hitem)
{
- Buffer buf;
- Buffer metabuf;
- BlockNumber blkno;
- HashMetaPage metap;
- IndexTuple itup;
- InsertIndexResult res;
- ScanKey itup_scankey;
- int natts;
- Page page;
-
- metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_READ);
- metap = (HashMetaPage) BufferGetPage(metabuf);
- _hash_checkpage((Page) metap, LH_META_PAGE);
-
- /* we need a scan key to do our search, so build one */
- itup = &(hitem->hash_itup);
- if ((natts = rel->rd_rel->relnatts) != 1)
- elog(WARN, "Hash indices valid for only one index key.");
- itup_scankey = _hash_mkscankey(rel, itup, metap);
-
- /*
- * find the first page in the bucket chain containing this key and
- * place it in buf. _hash_search obtains a read lock for us.
- */
- _hash_search(rel, natts, itup_scankey, &buf, metap);
- page = BufferGetPage(buf);
- _hash_checkpage(page, LH_BUCKET_PAGE);
-
- /*
- * trade in our read lock for a write lock so that we can do the
- * insertion.
- */
- blkno = BufferGetBlockNumber(buf);
- _hash_relbuf(rel, buf, HASH_READ);
- buf = _hash_getbuf(rel, blkno, HASH_WRITE);
-
-
- /*
- * XXX btree comment (haven't decided what to do in hash): don't
- * think the bucket can be split while we're reading the metapage.
- *
- * If the page was split between the time that we surrendered our
- * read lock and acquired our write lock, then this page may no
- * longer be the right place for the key we want to insert.
- */
-
- /* do the insertion */
- res = _hash_insertonpg(rel, buf, natts, itup_scankey,
- hitem, metabuf);
-
- /* be tidy */
- _hash_freeskey(itup_scankey);
-
- return (res);
+ Buffer buf;
+ Buffer metabuf;
+ BlockNumber blkno;
+ HashMetaPage metap;
+ IndexTuple itup;
+ InsertIndexResult res;
+ ScanKey itup_scankey;
+ int natts;
+ Page page;
+
+ metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_READ);
+ metap = (HashMetaPage) BufferGetPage(metabuf);
+ _hash_checkpage((Page) metap, LH_META_PAGE);
+
+ /* we need a scan key to do our search, so build one */
+ itup = &(hitem->hash_itup);
+ if ((natts = rel->rd_rel->relnatts) != 1)
+ elog(WARN, "Hash indices valid for only one index key.");
+ itup_scankey = _hash_mkscankey(rel, itup, metap);
+
+ /*
+ * find the first page in the bucket chain containing this key and
+ * place it in buf. _hash_search obtains a read lock for us.
+ */
+ _hash_search(rel, natts, itup_scankey, &buf, metap);
+ page = BufferGetPage(buf);
+ _hash_checkpage(page, LH_BUCKET_PAGE);
+
+ /*
+ * trade in our read lock for a write lock so that we can do the
+ * insertion.
+ */
+ blkno = BufferGetBlockNumber(buf);
+ _hash_relbuf(rel, buf, HASH_READ);
+ buf = _hash_getbuf(rel, blkno, HASH_WRITE);
+
+
+ /*
+ * XXX btree comment (haven't decided what to do in hash): don't think
+ * the bucket can be split while we're reading the metapage.
+ *
+ * If the page was split between the time that we surrendered our read
+ * lock and acquired our write lock, then this page may no longer be
+ * the right place for the key we want to insert.
+ */
+
+ /* do the insertion */
+ res = _hash_insertonpg(rel, buf, natts, itup_scankey,
+ hitem, metabuf);
+
+ /* be tidy */
+ _hash_freeskey(itup_scankey);
+
+ return (res);
}
/*
- * _hash_insertonpg() -- Insert a tuple on a particular page in the table.
+ * _hash_insertonpg() -- Insert a tuple on a particular page in the table.
*
- * This recursive procedure does the following things:
+ * This recursive procedure does the following things:
*
- * + if necessary, splits the target page.
- * + inserts the tuple.
+ * + if necessary, splits the target page.
+ * + inserts the tuple.
*
- * On entry, we must have the right buffer on which to do the
- * insertion, and the buffer must be pinned and locked. On return,
- * we will have dropped both the pin and the write lock on the buffer.
+ * On entry, we must have the right buffer on which to do the
+ * insertion, and the buffer must be pinned and locked. On return,
+ * we will have dropped both the pin and the write lock on the buffer.
*
*/
-static InsertIndexResult
+static InsertIndexResult
_hash_insertonpg(Relation rel,
- Buffer buf,
- int keysz,
- ScanKey scankey,
- HashItem hitem,
- Buffer metabuf)
+ Buffer buf,
+ int keysz,
+ ScanKey scankey,
+ HashItem hitem,
+ Buffer metabuf)
{
- InsertIndexResult res;
- Page page;
- BlockNumber itup_blkno;
- OffsetNumber itup_off;
- int itemsz;
- HashPageOpaque pageopaque;
- bool do_expand = false;
- Buffer ovflbuf;
- HashMetaPage metap;
- Bucket bucket;
-
- metap = (HashMetaPage) BufferGetPage(metabuf);
- _hash_checkpage((Page) metap, LH_META_PAGE);
-
- page = BufferGetPage(buf);
- _hash_checkpage(page, LH_BUCKET_PAGE|LH_OVERFLOW_PAGE);
- pageopaque = (HashPageOpaque) PageGetSpecialPointer(page);
- bucket = pageopaque->hasho_bucket;
-
- itemsz = IndexTupleDSize(hitem->hash_itup)
- + (sizeof(HashItemData) - sizeof(IndexTupleData));
- itemsz = DOUBLEALIGN(itemsz);
-
- while (PageGetFreeSpace(page) < itemsz) {
- /*
- * no space on this page; check for an overflow page
- */
- if (BlockNumberIsValid(pageopaque->hasho_nextblkno)) {
- /*
- * ovfl page exists; go get it. if it doesn't have room,
- * we'll find out next pass through the loop test above.
- */
- ovflbuf = _hash_getbuf(rel, pageopaque->hasho_nextblkno,
- HASH_WRITE);
- _hash_relbuf(rel, buf, HASH_WRITE);
- buf = ovflbuf;
- page = BufferGetPage(buf);
- } else {
- /*
- * we're at the end of the bucket chain and we haven't
- * found a page with enough room. allocate a new overflow
- * page.
- */
- do_expand = true;
- ovflbuf = _hash_addovflpage(rel, &metabuf, buf);
- _hash_relbuf(rel, buf, HASH_WRITE);
- buf = ovflbuf;
- page = BufferGetPage(buf);
-
- if (PageGetFreeSpace(page) < itemsz) {
- /* it doesn't fit on an empty page -- give up */
- elog(WARN, "hash item too large");
- }
- }
- _hash_checkpage(page, LH_OVERFLOW_PAGE);
+ InsertIndexResult res;
+ Page page;
+ BlockNumber itup_blkno;
+ OffsetNumber itup_off;
+ int itemsz;
+ HashPageOpaque pageopaque;
+ bool do_expand = false;
+ Buffer ovflbuf;
+ HashMetaPage metap;
+ Bucket bucket;
+
+ metap = (HashMetaPage) BufferGetPage(metabuf);
+ _hash_checkpage((Page) metap, LH_META_PAGE);
+
+ page = BufferGetPage(buf);
+ _hash_checkpage(page, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE);
pageopaque = (HashPageOpaque) PageGetSpecialPointer(page);
- Assert(pageopaque->hasho_bucket == bucket);
- }
-
- itup_off = _hash_pgaddtup(rel, buf, keysz, scankey, itemsz, hitem);
- itup_blkno = BufferGetBlockNumber(buf);
-
- /* by here, the new tuple is inserted */
- res = (InsertIndexResult) palloc(sizeof(InsertIndexResultData));
-
- ItemPointerSet(&(res->pointerData), itup_blkno, itup_off);
-
- if (res != NULL) {
- /*
- * Increment the number of keys in the table.
- * We switch lock access type just for a moment
- * to allow greater accessibility to the metapage.
- */
- metap = (HashMetaPage) _hash_chgbufaccess(rel, &metabuf,
- HASH_READ, HASH_WRITE);
- metap->hashm_nkeys += 1;
- metap = (HashMetaPage) _hash_chgbufaccess(rel, &metabuf,
- HASH_WRITE, HASH_READ);
-
- }
-
- _hash_wrtbuf(rel, buf);
-
- if (do_expand ||
- (metap->hashm_nkeys / (metap->hashm_maxbucket + 1))
- > metap->hashm_ffactor) {
- _hash_expandtable(rel, metabuf);
- }
- _hash_relbuf(rel, metabuf, HASH_READ);
- return (res);
-}
+ bucket = pageopaque->hasho_bucket;
+
+ itemsz = IndexTupleDSize(hitem->hash_itup)
+ + (sizeof(HashItemData) - sizeof(IndexTupleData));
+ itemsz = DOUBLEALIGN(itemsz);
+
+ while (PageGetFreeSpace(page) < itemsz)
+ {
+
+ /*
+ * no space on this page; check for an overflow page
+ */
+ if (BlockNumberIsValid(pageopaque->hasho_nextblkno))
+ {
+
+ /*
+ * ovfl page exists; go get it. if it doesn't have room,
+ * we'll find out next pass through the loop test above.
+ */
+ ovflbuf = _hash_getbuf(rel, pageopaque->hasho_nextblkno,
+ HASH_WRITE);
+ _hash_relbuf(rel, buf, HASH_WRITE);
+ buf = ovflbuf;
+ page = BufferGetPage(buf);
+ }
+ else
+ {
+
+ /*
+ * we're at the end of the bucket chain and we haven't found a
+ * page with enough room. allocate a new overflow page.
+ */
+ do_expand = true;
+ ovflbuf = _hash_addovflpage(rel, &metabuf, buf);
+ _hash_relbuf(rel, buf, HASH_WRITE);
+ buf = ovflbuf;
+ page = BufferGetPage(buf);
+
+ if (PageGetFreeSpace(page) < itemsz)
+ {
+ /* it doesn't fit on an empty page -- give up */
+ elog(WARN, "hash item too large");
+ }
+ }
+ _hash_checkpage(page, LH_OVERFLOW_PAGE);
+ pageopaque = (HashPageOpaque) PageGetSpecialPointer(page);
+ Assert(pageopaque->hasho_bucket == bucket);
+ }
+
+ itup_off = _hash_pgaddtup(rel, buf, keysz, scankey, itemsz, hitem);
+ itup_blkno = BufferGetBlockNumber(buf);
+
+ /* by here, the new tuple is inserted */
+ res = (InsertIndexResult) palloc(sizeof(InsertIndexResultData));
+
+ ItemPointerSet(&(res->pointerData), itup_blkno, itup_off);
+
+ if (res != NULL)
+ {
+
+ /*
+ * Increment the number of keys in the table. We switch lock
+ * access type just for a moment to allow greater accessibility to
+ * the metapage.
+ */
+ metap = (HashMetaPage) _hash_chgbufaccess(rel, &metabuf,
+ HASH_READ, HASH_WRITE);
+ metap->hashm_nkeys += 1;
+ metap = (HashMetaPage) _hash_chgbufaccess(rel, &metabuf,
+ HASH_WRITE, HASH_READ);
+
+ }
+
+ _hash_wrtbuf(rel, buf);
+
+ if (do_expand ||
+ (metap->hashm_nkeys / (metap->hashm_maxbucket + 1))
+ > metap->hashm_ffactor)
+ {
+ _hash_expandtable(rel, metabuf);
+ }
+ _hash_relbuf(rel, metabuf, HASH_READ);
+ return (res);
+}
/*
- * _hash_pgaddtup() -- add a tuple to a particular page in the index.
+ * _hash_pgaddtup() -- add a tuple to a particular page in the index.
*
- * This routine adds the tuple to the page as requested, and keeps the
- * write lock and reference associated with the page's buffer. It is
- * an error to call pgaddtup() without a write lock and reference.
+ * This routine adds the tuple to the page as requested, and keeps the
+ * write lock and reference associated with the page's buffer. It is
+ * an error to call pgaddtup() without a write lock and reference.
*/
-static OffsetNumber
+static OffsetNumber
_hash_pgaddtup(Relation rel,
- Buffer buf,
- int keysz,
- ScanKey itup_scankey,
- Size itemsize,
- HashItem hitem)
+ Buffer buf,
+ int keysz,
+ ScanKey itup_scankey,
+ Size itemsize,
+ HashItem hitem)
{
- OffsetNumber itup_off;
- Page page;
-
- page = BufferGetPage(buf);
- _hash_checkpage(page, LH_BUCKET_PAGE|LH_OVERFLOW_PAGE);
-
- itup_off = OffsetNumberNext(PageGetMaxOffsetNumber(page));
- PageAddItem(page, (Item) hitem, itemsize, itup_off, LP_USED);
-
- /* write the buffer, but hold our lock */
- _hash_wrtnorelbuf(rel, buf);
-
- return (itup_off);
+ OffsetNumber itup_off;
+ Page page;
+
+ page = BufferGetPage(buf);
+ _hash_checkpage(page, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE);
+
+ itup_off = OffsetNumberNext(PageGetMaxOffsetNumber(page));
+ PageAddItem(page, (Item) hitem, itemsize, itup_off, LP_USED);
+
+ /* write the buffer, but hold our lock */
+ _hash_wrtnorelbuf(rel, buf);
+
+ return (itup_off);
}
diff --git a/src/backend/access/hash/hashovfl.c b/src/backend/access/hash/hashovfl.c
index d976c4818c8..b6882d4d3e1 100644
--- a/src/backend/access/hash/hashovfl.c
+++ b/src/backend/access/hash/hashovfl.c
@@ -1,400 +1,423 @@
/*-------------------------------------------------------------------------
*
* hashovfl.c--
- * Overflow page management code for the Postgres hash access method
+ * Overflow page management code for the Postgres hash access method
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/hash/hashovfl.c,v 1.9 1997/08/12 22:51:34 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/hash/hashovfl.c,v 1.10 1997/09/07 04:37:57 momjian Exp $
*
* NOTES
- * Overflow pages look like ordinary relation pages.
+ * Overflow pages look like ordinary relation pages.
*
*-------------------------------------------------------------------------
*/
#include <postgres.h>
-
+
#include <access/hash.h>
#include <storage/bufmgr.h>
#include <utils/memutils.h>
#ifndef HAVE_MEMMOVE
-# include <regex/utils.h>
+#include <regex/utils.h>
#else
-# include <string.h>
+#include <string.h>
#endif
-static OverflowPageAddress _hash_getovfladdr(Relation rel, Buffer *metabufp);
-static uint32 _hash_firstfreebit(uint32 map);
+static OverflowPageAddress _hash_getovfladdr(Relation rel, Buffer * metabufp);
+static uint32 _hash_firstfreebit(uint32 map);
/*
- * _hash_addovflpage
+ * _hash_addovflpage
+ *
+ * Add an overflow page to the page currently pointed to by the buffer
+ * argument 'buf'.
*
- * Add an overflow page to the page currently pointed to by the buffer
- * argument 'buf'.
+ * *Metabufp has a read lock upon entering the function; buf has a
+ * write lock.
*
- * *Metabufp has a read lock upon entering the function; buf has a
- * write lock.
- *
*/
Buffer
-_hash_addovflpage(Relation rel, Buffer *metabufp, Buffer buf)
+_hash_addovflpage(Relation rel, Buffer * metabufp, Buffer buf)
{
-
- OverflowPageAddress oaddr;
- BlockNumber ovflblkno;
- Buffer ovflbuf;
- HashMetaPage metap;
- HashPageOpaque ovflopaque;
- HashPageOpaque pageopaque;
- Page page;
- Page ovflpage;
-
- /* this had better be the last page in a bucket chain */
- page = BufferGetPage(buf);
- _hash_checkpage(page, LH_BUCKET_PAGE|LH_OVERFLOW_PAGE);
- pageopaque = (HashPageOpaque) PageGetSpecialPointer(page);
- Assert(!BlockNumberIsValid(pageopaque->hasho_nextblkno));
-
- metap = (HashMetaPage) BufferGetPage(*metabufp);
- _hash_checkpage((Page) metap, LH_META_PAGE);
-
- /* allocate an empty overflow page */
- oaddr = _hash_getovfladdr(rel, metabufp);
- if (oaddr == InvalidOvflAddress) {
- elog(WARN, "_hash_addovflpage: problem with _hash_getovfladdr.");
- }
- ovflblkno = OADDR_TO_BLKNO(OADDR_OF(SPLITNUM(oaddr), OPAGENUM(oaddr)));
- Assert(BlockNumberIsValid(ovflblkno));
- ovflbuf = _hash_getbuf(rel, ovflblkno, HASH_WRITE);
- Assert(BufferIsValid(ovflbuf));
- ovflpage = BufferGetPage(ovflbuf);
-
- /* initialize the new overflow page */
- _hash_pageinit(ovflpage, BufferGetPageSize(ovflbuf));
- ovflopaque = (HashPageOpaque) PageGetSpecialPointer(ovflpage);
- ovflopaque->hasho_prevblkno = BufferGetBlockNumber(buf);
- ovflopaque->hasho_nextblkno = InvalidBlockNumber;
- ovflopaque->hasho_flag = LH_OVERFLOW_PAGE;
- ovflopaque->hasho_oaddr = oaddr;
- ovflopaque->hasho_bucket = pageopaque->hasho_bucket;
- _hash_wrtnorelbuf(rel, ovflbuf);
-
- /* logically chain overflow page to previous page */
- pageopaque->hasho_nextblkno = ovflblkno;
- _hash_wrtnorelbuf(rel, buf);
- return (ovflbuf);
+
+ OverflowPageAddress oaddr;
+ BlockNumber ovflblkno;
+ Buffer ovflbuf;
+ HashMetaPage metap;
+ HashPageOpaque ovflopaque;
+ HashPageOpaque pageopaque;
+ Page page;
+ Page ovflpage;
+
+ /* this had better be the last page in a bucket chain */
+ page = BufferGetPage(buf);
+ _hash_checkpage(page, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE);
+ pageopaque = (HashPageOpaque) PageGetSpecialPointer(page);
+ Assert(!BlockNumberIsValid(pageopaque->hasho_nextblkno));
+
+ metap = (HashMetaPage) BufferGetPage(*metabufp);
+ _hash_checkpage((Page) metap, LH_META_PAGE);
+
+ /* allocate an empty overflow page */
+ oaddr = _hash_getovfladdr(rel, metabufp);
+ if (oaddr == InvalidOvflAddress)
+ {
+ elog(WARN, "_hash_addovflpage: problem with _hash_getovfladdr.");
+ }
+ ovflblkno = OADDR_TO_BLKNO(OADDR_OF(SPLITNUM(oaddr), OPAGENUM(oaddr)));
+ Assert(BlockNumberIsValid(ovflblkno));
+ ovflbuf = _hash_getbuf(rel, ovflblkno, HASH_WRITE);
+ Assert(BufferIsValid(ovflbuf));
+ ovflpage = BufferGetPage(ovflbuf);
+
+ /* initialize the new overflow page */
+ _hash_pageinit(ovflpage, BufferGetPageSize(ovflbuf));
+ ovflopaque = (HashPageOpaque) PageGetSpecialPointer(ovflpage);
+ ovflopaque->hasho_prevblkno = BufferGetBlockNumber(buf);
+ ovflopaque->hasho_nextblkno = InvalidBlockNumber;
+ ovflopaque->hasho_flag = LH_OVERFLOW_PAGE;
+ ovflopaque->hasho_oaddr = oaddr;
+ ovflopaque->hasho_bucket = pageopaque->hasho_bucket;
+ _hash_wrtnorelbuf(rel, ovflbuf);
+
+ /* logically chain overflow page to previous page */
+ pageopaque->hasho_nextblkno = ovflblkno;
+ _hash_wrtnorelbuf(rel, buf);
+ return (ovflbuf);
}
/*
- * _hash_getovfladdr()
+ * _hash_getovfladdr()
*
- * Find an available overflow page and return its address.
+ * Find an available overflow page and return its address.
*
- * When we enter this function, we have a read lock on *metabufp which
- * we change to a write lock immediately. Before exiting, the write lock
- * is exchanged for a read lock.
+ * When we enter this function, we have a read lock on *metabufp which
+ * we change to a write lock immediately. Before exiting, the write lock
+ * is exchanged for a read lock.
*
*/
-static OverflowPageAddress
-_hash_getovfladdr(Relation rel, Buffer *metabufp)
+static OverflowPageAddress
+_hash_getovfladdr(Relation rel, Buffer * metabufp)
{
- HashMetaPage metap;
- Buffer mapbuf = 0;
- BlockNumber blkno;
- PageOffset offset;
- OverflowPageAddress oaddr;
- SplitNumber splitnum;
- uint32 *freep = NULL;
- uint32 max_free;
- uint32 bit;
- uint32 first_page;
- uint32 free_bit;
- uint32 free_page;
- uint32 in_use_bits;
- uint32 i, j;
-
- metap = (HashMetaPage) _hash_chgbufaccess(rel, metabufp, HASH_READ, HASH_WRITE);
-
- splitnum = metap->OVFL_POINT;
- max_free = metap->SPARES[splitnum];
-
- free_page = (max_free - 1) >> (metap->BSHIFT + BYTE_TO_BIT);
- free_bit = (max_free - 1) & (BMPGSZ_BIT(metap) - 1);
-
- /* Look through all the free maps to find the first free block */
- first_page = metap->LAST_FREED >> (metap->BSHIFT + BYTE_TO_BIT);
- for ( i = first_page; i <= free_page; i++ ) {
- Page mappage;
-
- blkno = metap->hashm_mapp[i];
- mapbuf = _hash_getbuf(rel, blkno, HASH_WRITE);
- mappage = BufferGetPage(mapbuf);
- _hash_checkpage(mappage, LH_BITMAP_PAGE);
- freep = HashPageGetBitmap(mappage);
- Assert(freep);
-
- if (i == free_page)
- in_use_bits = free_bit;
- else
- in_use_bits = BMPGSZ_BIT(metap) - 1;
-
- if (i == first_page) {
- bit = metap->LAST_FREED & (BMPGSZ_BIT(metap) - 1);
- j = bit / BITS_PER_MAP;
- bit = bit & ~(BITS_PER_MAP - 1);
- } else {
- bit = 0;
- j = 0;
+ HashMetaPage metap;
+ Buffer mapbuf = 0;
+ BlockNumber blkno;
+ PageOffset offset;
+ OverflowPageAddress oaddr;
+ SplitNumber splitnum;
+ uint32 *freep = NULL;
+ uint32 max_free;
+ uint32 bit;
+ uint32 first_page;
+ uint32 free_bit;
+ uint32 free_page;
+ uint32 in_use_bits;
+ uint32 i,
+ j;
+
+ metap = (HashMetaPage) _hash_chgbufaccess(rel, metabufp, HASH_READ, HASH_WRITE);
+
+ splitnum = metap->OVFL_POINT;
+ max_free = metap->SPARES[splitnum];
+
+ free_page = (max_free - 1) >> (metap->BSHIFT + BYTE_TO_BIT);
+ free_bit = (max_free - 1) & (BMPGSZ_BIT(metap) - 1);
+
+ /* Look through all the free maps to find the first free block */
+ first_page = metap->LAST_FREED >> (metap->BSHIFT + BYTE_TO_BIT);
+ for (i = first_page; i <= free_page; i++)
+ {
+ Page mappage;
+
+ blkno = metap->hashm_mapp[i];
+ mapbuf = _hash_getbuf(rel, blkno, HASH_WRITE);
+ mappage = BufferGetPage(mapbuf);
+ _hash_checkpage(mappage, LH_BITMAP_PAGE);
+ freep = HashPageGetBitmap(mappage);
+ Assert(freep);
+
+ if (i == free_page)
+ in_use_bits = free_bit;
+ else
+ in_use_bits = BMPGSZ_BIT(metap) - 1;
+
+ if (i == first_page)
+ {
+ bit = metap->LAST_FREED & (BMPGSZ_BIT(metap) - 1);
+ j = bit / BITS_PER_MAP;
+ bit = bit & ~(BITS_PER_MAP - 1);
+ }
+ else
+ {
+ bit = 0;
+ j = 0;
+ }
+ for (; bit <= in_use_bits; j++, bit += BITS_PER_MAP)
+ if (freep[j] != ALL_SET)
+ goto found;
+ }
+
+ /* No Free Page Found - have to allocate a new page */
+ metap->LAST_FREED = metap->SPARES[splitnum];
+ metap->SPARES[splitnum]++;
+ offset = metap->SPARES[splitnum] -
+ (splitnum ? metap->SPARES[splitnum - 1] : 0);
+
+#define OVMSG "HASH: Out of overflow pages. Out of luck.\n"
+
+ if (offset > SPLITMASK)
+ {
+ if (++splitnum >= NCACHED)
+ {
+ elog(WARN, OVMSG);
+ }
+ metap->OVFL_POINT = splitnum;
+ metap->SPARES[splitnum] = metap->SPARES[splitnum - 1];
+ metap->SPARES[splitnum - 1]--;
+ offset = 0;
}
- for (; bit <= in_use_bits; j++, bit += BITS_PER_MAP)
- if (freep[j] != ALL_SET)
- goto found;
- }
-
- /* No Free Page Found - have to allocate a new page */
- metap->LAST_FREED = metap->SPARES[splitnum];
- metap->SPARES[splitnum]++;
- offset = metap->SPARES[splitnum] -
- (splitnum ? metap->SPARES[splitnum - 1] : 0);
-
-#define OVMSG "HASH: Out of overflow pages. Out of luck.\n"
-
- if (offset > SPLITMASK) {
- if (++splitnum >= NCACHED) {
- elog(WARN, OVMSG);
+
+ /* Check if we need to allocate a new bitmap page */
+ if (free_bit == BMPGSZ_BIT(metap) - 1)
+ {
+ /* won't be needing old map page */
+
+ _hash_relbuf(rel, mapbuf, HASH_WRITE);
+
+ free_page++;
+ if (free_page >= NCACHED)
+ {
+ elog(WARN, OVMSG);
+ }
+
+ /*
+ * This is tricky. The 1 indicates that you want the new page
+ * allocated with 1 clear bit. Actually, you are going to
+ * allocate 2 pages from this map. The first is going to be the
+ * map page, the second is the overflow page we were looking for.
+ * The init_bitmap routine automatically, sets the first bit of
+ * itself to indicate that the bitmap itself is in use. We would
+ * explicitly set the second bit, but don't have to if we tell
+ * init_bitmap not to leave it clear in the first place.
+ */
+ if (_hash_initbitmap(rel, metap, OADDR_OF(splitnum, offset),
+ 1, free_page))
+ {
+ elog(WARN, "overflow_page: problem with _hash_initbitmap.");
+ }
+ metap->SPARES[splitnum]++;
+ offset++;
+ if (offset > SPLITMASK)
+ {
+ if (++splitnum >= NCACHED)
+ {
+ elog(WARN, OVMSG);
+ }
+ metap->OVFL_POINT = splitnum;
+ metap->SPARES[splitnum] = metap->SPARES[splitnum - 1];
+ metap->SPARES[splitnum - 1]--;
+ offset = 0;
+ }
}
- metap->OVFL_POINT = splitnum;
- metap->SPARES[splitnum] = metap->SPARES[splitnum-1];
- metap->SPARES[splitnum-1]--;
- offset = 0;
- }
-
- /* Check if we need to allocate a new bitmap page */
- if (free_bit == BMPGSZ_BIT(metap) - 1) {
- /* won't be needing old map page */
-
- _hash_relbuf(rel, mapbuf, HASH_WRITE);
-
- free_page++;
- if (free_page >= NCACHED) {
- elog(WARN, OVMSG);
+ else
+ {
+
+ /*
+ * Free_bit addresses the last used bit. Bump it to address the
+ * first available bit.
+ */
+ free_bit++;
+ SETBIT(freep, free_bit);
+ _hash_wrtbuf(rel, mapbuf);
}
-
+
+ /* Calculate address of the new overflow page */
+ oaddr = OADDR_OF(splitnum, offset);
+ _hash_chgbufaccess(rel, metabufp, HASH_WRITE, HASH_READ);
+ return (oaddr);
+
+found:
+ bit = bit + _hash_firstfreebit(freep[j]);
+ SETBIT(freep, bit);
+ _hash_wrtbuf(rel, mapbuf);
+
/*
- * This is tricky. The 1 indicates that you want the new page
- * allocated with 1 clear bit. Actually, you are going to
<