Skip to content

Commit 4a62480

Browse files
committed
- Add the use of prepared statement in the JDBC table type.
modified: storage/connect/jdbconn.cpp modified: storage/connect/jdbconn.h modified: storage/connect/tabjdbc.cpp modified: storage/connect/tabjdbc.h
1 parent c086a96 commit 4a62480

File tree

4 files changed

+200
-131
lines changed

4 files changed

+200
-131
lines changed

storage/connect/jdbconn.cpp

Lines changed: 153 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -708,15 +708,10 @@ JDBConn::JDBConn(PGLOBAL g, TDBJDBC *tdbp)
708708
m_Tdb = tdbp;
709709
jvm = nullptr; // Pointer to the JVM (Java Virtual Machine)
710710
env= nullptr; // Pointer to native interface
711-
jdi = nullptr;
712-
job = nullptr;
713-
xqid = nullptr;
714-
xuid = nullptr;
715-
xid = nullptr;
716-
grs = nullptr;
717-
readid = nullptr;
718-
fetchid = nullptr;
719-
typid = nullptr;
711+
jdi = nullptr; // Pointer to the JdbcInterface class
712+
job = nullptr; // The JdbcInterface class object
713+
xqid = xuid = xid = grs = readid = fetchid = typid = nullptr;
714+
prepid = xpid = pcid = nullptr;
720715
//m_LoginTimeout = DEFAULT_LOGIN_TIMEOUT;
721716
//m_QueryTimeout = DEFAULT_QUERY_TIMEOUT;
722717
//m_UpdateOptions = 0;
@@ -1245,7 +1240,7 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val)
12451240
fldid = env->GetMethodID(jdi, "DoubleField", "(ILjava/lang/String;)D");
12461241

12471242
if (fldid != nullptr)
1248-
val->SetValue((double)env->CallDoubleMethod(job, fldid, rank,jn));
1243+
val->SetValue((double)env->CallDoubleMethod(job, fldid, rank, jn));
12491244
else
12501245
val->Reset();
12511246

@@ -1318,10 +1313,23 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val)
13181313
/***********************************************************************/
13191314
/* Prepare an SQL statement for insert. */
13201315
/***********************************************************************/
1321-
int JDBConn::PrepareSQL(char *sql)
1316+
bool JDBConn::PrepareSQL(char *sql)
13221317
{
1323-
// TODO: implement prepared statement
1324-
return 0;
1318+
if (prepid == nullptr) {
1319+
prepid = env->GetMethodID(jdi, "CreatePrepStmt", "(Ljava/lang/String;)Z");
1320+
1321+
if (prepid == nullptr) {
1322+
strcpy(m_G->Message, "Cannot find method CreatePrepStmt");
1323+
return true;
1324+
} // endif prepid
1325+
1326+
} // endif prepid
1327+
1328+
// Create the prepared statement
1329+
jstring qry = env->NewStringUTF(sql);
1330+
jboolean b = env->CallBooleanMethod(job, prepid, qry);
1331+
env->DeleteLocalRef(qry);
1332+
return (bool)b;
13251333
} // end of PrepareSQL
13261334

13271335
/***********************************************************************/
@@ -1416,112 +1424,165 @@ int JDBConn::GetResultSize(char *sql, JDBCCOL *colp)
14161424
return colp->GetIntValue();
14171425
} // end of GetResultSize
14181426

