1 //-< TESTDB.CPP >----------------------------------------------------*--------*
2 // FastDB Version 1.0 (c) 1999 GARRET * ? *
3 // (Main Memory Database Management System) * /\| *
4 // * / \ *
5 // Created: 10-Dec-98 K.A. Knizhnik * / [] \ *
6 // Last update: 12-Dec-98 K.A. Knizhnik * GARRET *
7 //-------------------------------------------------------------------*--------*
8 // Sample of database application: supplier/contract/details database
9 //-------------------------------------------------------------------*--------*
10
11 #include "fastdb.h"
12 #include <stdio.h>
13
14 USE_FASTDB_NAMESPACE
15
16 class Contract;
17
18 class Detail {
19 public:
20 char const* name;
21 char const* material;
22 char const* color;
23 real4 weight;
24
25 dbArray< dbReference<Contract> > contracts;
26
27 TYPE_DESCRIPTOR((KEY(name, INDEXED|HASHED),
28 KEY(material, HASHED),
29 KEY(color, HASHED),
30 KEY(weight, INDEXED),
31 RELATION(contracts, detail)));
32 };
33
34 class Supplier {
35 public:
36 char const* company;
37 char const* location;
38 bool foreign;
39
40 dbArray< dbReference<Contract> > contracts;
41
42 TYPE_DESCRIPTOR((KEY(company, INDEXED|HASHED),
43 KEY(location, HASHED),
44 FIELD(foreign),
45 RELATION(contracts, supplier)));
46 };
47
48
49 class Contract {
50 public:
51 dbDateTime delivery;
52 int4 quantity;
53 db_int8 price;
54 dbReference<Detail> detail;
55 dbReference<Supplier> supplier;
56
57 TYPE_DESCRIPTOR((KEY(delivery, HASHED|INDEXED),
58 KEY(quantity, INDEXED),
59 KEY(price, INDEXED),
60 RELATION(detail, contracts),
61 RELATION(supplier, contracts)));
62 };
63
64
65 REGISTER(Detail);
66 REGISTER(Supplier);
67 REGISTER(Contract);
68
input(char const * prompt,char * buf,size_t buf_size)69 void input(char const* prompt, char* buf, size_t buf_size)
70 {
71 char* p;
72 do {
73 printf(prompt);
74 *buf = '\0';
75 fgets(buf,(int) buf_size, stdin);
76 p = buf + strlen(buf);
77 } while (p <= buf+1);
78
79 if (*(p-1) == '\n') {
80 *--p = '\0';
81 }
82 }
83
main()84 int main()
85 {
86 const int maxStrLen = 256;
87
88 dbDatabase db;
89
90 char buf[maxStrLen];
91 char name[maxStrLen];
92 char company[maxStrLen];
93 char material[maxStrLen];
94 char address[maxStrLen];
95
96 int d, m, y;
97 int i, n;
98 int choice;
99 int quantity;
100 db_int8 price;
101
102 dbDateTime from, till;
103
104 Contract contract;
105 Supplier supplier;
106 Detail detail;
107
108 dbQuery q1, q2, q3, q4, q6, q9, q10;
109 q1 = "exists i:(contracts[i].supplier.company=",company,")";
110 q2 = "name like",name;
111 q3 = "supplier.location =",address;
112 q4 = between("delivery", from, till),"and price >",price,
113 "order by",dbDateTime::ascent("delivery");
114 q6 = "price >=",price,"or quantity >=",quantity;
115 q9 = "company =",company;
116 q10 = "supplier.company =",company,"and detail.name like",name;
117
118 dbCursor<Detail> details;
119 dbCursor<Contract> contracts;
120 dbCursor<Supplier> suppliers;
121 dbCursor<Contract> updateContracts(dbCursorForUpdate);
122
123 if (db.open(_T("testdb"))) {
124 while (true) {
125 printf(
126 "\n\n MENU:\n\
127 1. Details shipped by supplier\n\
128 2. Suppliers of the detail\n\
129 3. Contracts from specified city\n\
130 4. Expensive details to be delivered in specified period\n\
131 5. Foreign suppliers\n\
132 6. Important contracts\n\
133 7. New supplier\n\
134 8. New detail\n\
135 9. New contract\n\
136 10. Cancel contract\n\
137 11. Update contract\n\
138 12. Exit\n\n");
139 input(">> ", buf, sizeof buf);
140 if (sscanf(buf, "%d", &choice) != 1) {
141 continue;
142 }
143 switch (choice) {
144 case 1:
145 printf("Details shipped by supplier\n");
146 input("Supplier company: ", company, sizeof company);
147 if (details.select(q1) > 0) {
148 printf("Detail\tMaterial\tColor\tWeight\n");
149 do {
150 printf("%s\t%s\t%s\t%f\n",
151 details->name, details->material,
152 details->color, details->weight);
153 } while (details.next());
154 } else {
155 printf("No details shipped by this supplier\n");
156 }
157 break;
158 case 2:
159 printf("Suppliers of the detail\n");
160 input("Regular expression for detail name: ",name,sizeof name);
161 if (details.select(q2) > 0) {
162 printf("Detail\tCompany\tLocation\tPrice\n");
163 do {
164 n = (int)details->contracts.length();
165 for (i = 0; i < n; i++) {
166 contracts.at(details->contracts[i]);
167 suppliers.at(contracts->supplier);
168 printf("%s\t%s\t%s\t" INT8_FORMAT "\n",
169 details->name,
170 suppliers->company, suppliers->location,
171 contracts->price);
172 }
173 } while (details.next());
174 } else {
175 printf("No such details\n");
176 }
177 break;
178 case 3:
179 printf("Contracts from specified city\n");
180 input("City: ", address, sizeof address);
181 if (contracts.select(q3) > 0) {
182 printf("Detail\tCompany\tQuantity\n");
183 do {
184 printf("%s\t%s\t%d\n",
185 details.at(contracts->detail)->name,
186 suppliers.at(contracts->supplier)->company,
187 contracts->quantity);
188 } while (contracts.next());
189 } else {
190 printf("No contracts with companies in this city");
191 }
192 break;
193 case 4:
194 printf("Expensive details to be delivered in specified period\n");
195 input("Delivered after (DD-MM-YYYY): ", buf, sizeof buf);
196 if (sscanf(buf, "%d-%d-%d\n", &d, &m, &y) != 3) {
197 printf("Wrong date\n");
198 continue;
199 }
200 from = dbDateTime(y, m, d);
201 input("Delivered before (DD-MM-YYYY): ", buf, sizeof buf);
202 if (sscanf(buf, "%d-%d-%d\n", &d, &m, &y) != 3) {
203 printf("Wrong date\n");
204 continue;
205 }
206 till = dbDateTime(y, m, d);
207 input("Minimal contract price: ", buf, sizeof buf);
208 if (sscanf(buf, INT8_FORMAT, &price) != 1) {
209 printf("Bad value\n");
210 continue;
211 }
212 if (contracts.select(q4) > 0) {
213 printf("Detail\tDate\tPrice\n");
214 do {
215 printf("%s\t%s\t" INT8_FORMAT "\n",
216 details.at(contracts->detail)->name,
217 contracts->delivery.asString(buf, sizeof buf),
218 contracts->price);
219 } while (contracts.next());
220 } else {
221 printf("No such contracts\n");
222 }
223 break;
224 case 5:
225 printf("Foreign suppliers\n");
226 if (suppliers.select("foreign and length(contracts) > 0") > 0){
227 printf("Company\tLocation\n");
228 do {
229 printf("%s\t%s\n", suppliers->company,
230 suppliers->location);
231 } while (suppliers.next());
232 } else {
233 printf("No such suppliers\n");
234 }
235 break;
236 case 6:
237 printf("Important contracts\n");
238 input("Minimal contract price: ", buf, sizeof buf);
239 if (sscanf(buf, INT8_FORMAT, &price) != 1) {
240 printf("Bad value\n");
241 continue;
242 }
243 input("Minimal contract quantity: ", buf, sizeof buf);
244 if (sscanf(buf, "%d", &quantity) != 1) {
245 printf("Bad value\n");
246 continue;
247 }
248 if (contracts.select(q6) > 0) {
249 printf("Company\tPrice\tQuantity\tDelivery\n");
250 do {
251 printf("%s\t" INT8_FORMAT "\t%d\t%s\n",
252 suppliers.at(contracts->supplier)->company,
253 contracts->price, contracts->quantity,
254 contracts->delivery.asString(buf, sizeof buf,
255 "%A %x"));
256 } while (contracts.next());
257 } else {
258 printf("No such contracts\n");
259 }
260 break;
261 case 7:
262 printf("New supplier\n");
263 input("Company name: ", company, sizeof company);
264 input("Company location: ", address, sizeof address);
265 input("Foreign company (y/n): ", buf, sizeof buf);
266 supplier.company = company;
267 supplier.location = address;
268 supplier.foreign = (*buf == 'y');
269 insert(supplier);
270 break;
271 case 8:
272 printf("New detail\n");
273 input("Detail name: ", name, sizeof name);
274 input("Detail material: ", material, sizeof material);
275 input("Detail weight: ", buf, sizeof buf);
276 sscanf(buf, "%f", &detail.weight);
277 input("Detail color: ", buf, sizeof buf);
278 detail.name = name;
279 detail.material = material;
280 detail.color = buf;
281 insert(detail);
282 break;
283 case 9:
284 printf("New contract\n");
285 db.lock(); // prevent deadlock
286 input("Supplier company: ", company, sizeof company);
287 if (suppliers.select(q9) == 0) {
288 printf("No such supplier\n");
289 continue;
290 }
291 input("Detail name: ", name, sizeof name);
292 if (details.select(q2) == 0) {
293 printf("No such detail\n");
294 continue;
295 } else if (details.getNumberOfRecords() != 1) {
296 printf("More than one record match this pattern");
297 continue;
298 }
299 input("Contract price: ", buf, sizeof buf);
300 sscanf(buf, INT8_FORMAT, &contract.price);
301 input("Contract quantity: ", buf, sizeof buf);
302 sscanf(buf, "%d", &contract.quantity);
303 input("Delivered after (days): ", buf, sizeof buf);
304 sscanf(buf, "%d", &d);
305 contract.delivery =
306 dbDateTime::currentDate() + dbDateTime(24*d,0);
307 contract.supplier = suppliers.currentId();
308 contract.detail = details.currentId();
309 insert(contract);
310 break;
311 case 10:
312 printf("Cancel contract\n");
313 input("Supplier company: ", company, sizeof company);
314 input("Detail name pattern: ", name, sizeof name);
315 if (updateContracts.select(q10) == 0) {
316 printf("No such contracts\n");
317 } else {
318 updateContracts.removeAllSelected();
319 // Just test rollback
320 input("Really cancel contract (y/n) ? ", buf, sizeof buf);
321 if (*buf != 'y') {
322 printf("Not confirmed\n");
323 db.rollback();
324 continue;
325 }
326 }
327 break;
328 case 11:
329 printf("Update contract\n");
330 input("Supplier company: ", company, sizeof company);
331 input("Detail name pattern: ", name, sizeof name);
332 if (updateContracts.select(q10) == 0) {
333 printf("No such contracts\n");
334 break;
335 }
336 do {
337 printf("Contract with company %s for shipping %d details "
338 "%s for $" INT8_FORMAT " at %s\n",
339 suppliers.at(updateContracts->supplier)->company,
340 updateContracts->quantity,
341 details.at(updateContracts->detail)->name,
342 updateContracts->price,
343 updateContracts->delivery.asString(buf,sizeof buf));
344 input("Change this contract (y/n) ? ", buf, sizeof buf);
345 if (*buf == 'y') {
346 input("New contract price: ", buf, sizeof buf);
347 sscanf(buf, INT8_FORMAT, &updateContracts->price);
348 input("New number of details: ", buf, sizeof buf);
349 sscanf(buf, "%d", &updateContracts->quantity);
350 updateContracts.update();
351 }
352 } while (updateContracts.next());
353 break;
354 case 12:
355 input("Do you really want to exit (y/n) ? ", buf, sizeof buf);
356 if (*buf == 'y') {
357 printf("Close database session\n");
358 db.close();
359 return EXIT_SUCCESS;
360 }
361 break;
362 default:
363 printf("Please choose menu items 1..12\n");
364 continue;
365 }
366 printf("Press any key to continue...\n");
367 getchar();
368 db.commit();
369 }
370 } else {
371 printf("failed to open database\n");
372 return EXIT_FAILURE;
373 }
374 }
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389