55 *
66 *
77 * IDENTIFICATION
8- * $Id: nbtsort.c,v 1.10 1997/02/14 22:47:19 momjian Exp $
8+ * $Id: nbtsort.c,v 1.11 1997/02/22 10:04:16 vadim Exp $
99 *
1010 * NOTES
1111 *
@@ -81,6 +81,43 @@ extern int NDirectFileRead;
8181extern int NDirectFileWrite ;
8282extern char * mktemp (char * template );
8383
84+ /*
85+ * this is what we use to shovel BTItems in and out of memory. it's
86+ * bigger than a standard block because we are doing a lot of strictly
87+ * sequential i/o. this is obviously something of a tradeoff since we
88+ * are potentially reading a bunch of zeroes off of disk in many
89+ * cases.
90+ *
91+ * BTItems are packed in and DOUBLEALIGN'd.
92+ *
93+ * the fd should not be going out to disk, strictly speaking, but it's
94+ * the only thing like that so i'm not going to worry about wasting a
95+ * few bytes.
96+ */
97+ typedef struct {
98+ int bttb_magic ;/* magic number */
99+ int bttb_fd ;/* file descriptor */
100+ int bttb_top ;/* top of free space within bttb_data */
101+ short bttb_ntup ;/* number of tuples in this block */
102+ short bttb_eor ;/* End-Of-Run marker */
103+ char bttb_data [TAPEBLCKSZ - 2 * sizeof (double )];
104+ }BTTapeBlock ;
105+
106+ /*
107+ * this structure holds the bookkeeping for a simple balanced multiway
108+ * merge. (polyphase merging is hairier than i want to get into right
109+ * now, and i don't see why i have to care how many "tapes" i use
110+ * right now. though if psort was in a condition that i could hack it
111+ * to do this, you bet i would.)
112+ */
113+ typedef struct {
114+ int bts_ntapes ;
115+ int bts_tape ;
116+ BTTapeBlock * * bts_itape ;/* input tape blocks */
117+ BTTapeBlock * * bts_otape ;/* output tape blocks */
118+ bool isunique ;
119+ }BTSpool ;
120+
84121/*-------------------------------------------------------------------------
85122 * sorting comparison routine - returns {-1,0,1} depending on whether
86123 * the key in the left BTItem is {<,=,>} the key in the right BTItem.
@@ -105,11 +142,13 @@ typedef struct {
105142}BTSortKey ;
106143
107144static Relation _bt_sortrel ;
145+ static BTSpool * _bt_inspool ;
108146
109147static void
110- _bt_isortcmpinit (Relation index )
148+ _bt_isortcmpinit (Relation index , BTSpool * spool )
111149{
112150_bt_sortrel = index ;
151+ _bt_inspool = spool ;
113152}
114153
115154static int
@@ -129,6 +168,11 @@ _bt_isortcmp(BTSortKey *k1, BTSortKey *k2)
129168k2 -> btsk_datum ,k1 -> btsk_datum )) {
130169return (-1 );/* 1 < 2 */
131170 }
171+ if (_bt_inspool -> isunique )
172+ {
173+ _bt_spooldestroy ((void * )_bt_inspool );
174+ elog (WARN ,"Cannot insert a duplicate key into a unique index." );
175+ }
132176return (0 );/* 1 = 2 */
133177}
134178
@@ -159,7 +203,6 @@ _bt_setsortkey(Relation index, BTItem bti, BTSortKey *sk)
159203 * XXX these probably ought to be generic library functions.
160204 *-------------------------------------------------------------------------
161205 */
162-
163206typedef struct {
164207int btpqe_tape ;/* tape identifier */
165208BTSortKey btpqe_item ;/* pointer to BTItem in tape buffer */
@@ -256,29 +299,6 @@ _bt_pqadd(BTPriQueue *q, BTPriQueueElem *e)
256299 ((tape)->bttb_ntup <= 0)
257300#define BTTAPEMAGIC 0x19660226
258301
259- /*
260- * this is what we use to shovel BTItems in and out of memory. it's
261- * bigger than a standard block because we are doing a lot of strictly
262- * sequential i/o. this is obviously something of a tradeoff since we
263- * are potentially reading a bunch of zeroes off of disk in many
264- * cases.
265- *
266- * BTItems are packed in and DOUBLEALIGN'd.
267- *
268- * the fd should not be going out to disk, strictly speaking, but it's
269- * the only thing like that so i'm not going to worry about wasting a
270- * few bytes.
271- */
272- typedef struct {
273- int bttb_magic ;/* magic number */
274- int bttb_fd ;/* file descriptor */
275- int bttb_top ;/* top of free space within bttb_data */
276- short bttb_ntup ;/* number of tuples in this block */
277- short bttb_eor ;/* End-Of-Run marker */
278- char bttb_data [TAPEBLCKSZ - 2 * sizeof (double )];
279- }BTTapeBlock ;
280-
281-
282302/*
283303 * reset the tape header for its next use without doing anything to
284304 * the physical tape file. (setting bttb_top to 0 makes the block
@@ -455,26 +475,12 @@ _bt_tapeadd(BTTapeBlock *tape, BTItem item, int itemsz)
455475 *-------------------------------------------------------------------------
456476 */
457477
458- /*
459- * this structure holds the bookkeeping for a simple balanced multiway
460- * merge. (polyphase merging is hairier than i want to get into right
461- * now, and i don't see why i have to care how many "tapes" i use
462- * right now. though if psort was in a condition that i could hack it
463- * to do this, you bet i would.)
464- */
465- typedef struct {
466- int bts_ntapes ;
467- int bts_tape ;
468- BTTapeBlock * * bts_itape ;/* input tape blocks */
469- BTTapeBlock * * bts_otape ;/* output tape blocks */
470- }BTSpool ;
471-
472478/*
473479 * create and initialize a spool structure, including the underlying
474480 * files.
475481 */
476482void *
477- _bt_spoolinit (Relation index ,int ntapes )
483+ _bt_spoolinit (Relation index ,int ntapes , bool isunique )
478484{
479485BTSpool * btspool = (BTSpool * )palloc (sizeof (BTSpool ));
480486int i ;
@@ -486,6 +492,7 @@ _bt_spoolinit(Relation index, int ntapes)
486492 (void )memset ((char * )btspool ,0 ,sizeof (BTSpool ));
487493btspool -> bts_ntapes = ntapes ;
488494btspool -> bts_tape = 0 ;
495+ btspool -> isunique = isunique ;
489496
490497btspool -> bts_itape =
491498(BTTapeBlock * * )palloc (sizeof (BTTapeBlock * )* ntapes );
@@ -504,7 +511,7 @@ _bt_spoolinit(Relation index, int ntapes)
504511 }
505512pfree ((void * )fname );
506513
507- _bt_isortcmpinit (index );
514+ _bt_isortcmpinit (index , btspool );
508515
509516return ((void * )btspool );
510517}
@@ -597,6 +604,8 @@ _bt_spool(Relation index, BTItem btitem, void *spool)
597604BTTapeBlock * itape ;
598605Size itemsz ;
599606
607+ _bt_isortcmpinit (index ,btspool );
608+
600609itape = btspool -> bts_itape [btspool -> bts_tape ];
601610itemsz = BTITEMSZ (btitem );
602611itemsz = DOUBLEALIGN (itemsz );
@@ -633,7 +642,6 @@ _bt_spool(Relation index, BTItem btitem, void *spool)
633642/*
634643 * qsort the pointer array.
635644 */
636- _bt_isortcmpinit (index );
637645qsort ((void * )parray ,itape -> bttb_ntup ,sizeof (BTSortKey ),
638646 (int (* )(const void * ,const void * ))_bt_isortcmp );
639647}
@@ -1298,5 +1306,6 @@ _bt_upperbuild(Relation index)
12981306void
12991307_bt_leafbuild (Relation index ,void * spool )
13001308{
1309+ _bt_isortcmpinit (index , (BTSpool * )spool );
13011310_bt_merge (index , (BTSpool * )spool );
13021311}