Pseudo-code for Getting the Table Expression
This example code shows how the IP can use the various API calls to get details of the Search Expression and Join Expression. The starting point is a call to dam_getTableSearchExp from the EXECUTE function of the IP.
{
int iTableNum;
DAM_HLOGEXP hSearchExp, hJoinExp;
int iJoinType;
int bPartialExp;
/* get the search expression and Join expression handles */
iTableNum = 0;
dam_getTableSearchExp(hstmt, &iTableNum, &hSearchExp, &iJoinType, &hJoinExp, &bPartialExp);
/* get filter conditions */
ip_print_logexp(hSearchExp);
/* check the Join type */
if (hJoinExp) {
if (iJoinType == SQL_JOIN_LEFT_OUTER) printf(" OUTER JOIN ");
if (iJoinType == SQL_JOIN_LEFT_INNER || iJoinType == SQL_JOIN_OLD_STYLE)
printf("INNER JOIN ");
/* get Join conditions */
ip_print_logexp(hJoinExp);
}
int ip_print_logexp(DAM_HLOGEXP hSearchExp)
{
int iType; /* AND, OR, NOT or CONDITION */
DAM_HLOGEXP hLeft, hRight;
DAM_HCOND hCond;
/* get and print the logical expression */
damex_describeLogicExp(hSearchExp,
&iType, /* AND, OR, NOT or CONDITION */
&hLeft,
&hRight,&hCond);
switch (iType) {
case SQL_EXP_COND:
ip_print_cond(hCond);
break;
case SQL_EXP_AND:
/* left-expression AND right-expression */
ip_print_logexp(hLeft);
printf( " AND ");
ip_print_logexp(hRight);
break;
case SQL_EXP_OR:
/* left-expression OR right-expression */
ip_print_logexp(hLeft);
printf( " OR ");
ip_print_logexp(hRight);
break;
case SQL_EXP_NOT:
/* NOT left-expression */
printf( " NOT ");
ip_print_logexp(hLeft);
break;
}
return DAM_SUCCESS;
}
int ip_print_cond(DAM_HCOND hCond)
{
int iType;
DAM_HVALEXP hLeft, hRight, hExtra;
damex_describeCond(hCond,
&iType, /* >, <, =, BETWEEN etc.*/
&hLeft,
&hRight,
&hExtra); /* used for BETWEEN */
/* EXISTS and UNIQUE predicates */
if (iType & (SQL_OP_EXISTS | SQL_OP_UNIQUE)) {
if (iType & SQL_OP_NOT) printf( " NOT ");
if (iType & SQL_OP_EXISTS) printf( " EXISTS ");
if (iType & SQL_OP_UNIQUE) printf( " UNIQUE ");
ip_print_valexp(hLeft);
}
/* conditional predicates */
if (iType & ( SQL_OP_SMALLER | SQL_OP_GREATER | SQL_OP_EQUAL)) {
ip_print_valexp(hLeft);
if (iType & SQL_OP_NOT) {
if (iType & SQL_OP_EQUAL) printf( " <> ");
}
else {
printf( " ");
if (iType & SQL_OP_SMALLER) printf( "<");
if (iType & SQL_OP_GREATER) printf( ">");
if (iType & SQL_OP_EQUAL) printf( "=");
printf( " ");
}
if (iType & (SQL_OP_QUANTIFIER_ALL | SQL_OP_QUANTIFIER_SOME | SQL_OP_QUANTIFIER_ANY) {
if (iType & SQL_OP_QUANTIFIER_ALL) printf( " ALL ");
if (iType & SQL_OP_QUANTIFIER_SOME) printf( " SOME ");
if (iType & SQL_OP_QUANTIFIER_ANY) printf( " ANY ");
}
ip_print_valexp(hRight);
} /* conditional predicate */
/* like predicate */
if (iType & SQL_OP_LIKE) {
ip_print_valexp(hLeft);
if (iType & SQL_OP_NOT) printf( " NOT ");
printf( " LIKE ");
ip_print_valexp(hRight);
if (hExtra) {
printf( " ESCAPE ");
ip_print_valexp(hExtra);
}
} /* like predicate */
/* Is NULL predicate */
if (iType & SQL_OP_ISNULL) {
ip_print_valexp(hLeft);
if (iType & SQL_OP_NOT)
printf( " IS NOT NULL ");
else
printf( " IS NULL ");
}
/* IN predicate */
if (iType & SQL_OP_IN) {
ip_print_valexp(hLeft);
if (iType & SQL_OP_NOT) printf( " NOT ");
printf( " IN (");
ip_print_valexp(hRight);
pintf( " )");
}
/* BETWEEN predicate */
if (iType & SQL_OP_BETWEEN) {
/* check if the between is a form of ( >= and < ) OR (> and <)
OR (> and <=)
*/
if ((iType & SQL_OP_BETWEEN_OPEN_LEFT) ||
(iType & SQL_OP_BETWEEN_OPEN_RIGHT)) {
/* format it as two conditions */
ip_print_valexp(hLeft);
if (iType & SQL_OP_BETWEEN_OPEN_LEFT)
printf( " > ");
else
printf( " >= ");
ip_print_valexp(hRight);
printf( " AND ");
ip_print_valexp(hLeft);
if (iType & SQL_OP_BETWEEN_OPEN_RIGHT)
printf( " < ");
else
printf( " <= ");
ip_print_valexp(hExtra);
}
else {
/* standard BETWEEN pattern */
ip_print_valexp(hLeft);
if (iType & SQL_OP_NOT) printf( " NOT ");
printf( " BETWEEN ");
ip_print_valexp(hRight);
printf( " AND ");
ip_print_valexp(hExtra);
}
} /* BETWEEN */
return DAM_SUCCESS;
}
int ip_print_valexp(DAM_HVALEXP hValExp)
{
int iType; /* literal value, column, +, -, *, / etc */
int iFuncType;
DAM_HVALEXP hLeftValExp;
DAM_HVALEXP hRightValExp;
DAM_HVAL hVal;
DAM_HSCALAR_VALEXP hScalarValExp;
damex_describeValExp(hValExp, &iType, /* literal value, column, +, -, *, / etc */
&iFuncType,
&hLeftValExp,
&hRightValExp,
&hVal,
&hScalarValExp
);
/* function type (SQL_F_COUNT, SQL_F_MIN etc will not occur in search expressions */
switch (iType) {
case SQL_VAL_EXP_VAL:
ip_print_val(hVal);
break;
case SQL_VAL_EXP_ADD:
case SQL_VAL_EXP_SUBTRACT:
ip_print_valexp(hLeftValExp);
if (iType == SQL_VAL_EXP_AND) printf( "+");
if (iType == SQL_VAL_EXP_SUBTRACT) printf( "-");
if (iType == SQL_VAL_EXP_MULTIPLE) printf( "*");
if (iType == SQL_VAL_EXP_DIVIDE) printf( "/");
ip_print_valexp(hRightValExp);
break;
case SQL_VAL_EXP_SCALAR:
ip_print_scalar_valexp(hScalarValExp);
break;
}
return DAM_SUCCESS;
}
int ip_print_scalar_valexp(DAM_HSCALAR_VALEXP hScalarValExp)
{
char sName[DAM_MAX_ID_LEN+1];
char sQualifierName[DAM_MAX_ID_LEN+1];
DAM_HVALEXP_LIST hValExpList;
damex_describeScalarValExpEx2(hScalarValExp, sQualifierName, sName,
&hValExpList);
printf( "%s", sQualifierName, sName);
printf( "( ");
if (hValExpList) ip_print_valexp_list(hValExpList);
printf( ") ");
return DAM_SUCCESS;
}
int ip_print_valexp_list(DAM_HVALEXP_LIST hValExpList)
{
DAM_HVALEXP hValExp;
int iFirst = TRUE;
hValExp = damex_getFirstValExp(hValExpList);
while (hValExp) {
if (!iFirst)
printf( ", ");
else
iFirst = FALSE;
ip_print_valexp(hValExp);
hValExp = damex_getNextValExp(hValExpList);
}
printf( " ");
return DAM_SUCCESS;
}
int ip_print_val(DAM_HQUERY hquery, DAM_HVAL hVal)
{
int iType; /* literal value, column */
int iXoType; /* type of literal value – INTEGER, CHAR etc */
void *pData;
DAM_HCOL hCol;
DAM_HQUERY hSubQuery;
damex_describeVal(hVal, &iType,
&iXoType,
&pData,
&hCol,
&hSubQuery);
switch (iType) {
case SQL_VAL_DATA_CHAIN:
break;
case SQL_VAL_NULL:
printf( "NULL"); break;
case SQL_VAL_QUERY: /* query */
ip_print_query_values(hSubQuery);
break;
case SQL_VAL_COL: /* value is the column value */
ip_print_col(hCol); break;
case SQL_VAL_INTERVAL:
break;
case SQL_VAL_LITERAL: /* value is a Xo Type literal */
ip_print_data(iXoType, pData);
break;
default:
printf( "Invalid Value Type:%d", iType); break;
}
return DAM_SUCCESS;
}
int ip_print_query_values(DAM_HQUERY hQuery)
{
int iRetCode;
int iXoType;
void *pVal;
int iValLen;
int bFoundVal = FALSE;
iRetCode = dam_getQueryFirstResultValue(hQuery, &iXoType, &pVal, &iValLen);
while (iRetCode == DAM_SUCCESS) {
if (bFoundVal)
printf(", ");
if (iValLen == XO_NULL_DATA)
printf( "NULL");
else
ip_print_data(iXoType, pVal);
bFoundVal = TRUE;
iRetCode = dam_getQueryNextResultValue(hQuery, &iXoType, &pVal, &iValLen);
}
/* when results are empty, we will use NULL value */
if (!bFoundVal)
printf("NULL");
if (iRetCode != DAM_NO_DATA_FOUND) return iRetCode;
return DAM_SUCCESS;
}
int ip_print_data(int iXoType, void *pData)
{
xo_tm *pxoTime;
switch (iXoType) {
case XO_TYPE_CHAR: /* pVal is a char literal */
case XO_TYPE_VARCHAR:
case XO_TYPE_NUMERIC:
case XO_TYPE_DECIMAL:
printf( "'%s'", (char *)pData);
break;
case XO_TYPE_INTEGER: /* pVal is a integer literal */
printf( "%ld", *(long *)pData);
break;
case XO_TYPE_SMALLINT: /* pVal is small integer literal */
printf( "%d", (int)(*(short *)pData));
break;
case XO_TYPE_FLOAT: /* pVal is a double literal */
case XO_TYPE_DOUBLE:
printf( "%Lf", *(double *)pData);
break;
case XO_TYPE_REAL: /* pVal is a float literal */
printf( "%f", *(float *)pData);
break;
case XO_TYPE_DATE:
pxoTime = (xo_tm *)pData;
printf( "{d '%d-%02d-%02d'}", pxoTime->tm_year,
pxoTime->tm_mon+1, pxoTime->tm_mday);
break;
case XO_TYPE_TIME:
pxoTime = (xo_tm *)pData;
printf( "{t '%02d:%02d:%02d'}", pxoTime->tm_hour,
pxoTime->tm_min, pxoTime->tm_sec);
break;
case XO_TYPE_TIMESTAMP:
pxoTime = (xo_tm *)pData;
if (pxoTime->tm_frac > 0) {
int frac;
frac = (int) (pxoTime->tm_frac * 0.000001);
printf( "{ts '%d-%02d-%02d %02d:%02d:%02d.%03d'}",
pxoTime->tm_year, pxoTime->tm_mon+1, pxoTime->tm_mday,
pxoTime->tm_hour, pxoTime->tm_min, pxoTime->tm_sec, frac);
}
else
printf( "{ts '%d-%02d-%02d %02d:%02d:%02d'}",
pxoTime->tm_year, pxoTime->tm_mon+1, pxoTime->tm_mday,
pxoTime->tm_hour, pxoTime->tm_min, pxoTime->tm_sec);
break;
default:
printf( "Invalid Xo Value Type:%d", iXoType);
break;
}
return DAM_SUCCESS;
}
int ip_print_col(DAM_HCOL hCol)
{
int iTableNum, iColNum;
char sColName[DAM_MAX_ID_LEN+1];
DAM_HSTMT hstmt = pStmtDA->dam_hstmt; /* we need to pass this variable as argument */
damex_describeCol(hCol,
&iTableNum,
&iColNum,
sColName, NULL, NULL, NULL, NULL);
/* check for correlated column and join columns */
if (damex_isCorrelatedCol(hCol) ||
(pStmtDA->iCurTableNum != DAM_NOT_SET && iTableNum != pStmtDA->iCurTableNum)) {
int iValLen;
void *pVal;
dam_getJoinColValue(hstmt, hCol, XO_TYPE_CHAR, &pVal, &iValLen);
if (iValLen == XO_NULL_DATA)
printf( " NULL ");
else
printf( " '%s' ", (char *)pVal);
}
else {
printf( "T%d.%s", iTableNum, sColName);
}
return DAM_SUCCESS;
}