1 /*-
2  * Copyright (c) 2009, 2020 Oracle and/or its affiliates.  All rights reserved.
3  *
4  * See the file LICENSE for license information.
5  *
6  */
7 using System;
8 using System.Collections;
9 using System.Collections.Generic;
10 using System.IO;
11 using System.Text;
12 using System.Threading;
13 using System.Xml;
14 using NUnit.Framework;
15 using BerkeleyDB;
16 
17 namespace CsharpAPITest
18 {
19 	[TestFixture]
20 	public class JoinCursorTest : CSharpTestFixture
21 	{
22 
23 		[TestFixtureSetUp]
SetUpTestFixture()24 		public void SetUpTestFixture()
25 		{
26 			testFixtureName = "JoinCursorTest";
27 			base.SetUpTestfixture();
28 		}
29 
30 		[Test]
TestJoin()31 		public void TestJoin()
32 		{
33 			testName = "TestJoin";
34 			SetUpTest(true);
35 			string dbFileName = testHome + "/" + testName + ".db";
36 			string secFileName1 = testHome + "/" + "sec_" + testName + "1.db";
37 			string secFileName2 = testHome + "/" + "sec_" + testName + "2.db";
38 
39 			// Open a primary database.
40 			BTreeDatabaseConfig dbCfg = new BTreeDatabaseConfig();
41 			dbCfg.Creation = CreatePolicy.IF_NEEDED;
42 			BTreeDatabase db = BTreeDatabase.Open(dbFileName, dbCfg);
43 
44 			for (int i = 0; i < 10; i++)
45 				db.Put(new DatabaseEntry(BitConverter.GetBytes(i)),
46 				    new DatabaseEntry(BitConverter.GetBytes(i)));
47 
48 			/*
49 			 * Open two databases, their secondary databases and
50 			 * secondary cursors.
51 			 */
52 			SecondaryBTreeDatabase secDB1, secDB2;
53 			SecondaryCursor[] cursors = new SecondaryCursor[2];
54 			GetSecCursor(db, secFileName1,
55 			    new SecondaryKeyGenDelegate(KeyGenOnBigByte),
56 			    out secDB1, out cursors[0], false, null);
57 			GetSecCursor(db, secFileName2,
58 			    new SecondaryKeyGenDelegate(KeyGenOnLittleByte),
59 			    out secDB2, out cursors[1], true, null);
60 
61 			// Get join cursor.
62 			JoinCursor joinCursor = db.Join(cursors, true);
63 			Assert.IsNotNull(joinCursor.GetEnumerator().Current);
64 
65 			// Close all.
66 			joinCursor.Dispose();
67 			cursors[0].Close();
68 			cursors[1].Close();
69 			secDB1.Close();
70 			secDB2.Close();
71 			db.Close();
72 		}
73 
74 		[Test]
TestMoveJoinCursor()75 		public void TestMoveJoinCursor()
76 		{
77 			testName = "TestMoveJoinCursor";
78 			SetUpTest(true);
79 			string dbFileName = testHome + "/" + testName + ".db";
80 			string secFileName1 = testHome + "/" + "sec_" + testName + "1.db";
81 			string secFileName2 = testHome + "/" + "sec_" + testName + "2.db";
82 
83 			// Open a primary database.
84 			BTreeDatabaseConfig dbCfg = new BTreeDatabaseConfig();
85 			dbCfg.Creation = CreatePolicy.IF_NEEDED;
86 			BTreeDatabase db = BTreeDatabase.Open(dbFileName, dbCfg);
87 
88 			/*
89 			 * Open a secondary database on high byte of
90 			 * its data and another secondary database on
91 			 * little byte of its data.
92 			 */
93 			SecondaryBTreeDatabase secDB1, secDB2;
94 			SecondaryCursor[] cursors = new SecondaryCursor[2];
95 			byte[] byteValue = new byte[1];
96 
97 			byteValue[0] = 0;
98 			GetSecCursor(db, secFileName1,
99 			    new SecondaryKeyGenDelegate(KeyGenOnBigByte),
100 			    out secDB1, out cursors[0], false,
101 			    new DatabaseEntry(byteValue));
102 
103 			byteValue[0] = 1;
104 			GetSecCursor(db, secFileName2,
105 			    new SecondaryKeyGenDelegate(KeyGenOnLittleByte),
106 			    out secDB2, out cursors[1], true,
107 			    new DatabaseEntry(byteValue));
108 
109 			// Get join cursor.
110 			JoinCursor joinCursor = db.Join(cursors, true);
111 
112 			/*
113 			 * MoveNextJoinItem do not use data value found
114 			 * in all of the cursor so the data in Current won't be
115 			 * changed.
116 			 */
117 			Assert.IsTrue(joinCursor.MoveNextItem());
118 			Assert.AreEqual(0, joinCursor.Current.Key.Data[
119 			    joinCursor.Current.Key.Data.Length - 1]);
120 			Assert.AreEqual(1, joinCursor.Current.Key.Data[0]);
121 			Assert.IsNull(joinCursor.Current.Value.Data);
122 
123 			// Iterate on join cursor.
124 			foreach (KeyValuePair<DatabaseEntry, DatabaseEntry> pair in joinCursor)
125 			{
126 				/*
127 				 * Confirm that the key got by join cursor has 0 at
128 				 * its highest byte and 1 at its lowest byte.
129 				 */
130 				Assert.AreEqual(0, pair.Key.Data[pair.Key.Data.Length - 1]);
131 				Assert.AreEqual(1, pair.Key.Data[0]);
132 			}
133 
134 			Assert.IsFalse(joinCursor.MoveNext());
135 
136 			// Close all.
137 			joinCursor.Close();
138 			cursors[0].Close();
139 			cursors[1].Close();
140 			secDB1.Close();
141 			secDB2.Close();
142 			db.Close();
143 		}
144 
GetSecCursor(BTreeDatabase db, string secFileName, SecondaryKeyGenDelegate keyGen, out SecondaryBTreeDatabase secDB, out SecondaryCursor cursor, bool ifCfg, DatabaseEntry data)145 		public void GetSecCursor(BTreeDatabase db,
146 		    string secFileName, SecondaryKeyGenDelegate keyGen,
147 		    out SecondaryBTreeDatabase secDB,
148 		    out SecondaryCursor cursor, bool ifCfg,
149 		    DatabaseEntry data)
150 		{
151 			// Open secondary database.
152 			SecondaryBTreeDatabaseConfig secCfg =
153 			    new SecondaryBTreeDatabaseConfig(db, keyGen);
154 			secCfg.Creation = CreatePolicy.IF_NEEDED;
155 			secCfg.Duplicates = DuplicatesPolicy.SORTED;
156 			secDB = SecondaryBTreeDatabase.Open(secFileName, secCfg);
157 
158 			int[] intArray = new int[4];
159 			intArray[0] = 0;
160 			intArray[1] = 1;
161 			intArray[2] = 2049;
162 			intArray[3] = 65537;
163 			for (int i = 0; i < 4; i++)
164 			{
165 				DatabaseEntry record = new DatabaseEntry(
166 				    BitConverter.GetBytes(intArray[i]));
167 				db.Put(record, record);
168 			}
169 
170 			// Get secondary cursor on the secondary database.
171 			if (ifCfg == false)
172 				cursor = secDB.SecondaryCursor();
173 			else
174 				cursor = secDB.SecondaryCursor(new CursorConfig());
175 
176 			// Position the cursor.
177 			if (data != null)
178 				Assert.IsTrue(cursor.Move(data, true));
179 		}
180 
KeyGenOnLittleByte( DatabaseEntry key, DatabaseEntry data)181 		public DatabaseEntry KeyGenOnLittleByte(
182 		    DatabaseEntry key, DatabaseEntry data)
183 		{
184 			byte[] byteArr = new byte[1];
185 			byteArr[0] = data.Data[0];
186 			DatabaseEntry dbtGen = new DatabaseEntry(byteArr);
187 			return dbtGen;
188 		}
189 
KeyGenOnBigByte( DatabaseEntry key, DatabaseEntry data)190 		public DatabaseEntry KeyGenOnBigByte(
191 		    DatabaseEntry key, DatabaseEntry data)
192 		{
193 			byte[] byteArr = new byte[1];
194 			byteArr[0] = data.Data[data.Data.Length - 1];
195 			DatabaseEntry dbtGen = new DatabaseEntry(byteArr);
196 			return dbtGen;
197 		}
198 	}
199 }
200