276 lines
7.0 KiB
C
276 lines
7.0 KiB
C
/*-
|
|
* See the file LICENSE for redistribution information.
|
|
*
|
|
* Copyright (c) 2004,2008 Oracle. All rights reserved.
|
|
*/
|
|
|
|
#include "gettingstarted_common.h"
|
|
|
|
/* Forward declarations */
|
|
int usage(void);
|
|
char *show_inventory_item(void *);
|
|
int show_all_records(STOCK_DBS *);
|
|
int show_records(STOCK_DBS *, char *);
|
|
int show_vendor_record(char *, DB *);
|
|
|
|
int
|
|
usage()
|
|
{
|
|
fprintf(stderr, "example_database_read [-i <item name>]");
|
|
fprintf(stderr, " [-h <database home>]\n");
|
|
|
|
fprintf(stderr,
|
|
"\tNote: Any path specified to the -h parameter must end\n");
|
|
fprintf(stderr, " with your system's path delimiter (/ or \\)\n");
|
|
return (-1);
|
|
}
|
|
|
|
/*
|
|
* Searches for a inventory item based on that item's name. The search is
|
|
* performed using the item name secondary database. Displays all
|
|
* inventory items that use the specified name, as well as the vendor
|
|
* associated with that inventory item.
|
|
*
|
|
* If no item name is provided, then all inventory items are displayed.
|
|
*/
|
|
int
|
|
main(int argc, char *argv[])
|
|
{
|
|
STOCK_DBS my_stock;
|
|
int ch, ret;
|
|
char *itemname;
|
|
|
|
/* Initialize the STOCK_DBS struct */
|
|
initialize_stockdbs(&my_stock);
|
|
|
|
/* Parse the command line arguments */
|
|
itemname = NULL;
|
|
while ((ch = getopt(argc, argv, "h:i:?")) != EOF)
|
|
switch (ch) {
|
|
case 'h':
|
|
if (optarg[strlen(optarg)-1] != '/' &&
|
|
optarg[strlen(optarg)-1] != '\\')
|
|
return (usage());
|
|
my_stock.db_home_dir = optarg;
|
|
break;
|
|
case 'i':
|
|
itemname = optarg;
|
|
break;
|
|
case '?':
|
|
default:
|
|
return (usage());
|
|
}
|
|
|
|
/* Identify the files that hold our databases */
|
|
set_db_filenames(&my_stock);
|
|
|
|
/* Open all databases */
|
|
ret = databases_setup(&my_stock, "example_database_read", stderr);
|
|
if (ret != 0) {
|
|
fprintf(stderr, "Error opening databases\n");
|
|
databases_close(&my_stock);
|
|
return (ret);
|
|
}
|
|
|
|
if (itemname == NULL)
|
|
ret = show_all_records(&my_stock);
|
|
else
|
|
ret = show_records(&my_stock, itemname);
|
|
|
|
/* close our databases */
|
|
databases_close(&my_stock);
|
|
return (ret);
|
|
}
|
|
|
|
int show_all_records(STOCK_DBS *my_stock)
|
|
{
|
|
DBC *inventory_cursorp;
|
|
DBT key, data;
|
|
char *the_vendor;
|
|
int exit_value, ret;
|
|
|
|
/* Initialize our DBTs. */
|
|
memset(&key, 0, sizeof(DBT));
|
|
memset(&data, 0, sizeof(DBT));
|
|
|
|
/* Get a cursor to the inventory db */
|
|
my_stock->inventory_dbp->cursor(my_stock->inventory_dbp, NULL,
|
|
&inventory_cursorp, 0);
|
|
|
|
/*
|
|
* Iterate over the inventory database, from the first record
|
|
* to the last, displaying each in turn.
|
|
*/
|
|
exit_value = 0;
|
|
while ((ret =
|
|
inventory_cursorp->get(inventory_cursorp, &key, &data, DB_NEXT)) == 0)
|
|
{
|
|
the_vendor = show_inventory_item(data.data);
|
|
ret = show_vendor_record(the_vendor, my_stock->vendor_dbp);
|
|
if (ret) {
|
|
exit_value = ret;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Close the cursor */
|
|
inventory_cursorp->close(inventory_cursorp);
|
|
return (exit_value);
|
|
}
|
|
|
|
/*
|
|
* Search for an inventory item given its name (using the inventory item
|
|
* secondary database) and display that record and any duplicates that may
|
|
* exist.
|
|
*/
|
|
int
|
|
show_records(STOCK_DBS *my_stock, char *itemname)
|
|
{
|
|
DBC *itemname_cursorp;
|
|
DBT key, data;
|
|
char *the_vendor;
|
|
int ret, exit_value;
|
|
|
|
/* Initialize our DBTs. */
|
|
memset(&key, 0, sizeof(DBT));
|
|
memset(&data, 0, sizeof(DBT));
|
|
|
|
/* Get a cursor to the itemname db */
|
|
my_stock->itemname_sdbp->cursor(my_stock->itemname_sdbp, NULL,
|
|
&itemname_cursorp, 0);
|
|
|
|
/*
|
|
* Get the search key. This is the name on the inventory
|
|
* record that we want to examine.
|
|
*/
|
|
key.data = itemname;
|
|
key.size = (u_int32_t)strlen(itemname) + 1;
|
|
|
|
/*
|
|
* Position our cursor to the first record in the secondary
|
|
* database that has the appropriate key.
|
|
*/
|
|
exit_value = 0;
|
|
ret = itemname_cursorp->get(itemname_cursorp, &key, &data, DB_SET);
|
|
if (!ret) {
|
|
do {
|
|
/*
|
|
* Show the inventory record and the vendor responsible
|
|
* for this inventory item.
|
|
*/
|
|
the_vendor = show_inventory_item(data.data);
|
|
ret = show_vendor_record(the_vendor, my_stock->vendor_dbp);
|
|
if (ret) {
|
|
exit_value = ret;
|
|
break;
|
|
}
|
|
/*
|
|
* Our secondary allows duplicates, so we need to loop over
|
|
* the next duplicate records and show them all. This is done
|
|
* because an inventory item's name is not a unique value.
|
|
*/
|
|
} while (itemname_cursorp->get(itemname_cursorp, &key, &data,
|
|
DB_NEXT_DUP) == 0);
|
|
} else {
|
|
printf("No records found for '%s'\n", itemname);
|
|
}
|
|
|
|
/* Close the cursor */
|
|
itemname_cursorp->close(itemname_cursorp);
|
|
|
|
return (exit_value);
|
|
}
|
|
|
|
/*
|
|
* Shows an inventory item. How we retrieve the inventory
|
|
* item values from the provided buffer is strictly dependent
|
|
* on the order that those items were originally stored in the
|
|
* DBT. See load_inventory_database in example_database_load
|
|
* for how this was done.
|
|
*/
|
|
char *
|
|
show_inventory_item(void *vBuf)
|
|
{
|
|
float price;
|
|
int quantity;
|
|
size_t buf_pos;
|
|
char *category, *name, *sku, *vendor_name;
|
|
char *buf = (char *)vBuf;
|
|
|
|
price = *((float *)buf);
|
|
buf_pos = sizeof(float);
|
|
|
|
quantity = *((int *)(buf + buf_pos));
|
|
buf_pos += sizeof(int);
|
|
|
|
name = buf + buf_pos;
|
|
buf_pos += strlen(name) + 1;
|
|
|
|
sku = buf + buf_pos;
|
|
buf_pos += strlen(sku) + 1;
|
|
|
|
category = buf + buf_pos;
|
|
buf_pos += strlen(category) + 1;
|
|
|
|
vendor_name = buf + buf_pos;
|
|
|
|
printf("name: %s\n", name);
|
|
printf("\tSKU: %s\n", sku);
|
|
printf("\tCategory: %s\n", category);
|
|
printf("\tPrice: %.2f\n", price);
|
|
printf("\tQuantity: %i\n", quantity);
|
|
printf("\tVendor:\n");
|
|
|
|
return (vendor_name);
|
|
}
|
|
|
|
/*
|
|
* Shows a vendor record. Each vendor record is an instance of
|
|
* a vendor structure. See load_vendor_database() in
|
|
* example_database_load for how this structure was originally
|
|
* put into the database.
|
|
*/
|
|
int
|
|
show_vendor_record(char *vendor_name, DB *vendor_dbp)
|
|
{
|
|
DBT key, data;
|
|
VENDOR my_vendor;
|
|
int ret;
|
|
|
|
/* Zero our DBTs */
|
|
memset(&key, 0, sizeof(DBT));
|
|
memset(&data, 0, sizeof(DBT));
|
|
|
|
/* Set the search key to the vendor's name */
|
|
key.data = vendor_name;
|
|
key.size = (u_int32_t)strlen(vendor_name) + 1;
|
|
|
|
/*
|
|
* Make sure we use the memory we set aside for the VENDOR
|
|
* structure rather than the memory that DB allocates.
|
|
* Some systems may require structures to be aligned in memory
|
|
* in a specific way, and DB may not get it right.
|
|
*/
|
|
|
|
data.data = &my_vendor;
|
|
data.ulen = sizeof(VENDOR);
|
|
data.flags = DB_DBT_USERMEM;
|
|
|
|
/* Get the record */
|
|
ret = vendor_dbp->get(vendor_dbp, NULL, &key, &data, 0);
|
|
if (ret != 0) {
|
|
vendor_dbp->err(vendor_dbp, ret, "Error searching for vendor: '%s'",
|
|
vendor_name);
|
|
return (ret);
|
|
} else {
|
|
printf("\t\t%s\n", my_vendor.name);
|
|
printf("\t\t%s\n", my_vendor.street);
|
|
printf("\t\t%s, %s\n", my_vendor.city, my_vendor.state);
|
|
printf("\t\t%s\n\n", my_vendor.zipcode);
|
|
printf("\t\t%s\n\n", my_vendor.phone_number);
|
|
printf("\t\tContact: %s\n", my_vendor.sales_rep);
|
|
printf("\t\t%s\n", my_vendor.sales_rep_phone);
|
|
}
|
|
return (0);
|
|
}
|