diff --git a/dsn/odbc_dsn.c b/dsn/odbc_dsn.c index d542db18..e482a150 100644 --- a/dsn/odbc_dsn.c +++ b/dsn/odbc_dsn.c @@ -92,6 +92,7 @@ MADB_DsnMap DsnMap[] = { {&DsnKeys[32], 4, cbTls11, 1, 0}, {&DsnKeys[32], 4, cbTls12, 2, 0}, {&DsnKeys[32], 4, cbTls13, 4, 0}, + {&DsnKeys[33], 4, cbForceTls, 0, 0}, {NULL, 0, 0, 0, 0} }; diff --git a/dsn/odbc_dsn.rc b/dsn/odbc_dsn.rc index fa8d9528..8e36b435 100644 --- a/dsn/odbc_dsn.rc +++ b/dsn/odbc_dsn.rc @@ -190,7 +190,9 @@ BEGIN LTEXT "Cipher",IDC_STATIC,15,76,56,8,0,WS_EX_TRANSPARENT EDITTEXT txtSslCipher,84,76,110,10,ES_AUTOHSCROLL - CONTROL "Verify Certificate",cbSslVerify,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,84,90,97,10,WS_EX_TRANSPARENT + CONTROL "Verify Certificate",cbSslVerify,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,90,68,10,WS_EX_TRANSPARENT + + CONTROL "Force TLS Use",cbForceTls,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,84,90,97,10,WS_EX_TRANSPARENT LTEXT "Allowed TLS versions(Not checking any means that all are allowed)",IDC_STATIC,15,104,264,8,0,WS_EX_TRANSPARENT CONTROL "v.1.1",cbTls11,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,115,30,10,WS_EX_TRANSPARENT diff --git a/dsn/resource.h b/dsn/resource.h index d36658d8..9044fa23 100644 Binary files a/dsn/resource.h and b/dsn/resource.h differ diff --git a/ma_connection.c b/ma_connection.c index 2380e019..8251fab9 100644 --- a/ma_connection.c +++ b/ma_connection.c @@ -352,7 +352,7 @@ SQLRETURN MADB_DbcGetAttr(MADB_Dbc *Dbc, SQLINTEGER Attribute, SQLPOINTER ValueP *(SQLUINTEGER *)ValuePtr= 0; break; case SQL_ATTR_METADATA_ID: - *(SQLINTEGER *)ValuePtr= Dbc->MetadataId; + *(SQLUINTEGER *)ValuePtr= Dbc->MetadataId; case SQL_ATTR_ODBC_CURSORS: *(SQLINTEGER *)ValuePtr= SQL_CUR_USE_ODBC; break; @@ -601,7 +601,7 @@ SQLRETURN MADB_DbcConnectDB(MADB_Dbc *Connection, if( !MADB_IS_EMPTY(Dsn->ConnCPluginsDir)) { - mysql_options(Connection->mariadb, MYSQL_PLUGIN_DIR, Dsn->ConnCPluginsDir); + mysql_optionsv(Connection->mariadb, MYSQL_PLUGIN_DIR, Dsn->ConnCPluginsDir); } else { @@ -649,24 +649,21 @@ SQLRETURN MADB_DbcConnectDB(MADB_Dbc *Connection, } /* todo: error handling */ - mysql_options(Connection->mariadb, MYSQL_SET_CHARSET_NAME, Connection->Charset.cs_info->csname); + mysql_optionsv(Connection->mariadb, MYSQL_SET_CHARSET_NAME, Connection->Charset.cs_info->csname); if (Dsn->InitCommand && Dsn->InitCommand[0]) - mysql_options(Connection->mariadb, MYSQL_INIT_COMMAND, Dsn->InitCommand); + mysql_optionsv(Connection->mariadb, MYSQL_INIT_COMMAND, Dsn->InitCommand); if (Dsn->ConnectionTimeout) - mysql_options(Connection->mariadb, MYSQL_OPT_CONNECT_TIMEOUT, (const char *)&Dsn->ConnectionTimeout); + mysql_optionsv(Connection->mariadb, MYSQL_OPT_CONNECT_TIMEOUT, (const char *)&Dsn->ConnectionTimeout); Connection->Options= Dsn->Options; - /* TODO: set DSN FLags (Options): - Some of them (like reconnect) can be set via mysql_options, some of them are connection - attributes - */ + if (DSN_OPTION(Connection, MADB_OPT_FLAG_AUTO_RECONNECT)) - mysql_options(Connection->mariadb, MYSQL_OPT_RECONNECT, &my_reconnect); + mysql_optionsv(Connection->mariadb, MYSQL_OPT_RECONNECT, &my_reconnect); if (Dsn->IsNamedPipe) /* DSN_OPTION(Connection, MADB_OPT_FLAG_NAMED_PIPE) */ - mysql_options(Connection->mariadb, MYSQL_OPT_NAMED_PIPE, (void *)Dsn->ServerName); + mysql_optionsv(Connection->mariadb, MYSQL_OPT_NAMED_PIPE, (void *)Dsn->ServerName); if (DSN_OPTION(Connection, MADB_OPT_FLAG_NO_SCHEMA)) client_flags|= CLIENT_NO_SCHEMA; @@ -681,12 +678,12 @@ SQLRETURN MADB_DbcConnectDB(MADB_Dbc *Connection, client_flags|= CLIENT_MULTI_STATEMENTS; /* enable truncation reporting */ - mysql_options(Connection->mariadb, MYSQL_REPORT_DATA_TRUNCATION, &ReportDataTruncation); + mysql_optionsv(Connection->mariadb, MYSQL_REPORT_DATA_TRUNCATION, &ReportDataTruncation); if (Dsn->Socket) { int protocol= MYSQL_PROTOCOL_SOCKET; - mysql_options(Connection->mariadb, MYSQL_OPT_PROTOCOL, (void*)&protocol); + mysql_optionsv(Connection->mariadb, MYSQL_OPT_PROTOCOL, (void*)&protocol); } { @@ -756,19 +753,24 @@ SQLRETURN MADB_DbcConnectDB(MADB_Dbc *Connection, if (Dsn->SslVerify) { const unsigned int verify= 0x01010101; - mysql_options(Connection->mariadb, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, (const char*)&verify); + mysql_optionsv(Connection->mariadb, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, (const char*)&verify); } else { const unsigned int verify= 0; - mysql_options(Connection->mariadb, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, (const char*)&verify); + mysql_optionsv(Connection->mariadb, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, (const char*)&verify); } } + if (Dsn->ForceTls != '\0') + { + const unsigned int ForceTls= 0x01010101; + mysql_optionsv(Connection->mariadb, MYSQL_OPT_SSL_ENFORCE, (const char*)&ForceTls); + } if (!MADB_IS_EMPTY(Dsn->SslCrlPath)) { - mysql_options(Connection->mariadb, MYSQL_OPT_SSL_CRLPATH, Dsn->SslCrlPath); + mysql_optionsv(Connection->mariadb, MYSQL_OPT_SSL_CRLPATH, Dsn->SslCrlPath); } if (!mysql_real_connect(Connection->mariadb, diff --git a/ma_dsn.c b/ma_dsn.c index 10271b57..dfc305a4 100644 --- a/ma_dsn.c +++ b/ma_dsn.c @@ -68,6 +68,7 @@ MADB_DsnKey DsnKeys[]= {"SAVEFILE", offsetof(MADB_Dsn, SaveFile), DSN_TYPE_STRING, 0, 0}, /* 30 */ {"USE_MYCNF", offsetof(MADB_Dsn, ReadMycnf), DSN_TYPE_OPTION, MADB_OPT_FLAG_USE_CNF, 0}, {"TLSVERSION", offsetof(MADB_Dsn, TlsVersion), DSN_TYPE_CBOXGROUP, 0, 0}, + {"FORCETLS", offsetof(MADB_Dsn, ForceTls), DSN_TYPE_BOOL, 0, 0}, /* Aliases. Here offset is index of aliased key */ {"SERVERNAME", DSNKEY_SERVER_INDEX, DSN_TYPE_STRING, 0, 1}, {"USER", DSNKEY_UID_INDEX, DSN_TYPE_STRING, 0, 1}, diff --git a/ma_dsn.h b/ma_dsn.h index 6d427fd7..bffb4e5e 100644 --- a/ma_dsn.h +++ b/ma_dsn.h @@ -131,6 +131,7 @@ typedef struct st_madb_dsn char *SslFpList; my_bool SslVerify; char TlsVersion; + my_bool ForceTls; char *SaveFile; my_bool ReadMycnf; /* --- Internal --- */ diff --git a/ma_odbc.h b/ma_odbc.h index f301297a..ba083868 100644 --- a/ma_odbc.h +++ b/ma_odbc.h @@ -237,7 +237,7 @@ typedef struct void* BookmarkPtr; SQLLEN BookmarkLength; SQLSMALLINT BookmarkType; - SQLUINTEGER MetadataId; + SQLULEN MetadataId; SQLULEN SimulateCursor; } MADB_StmtOptions; diff --git a/ma_statement.c b/ma_statement.c index 691ca8ca..c25bdf77 100644 --- a/ma_statement.c +++ b/ma_statement.c @@ -50,6 +50,7 @@ SQLRETURN MADB_StmtInit(MADB_Dbc *Connection, SQLHANDLE *pHStmt) /* default behaviour is SQL_CURSOR_STATIC */ Stmt->Options.CursorType= SQL_CURSOR_STATIC; Stmt->Options.UseBookmarks= SQL_UB_OFF; + Stmt->Options.MetadataId= Connection->MetadataId; Stmt->Apd= Stmt->IApd; Stmt->Ard= Stmt->IArd; @@ -2441,7 +2442,7 @@ SQLRETURN MADB_StmtSetAttr(MADB_Stmt *Stmt, SQLINTEGER Attribute, SQLPOINTER Val Stmt->Options.MaxRows= (SQLULEN)ValuePtr; break; case SQL_ATTR_METADATA_ID: - Stmt->Options.MetadataId=(SQLUINTEGER)(SQLULEN)ValuePtr; + Stmt->Options.MetadataId= (SQLULEN)ValuePtr; break; case SQL_ATTR_NOSCAN: if ((SQLULEN)ValuePtr != SQL_NOSCAN_ON) @@ -3339,12 +3340,12 @@ SQLRETURN MADB_StmtTablePrivileges(MADB_Stmt *Stmt, char *CatalogName, SQLSMALLI /* }}} */ /* {{{ MADB_StmtTables */ -SQLRETURN MADB_StmtTables(MADB_Stmt *Stmt, char *CatalogName, SQLSMALLINT NameLength1, - char *SchemaName, SQLSMALLINT NameLength2, char *TableName, - SQLSMALLINT NameLength3, char *TableType, SQLSMALLINT NameLength4) +SQLRETURN MADB_StmtTables(MADB_Stmt *Stmt, char *CatalogName, SQLSMALLINT CatalogNameLength, + char *SchemaName, SQLSMALLINT SchemaNameLength, char *TableName, + SQLSMALLINT TableNameLength, char *TableType, SQLSMALLINT TableTypeLength) { MADB_DynString StmtStr; - char Quote[2]; + char Quote[2]; SQLRETURN ret; /* @@ -3360,11 +3361,12 @@ SQLRETURN MADB_StmtTables(MADB_Stmt *Stmt, char *CatalogName, SQLSMALLINT NameLe MDBUG_C_ENTER(Stmt->Connection, "MADB_StmtTables"); - ADJUST_LENGTH(CatalogName, NameLength1); - ADJUST_LENGTH(TableName, NameLength3); - ADJUST_LENGTH(TableType, NameLength4); + ADJUST_LENGTH(CatalogName, CatalogNameLength); + ADJUST_LENGTH(SchemaName, SchemaNameLength); + ADJUST_LENGTH(TableName, TableNameLength); + ADJUST_LENGTH(TableType, TableTypeLength); - if (NameLength1 > 64 || NameLength3 > 64) + if (CatalogNameLength > 64 || TableNameLength > 64) { MADB_SetError(&Stmt->Error, MADB_ERR_HY090, "Table and catalog names are limited to 64 chars", 0); return Stmt->Error.ReturnValue; @@ -3375,7 +3377,8 @@ SQLRETURN MADB_StmtTables(MADB_Stmt *Stmt, char *CatalogName, SQLSMALLINT NameLe the result set contains a list of valid catalogs for the data source. (All columns except the TABLE_CAT column contain NULLs */ - if (CatalogName && NameLength1 && !NameLength3 && !strcmp(CatalogName, SQL_ALL_TABLE_TYPES)) + if (CatalogName && CatalogNameLength && TableName != NULL && !TableNameLength && + SchemaName != NULL && SchemaNameLength == 0 && !strcmp(CatalogName, SQL_ALL_CATALOGS)) { MADB_InitDynamicString(&StmtStr, "SELECT SCHEMA_NAME AS TABLE_CAT, CONVERT(NULL,CHAR(64)) AS TABLE_SCHEM, " "CONVERT(NULL,CHAR(64)) AS TABLE_NAME, NULL AS TABLE_TYPE, NULL AS REMARKS " @@ -3388,7 +3391,8 @@ SQLRETURN MADB_StmtTables(MADB_Stmt *Stmt, char *CatalogName, SQLSMALLINT NameLe the result set contains a list of valid table types for the data source. (All columns except the TABLE_TYPE column contain NULLs.) */ - else if (!NameLength1 && !NameLength3 && TableType && NameLength4 && + else if (CatalogName != NULL && !CatalogNameLength && TableName != NULL && !TableNameLength && + SchemaName != NULL && SchemaNameLength == 0 && TableType && TableTypeLength && !strcmp(TableType, SQL_ALL_TABLE_TYPES)) { MADB_InitDynamicString(&StmtStr, "SELECT NULL AS TABLE_CAT, NULL AS TABLE_SCHEM, " @@ -3400,6 +3404,16 @@ SQLRETURN MADB_StmtTables(MADB_Stmt *Stmt, char *CatalogName, SQLSMALLINT NameLe "SELECT NULL, NULL, NULL, 'SYSTEM VIEW', NULL FROM DUAL", 8192, 512); } + /* Since we treat our databases as catalogs, the only acceptable value for schema is NULL or "%" + if that is not the special case of call for schemas list. Otherwise we return empty resultset*/ + else if (SchemaName && + (!strcmp(SchemaName,SQL_ALL_SCHEMAS) && CatalogName && CatalogNameLength == 0 && TableName && TableNameLength == 0 || + strcmp(SchemaName, SQL_ALL_SCHEMAS))) + { + MADB_InitDynamicString(&StmtStr, "SELECT NULL AS TABLE_CAT, NULL AS TABLE_SCHEM, " + "NULL AS TABLE_NAME, NULL AS TABLE_TYPE, NULL AS REMARKS " + "FROM DUAL WHERE 1=0", 8192, 512); + } else { MADB_InitDynamicString(&StmtStr, "SELECT TABLE_SCHEMA AS TABLE_CAT, NULL AS TABLE_SCHEM, TABLE_NAME, " @@ -3407,29 +3421,31 @@ SQLRETURN MADB_StmtTables(MADB_Stmt *Stmt, char *CatalogName, SQLSMALLINT NameLe "TABLE_COMMENT AS REMARKS FROM INFORMATION_SCHEMA.TABLES WHERE 1=1 ", 8192, 512); if (Stmt->Options.MetadataId== SQL_TRUE) + { strcpy(Quote, "`"); + } else + { strcpy(Quote, "'"); + } - MADB_DynstrAppend(&StmtStr, " AND TABLE_SCHEMA "); - if (CatalogName && NameLength1) + if (CatalogName) { + MADB_DynstrAppend(&StmtStr, " AND TABLE_SCHEMA "); MADB_DynstrAppend(&StmtStr, "LIKE "); MADB_DynstrAppend(&StmtStr, Quote); MADB_DynstrAppend(&StmtStr, CatalogName); MADB_DynstrAppend(&StmtStr, Quote); } - else - MADB_DynstrAppend(&StmtStr, "= DATABASE() "); - if (TableName && NameLength3) + if (TableName && TableNameLength) { MADB_DynstrAppend(&StmtStr, " AND TABLE_NAME LIKE "); MADB_DynstrAppend(&StmtStr, Quote); MADB_DynstrAppend(&StmtStr, TableName); MADB_DynstrAppend(&StmtStr, Quote); } - if (TableType && NameLength4 && strcmp(TableType, SQL_ALL_TABLE_TYPES) != 0) + if (TableType && TableTypeLength && strcmp(TableType, SQL_ALL_TABLE_TYPES) != 0) { unsigned int i; char *myTypes[3]= {"TABLE", "VIEW", "SYNONYM"}; diff --git a/test/catalog1.c b/test/catalog1.c index a6bdb83e..f466e4d1 100644 --- a/test/catalog1.c +++ b/test/catalog1.c @@ -76,155 +76,141 @@ ODBC_TEST(my_drop_table) ODBC_TEST(my_table_dbs) { - SQLCHAR database[100]; - SQLRETURN rc; - SQLINTEGER nrows= 0 ; - SQLLEN lenOrNull, rowCount= 0; - - diag("fix me"); - return SKIP; + SQLCHAR database[100]; + SQLRETURN rc; + SQLINTEGER nrows= 0 ; + SQLLEN lenOrNull, rowCount= 0; - OK_SIMPLE_STMT(Stmt, "DROP DATABASE IF EXISTS my_all_db_test1"); - OK_SIMPLE_STMT(Stmt, "DROP DATABASE IF EXISTS my_all_db_test2"); - OK_SIMPLE_STMT(Stmt, "DROP DATABASE IF EXISTS my_all_db_test3"); - OK_SIMPLE_STMT(Stmt, "DROP DATABASE IF EXISTS my_all_db_test4"); + OK_SIMPLE_STMT(Stmt, "DROP DATABASE IF EXISTS my_all_db_test1"); + OK_SIMPLE_STMT(Stmt, "DROP DATABASE IF EXISTS my_all_db_test2"); + OK_SIMPLE_STMT(Stmt, "DROP DATABASE IF EXISTS my_all_db_test3"); + OK_SIMPLE_STMT(Stmt, "DROP DATABASE IF EXISTS my_all_db_test4"); - /* This call caused problems when database names returned as '%' */ - CHECK_STMT_RC(Stmt, SQLTables(Stmt,(SQLCHAR*)SQL_ALL_CATALOGS,1,NULL,0,NULL,0,NULL,0)); + /* This call caused problems when database names returned as '%' */ + CHECK_STMT_RC(Stmt, SQLTables(Stmt,(SQLCHAR*)SQL_ALL_CATALOGS, 1, NULL, 0, NULL, 0, NULL, 0)); - while (SQLFetch(Stmt) == SQL_SUCCESS) - { - ++nrows; - CHECK_STMT_RC(Stmt, SQLGetData(Stmt, 1, SQL_C_CHAR, database, - sizeof(database), NULL)); - /* the table catalog in the results must not be '%' */ - FAIL_IF(database[0] == '%', "table catalog can't be '%'"); - } - /* we should have got rows... */ - FAIL_IF(nrows=0, "nrows should be > 0"); - - CHECK_STMT_RC(Stmt, SQLFreeStmt(Stmt, SQL_CLOSE)); + while (SQLFetch(Stmt) == SQL_SUCCESS) + { + ++nrows; + CHECK_STMT_RC(Stmt, SQLGetData(Stmt, 1, SQL_C_CHAR, database, + sizeof(database), NULL)); + /* the table catalog in the results must not be '%' */ + FAIL_IF(database[0] == '%', "table catalog can't be '%'"); + } + /* we should have got rows... */ + FAIL_IF(nrows == 0, "nrows should be > 0"); - CHECK_STMT_RC(Stmt, SQLTables(Stmt,(SQLCHAR *)SQL_ALL_CATALOGS,1,"",0,"",0,NULL,0)); + CHECK_STMT_RC(Stmt, SQLFreeStmt(Stmt, SQL_CLOSE)); - /* Added calls to SQLRowCount just to have tests of it with SQLTAbles. */ - CHECK_STMT_RC(Stmt, SQLRowCount(Stmt, &rowCount)); - nrows = my_print_non_format_result(Stmt); + CHECK_STMT_RC(Stmt, SQLTables(Stmt,(SQLCHAR *)SQL_ALL_CATALOGS, 1, "", 0, "", 0, NULL, 0)); - is_num(rowCount, nrows); - rc = SQLFreeStmt(Stmt, SQL_CLOSE); - CHECK_STMT_RC(Stmt,rc); + /* Added calls to SQLRowCount just to have tests of it with SQLTables. */ + CHECK_STMT_RC(Stmt, SQLRowCount(Stmt, &rowCount)); + nrows = my_print_non_format_result(Stmt); - rc = SQLTables(Stmt,(SQLCHAR *)SQL_ALL_CATALOGS,SQL_NTS,"",0,"",0, - NULL,0); - CHECK_STMT_RC(Stmt,rc); + is_num(rowCount, nrows); + CHECK_STMT_RC(Stmt, SQLFreeStmt(Stmt, SQL_CLOSE)); - is_num(nrows, my_print_non_format_result(Stmt)); - rc = SQLFreeStmt(Stmt, SQL_CLOSE); - CHECK_STMT_RC(Stmt,rc); + CHECK_STMT_RC(Stmt, SQLTables(Stmt,(SQLCHAR *)SQL_ALL_CATALOGS, SQL_NTS, "", 0, "", 0, + NULL, 0)); - rc = SQLTables(Stmt,(SQLCHAR *)my_schema,4,NULL,0,NULL,0,NULL,0); - CHECK_STMT_RC(Stmt,rc); + is_num(nrows, my_print_non_format_result(Stmt)); + CHECK_STMT_RC(Stmt, SQLFreeStmt(Stmt, SQL_CLOSE)); - CHECK_STMT_RC(Stmt, SQLRowCount(Stmt, &rowCount)); - is_num(rowCount, my_print_non_format_result(Stmt)); + CHECK_STMT_RC(Stmt, SQLTables(Stmt,(SQLCHAR *)my_schema, (SQLSMALLINT)strlen(my_schema), NULL, 0, NULL, 0, NULL, 0)); - rc = SQLFreeStmt(Stmt, SQL_CLOSE); - CHECK_STMT_RC(Stmt,rc); + CHECK_STMT_RC(Stmt, SQLRowCount(Stmt, &rowCount)); + is_num(rowCount, my_print_non_format_result(Stmt)); - /* test fails on Win2003 x86 w/DM if len=5, SQL_NTS is used instead */ - rc = SQLTables(Stmt,(SQLCHAR *)"mysql",SQL_NTS,NULL,0,NULL,0,NULL,0); - CHECK_STMT_RC(Stmt,rc); + CHECK_STMT_RC(Stmt, SQLFreeStmt(Stmt, SQL_CLOSE)); - FAIL_IF(my_print_non_format_result(Stmt) == 0, "0"); - rc = SQLFreeStmt(Stmt, SQL_CLOSE); - CHECK_STMT_RC(Stmt,rc); + /* test fails on Win2003 x86 w/DM if len=5, SQL_NTS is used instead */ + CHECK_STMT_RC(Stmt, SQLTables(Stmt,(SQLCHAR *)"mysql", SQL_NTS, NULL, 0, NULL, 0, NULL, 0)); - rc = SQLTables(Stmt,(SQLCHAR *)"%",1,"",0,"",0,NULL,0); - CHECK_STMT_RC(Stmt,rc); + FAIL_IF(my_print_non_format_result(Stmt) == 0, "0 tables returned for mysql"); + CHECK_STMT_RC(Stmt, SQLFreeStmt(Stmt, SQL_CLOSE)); - rc = SQLFetch(Stmt); - CHECK_STMT_RC(Stmt,rc); + CHECK_STMT_RC(Stmt, SQLTables(Stmt, (SQLCHAR *)"%", 1, "", 0, "", 0, NULL, 0)); - memset(database,0,100); - rc = SQLGetData(Stmt,1,SQL_C_CHAR,database,100,NULL); - CHECK_STMT_RC(Stmt,rc); - diag("catalog: %s", database); + CHECK_STMT_RC(Stmt, SQLFetch(Stmt)); - memset(database,0,100); - rc = SQLGetData(Stmt,2,SQL_C_CHAR,database,100,&lenOrNull); - CHECK_STMT_RC(Stmt,rc); - diag("schema: %s", database); - IS(lenOrNull == SQL_NULL_DATA); + memset(database,0,sizeof(database)); + rc = SQLGetData(Stmt,1,SQL_C_CHAR,database, (SQLLEN)sizeof(database),NULL); + CHECK_STMT_RC(Stmt,rc); + diag("catalog: %s", database); - memset(database,0,100); - rc = SQLGetData(Stmt,3,SQL_C_CHAR,database,100,&lenOrNull); - CHECK_STMT_RC(Stmt,rc); - diag("table: %s", database); -; + memset(database,0,sizeof(database)); + rc = SQLGetData(Stmt,2,SQL_C_CHAR,database, (SQLLEN)sizeof(database),&lenOrNull); + CHECK_STMT_RC(Stmt,rc); + diag("schema: %s", database); + IS(lenOrNull == SQL_NULL_DATA); - memset(database,0,100); - rc = SQLGetData(Stmt,4,SQL_C_CHAR,database,100,&lenOrNull); - CHECK_STMT_RC(Stmt,rc); - diag("type: %s", database); + memset(database,0,sizeof(database)); + rc = SQLGetData(Stmt,3,SQL_C_CHAR,database, (SQLLEN)sizeof(database),&lenOrNull); + CHECK_STMT_RC(Stmt,rc); + diag("table: %s", database); + memset(database,0,sizeof(database)); + rc = SQLGetData(Stmt,4,SQL_C_CHAR,database, (SQLLEN)sizeof(database),&lenOrNull); + CHECK_STMT_RC(Stmt,rc); + diag("type: %s", database); - memset(database,0,100); - rc = SQLGetData(Stmt,5,SQL_C_CHAR, database,100,&lenOrNull); - CHECK_STMT_RC(Stmt,rc); - diag("database remark: %s", database); + memset(database,0,sizeof(database)); + rc = SQLGetData(Stmt,5,SQL_C_CHAR, database, (SQLLEN)sizeof(database),&lenOrNull); + CHECK_STMT_RC(Stmt,rc); + diag("database remark: %s", database); - SQLFreeStmt(Stmt,SQL_UNBIND); - SQLFreeStmt(Stmt,SQL_CLOSE); + SQLFreeStmt(Stmt,SQL_UNBIND); + SQLFreeStmt(Stmt,SQL_CLOSE); - OK_SIMPLE_STMT(Stmt, "CREATE DATABASE my_all_db_test1"); - OK_SIMPLE_STMT(Stmt, "CREATE DATABASE my_all_db_test2"); - OK_SIMPLE_STMT(Stmt, "CREATE DATABASE my_all_db_test3"); - OK_SIMPLE_STMT(Stmt, "CREATE DATABASE my_all_db_test4"); + OK_SIMPLE_STMT(Stmt, "CREATE DATABASE my_all_db_test1"); + OK_SIMPLE_STMT(Stmt, "CREATE DATABASE my_all_db_test2"); + OK_SIMPLE_STMT(Stmt, "CREATE DATABASE my_all_db_test3"); + OK_SIMPLE_STMT(Stmt, "CREATE DATABASE my_all_db_test4"); - rc = SQLTables(Stmt, (SQLCHAR *)SQL_ALL_CATALOGS, 1, "", 0, "", 0, "", 0); - CHECK_STMT_RC(Stmt,rc); + rc = SQLTables(Stmt, (SQLCHAR *)SQL_ALL_CATALOGS, 1, "", 0, "", 0, "", 0); + CHECK_STMT_RC(Stmt,rc); - nrows += 4; - is_num(nrows, my_print_non_format_result(Stmt)); - rc = SQLFreeStmt(Stmt, SQL_CLOSE); - CHECK_STMT_RC(Stmt,rc); + nrows += 4; + is_num(nrows, my_print_non_format_result(Stmt)); + rc = SQLFreeStmt(Stmt, SQL_CLOSE); + CHECK_STMT_RC(Stmt,rc); - rc = SQLTables(Stmt,(SQLCHAR *)SQL_ALL_CATALOGS, SQL_NTS, - "", 0, "", 0, "", 0); - CHECK_STMT_RC(Stmt,rc); + rc = SQLTables(Stmt,(SQLCHAR *)SQL_ALL_CATALOGS, SQL_NTS, + "", 0, "", 0, "", 0); + CHECK_STMT_RC(Stmt,rc); - is_num(my_print_non_format_result(Stmt), nrows); - rc = SQLFreeStmt(Stmt, SQL_CLOSE); - CHECK_STMT_RC(Stmt,rc); + is_num(my_print_non_format_result(Stmt), nrows); + rc = SQLFreeStmt(Stmt, SQL_CLOSE); + CHECK_STMT_RC(Stmt,rc); - rc = SQLTables(Stmt, (SQLCHAR *)"my_all_db_test", SQL_NTS, - "", 0, "", 0, "", 0); - CHECK_STMT_RC(Stmt,rc); + rc = SQLTables(Stmt, (SQLCHAR *)"my_all_db_test", SQL_NTS, + "", 0, "", 0, "", 0); + CHECK_STMT_RC(Stmt,rc); - CHECK_STMT_RC(Stmt, SQLRowCount(Stmt, &rowCount)); - is_num(rowCount, 0); + CHECK_STMT_RC(Stmt, SQLRowCount(Stmt, &rowCount)); + is_num(rowCount, 0); - is_num(my_print_non_format_result(Stmt), 0); - rc = SQLFreeStmt(Stmt, SQL_CLOSE); - CHECK_STMT_RC(Stmt,rc); + is_num(my_print_non_format_result(Stmt), 0); + rc = SQLFreeStmt(Stmt, SQL_CLOSE); + CHECK_STMT_RC(Stmt,rc); - rc = SQLTables(Stmt, (SQLCHAR *)"my_all_db_test%", SQL_NTS, - "", 0, "", 0, NULL, 0); - CHECK_STMT_RC(Stmt,rc); - CHECK_STMT_RC(Stmt, SQLRowCount(Stmt, &rowCount)); - is_num(my_print_non_format_result(Stmt), 4); - rc = SQLFreeStmt(Stmt, SQL_CLOSE); - CHECK_STMT_RC(Stmt,rc); + rc = SQLTables(Stmt, (SQLCHAR *)"my_all_db_test%", SQL_NTS, + "", 0, "", 0, NULL, 0); + CHECK_STMT_RC(Stmt,rc); + CHECK_STMT_RC(Stmt, SQLRowCount(Stmt, &rowCount)); + is_num(my_print_non_format_result(Stmt), 0); /* MySQL's driver returns 4 rows for matching DB's here. + But I don't think it's in accordance with specs. And MSSQL driver + does not do that */ + CHECK_STMT_RC(Stmt, SQLFreeStmt(Stmt, SQL_CLOSE)); - /* unknown table should be empty */ - rc = SQLTables(Stmt, (SQLCHAR *)"my_all_db_test%", SQL_NTS, - NULL, 0, (SQLCHAR *)"xyz", SQL_NTS, NULL, 0); - CHECK_STMT_RC(Stmt,rc); + /* unknown table should be empty */ + rc = SQLTables(Stmt, (SQLCHAR *)"my_all_db_test%", SQL_NTS, + NULL, 0, (SQLCHAR *)"xyz", SQL_NTS, NULL, 0); + CHECK_STMT_RC(Stmt,rc); - is_num(my_print_non_format_result(Stmt), 0); - rc = SQLFreeStmt(Stmt, SQL_CLOSE); - CHECK_STMT_RC(Stmt,rc); + is_num(my_print_non_format_result(Stmt), 0); + CHECK_STMT_RC(Stmt, SQLFreeStmt(Stmt, SQL_CLOSE)); OK_SIMPLE_STMT(Stmt, "DROP DATABASE my_all_db_test1"); OK_SIMPLE_STMT(Stmt, "DROP DATABASE my_all_db_test2"); @@ -755,14 +741,20 @@ ODBC_TEST(tmysql_showkeys) ODBC_TEST(t_sqltables) { - SQLINTEGER rows; - SQLLEN rowCount; + SQLLEN rowCount, LenInd; SQLHDBC hdbc1; SQLHSTMT Stmt1; + int AllTablesCount= 0, Rows; + SQLCHAR Buffer[64]; + + if (!SQL_SUCCEEDED(SQLExecDirect(Stmt, "DROP SCHEMA IF EXISTS mariadbodbc_sqltables", SQL_NTS))) + { + odbc_print_error(SQL_HANDLE_STMT, Stmt); + } - if (!SQL_SUCCEEDED(SQLExecDirect(Stmt, "DROP SCHEMA IF EXISTS mariadbodbc_sqltables", SQL_NTS)) - || !SQL_SUCCEEDED(SQLExecDirect(Stmt, "CREATE SCHEMA mariadbodbc_sqltables", SQL_NTS))) + if (!SQL_SUCCEEDED(SQLExecDirect(Stmt, "CREATE SCHEMA mariadbodbc_sqltables", SQL_NTS))) { + odbc_print_error(SQL_HANDLE_STMT, Stmt); skip("Test user has no rights to drop/create databases"); } @@ -771,12 +763,27 @@ ODBC_TEST(t_sqltables) FAIL_IF(Stmt1 == NULL, ""); OK_SIMPLE_STMT(Stmt1, "CREATE TABLE t1 (a int)"); - OK_SIMPLE_STMT(Stmt1, "CREATE TABLE t2 LIKE t1"); - OK_SIMPLE_STMT(Stmt1, "CREATE TABLE t3 LIKE t1"); + OK_SIMPLE_STMT(Stmt1, "CREATE TABLE t2 (a int)"); + OK_SIMPLE_STMT(Stmt1, "CREATE TABLE t3 (a int)"); CHECK_STMT_RC(Stmt1, SQLTables(Stmt1, NULL, 0, NULL, 0, NULL, 0, NULL, 0)); - myrowcount(Stmt1); + AllTablesCount= myrowcount(Stmt1); + FAIL_IF(AllTablesCount <= 3, "There should be more than 3 tables"); /* 3 tables in current db */ + + CHECK_STMT_RC(Stmt1, SQLFreeStmt(Stmt1, SQL_CLOSE)); + + CHECK_STMT_RC(Stmt1, SQLTables(Stmt1, (SQLCHAR *)"%", SQL_NTS, NULL, 0, NULL, 0, NULL, 0)); + + Rows= 0; + while (SQLFetch(Stmt1) != SQL_NO_DATA_FOUND) + { + ++Rows; + CHECK_STMT_RC(Stmt1, SQLGetData(Stmt1, 3, SQL_C_CHAR, Buffer, sizeof(Buffer), &LenInd)); + FAIL_IF(LenInd == SQL_NULL_DATA, "Table Name should not be NULL") + } + /* % catalog should give the same result as NULL. May fail if any table added/dropped between calls */ + is_num(Rows, AllTablesCount); CHECK_STMT_RC(Stmt1, SQLFreeStmt(Stmt1, SQL_CLOSE)); @@ -789,38 +796,29 @@ ODBC_TEST(t_sqltables) CHECK_STMT_RC(Stmt1, SQLTables(Stmt1, NULL, 0, NULL, 0, NULL, 0, (SQLCHAR *)"TABLE", SQL_NTS)); + Rows= my_print_non_format_result_ex(Stmt1, FALSE); CHECK_STMT_RC(Stmt1, SQLRowCount(Stmt1, &rowCount)); - is_num(myrowcount(Stmt1), rowCount); - + is_num(Rows, rowCount); CHECK_STMT_RC(Stmt1, SQLFreeStmt(Stmt1, SQL_CLOSE)); - CHECK_STMT_RC(Stmt1,SQLTables(Stmt1, (SQLCHAR *)"TEST", SQL_NTS, + CHECK_STMT_RC(Stmt1, SQLTables(Stmt1, (SQLCHAR *)"TEST", SQL_NTS, (SQLCHAR *)"TEST", SQL_NTS, NULL, 0, (SQLCHAR *)"TABLE", SQL_NTS)); - myrowcount(Stmt1); - - CHECK_STMT_RC(Stmt1, SQLFreeStmt(Stmt1, SQL_CLOSE)); - - CHECK_STMT_RC(Stmt1, SQLTables(Stmt1, (SQLCHAR *)"%", SQL_NTS, NULL, 0, NULL, 0, NULL, 0)); - - myrowcount(Stmt1); - - CHECK_STMT_RC(Stmt1, SQLFreeStmt(Stmt1, SQL_CLOSE)); + is_num(my_print_non_format_result(Stmt1), 0); CHECK_STMT_RC(Stmt1, SQLTables(Stmt1, NULL, 0, (SQLCHAR *)"%", SQL_NTS, NULL, 0, NULL, 0)); - myrowcount(Stmt1); + diag("all schemas %d", myrowcount(Stmt1)); CHECK_STMT_RC(Stmt1, SQLFreeStmt(Stmt1, SQL_CLOSE)); + /* List of table types - table, view, system view */ CHECK_STMT_RC(Stmt1, SQLTables(Stmt1, "", 0, "", 0, "", 0, (SQLCHAR *)"%", SQL_NTS)); - rows= myrowcount(Stmt1); - is_num(rows, 3); - - CHECK_STMT_RC(Stmt1, SQLFreeStmt(Stmt1, SQL_CLOSE)); + is_num(my_print_non_format_result(Stmt1), 3); + /* my_print_non_format_result closes cursor by default */ OK_SIMPLE_STMT(Stmt, "DROP SCHEMA mariadbodbc_sqltables"); @@ -862,14 +860,14 @@ ODBC_TEST(my_information_schema) SQL_DRIVER_NOPROMPT)); CHECK_DBC_RC(Connection1, SQLAllocStmt(Connection1, &Stmt1)); - rc = SQLTables(Stmt1, "istest__", SQL_NTS, "", 0, "istab%", SQL_NTS, NULL, 0); + rc = SQLTables(Stmt1, "istest__", SQL_NTS, NULL, 0, "istab%", SQL_NTS, NULL, 0); CHECK_STMT_RC(Stmt1,rc); /* all tables from all databases should be displayed */ is_num(my_print_non_format_result(Stmt1), 3); rc = SQLFreeStmt(Stmt1, SQL_CLOSE); - rc = SQLTables(Stmt1, NULL, 0, NULL, 0, "istab%", SQL_NTS, NULL, 0); + rc = SQLTables(Stmt1, "istest\\_\\_", SQL_NTS, NULL, 0, "istab%", SQL_NTS, NULL, 0); CHECK_STMT_RC(Stmt1,rc); is_num(my_print_non_format_result(Stmt1), 1); @@ -999,7 +997,7 @@ ODBC_TEST(empty_set) /* SQLTables(): empty catalog with existing table */ OK_SIMPLE_STMT(Stmt, "drop table if exists t_sqltables_empty"); OK_SIMPLE_STMT(Stmt, "create table t_sqltables_empty (x int)"); - CHECK_STMT_RC(Stmt, SQLTables(Stmt, "", SQL_NTS, NULL, 0, + CHECK_STMT_RC(Stmt, SQLTables(Stmt, NULL, SQL_NTS, NULL, 0, (SQLCHAR *) "t_sqltables_empty", SQL_NTS, NULL, SQL_NTS)); CHECK_STMT_RC(Stmt, SQLNumResultCols(Stmt, &columns)); diff --git a/test/tap.h b/test/tap.h index 4c663706..a4d9d56b 100644 --- a/test/tap.h +++ b/test/tap.h @@ -208,7 +208,7 @@ void mark_all_tests_normal(MA_ODBC_TESTS *tests) } -void usage() +void Usage() { fprintf(stdout, "Valid options:\n"); fprintf(stdout, "-d DSN Name\n"); @@ -218,6 +218,7 @@ void usage() fprintf(stdout, "-s default database (schema)\n"); fprintf(stdout, "-S Server name/address\n"); fprintf(stdout, "-P Port number\n"); + fprintf(stdout, "-o Use only DSN for the connection"); fprintf(stdout, "? Displays this text\n"); } @@ -271,7 +272,7 @@ void get_options(int argc, char **argv) { if (argv[i][0] != '-' || argv[i][1] == 0 || argc == i + 1) { - usage(); + Usage(); exit(0); } @@ -297,13 +298,17 @@ void get_options(int argc, char **argv) case 'D': my_drivername= (SQLCHAR*)argv[i+1]; break; + case 'o': + UseDsnOnly= TRUE; + --i; /* -o doesn't have value, thus we need to decrement argument index so we do not miss next option */ + break; case '?': - usage(); + Usage(); exit(0); break; default: fprintf(stdout, "Unknown option %c\n", argv[i][1]); - usage(); + Usage(); exit(0); } } @@ -561,7 +566,7 @@ int ma_print_result_getdata(SQLHSTMT Stmt) #define OK_SIMPLE_STMT(stmt, stmtstr)\ -if (SQLExecDirect((stmt), (SQLCHAR*)(stmtstr), (SQLINTEGER)strlen(stmtstr)) != SQL_SUCCESS)\ +if (!SQL_SUCCEEDED(SQLExecDirect((stmt), (SQLCHAR*)(stmtstr), (SQLINTEGER)strlen(stmtstr))))\ {\ fprintf(stdout, "Error in %s:%d:\n", __FILE__, __LINE__);\ odbc_print_error(SQL_HANDLE_STMT, (stmt));\ @@ -783,6 +788,7 @@ SQLHANDLE DoConnect(SQLHANDLE Connection, BOOL DoWConnect, if (UseDsnOnly != FALSE) { _snprintf(DSNString, 1024, "DSN=%s", dsn ? dsn : (const char*)my_dsn); + diag(DSNString); } else { @@ -790,12 +796,12 @@ SQLHANDLE DoConnect(SQLHANDLE Connection, BOOL DoWConnect, uid ? uid : (const char*)my_uid, pwd ? pwd : (const char*)my_pwd, port ? port : my_port, schema ? schema : (const char*)my_schema, options ? *options : my_options, server ? server : (const char*)my_servername, add_parameters ? add_parameters : ""); - } - diag("DSN=%s;UID=%s;PWD={%s};PORT=%u;DATABASE=%s;OPTION=%lu;SERVER=%s;%s", dsn ? dsn : (const char*)my_dsn, + diag("DSN=%s;UID=%s;PWD={%s};PORT=%u;DATABASE=%s;OPTION=%lu;SERVER=%s;%s", dsn ? dsn : (const char*)my_dsn, uid ? uid : (const char*)my_uid, "********", port ? port : my_port, schema ? schema : (const char*)my_schema, options ? *options : my_options, server ? server : (const char*)my_servername, add_parameters ? add_parameters : ""); - + } + if (DoWConnect == FALSE) { if (!SQL_SUCCEEDED(SQLDriverConnect(Connection, NULL, (SQLCHAR *)DSNString, SQL_NTS, (SQLCHAR *)DSNOut, 1024, &Length, SQL_DRIVER_NOPROMPT)))