1# Copyright (c) 1996, 2020 Oracle and/or its affiliates.  All rights reserved.
2#
3# See the file LICENSE for license information.
4#
5# $Id$
6#
7# TEST	test028
8# TEST	Cursor delete test
9# TEST	Test put operations after deleting through a cursor.
10proc test028 { method args } {
11	global dupnum
12	global dupstr
13	global alphabet
14	source ./include.tcl
15
16	set args [convert_args $method $args]
17	set omethod [convert_method $method]
18
19	puts "Test028: $method put after cursor delete test"
20
21	if { [is_rbtree $method] == 1 } {
22		puts "Test028 skipping for method $method"
23		return
24	}
25	if { [is_record_based $method] == 1 } {
26		set key 10
27	} else {
28		set key "put_after_cursor_del"
29		if { [is_compressed $args] == 0 } {
30			append args " -dup"
31		}
32	}
33
34	# Create the database and open the dictionary
35	set txnenv 0
36	set eindex [lsearch -exact $args "-env"]
37	#
38	# If we are using an env, then testfile should just be the db name.
39	# Otherwise it is the test directory and the name.
40	if { $eindex == -1 } {
41		set testfile $testdir/test028.db
42		set env NULL
43	} else {
44		set testfile test028.db
45		incr eindex
46		set env [lindex $args $eindex]
47		set txnenv [is_txnenv $env]
48		if { $txnenv == 1 } {
49			append args " -auto_commit "
50		}
51		set testdir [get_home $env]
52	}
53	set t1 $testdir/t1
54	cleanup $testdir $env
55	set db [eval {berkdb_open \
56	     -create -mode 0644} $args {$omethod $testfile}]
57	error_check_good dbopen [is_valid_db $db] TRUE
58
59	set ndups 20
60	set txn ""
61	set pflags ""
62	set gflags ""
63
64	if { [is_record_based $method] == 1 } {
65		set gflags " -recno"
66	}
67
68	if { $txnenv == 1 } {
69		set t [$env txn]
70		error_check_good txn [is_valid_txn $t $env] TRUE
71		set txn "-txn $t"
72	}
73	set dbc [eval {$db cursor} $txn]
74	error_check_good db_cursor [is_substr $dbc $db] 1
75
76	foreach i { offpage onpage } {
77		foreach b { bigitem smallitem } {
78			if { $i == "onpage" } {
79				if { $b == "bigitem" } {
80					set dupstr [repeat $alphabet 100]
81				} else {
82					set dupstr DUP
83				}
84			} else {
85				if { $b == "bigitem" } {
86					set dupstr [repeat $alphabet 100]
87				} else {
88					set dupstr [repeat $alphabet 50]
89				}
90			}
91
92			if { $b == "bigitem" } {
93				set dupstr [repeat $dupstr 10]
94			}
95			puts "\tTest028: $i/$b"
96
97			puts "\tTest028.a: Insert key with single data item"
98			set ret [eval {$db put} \
99			    $txn $pflags {$key [chop_data $method $dupstr]}]
100			error_check_good db_put $ret 0
101
102			# Now let's get the item and make sure its OK.
103			puts "\tTest028.b: Check initial entry"
104			set ret [eval {$db get} $txn $gflags {$key}]
105			error_check_good db_get \
106			    $ret [list [list $key [pad_data $method $dupstr]]]
107
108			# Now try a put with NOOVERWRITE SET (should be error)
109			puts "\tTest028.c: No_overwrite test"
110			set ret [eval {$db put} $txn \
111			    {-nooverwrite $key [chop_data $method $dupstr]}]
112			error_check_good \
113			    db_put [is_substr $ret "DB_KEYEXIST"] 1
114
115			# Now delete the item with a cursor
116			puts "\tTest028.d: Delete test"
117			set ret [$dbc get -set $key]
118			error_check_bad dbc_get:SET [llength $ret] 0
119
120			set ret [$dbc del]
121			error_check_good dbc_del $ret 0
122
123			puts "\tTest028.e: Reput the item"
124			set ret [eval {$db put} $txn \
125			    {-nooverwrite $key [chop_data $method $dupstr]}]
126			error_check_good db_put $ret 0
127
128			puts "\tTest028.f: Retrieve the item"
129			set ret [eval {$db get} $txn $gflags {$key}]
130			error_check_good db_get $ret \
131			    [list [list $key [pad_data $method $dupstr]]]
132
133			# Delete the key to set up for next test
134			set ret [eval {$db del} $txn {$key}]
135			error_check_good db_del $ret 0
136
137			# Now repeat the above set of tests with
138			# duplicates (if not RECNO).
139			if { [is_record_based $method] == 1 ||\
140			    [is_compressed $args] == 1 } {
141				continue;
142			}
143
144			puts "\tTest028.g: Insert key with duplicates"
145			for { set count 0 } { $count < $ndups } { incr count } {
146				set ret [eval {$db put} $txn \
147				    {$key [chop_data $method $count$dupstr]}]
148				error_check_good db_put $ret 0
149			}
150
151			puts "\tTest028.h: Check dups"
152			set dupnum 0
153			dump_file $db $txn $t1 test028.check
154
155			# Try no_overwrite
156			puts "\tTest028.i: No_overwrite test"
157			set ret [eval {$db put} \
158			    $txn {-nooverwrite $key $dupstr}]
159			error_check_good \
160			    db_put [is_substr $ret "DB_KEYEXIST"] 1
161
162			# Now delete all the elements with a cursor
163			puts "\tTest028.j: Cursor Deletes"
164			set count 0
165			for { set ret [$dbc get -set $key] } {
166			    [string length $ret] != 0 } {
167			    set ret [$dbc get -next] } {
168				set k [lindex [lindex $ret 0] 0]
169				set d [lindex [lindex $ret 0] 1]
170				error_check_good db_seq(key) $k $key
171				error_check_good db_seq(data) $d $count$dupstr
172				set ret [$dbc del]
173				error_check_good dbc_del $ret 0
174				incr count
175				if { $count == [expr $ndups - 1] } {
176					puts "\tTest028.k:\
177						Duplicate No_Overwrite test"
178					set ret [eval {$db put} $txn \
179					    {-nooverwrite $key $dupstr}]
180					error_check_good db_put [is_substr \
181					    $ret "DB_KEYEXIST"] 1
182				}
183			}
184
185			# Make sure all the items are gone
186			puts "\tTest028.l: Get after delete"
187			set ret [$dbc get -set $key]
188			error_check_good get_after_del [string length $ret] 0
189
190			puts "\tTest028.m: Reput the item"
191			set ret [eval {$db put} \
192			    $txn {-nooverwrite $key 0$dupstr}]
193			error_check_good db_put $ret 0
194			for { set count 1 } { $count < $ndups } { incr count } {
195				set ret [eval {$db put} $txn \
196				    {$key $count$dupstr}]
197				error_check_good db_put $ret 0
198			}
199
200			puts "\tTest028.n: Retrieve the item"
201			set dupnum 0
202			dump_file $db $txn $t1 test028.check
203
204			# Clean out in prep for next test
205			set ret [eval {$db del} $txn {$key}]
206			error_check_good db_del $ret 0
207		}
208	}
209	error_check_good dbc_close [$dbc close] 0
210	if { $txnenv == 1 } {
211		error_check_good txn [$t commit] 0
212	}
213	error_check_good db_close [$db close] 0
214
215}
216
217# Check function for test028; keys and data are identical
218proc test028.check { key data } {
219	global dupnum
220	global dupstr
221	error_check_good "Bad key" $key put_after_cursor_del
222	error_check_good "data mismatch for $key" $data $dupnum$dupstr
223	incr dupnum
224}
225