1419-
#if 0
14201427
/***********************************************************************/
14211428
/* Execute a prepared statement. */
14221429
/***********************************************************************/
14231430
int JDBConn::ExecuteSQL(void)
14241431
{
1432+
int rc = RC_FX;
14251433
PGLOBAL& g = m_G;
1426-
SWORD ncol = 0;
1427-
RETCODE rc;
1428-
SQLLEN afrw = -1;
1429-
1430-
try {
1431-
do {
1432-
rc = SQLExecute(m_hstmt);
1433-
} while (rc == SQL_STILL_EXECUTING);
1434-
1435-
if (!Check(rc))
1436-
ThrowDJX(rc, "SQLExecute", m_hstmt);
14371434

1438-
if (!Check(rc = SQLNumResultCols(m_hstmt, &ncol)))
1439-
ThrowDJX(rc, "SQLNumResultCols", m_hstmt);
1435+
if (xpid == nullptr) {
1436+
// Get the methods used to execute a prepared statement
1437+
xpid = env->GetMethodID(jdi, "ExecutePrep", "()I");
14401438

1441-
if (ncol) {
1442-
// This should never happen while inserting
1443-
strcpy(g->Message, "Logical error while inserting");
1444-
} else {
1445-
// Insert, Update or Delete statement
1446-
if (!Check(rc = SQLRowCount(m_hstmt, &afrw)))
1447-
ThrowDJX(rc, "SQLRowCount", m_hstmt);
1439+
if (xpid == nullptr) {
1440+
strcpy(g->Message, "Cannot find method ExecutePrep");
1441+
return rc;
1442+
} // endif xpid
14481443

1449-
} // endif ncol
1444+
} // endif xpid
14501445

1451-
}
1452-
catch (DJX *x) {
1453-
sprintf(m_G->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
1454-
SQLCancel(m_hstmt);
1455-
rc = SQLFreeStmt(m_hstmt, SQL_DROP);
1456-
m_hstmt = NULL;
1446+
jint n = env->CallIntMethod(job, xpid);
14571447

1458-
if (m_Transact) {
1459-
rc = SQLEndTran(SQL_HANDLE_DBC, m_hdbc, SQL_ROLLBACK);
1460-
m_Transact = false;
1461-
} // endif m_Transact
1462-
1463-
afrw = -1;
1464-
} // end try/catch
1448+
switch ((int)n) {
1449+
case -1:
1450+
case -2:
1451+
strcpy(g->Message, "Exception error thrown while executing SQL");
1452+
break;
1453+
case -3:
1454+
strcpy(g->Message, "SQL statement is not prepared");
1455+
break;
1456+
default:
1457+
m_Aff = (int)n;
1458+
rc = RC_OK;
1459+
} // endswitch n
14651460

1466-
return (int)afrw;
1461+
return rc;
14671462
} // end of ExecuteSQL
14681463

14691464
/***********************************************************************/
1470-
/* Bind a parameter for inserting. */
1465+
/* Set a parameter for inserting. */
14711466
/***********************************************************************/
1472-
bool JDBConn::BindParam(JDBCCOL *colp)
1467+
bool JDBConn::SetParam(JDBCCOL *colp)
14731468
{
1474-
void *buf;
1475-
int buftype = colp->GetResultType();
1476-
SQLUSMALLINT n = colp->GetRank();
1477-
SQLSMALLINT ct, sqlt, dec, nul;
1478-
SQLULEN colsize;
1479-
SQLLEN len;
1480-
SQLLEN *strlen = colp->GetStrLen();
1481-
SQLRETURN rc;
1469+
PGLOBAL& g = m_G;
1470+
int rc = false;
1471+
PVAL val = colp->GetValue();
1472+
jint n, i = (jint)colp->GetRank();
1473+
jshort s;
1474+
jlong lg;
1475+
//jfloat f;
1476+
jdouble d;
1477+
jclass dat;
1478+
jobject datobj;
1479+
jstring jst = nullptr;
1480+
jthrowable exc;
1481+
jmethodID dtc, setid = nullptr;
14821482

1483-
#if 0
1484-
try {
1485-
// This function is often not or badly implemented by data sources
1486-
rc = SQLDescribeParam(m_hstmt, n, &sqlt, &colsize, &dec, &nul);
1483+
switch (val->GetType()) {
1484+
case TYPE_STRING:
1485+
setid = env->GetMethodID(jdi, "SetStringParm", "(ILjava/lang/String;)V");
14871486

1488-
if (!Check(rc))
1489-
ThrowDJX(rc, "SQLDescribeParam", m_hstmt);
1487+
if (setid == nullptr) {
1488+
strcpy(g->Message, "Cannot fing method SetStringParm");
1489+
return true;
1490+
} // endif setid
14901491

1491-
}
1492-
catch (DJX *x) {
1493-
sprintf(m_G->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
1494-
#endif // 0
1495-
colsize = colp->GetPrecision();
1496-
sqlt = GetJDBCType(buftype);
1497-
dec = IsTypeNum(buftype) ? colp->GetScale() : 0;
1498-
nul = colp->IsNullable() ? SQL_NULLABLE : SQL_NO_NULLS;
1499-
//} // end try/catch
1492+
jst = env->NewStringUTF(val->GetCharValue());
1493+
env->CallVoidMethod(job, setid, i, jst);
1494+
break;
1495+
case TYPE_INT:
1496+
setid = env->GetMethodID(jdi, "SetIntParm", "(II)V");
15001497

1501-
buf = colp->GetBuffer(0);
1502-
len = IsTypeChar(buftype) ? colp->GetBuflen() : 0;
1503-
ct = GetJDBCCType(buftype);
1504-
*strlen = IsTypeChar(buftype) ? SQL_NTS : 0;
1498+
if (setid == nullptr) {
1499+
strcpy(g->Message, "Cannot fing method SetIntParm");
1500+
return true;
1501+
} // endif setid
15051502

1506-
try {
1507-
rc = SQLBindParameter(m_hstmt, n, SQL_PARAM_INPUT, ct, sqlt,
1508-
colsize, dec, buf, len, strlen);
1503+
n = (jint)val->GetIntValue();
1504+
env->CallVoidMethod(job, setid, i, n);
1505+
break;
1506+
case TYPE_TINY:
1507+
case TYPE_SHORT:
1508+
setid = env->GetMethodID(jdi, "SetShortParm", "(IS)V");
15091509

1510-
if (!Check(rc))
1511-
ThrowDJX(rc, "SQLBindParameter", m_hstmt);
1510+
if (setid == nullptr) {
1511+
strcpy(g->Message, "Cannot fing method SetShortParm");
1512+
return true;
1513+
} // endif setid
15121514

1513-
}
1514-
catch (DJX *x) {
1515-
strcpy(m_G->Message, x->GetErrorMessage(0));
1516-
SQLCancel(m_hstmt);
1517-
rc = SQLFreeStmt(m_hstmt, SQL_DROP);
1518-
m_hstmt = NULL;
1515+
s = (jshort)val->GetShortValue();
1516+
env->CallVoidMethod(job, setid, i, s);
1517+
break;
1518+
case TYPE_BIGINT:
1519+
setid = env->GetMethodID(jdi, "SetBigintParm", "(IJ)V");
1520+
1521+
if (setid == nullptr) {
1522+
strcpy(g->Message, "Cannot fing method SetBigintParm");
15191523
return true;
1520-
} // end try/catch
1524+
} // endif setid
15211525

1522-
return false;
1523-
} // end of BindParam
1526+
lg = (jlong)val->GetBigintValue();
1527+
env->CallVoidMethod(job, setid, i, lg);
1528+
break;
1529+
case TYPE_DOUBLE:
1530+
case TYPE_DECIM:
1531+
setid = env->GetMethodID(jdi, "SetDoubleParm", "(ID)V");
1532+
1533+
if (setid == nullptr) {
1534+
strcpy(g->Message, "Cannot fing method SetDoubleParm");
1535+
return true;
1536+
} // endif setid
15241537

1538+
d = (jdouble)val->GetFloatValue();
1539+
env->CallVoidMethod(job, setid, i, d);
1540+
break;
1541+
case TYPE_DATE:
1542+
if ((dat = env->FindClass("java/sql/Timestamp")) == nullptr) {
1543+
strcpy(g->Message, "Cannot find Timestamp class");
1544+
return true;
1545+
} else if (!(dtc = env->GetMethodID(dat, "<init>", "(J)V"))) {
1546+
strcpy(g->Message, "Cannot find Timestamp class constructor");
1547+
return true;
1548+
} // endif's
1549+
1550+
lg = (jlong)val->GetBigintValue() * 1000;
1551+
1552+
if ((datobj = env->NewObject(dat, dtc, lg)) == nullptr) {
1553+
strcpy(g->Message, "Cannot make Timestamp object");
1554+
return true;
1555+
} else if ((setid = env->GetMethodID(jdi, "SetTimestampParm",
1556+
"(ILjava/sql/Timestamp;)V")) == nullptr) {
1557+
strcpy(g->Message, "Cannot find method SetTimestampParm");
1558+
return true;
1559+
} // endif setid
1560+
1561+
env->CallVoidMethod(job, setid, i, datobj);
1562+
break;
1563+
default:
1564+
sprintf(g->Message, "Parm type %d not supported", val->GetType());
1565+
return true;
1566+
} // endswitch Type
1567+
1568+
if ((exc = env->ExceptionOccurred()) != nullptr) {
1569+
jboolean isCopy = false;
1570+
jmethodID tid = env->GetMethodID(env->FindClass("java/lang/Object"), "toString", "()Ljava/lang/String;");
1571+
jstring s = (jstring)env->CallObjectMethod(exc, tid);
1572+
const char* utf = env->GetStringUTFChars(s, &isCopy);
1573+
sprintf(g->Message, "SetParam: %s", utf);
1574+
env->DeleteLocalRef(s);
1575+
env->ExceptionClear();
1576+
rc = true;
1577+
} // endif exc
1578+
1579+
if (jst)
1580+
env->DeleteLocalRef(jst);
1581+
1582+
return rc;
1583+
} // end of SetParam
1584+
1585+
#if 0
15251586
/***********************************************************************/
15261587
/* Get the list of Data Sources and set it in qrp. */
15271588
/***********************************************************************/

storage/connect/jdbconn.h

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,9 @@ class JDBConn : public BLOCK {
103103
int ExecuteQuery(char *sql);
104104
int ExecuteUpdate(char *sql);
105105
int Fetch(int pos = 0);
106-
int PrepareSQL(char *sql);
107-
//int ExecuteSQL(void);
108-
//bool BindParam(JDBCCOL *colp);
106+
bool PrepareSQL(char *sql);
107+
int ExecuteSQL(void);
108+
bool SetParam(JDBCCOL *colp);
109109
int ExecSQLcommand(char *sql);
110110
void SetColumnValue(int rank, PSZ name, PVAL val);
111111
int GetCatInfo(JCATPARM *cap);
@@ -134,10 +134,6 @@ class JDBConn : public BLOCK {
134134
//void Free(void);
135135

136136
protected:
137-
// Static members
138-
//static HENV m_henv;
139-
//static int m_nAlloc; // per-Appl reference to HENV above
140-
141137
// Members
142138
PGLOBAL m_G;
143139
TDBJDBC *m_Tdb;
@@ -152,7 +148,10 @@ class JDBConn : public BLOCK {
152148
jmethodID readid; // The ReadNext method ID
153149
jmethodID fetchid; // The Fetch method ID
154150
jmethodID typid; // The ColumnType method ID
155-
//DWORD m_LoginTimeout;
151+
jmethodID prepid; // The CreatePrepStmt method ID
152+
jmethodID xpid; // The ExecutePrep method ID
153+
jmethodID pcid; // The ClosePrepStmt method ID
154+
//DWORD m_LoginTimeout;
156155
//DWORD m_QueryTimeout;
157156
//DWORD m_UpdateOptions;
158157
char m_IDQuoteChar[2];

0 commit comments

Comments
 (0)