in src/odbc/rsodbc/rscatalog.cpp [489:720]
SQLRETURN SQL_API RsCatalog::RS_SQLTables(SQLHSTMT phstmt,
SQLCHAR *pCatalogName,
SQLSMALLINT cbCatalogName,
SQLCHAR *pSchemaName,
SQLSMALLINT cbSchemaName,
SQLCHAR *pTableName,
SQLSMALLINT cbTableName,
SQLCHAR *pTableType,
SQLSMALLINT cbTableType)
{
SQLRETURN rc = SQL_SUCCESS;
RS_STMT_INFO *pStmt = (RS_STMT_INFO *)phstmt;
// Clear error list
pStmt->pErrorList = clearErrorList(pStmt->pErrorList);
if(showDiscoveryVersion(pStmt) >= MIN_SHOW_DISCOVERY_VERSION){
if (isNullOrEmptyString(pSchemaName) && isNullOrEmptyString(pTableName) && isSqlAllCatalogs(pCatalogName, cbCatalogName))
{
SQLHSTMT internalStmt;
rc = RS_CONN_INFO::RS_SQLAllocStmt(pStmt->phdbc, &internalStmt);
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
RS_LOG_ERROR("RS_CONN_INFO::RS_SQLAllocStmt", "Fail to allocate new statement for internal use");
addError(&pStmt->pErrorList, "HY000", "RS_CONN_INFO::RS_SQLAllocStmt, Fail to allocate new statement for internal use", 0, NULL);
return rc;
}
// Special SQLTables call : get catalog list
std::vector<std::string> intermediateRS;
rc = RsMetadataServerAPIHelper::sqlCatalogsServerAPI(internalStmt, intermediateRS, isSingleDatabaseMetaData(pStmt));
if(rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO){
RS_LOG_ERROR("RsMetadataServerAPIHelper.sqlCatalogsServerAPI", "Fail get intermediate result set for SQLTables");
addError(&pStmt->pErrorList,"HY000", "RsMetadataServerAPIHelper.sqlCatalogsServerAPI fail", 0, NULL);
return rc;
}
rc = RS_STMT_INFO::RS_SQLFreeStmt(internalStmt,SQL_DROP, TRUE);
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
RS_LOG_ERROR("RS_STMT_INFO::RS_SQLFreeStmt", "Fail to free statement for internal use");
addError(&pStmt->pErrorList, "HY000", "RS_STMT_INFO::RS_SQLFreeStmt, Fail to free statement for internal use", 0, NULL);
return rc;
}
rc = RsMetadataAPIPostProcessing::sqlCatalogsPostProcessing(phstmt, intermediateRS);
if(rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO){
RS_LOG_ERROR("RsMetadataAPIPostProcessing.sqlCatalogsPostProcessing", "Fail call post-processing for SQLTables");
addError(&pStmt->pErrorList,"HY000", "RsMetadataAPIPostProcessing.sqlCatalogsPostProcessing fail", 0, NULL);
return rc;
}
}
else
if(isNullOrEmptyString(pCatalogName) && isNullOrEmptyString(pTableName) && isSqlAllSchemas(pSchemaName, cbSchemaName))
{
SQLHSTMT internalStmt;
rc = RS_CONN_INFO::RS_SQLAllocStmt(pStmt->phdbc, &internalStmt);
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
RS_LOG_ERROR("RS_CONN_INFO::RS_SQLAllocStmt", "Fail to allocate new statement for internal use");
addError(&pStmt->pErrorList, "HY000", "RS_CONN_INFO::RS_SQLAllocStmt, Fail to allocate new statement for internal use", 0, NULL);
return rc;
}
// Special SQLTables call : get schema list
std::vector<SHOWSCHEMASResult> intermediateRS;
rc = RsMetadataServerAPIHelper::sqlSchemasServerAPI(internalStmt, intermediateRS, isSingleDatabaseMetaData(pStmt));
if(rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO){
RS_LOG_ERROR("RsMetadataServerAPIHelper.sqlSchemasServerAPI", "Fail get intermediate result set for SQLTables");
addError(&pStmt->pErrorList,"HY000", "RsMetadataServerAPIHelper.sqlSchemasServerAPI fail", 0, NULL);
return rc;
}
rc = RS_STMT_INFO::RS_SQLFreeStmt(internalStmt,SQL_DROP, TRUE);
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
RS_LOG_ERROR("RS_STMT_INFO::RS_SQLFreeStmt", "Fail to free statement for internal use");
addError(&pStmt->pErrorList, "HY000", "RS_STMT_INFO::RS_SQLFreeStmt, Fail to free statement for internal use", 0, NULL);
return rc;
}
rc = RsMetadataAPIPostProcessing::sqlSchemasPostProcessing(phstmt, intermediateRS);
if(rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO){
RS_LOG_ERROR("RsMetadataAPIPostProcessing.sqlSchemasPostProcessing", "Fail call post-processing for SQLTables");
addError(&pStmt->pErrorList,"HY000", "RsMetadataAPIPostProcessing.sqlSchemasPostProcessing fail", 0, NULL);
return rc;
}
}
else
if(isNullOrEmptyString(pCatalogName) && isNullOrEmptyString(pSchemaName) && isNullOrEmptyString(pTableName) && isSqlAllTableTypes(pTableType, cbTableType))
{
// Special SQLTables call : get table type list
rc = RsMetadataAPIPostProcessing::sqlTableTypesPostProcessing(phstmt);
if(rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO){
RS_LOG_ERROR("RsMetadataAPIPostProcessing.sqlTableTypesPostProcessing", "Fail call post-processing for SQLTables");
addError(&pStmt->pErrorList,"HY000", "RsMetadataAPIPostProcessing.sqlTableTypesPostProcessing fail", 0, NULL);
return rc;
}
}
else{
// Normal SQLTables call
std::string catalogName = (isNullOrEmptyString(pCatalogName)) ? "" : char2String(pCatalogName);
std::string schemaName = (isNullOrEmptyString(pSchemaName)) ? "" : char2String(pSchemaName);
std::string tableName = (isNullOrEmptyString(pTableName)) ? "" : char2String(pTableName);
// Return Empty ResultSet if catalog or schemaPattern or tableNamePattern is empty string
//bool retEmpty = isEmptyString(pCatalogName) || isEmptyString(pSchemaName) || isEmptyString(pTableName); // comment this out since the Driver will still accept empty string for now
bool retEmpty = false; // Map empty string to wildcard internally but will block them in the near future
SQLHSTMT internalStmt;
rc = RS_CONN_INFO::RS_SQLAllocStmt(pStmt->phdbc, &internalStmt);
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
RS_LOG_ERROR("RS_CONN_INFO::RS_SQLAllocStmt", "Fail to allocate new statement for internal use");
addError(&pStmt->pErrorList, "HY000", "RS_CONN_INFO::RS_SQLAllocStmt, Fail to allocate new statement for internal use", 0, NULL);
return rc;
}
std::vector<SHOWTABLESResult> intermediateRS;
rc = RsMetadataServerAPIHelper::sqlTablesServerAPI(internalStmt, catalogName, schemaName, tableName, retEmpty, intermediateRS, isSingleDatabaseMetaData(pStmt));
if(rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO){
RS_LOG_ERROR("RsMetadataServerAPIHelper.sqlTablesServerAPI", "Fail get intermediate result set for SQLTables");
addError(&pStmt->pErrorList,"HY000", "RsMetadataServerAPIHelper.sqlTablesServerAPI fail", 0, NULL);
return rc;
}
rc = RS_STMT_INFO::RS_SQLFreeStmt(internalStmt,SQL_DROP, TRUE);
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
RS_LOG_ERROR("RS_STMT_INFO::RS_SQLFreeStmt", "Fail to free statement for internal use");
addError(&pStmt->pErrorList, "HY000", "RS_STMT_INFO::RS_SQLFreeStmt, Fail to free statement for internal use", 0, NULL);
return rc;
}
std::string table_type = (!pTableType) ? "" : char2String(pTableType);
rc = RsMetadataAPIPostProcessing::sqlTablesPostProcessing(phstmt, table_type, retEmpty, intermediateRS);
if(rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO){
RS_LOG_ERROR("RsMetadataAPIPostProcessing.sqlTablesPostProcessing", "Fail call post-processing for SQLTables");
addError(&pStmt->pErrorList,"HY000", "RsMetadataAPIPostProcessing.sqlTablesPostProcessing fail", 0, NULL);
return rc;
}
}
}
else{
// Old code path is retained for supporting legacy cluster version which doesn't not support Server API SHOW command
char szCatalogQuery[MAX_CATALOG_QUERY_LEN];
if (isNullOrEmptyString(pSchemaName) && isNullOrEmptyString(pTableName) && isSqlAllCatalogs(pCatalogName, cbCatalogName))
{
if (isSingleDatabaseMetaData(pStmt))
rs_strncpy(szCatalogQuery, SQLTABLES_ALL_CATALOG_QUERY, sizeof(szCatalogQuery));
else
rs_strncpy(szCatalogQuery, SQLTABLES_ALL_CATALOG_QUERY_DATASHARE, sizeof(szCatalogQuery));
}
else
if(isNullOrEmptyString(pCatalogName) && isNullOrEmptyString(pTableName) && isSqlAllSchemas(pSchemaName, cbSchemaName))
{
if (isSingleDatabaseMetaData(pStmt))
rs_strncpy(szCatalogQuery, SQLTABLES_ALL_SCHEMAS_QUERY, sizeof(szCatalogQuery));
else
rs_strncpy(szCatalogQuery, SQLTABLES_ALL_SCHEMAS_QUERY_DATASHARE, sizeof(szCatalogQuery));
}
else
if(isNullOrEmptyString(pCatalogName) && isNullOrEmptyString(pSchemaName) && isNullOrEmptyString(pTableName) && isSqlAllTableTypes(pTableType, cbTableType))
{
rs_strncpy(szCatalogQuery, SQLTABLES_ALL_TABLE_TYPES_QUERY, sizeof(szCatalogQuery));
}
else
{
int schemaPatternType = getExtSchemaPatternMatch(pStmt, pSchemaName, cbSchemaName);
if (schemaPatternType == LOCAL_SCHEMA_QUERY)
{
// Join on pg_catalog
buildLocalSchemaTablesQuery(szCatalogQuery, pStmt,
pCatalogName,
cbCatalogName,
pSchemaName,
cbSchemaName,
pTableName,
cbTableName,
pTableType,
cbTableType);
}
else if (schemaPatternType == NO_SCHEMA_UNIVERSAL_QUERY)
{
if (isSingleDatabaseMetaData(pStmt))
{
// svv_tables
buildUniversalSchemaTablesQuery(szCatalogQuery, pStmt,
pCatalogName,
cbCatalogName,
pSchemaName,
cbSchemaName,
pTableName,
cbTableName,
pTableType,
cbTableType);
}
else {
// svv_all_tables
buildUniversalAllSchemaTablesQuery(szCatalogQuery, pStmt,
pCatalogName,
cbCatalogName,
pSchemaName,
cbSchemaName,
pTableName,
cbTableName,
pTableType,
cbTableType);
}
}
else if (schemaPatternType == EXTERNAL_SCHEMA_QUERY) {
// svv_external_tables
buildExternalSchemaTablesQuery(szCatalogQuery, pStmt,
pCatalogName,
cbCatalogName,
pSchemaName,
cbSchemaName,
pTableName,
cbTableName,
pTableType,
cbTableType);
}
}
setCatalogQueryBuf(pStmt, szCatalogQuery);
rc = RsExecute::RS_SQLExecDirect(phstmt, (SQLCHAR *)szCatalogQuery, SQL_NTS, TRUE, FALSE, FALSE, TRUE);
resetCatalogQueryFlag(pStmt);
}
return rc;
}