/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.bench;
import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.HashMap;
/**
* This class implements the functionality of one thread of BenchC.
*/
public class BenchCThread {
private static final int OP_NEW_ORDER = 0, OP_PAYMENT = 1,
OP_ORDER_STATUS = 2, OP_DELIVERY = 3,
OP_STOCK_LEVEL = 4;
private static final BigDecimal ONE = new BigDecimal("1");
private Database db;
private int warehouseId;
private int terminalId;
private HashMap<String, PreparedStatement> prepared = new HashMap<String, PreparedStatement>();
private BenchCRandom random;
private BenchC bench;
BenchCThread(Database db, BenchC bench, BenchCRandom random, int terminal)
throws SQLException {
this.db = db;
this.bench = bench;
this.terminalId = terminal;
db.setAutoCommit(false);
this.random = random;
warehouseId = random.getInt(1, bench.warehouses);
}
/**
* Process the list of operations (a 'deck') in random order.
*/
void process() throws SQLException {
int[] deck = { OP_NEW_ORDER, OP_NEW_ORDER, OP_NEW_ORDER,
OP_NEW_ORDER, OP_NEW_ORDER, OP_NEW_ORDER, OP_NEW_ORDER,
OP_NEW_ORDER, OP_NEW_ORDER, OP_NEW_ORDER, OP_PAYMENT,
OP_PAYMENT, OP_PAYMENT, OP_PAYMENT, OP_PAYMENT, OP_PAYMENT,
OP_PAYMENT, OP_PAYMENT, OP_PAYMENT, OP_PAYMENT,
OP_ORDER_STATUS, OP_DELIVERY, OP_STOCK_LEVEL };
int len = deck.length;
for (int i = 0; i < len; i++) {
int temp = deck[i];
int j = random.getInt(0, len);
deck[i] = deck[j];
deck[j] = temp;
}
for (int op : deck) {
switch (op) {
case OP_NEW_ORDER:
processNewOrder();
break;
case OP_PAYMENT:
processPayment();
break;
case OP_ORDER_STATUS:
processOrderStatus();
break;
case OP_DELIVERY:
processDelivery();
break;
case OP_STOCK_LEVEL:
processStockLevel();
break;
default:
throw new AssertionError("op=" + op);
}
}
}
private void processNewOrder() throws SQLException {
int dId = random.getInt(1, bench.districtsPerWarehouse);
int cId = random.getNonUniform(1023, 1, bench.customersPerDistrict);
int olCnt = random.getInt(5, 15);
boolean rollback = random.getInt(1, 100) == 1;
int[] supplyId = new int[olCnt];
int[] itemId = new int[olCnt];
int[] quantity = new int[olCnt];
int allLocal = 1;
for (int i = 0; i < olCnt; i++) {
int w;
if (bench.warehouses > 1 && random.getInt(1, 100) == 1) {
do {
w = random.getInt(1, bench.warehouses);
} while (w != warehouseId);
allLocal = 0;
} else {
w = warehouseId;
}
supplyId[i] = w;
int item;
if (rollback && i == olCnt - 1) {
// unused order number
item = -1;
} else {
item = random.getNonUniform(8191, 1, bench.items);
}
itemId[i] = item;
quantity[i] = random.getInt(1, 10);
}
char[] bg = new char[olCnt];
int[] stock = new int[olCnt];
BigDecimal[] amt = new BigDecimal[olCnt];
Timestamp datetime = new Timestamp(System.currentTimeMillis());
PreparedStatement prep;
ResultSet rs;
prep = prepare("UPDATE DISTRICT SET D_NEXT_O_ID=D_NEXT_O_ID+1 "
+ "WHERE D_ID=? AND D_W_ID=?");
prep.setInt(1, dId);
prep.setInt(2, warehouseId);
db.update(prep, "updateDistrict");
prep = prepare("SELECT D_NEXT_O_ID, D_TAX FROM DISTRICT "
+ "WHERE D_ID=? AND D_W_ID=?");
prep.setInt(1, dId);
prep.setInt(2, warehouseId);
rs = db.query(prep);
rs.next();
int oId = rs.getInt(1) - 1;
BigDecimal tax = rs.getBigDecimal(2);
rs.close();
prep = prepare("SELECT C_DISCOUNT, C_LAST, C_CREDIT, W_TAX "
+ "FROM CUSTOMER, WAREHOUSE "
+ "WHERE C_ID=? AND W_ID=? AND C_W_ID=W_ID AND C_D_ID=?");
prep.setInt(1, cId);
prep.setInt(2, warehouseId);
prep.setInt(3, dId);
rs = db.query(prep);
rs.next();
BigDecimal discount = rs.getBigDecimal(1);
// c_last
rs.getString(2);
// c_credit
rs.getString(3);
BigDecimal wTax = rs.getBigDecimal(4);
rs.close();
BigDecimal total = new BigDecimal("0");
for (int number = 1; number <= olCnt; number++) {
int olId = itemId[number - 1];
int olSupplyId = supplyId[number - 1];
int olQuantity = quantity[number - 1];
prep = prepare("SELECT I_PRICE, I_NAME, I_DATA "
+ "FROM ITEM WHERE I_ID=?");
prep.setInt(1, olId);
rs = db.query(prep);
if (!rs.next()) {
if (rollback) {
// item not found - correct behavior
db.rollback();
return;
}
throw new SQLException("item not found: " + olId + " "
+ olSupplyId);
}
BigDecimal price = rs.getBigDecimal(1);
// i_name
rs.getString(2);
String data = rs.getString(3);
rs.close();
prep = prepare("SELECT S_QUANTITY, S_DATA, "
+ "S_DIST_01, S_DIST_02, S_DIST_03, S_DIST_04, S_DIST_05, "
+ "S_DIST_06, S_DIST_07, S_DIST_08, S_DIST_09, S_DIST_10 "
+ "FROM STOCK WHERE S_I_ID=? AND S_W_ID=?");
prep.setInt(1, olId);
prep.setInt(2, olSupplyId);
rs = db.query(prep);
if (!rs.next()) {
if (rollback) {
// item not found - correct behavior
db.rollback();
return;
}
throw new SQLException("item not found: " + olId + " "
+ olSupplyId);
}
int sQuantity = rs.getInt(1);
String sData = rs.getString(2);
String[] dist = new String[10];
for (int i = 0; i < 10; i++) {
dist[i] = rs.getString(3 + i);
}
rs.close();
String distInfo = dist[dId - 1];
stock[number - 1] = sQuantity;
if ((data.indexOf("original") != -1)
&& (sData.indexOf("original") != -1)) {
bg[number - 1] = 'B';
} else {
bg[number - 1] = 'G';
}
if (sQuantity > olQuantity) {
sQuantity = sQuantity - olQuantity;
} else {
sQuantity = sQuantity - olQuantity + 91;
}
prep = prepare("UPDATE STOCK SET S_QUANTITY=? "
+ "WHERE S_W_ID=? AND S_I_ID=?");
prep.setInt(1, sQuantity);
prep.setInt(2, olSupplyId);
prep.setInt(3, olId);
db.update(prep, "updateStock");
BigDecimal olAmount = new BigDecimal(olQuantity).multiply(
price).multiply(ONE.add(wTax).add(tax)).multiply(
ONE.subtract(discount));
olAmount = olAmount.setScale(2, BigDecimal.ROUND_HALF_UP);
amt[number - 1] = olAmount;
total = total.add(olAmount);
prep = prepare("INSERT INTO ORDER_LINE (OL_O_ID, OL_D_ID, OL_W_ID, OL_NUMBER, "
+ "OL_I_ID, OL_SUPPLY_W_ID, "
+ "OL_QUANTITY, OL_AMOUNT, OL_DIST_INFO) "
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)");
prep.setInt(1, oId);
prep.setInt(2, dId);
prep.setInt(3, warehouseId);
prep.setInt(4, number);
prep.setInt(5, olId);
prep.setInt(6, olSupplyId);
prep.setInt(7, olQuantity);
prep.setBigDecimal(8, olAmount);
prep.setString(9, distInfo);
db.update(prep, "insertOrderLine");
}
prep = prepare("INSERT INTO ORDERS (O_ID, O_D_ID, O_W_ID, O_C_ID, "
+ "O_ENTRY_D, O_OL_CNT, O_ALL_LOCAL) "
+ "VALUES (?, ?, ?, ?, ?, ?, ?)");
prep.setInt(1, oId);
prep.setInt(2, dId);
prep.setInt(3, warehouseId);
prep.setInt(4, cId);
prep.setTimestamp(5, datetime);
prep.setInt(6, olCnt);
prep.setInt(7, allLocal);
db.update(prep, "insertOrders");
prep = prepare("INSERT INTO NEW_ORDER (NO_O_ID, NO_D_ID, NO_W_ID) "
+ "VALUES (?, ?, ?)");
prep.setInt(1, oId);
prep.setInt(2, dId);
prep.setInt(3, warehouseId);
db.update(prep, "insertNewOrder");
db.commit();
}
private void processPayment() throws SQLException {
int dId = random.getInt(1, bench.districtsPerWarehouse);
int wId, cdId;
if (bench.warehouses > 1 && random.getInt(1, 100) <= 15) {
do {
wId = random.getInt(1, bench.warehouses);
} while (wId != warehouseId);
cdId = random.getInt(1, bench.districtsPerWarehouse);
} else {
wId = warehouseId;
cdId = dId;
}
boolean byName;
String last;
int cId = 1;
if (random.getInt(1, 100) <= 60) {
byName = true;
last = random.getLastname(random.getNonUniform(255, 0, 999));
} else {
byName = false;
last = "";
cId = random.getNonUniform(1023, 1, bench.customersPerDistrict);
}
BigDecimal amount = random.getBigDecimal(random.getInt(100, 500000),
2);
Timestamp datetime = new Timestamp(System.currentTimeMillis());
PreparedStatement prep;
ResultSet rs;
prep = prepare("UPDATE DISTRICT SET D_YTD = D_YTD+? "
+ "WHERE D_ID=? AND D_W_ID=?");
prep.setBigDecimal(1, amount);
prep.setInt(2, dId);
prep.setInt(3, warehouseId);
db.update(prep, "updateDistrict");
prep = prepare("UPDATE WAREHOUSE SET W_YTD=W_YTD+? WHERE W_ID=?");
prep.setBigDecimal(1, amount);
prep.setInt(2, warehouseId);
db.update(prep, "updateWarehouse");
prep = prepare("SELECT W_STREET_1, W_STREET_2, W_CITY, W_STATE, W_ZIP, W_NAME "
+ "FROM WAREHOUSE WHERE W_ID=?");
prep.setInt(1, warehouseId);
rs = db.query(prep);
rs.next();
// w_street_1
rs.getString(1);
// w_street_2
rs.getString(2);
// w_city
rs.getString(3);
// w_state
rs.getString(4);
// w_zip
rs.getString(5);
String wName = rs.getString(6);
rs.close();
prep = prepare("SELECT D_STREET_1, D_STREET_2, D_CITY, D_STATE, D_ZIP, D_NAME "
+ "FROM DISTRICT WHERE D_ID=? AND D_W_ID=?");
prep.setInt(1, dId);
prep.setInt(2, warehouseId);
rs = db.query(prep);
rs.next();
// d_street_1
rs.getString(1);
// d_street_2
rs.getString(2);
// d_city
rs.getString(3);
// d_state
rs.getString(4);
// d_zip
rs.getString(5);
String dName = rs.getString(6);
rs.close();
BigDecimal balance;
String credit;
if (byName) {
prep = prepare("SELECT COUNT(C_ID) FROM CUSTOMER "
+ "WHERE C_LAST=? AND C_D_ID=? AND C_W_ID=?");
prep.setString(1, last);
prep.setInt(2, cdId);
prep.setInt(3, wId);
rs = db.query(prep);
rs.next();
int namecnt = rs.getInt(1);
rs.close();
if (namecnt == 0) {
// TODO TPC-C: check if this can happen
db.rollback();
return;
}
prep = prepare("SELECT C_FIRST, C_MIDDLE, C_ID, "
+ "C_STREET_1, C_STREET_2, C_CITY, C_STATE, C_ZIP, "
+ "C_PHONE, C_CREDIT, C_CREDIT_LIM, "
+ "C_DISCOUNT, C_BALANCE, C_SINCE FROM CUSTOMER "
+ "WHERE C_LAST=? AND C_D_ID=? AND C_W_ID=? "
+ "ORDER BY C_FIRST");
prep.setString(1, last);
prep.setInt(2, cdId);
prep.setInt(3, wId);
rs = db.query(prep);
// locate midpoint customer
if (namecnt % 2 != 0) {
namecnt++;
}
for (int n = 0; n < namecnt / 2; n++) {
rs.next();
}
// c_first
rs.getString(1);
// c_middle
rs.getString(2);
cId = rs.getInt(3);
// c_street_1
rs.getString(4);
// c_street_2
rs.getString(5);
// c_city
rs.getString(6);
// c_state
rs.getString(7);
// c_zip
rs.getString(8);
// c_phone
rs.getString(9);
credit = rs.getString(10);
// c_credit_lim
rs.getString(11);
// c_discount
rs.getBigDecimal(12);
balance = rs.getBigDecimal(13);
// c_since
rs.getTimestamp(14);
rs.close();
} else {
prep = prepare("SELECT C_FIRST, C_MIDDLE, C_LAST, "
+ "C_STREET_1, C_STREET_2, C_CITY, C_STATE, C_ZIP, "
+ "C_PHONE, C_CREDIT, C_CREDIT_LIM, "
+ "C_DISCOUNT, C_BALANCE, C_SINCE FROM CUSTOMER "
+ "WHERE C_ID=? AND C_D_ID=? AND C_W_ID=?");
prep.setInt(1, cId);
prep.setInt(2, cdId);
prep.setInt(3, wId);
rs = db.query(prep);
rs.next();
// c_first
rs.getString(1);
// c_middle
rs.getString(2);
// c_last
rs.getString(3);
// c_street_1
rs.getString(4);
// c_street_2
rs.getString(5);
// c_city
rs.getString(6);
// c_state
rs.getString(7);
// c_zip
rs.getString(8);
// c_phone
rs.getString(9);
credit = rs.getString(10);
// c_credit_lim
rs.getString(11);
// c_discount
rs.getBigDecimal(12);
balance = rs.getBigDecimal(13);
// c_since
rs.getTimestamp(14);
rs.close();
}
balance = balance.add(amount);
if (credit.equals("BC")) {
prep = prepare("SELECT C_DATA INTO FROM CUSTOMER "
+ "WHERE C_ID=? AND C_D_ID=? AND C_W_ID=?");
prep.setInt(1, cId);
prep.setInt(2, cdId);
prep.setInt(3, wId);
rs = db.query(prep);
rs.next();
String cData = rs.getString(1);
rs.close();
String cNewData = "| " + cId + " " + cdId + " " + wId
+ " " + dId + " " + warehouseId + " " + amount + " "
+ cData;
if (cNewData.length() > 500) {
cNewData = cNewData.substring(0, 500);
}
prep = prepare("UPDATE CUSTOMER SET C_BALANCE=?, C_DATA=? "
+ "WHERE C_ID=? AND C_D_ID=? AND C_W_ID=?");
prep.setBigDecimal(1, balance);
prep.setString(2, cNewData);
prep.setInt(3, cId);
prep.setInt(4, cdId);
prep.setInt(5, wId);
db.update(prep, "updateCustomer");
} else {
prep = prepare("UPDATE CUSTOMER SET C_BALANCE=? "
+ "WHERE C_ID=? AND C_D_ID=? AND C_W_ID=?");
prep.setBigDecimal(1, balance);
prep.setInt(2, cId);
prep.setInt(3, cdId);
prep.setInt(4, wId);
db.update(prep, "updateCustomer");
}
// MySQL bug?
// String h_data = w_name + " " + d_name;
String hData = wName + " " + dName;
prep = prepare("INSERT INTO HISTORY (H_C_D_ID, H_C_W_ID, H_C_ID, H_D_ID, "
+ "H_W_ID, H_DATE, H_AMOUNT, H_DATA) "
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
prep.setInt(1, cdId);
prep.setInt(2, wId);
prep.setInt(3, cId);
prep.setInt(4, dId);
prep.setInt(5, warehouseId);
prep.setTimestamp(6, datetime);
prep.setBigDecimal(7, amount);
prep.setString(8, hData);
db.update(prep, "insertHistory");
db.commit();
}
private void processOrderStatus() throws SQLException {
int dId = random.getInt(1, bench.districtsPerWarehouse);
boolean byName;
String last = null;
int cId = -1;
if (random.getInt(1, 100) <= 60) {
byName = true;
last = random.getLastname(random.getNonUniform(255, 0, 999));
} else {
byName = false;
cId = random.getNonUniform(1023, 1, bench.customersPerDistrict);
}
PreparedStatement prep;
ResultSet rs;
prep = prepare("UPDATE DISTRICT SET D_NEXT_O_ID=-1 WHERE D_ID=-1");
db.update(prep, "updateDistrict");
if (byName) {
prep = prepare("SELECT COUNT(C_ID) FROM CUSTOMER "
+ "WHERE C_LAST=? AND C_D_ID=? AND C_W_ID=?");
prep.setString(1, last);
prep.setInt(2, dId);
prep.setInt(3, warehouseId);
rs = db.query(prep);
rs.next();
int namecnt = rs.getInt(1);
rs.close();
if (namecnt == 0) {
// TODO TPC-C: check if this can happen
db.rollback();
return;
}
prep = prepare("SELECT C_BALANCE, C_FIRST, C_MIDDLE, C_ID "
+ "FROM CUSTOMER "
+ "WHERE C_LAST=? AND C_D_ID=? AND C_W_ID=? "
+ "ORDER BY C_FIRST");
prep.setString(1, last);
prep.setInt(2, dId);
prep.setInt(3, warehouseId);
rs = db.query(prep);
if (namecnt % 2 != 0) {
namecnt++;
}
for (int n = 0; n < namecnt / 2; n++) {
rs.next();
}
// c_balance
rs.getBigDecimal(1);
// c_first
rs.getString(2);
// c_middle
rs.getString(3);
rs.close();
} else {
prep = prepare("SELECT C_BALANCE, C_FIRST, C_MIDDLE, C_LAST "
+ "FROM CUSTOMER "
+ "WHERE C_ID=? AND C_D_ID=? AND C_W_ID=?");
prep.setInt(1, cId);
prep.setInt(2, dId);
prep.setInt(3, warehouseId);
rs = db.query(prep);
rs.next();
// c_balance
rs.getBigDecimal(1);
// c_first
rs.getString(2);
// c_middle
rs.getString(3);
// c_last
rs.getString(4);
rs.close();
}
prep = prepare("SELECT MAX(O_ID) "
+ "FROM ORDERS WHERE O_C_ID=? AND O_D_ID=? AND O_W_ID=?");
prep.setInt(1, cId);
prep.setInt(2, dId);
prep.setInt(3, warehouseId);
rs = db.query(prep);
int oId = -1;
if (rs.next()) {
oId = rs.getInt(1);
if (rs.wasNull()) {
oId = -1;
}
}
rs.close();
if (oId != -1) {
prep = prepare("SELECT O_ID, O_CARRIER_ID, O_ENTRY_D "
+ "FROM ORDERS WHERE O_ID=?");
prep.setInt(1, oId);
rs = db.query(prep);
rs.next();
oId = rs.getInt(1);
// o_carrier_id
rs.getInt(2);
// o_entry_d
rs.getTimestamp(3);
rs.close();
prep = prepare("SELECT OL_I_ID, OL_SUPPLY_W_ID, OL_QUANTITY, "
+ "OL_AMOUNT, OL_DELIVERY_D FROM ORDER_LINE "
+ "WHERE OL_O_ID=? AND OL_D_ID=? AND OL_W_ID=?");
prep.setInt(1, oId);
prep.setInt(2, dId);
prep.setInt(3, warehouseId);
rs = db.query(prep);
while (rs.next()) {
// o_i_id
rs.getInt(1);
// ol_supply_w_id
rs.getInt(2);
// ol_quantity
rs.getInt(3);
// ol_amount
rs.getBigDecimal(4);
// ol_delivery_d
rs.getTimestamp(5);
}
rs.close();
}
db.commit();
}
private void processDelivery() throws SQLException {
int carrierId = random.getInt(1, 10);
Timestamp datetime = new Timestamp(System.currentTimeMillis());
PreparedStatement prep;
ResultSet rs;
prep = prepare("UPDATE DISTRICT SET D_NEXT_O_ID=-1 WHERE D_ID=-1");
db.update(prep, "updateDistrict");
for (int dId = 1; dId <= bench.districtsPerWarehouse; dId++) {
prep = prepare("SELECT MIN(NO_O_ID) FROM NEW_ORDER "
+ "WHERE NO_D_ID=? AND NO_W_ID=?");
prep.setInt(1, dId);
prep.setInt(2, warehouseId);
rs = db.query(prep);
int noId = -1;
if (rs.next()) {
noId = rs.getInt(1);
if (rs.wasNull()) {
noId = -1;
}
}
rs.close();
if (noId != -1) {
prep = prepare("DELETE FROM NEW_ORDER "
+ "WHERE NO_O_ID=? AND NO_D_ID=? AND NO_W_ID=?");
prep.setInt(1, noId);
prep.setInt(2, dId);
prep.setInt(3, warehouseId);
db.update(prep, "deleteNewOrder");
prep = prepare("SELECT O_C_ID FROM ORDERS "
+ "WHERE O_ID=? AND O_D_ID=? AND O_W_ID=?");
prep.setInt(1, noId);
prep.setInt(2, dId);
prep.setInt(3, warehouseId);
rs = db.query(prep);
rs.next();
// o_c_id
rs.getInt(1);
rs.close();
prep = prepare("UPDATE ORDERS SET O_CARRIER_ID=? "
+ "WHERE O_ID=? AND O_D_ID=? AND O_W_ID=?");
prep.setInt(1, carrierId);
prep.setInt(2, noId);
prep.setInt(3, dId);
prep.setInt(4, warehouseId);
db.update(prep, "updateOrders");
prep = prepare("UPDATE ORDER_LINE SET OL_DELIVERY_D=? "
+ "WHERE OL_O_ID=? AND OL_D_ID=? AND OL_W_ID=?");
prep.setTimestamp(1, datetime);
prep.setInt(2, noId);
prep.setInt(3, dId);
prep.setInt(4, warehouseId);
db.update(prep, "updateOrderLine");
prep = prepare("SELECT SUM(OL_AMOUNT) FROM ORDER_LINE "
+ "WHERE OL_O_ID=? AND OL_D_ID=? AND OL_W_ID=?");
prep.setInt(1, noId);
prep.setInt(2, dId);
prep.setInt(3, warehouseId);
rs = db.query(prep);
rs.next();
BigDecimal amount = rs.getBigDecimal(1);
rs.close();
prep = prepare("UPDATE CUSTOMER SET C_BALANCE=C_BALANCE+? "
+ "WHERE C_ID=? AND C_D_ID=? AND C_W_ID=?");
prep.setBigDecimal(1, amount);
prep.setInt(2, noId);
prep.setInt(3, dId);
prep.setInt(4, warehouseId);
db.update(prep, "updateCustomer");
}
}
db.commit();
}
private void processStockLevel() throws SQLException {
int dId = (terminalId % bench.districtsPerWarehouse) + 1;
int threshold = random.getInt(10, 20);
PreparedStatement prep;
ResultSet rs;
prep = prepare("UPDATE DISTRICT SET D_NEXT_O_ID=-1 WHERE D_ID=-1");
db.update(prep, "updateDistrict");
prep = prepare("SELECT D_NEXT_O_ID FROM DISTRICT "
+ "WHERE D_ID=? AND D_W_ID=?");
prep.setInt(1, dId);
prep.setInt(2, warehouseId);
rs = db.query(prep);
rs.next();
int oId = rs.getInt(1);
rs.close();
prep = prepare("SELECT COUNT(DISTINCT S_I_ID) "
+ "FROM ORDER_LINE, STOCK WHERE "
+ "OL_W_ID=? AND "
+ "OL_D_ID=? AND "
+ "OL_O_ID<? AND "
+ "OL_O_ID>=?-20 AND "
+ "S_W_ID=? AND "
+ "S_I_ID=OL_I_ID AND "
+ "S_QUANTITY<?");
prep.setInt(1, warehouseId);
prep.setInt(2, dId);
prep.setInt(3, oId);
prep.setInt(4, oId);
prep.setInt(5, warehouseId);
prep.setInt(6, threshold);
rs = db.query(prep);
rs.next();
// stockCount
rs.getInt(1);
rs.close();
db.commit();
}
private PreparedStatement prepare(String sql) throws SQLException {
PreparedStatement prep = prepared.get(sql);
if (prep == null) {
prep = db.prepare(sql);
prepared.put(sql, prep);
}
return prep;
}
}