Commit 19091c84 authored by Philippe Pebay's avatar Philippe Pebay
Browse files

ENH: eliminated all SQL back-end specifics that remained from earlier

     implementations, and which did not fit the new URL-based model.
     Note that this also eliminated a COMP issue.
ENH: completed implementation of the PostgreSQL back end
ENH: updated the SQL tests accordingly
COMP: modified/fixed SQL compilation options
parent a746ab09
......@@ -23,11 +23,6 @@ IF(VTK_USE_POSTGRES AND VTK_PSQL_TEST_URL)
SET(ConditionalTests ${ConditionalTests} TestPostgreSQLDatabase.cxx)
ENDIF(VTK_USE_POSTGRES AND VTK_PSQL_TEST_URL)
IF(VTK_USE_MYSQL AND VTK_MYSQL_TEST_URL)
SET( MYSQL_TEST_HOST "localhost" CACHE STRING "Hostname of a MySQL instance to use for testing" )
SET( MYSQL_TEST_PORT 3306 CACHE STRING "Port number for a MySQL instance to use for testing" )
SET( MYSQL_TEST_USERNAME "testuser" CACHE STRING "Username for a MySQL instance to use for testing" )
SET( MYSQL_TEST_PASSWORD "testuser" CACHE STRING "Password for a MySQL instance to use for testing" )
SET( MYSQL_TEST_DATABASE "testdb" CACHE STRING "The name of the database schema to use for testing" )
INCLUDE_DIRECTORIES( ${MYSQL_INCLUDE_DIRECTORIES} )
SET(ConditionalTests ${ConditionalTests} TestMySQLDatabase.cxx)
ENDIF(VTK_USE_MYSQL AND VTK_MYSQL_TEST_URL)
......
......@@ -30,107 +30,99 @@
#include "vtkVariantArray.h"
#include "vtkToolkits.h"
int TestMySQLDatabase(int, char ** const)
int TestMySQLDatabase( int, char ** const )
{
const char *queryText = "SELECT name, age, weight FROM people WHERE age <= 20";
vtkMySQLDatabase *db = vtkMySQLDatabase::New();
db->SetHostName(VTK_MYSQL_TEST_HOST);
db->SetPorT(VTK_MYSQL_TEST_PORT);
db->SetUserName(VTK_MYSQL_TEST_USERNAME);
db->SetPassword(VTK_MYSQL_TEST_PASSWORD);
db->SetDatabaseName(VTK_MYSQL_TEST_DATABASE);
vtkMySQLDatabase* db = vtkMySQLDatabase::SafeDownCast( vtkSQLDatabase::CreateFromURL( VTK_MYSQL_TEST_URL ) );
bool status = db->Open();
if (!status)
if ( ! status )
{
cerr << "Couldn't open database.\n";
return 1;
}
vtkSQLQuery* query = db->GetQueryInstance();
vtkStdString createQuery("CREATE TABLE IF NOT EXISTS people (name TEXT, age INTEGER, weight FLOAT)");
vtkStdString createQuery( "CREATE TABLE IF NOT EXISTS people (name TEXT, age INTEGER, weight FLOAT)" );
cout << createQuery << endl;
query->SetQuery(createQuery.c_str());
if (!query->Execute())
query->SetQuery( createQuery.c_str() );
if ( !query->Execute() )
{
cerr << "Create query failed" << endl;
return 1;
}
for (int i = 0; i < 40; i++)
for ( int i = 0; i < 40; ++ i )
{
char insertQuery[200];
sprintf(insertQuery, "INSERT INTO people VALUES('John Doe %d', %d, %d)",
i, i, 10*i);
sprintf( insertQuery, "INSERT INTO people VALUES('John Doe %d', %d, %d)",
i, i, 10*i );
cout << insertQuery << endl;
query->SetQuery(insertQuery);
if (!query->Execute())
query->SetQuery( insertQuery );
if ( !query->Execute() )
{
cerr << "Insert query " << i << " failed" << endl;
return 1;
}
}
query->SetQuery(queryText);
const char* queryText = "SELECT name, age, weight FROM people WHERE age <= 20";
query->SetQuery( queryText );
cerr << endl << "Running query: " << query->GetQuery() << endl;
cerr << endl << "Using vtkSQLQuery directly to execute query:" << endl;
if (!query->Execute())
if ( !query->Execute() )
{
cerr << "Query failed" << endl;
return 1;
}
for (int col = 0; col < query->GetNumberOfFields(); col++)
for ( int col = 0; col < query->GetNumberOfFields(); ++ col )
{
if (col > 0)
if ( col > 0 )
{
cerr << ", ";
}
cerr << query->GetFieldName(col);
cerr << query->GetFieldName( col );
}
cerr << endl;
while (query->NextRow())
while ( query->NextRow() )
{
for (int field = 0; field < query->GetNumberOfFields(); field++)
for ( int field = 0; field < query->GetNumberOfFields(); ++ field )
{
if (field > 0)
if ( field > 0 )
{
cerr << ", ";
}
cerr << query->DataValue(field).ToString().c_str();
cerr << query->DataValue( field ).ToString().c_str();
}
cerr << endl;
}
cerr << endl << "Using vtkSQLQuery to execute query and retrieve by row:" << endl;
if (!query->Execute())
if ( !query->Execute() )
{
cerr << "Query failed" << endl;
return 1;
}
for (int col = 0; col < query->GetNumberOfFields(); col++)
for ( int col = 0; col < query->GetNumberOfFields(); ++ col )
{
if (col > 0)
if ( col > 0 )
{
cerr << ", ";
}
cerr << query->GetFieldName(col);
cerr << query->GetFieldName( col );
}
cerr << endl;
vtkVariantArray* va = vtkVariantArray::New();
while (query->NextRow(va))
while ( query->NextRow( va ) )
{
for (int field = 0; field < va->GetNumberOfValues(); field++)
for ( int field = 0; field < va->GetNumberOfValues(); ++ field )
{
if (field > 0)
if ( field > 0 )
{
cerr << ", ";
}
cerr << va->GetValue(field).ToString().c_str();
cerr << va->GetValue( field ).ToString().c_str();
}
cerr << endl;
}
......@@ -138,25 +130,25 @@ int TestMySQLDatabase(int, char ** const)
cerr << endl << "Using vtkRowQueryToTable to execute query:" << endl;
vtkRowQueryToTable* reader = vtkRowQueryToTable::New();
reader->SetQuery(query);
reader->SetQuery( query );
reader->Update();
vtkTable* table = reader->GetOutput();
for (vtkIdType col = 0; col < table->GetNumberOfColumns(); col++)
for ( vtkIdType col = 0; col < table->GetNumberOfColumns(); ++ col )
{
table->GetColumn(col)->Print(cerr);
table->GetColumn( col )->Print( cerr );
}
cerr << endl;
for (vtkIdType row = 0; row < table->GetNumberOfRows(); row++)
for ( vtkIdType row = 0; row < table->GetNumberOfRows(); ++ row )
{
for (vtkIdType col = 0; col < table->GetNumberOfColumns(); col++)
for ( vtkIdType col = 0; col < table->GetNumberOfColumns(); ++ col )
{
vtkVariant v = table->GetValue(row, col);
vtkVariant v = table->GetValue( row, col );
cerr << "row " << row << ", col " << col << " - "
<< v.ToString() << " (" << vtkImageScalarTypeNameMacro(v.GetType()) << ")" << endl;
<< v.ToString() << " ( " << vtkImageScalarTypeNameMacro( v.GetType()) << " )" << endl;
}
}
query->SetQuery("DROP TABLE people");
query->SetQuery( "DROP TABLE people" );
query->Execute();
reader->Delete();
......
......@@ -30,20 +30,25 @@
#include "vtkStringArray.h"
#include "vtkToolkits.h"
int TestPostgreSQLDatabase(int /*argc*/, char* /*argv*/[])
int TestPostgreSQLDatabase( int /*argc*/, char* /*argv*/[] )
{
// This test requires a database named "test" to be present
// on a Postgres server running on the local machine. The
// default user must have permission to add and drop databases
// as well as tables in the databases. A new database "vtktest"
// will be created and then destroyed by this test.
vtkPostgreSQLDatabase* db = vtkPostgreSQLDatabase::New();
db->SetURL( VTK_PSQL_TEST_URL );
db->Open();
vtkPostgreSQLDatabase* db = vtkPostgreSQLDatabase::SafeDownCast( vtkSQLDatabase::CreateFromURL( VTK_PSQL_TEST_URL ) );
bool status = db->Open();
if ( ! status )
{
cerr << "Couldn't open database.\n";
return 1;
}
vtkStringArray* dbNames = db->GetDatabases();
cout << "Database list:\n";
for ( int dbi = 0; dbi < dbNames->GetNumberOfValues(); ++dbi )
for ( int dbi = 0; dbi < dbNames->GetNumberOfValues(); ++ dbi )
{
cout << "+ " << dbNames->GetValue( dbi ) << endl;
}
......@@ -53,19 +58,9 @@ int TestPostgreSQLDatabase(int /*argc*/, char* /*argv*/[])
cerr << "Error: " << db->GetLastErrorText() << endl;
}
// Reconnect to the database we've just created.
db->SetURL( VTK_PSQL_TEST_URL );
bool status = db->Open();
if ( ! status )
{
cerr << "Couldn't open database.\n";
return 1;
}
vtkSQLQuery* query = db->GetQueryInstance();
vtkStdString dropQuery( "DROP TABLE IF EXISTS people" );
vtkStdString dropQuery( "DROP TABLE people" );
cout << dropQuery << endl;
query->SetQuery( dropQuery.c_str() );
if ( ! query->Execute() )
......@@ -83,7 +78,7 @@ int TestPostgreSQLDatabase(int /*argc*/, char* /*argv*/[])
return 1;
}
for ( int i = 0; i < 40; ++i )
for ( int i = 0; i < 40; ++ i )
{
char insertQuery[200];
sprintf( insertQuery, "INSERT INTO people VALUES('John Doe %d', %d, %d)", i, i, 10 * i );
......@@ -108,7 +103,7 @@ int TestPostgreSQLDatabase(int /*argc*/, char* /*argv*/[])
return 1;
}
for ( int col = 0; col < query->GetNumberOfFields(); ++col )
for ( int col = 0; col < query->GetNumberOfFields(); ++ col )
{
if ( col > 0 )
{
......@@ -119,7 +114,7 @@ int TestPostgreSQLDatabase(int /*argc*/, char* /*argv*/[])
cerr << endl;
while ( query->NextRow() )
{
for ( int field = 0; field < query->GetNumberOfFields(); ++field )
for ( int field = 0; field < query->GetNumberOfFields(); ++ field )
{
if ( field > 0 )
{
......@@ -136,7 +131,7 @@ int TestPostgreSQLDatabase(int /*argc*/, char* /*argv*/[])
cerr << "Query failed" << endl;
return 1;
}
for ( int col = 0; col < query->GetNumberOfFields(); ++col )
for ( int col = 0; col < query->GetNumberOfFields(); ++ col )
{
if ( col > 0 )
{
......@@ -148,7 +143,7 @@ int TestPostgreSQLDatabase(int /*argc*/, char* /*argv*/[])
vtkVariantArray* va = vtkVariantArray::New();
while ( query->NextRow( va ) )
{
for ( int field = 0; field < va->GetNumberOfValues(); ++field )
for ( int field = 0; field < va->GetNumberOfValues(); ++ field )
{
if ( field > 0 )
{
......@@ -165,14 +160,14 @@ int TestPostgreSQLDatabase(int /*argc*/, char* /*argv*/[])
reader->SetQuery( query );
reader->Update();
vtkTable* table = reader->GetOutput();
for ( vtkIdType col = 0; col < table->GetNumberOfColumns(); ++col )
for ( vtkIdType col = 0; col < table->GetNumberOfColumns(); ++ col )
{
table->GetColumn( col )->Print( cerr );
}
cerr << endl;
for ( vtkIdType row = 0; row < table->GetNumberOfRows(); ++row )
for ( vtkIdType row = 0; row < table->GetNumberOfRows(); ++ row )
{
for ( vtkIdType col = 0; col < table->GetNumberOfColumns(); ++col )
for ( vtkIdType col = 0; col < table->GetNumberOfColumns(); ++ col )
{
vtkVariant v = table->GetValue( row, col );
cerr << "row " << row << ", col " << col << " - "
......@@ -181,7 +176,6 @@ int TestPostgreSQLDatabase(int /*argc*/, char* /*argv*/[])
}
db->Close();
db->SetURL( VTK_PSQL_TEST_URL );
db->Open();
// Delete the database until we run the test again
if ( ! db->DropDatabase( "vtktest" ) )
......
......@@ -28,14 +28,12 @@
#include "vtkVariant.h"
#include "vtkVariantArray.h"
int TestSQLiteDatabase(int /*argc*/, char* /*argv*/[])
int TestSQLiteDatabase( int /*argc*/, char* /*argv*/[])
{
const char *queryText = "SELECT name, age, weight FROM people WHERE age <= 20";
vtkSQLiteDatabase *db = vtkSQLiteDatabase::New();
db->SetFileName(":memory:");
vtkSQLiteDatabase* db = vtkSQLiteDatabase::SafeDownCast( vtkSQLDatabase::CreateFromURL( "sqlite://:memory:" ) );
bool status = db->Open();
if (!status)
if ( ! status )
{
cerr << "Couldn't open database.\n";
return 1;
......@@ -45,20 +43,20 @@ int TestSQLiteDatabase(int /*argc*/, char* /*argv*/[])
vtkStdString createQuery("CREATE TABLE IF NOT EXISTS people (name TEXT, age INTEGER, weight FLOAT)");
cout << createQuery << endl;
query->SetQuery(createQuery.c_str());
query->SetQuery( createQuery.c_str());
if (!query->Execute())
{
cerr << "Create query failed" << endl;
return 1;
}
for (int i = 0; i < 40; i++)
for ( int i = 0; i < 40; i++)
{
char insertQuery[200];
sprintf(insertQuery, "INSERT INTO people VALUES('John Doe %d', %d, %d)",
i, i, 10*i);
sprintf( insertQuery, "INSERT INTO people VALUES('John Doe %d', %d, %d)",
i, i, 10*i );
cout << insertQuery << endl;
query->SetQuery(insertQuery);
query->SetQuery( insertQuery );
if (!query->Execute())
{
cerr << "Insert query " << i << " failed" << endl;
......@@ -66,8 +64,8 @@ int TestSQLiteDatabase(int /*argc*/, char* /*argv*/[])
}
}
query->SetQuery(queryText);
const char *queryText = "SELECT name, age, weight FROM people WHERE age <= 20";
query->SetQuery( queryText );
cerr << endl << "Running query: " << query->GetQuery() << endl;
cerr << endl << "Using vtkSQLQuery directly to execute query:" << endl;
......@@ -77,24 +75,24 @@ int TestSQLiteDatabase(int /*argc*/, char* /*argv*/[])
return 1;
}
for (int col = 0; col < query->GetNumberOfFields(); col++)
for ( int col = 0; col < query->GetNumberOfFields(); col++)
{
if (col > 0)
if ( col > 0)
{
cerr << ", ";
}
cerr << query->GetFieldName(col);
cerr << query->GetFieldName( col );
}
cerr << endl;
while (query->NextRow())
while ( query->NextRow())
{
for (int field = 0; field < query->GetNumberOfFields(); field++)
for ( int field = 0; field < query->GetNumberOfFields(); field++)
{
if (field > 0)
if ( field > 0)
{
cerr << ", ";
}
cerr << query->DataValue(field).ToString().c_str();
cerr << query->DataValue( field ).ToString().c_str();
}
cerr << endl;
}
......@@ -105,25 +103,25 @@ int TestSQLiteDatabase(int /*argc*/, char* /*argv*/[])
cerr << "Query failed" << endl;
return 1;
}
for (int col = 0; col < query->GetNumberOfFields(); col++)
for ( int col = 0; col < query->GetNumberOfFields(); col++)
{
if (col > 0)
if ( col > 0)
{
cerr << ", ";
}
cerr << query->GetFieldName(col);
cerr << query->GetFieldName( col );
}
cerr << endl;
vtkVariantArray* va = vtkVariantArray::New();
while (query->NextRow(va))
while ( query->NextRow( va ))
{
for (int field = 0; field < va->GetNumberOfValues(); field++)
for ( int field = 0; field < va->GetNumberOfValues(); field++)
{
if (field > 0)
if ( field > 0)
{
cerr << ", ";
}
cerr << va->GetValue(field).ToString().c_str();
cerr << va->GetValue( field ).ToString().c_str();
}
cerr << endl;
}
......@@ -131,21 +129,21 @@ int TestSQLiteDatabase(int /*argc*/, char* /*argv*/[])
cerr << endl << "Using vtkRowQueryToTable to execute query:" << endl;
vtkRowQueryToTable* reader = vtkRowQueryToTable::New();
reader->SetQuery(query);
reader->SetQuery( query );
reader->Update();
vtkTable* table = reader->GetOutput();
for (vtkIdType col = 0; col < table->GetNumberOfColumns(); col++)
for ( vtkIdType col = 0; col < table->GetNumberOfColumns(); col++)
{
table->GetColumn(col)->Print(cerr);
table->GetColumn( col )->Print( cerr );
}
cerr << endl;
for (vtkIdType row = 0; row < table->GetNumberOfRows(); row++)
for ( vtkIdType row = 0; row < table->GetNumberOfRows(); row++)
{
for (vtkIdType col = 0; col < table->GetNumberOfColumns(); col++)
for ( vtkIdType col = 0; col < table->GetNumberOfColumns(); col++)
{
vtkVariant v = table->GetValue(row, col);
vtkVariant v = table->GetValue( row, col );
cerr << "row " << row << ", col " << col << " - "
<< v.ToString() << " (" << vtkImageScalarTypeNameMacro(v.GetType()) << ")" << endl;
<< v.ToString() << " (" << vtkImageScalarTypeNameMacro( v.GetType()) << ")" << endl;
}
}
......
......@@ -12,30 +12,30 @@
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
/*----------------------------------------------------------------------------
Copyright (c) Sandia Corporation
See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
----------------------------------------------------------------------------*/
#include "vtkMySQLDatabase.h"
#include "vtkMySQLQuery.h"
#include <vtkStringArray.h>
#include <vtkObjectFactory.h>
#include "vtkObjectFactory.h"
#include "vtkStringArray.h"
#include <vtksys/SystemTools.hxx>
#include <assert.h>
#include <mysql.h>
// ----------------------------------------------------------------------
vtkCxxRevisionMacro(vtkMySQLDatabase, "1.2");
vtkCxxRevisionMacro(vtkMySQLDatabase, "1.3");
vtkStandardNewMacro(vtkMySQLDatabase);
// ----------------------------------------------------------------------
vtkMySQLDatabase::vtkMySQLDatabase()
: HostName(NULL),
UserName(NULL),
Password(NULL),
DatabaseName(NULL),
PorT(3306){
{
this->URL = NULL;
this->Connection = NULL;
mysql_init(& this->NullConnection);
this->Tables = vtkStringArray::New();
this->Tables->Register(this);
......@@ -44,60 +44,20 @@ vtkMySQLDatabase::vtkMySQLDatabase()
}
// ----------------------------------------------------------------------
vtkMySQLDatabase::~vtkMySQLDatabase()
{
this->Close();
this->SetHostName(NULL);
this->SetUserName(NULL);
this->SetPassword(NULL);
this->SetLastErrorText(NULL);
this->Tables->UnRegister(this);
}
// ----------------------------------------------------------------------
// The reason I'm writing this method out instead of just using
// vtkSetStringMacro is that I want to zero out the old string before
// I delete it. That way there's less chance that a password will be
// left floating around in main memory.
void
vtkMySQLDatabase::SetPassword(const char *pwd)
{
vtkDebugMacro(<< this->GetClassName() << " (" << this << "): setting "
<< "Password to " << (pwd?pwd:"(null)") );
if ( this->Password == NULL && pwd == NULL) { return;}
if ( this->Password && pwd && (!strcmp(this->Password,pwd))) { return;}
if (this->Password)
{
memset(this->Password, 0, strlen(this->Password) * sizeof(char));
delete [] this->Password;
this->Password = NULL;
if ( this->IsOpen() )
{
this->Close();
}
if (pwd)
{
size_t n = strlen(pwd) + 1;
char *cp1 = new char[n];
const char *cp2 = (pwd);
this->Password = cp1;
do { *cp1++ = *cp2++; } while ( --n );
}
else
{
this->Password = NULL;
}
this->Modified();
this->SetURL( NULL );
this->SetLastErrorText(NULL);
this->Tables->UnRegister(this);
}
// ----------------------------------------------------------------------
bool
vtkMySQLDatabase::IsSupported(int feature)
bool vtkMySQLDatabase::IsSupported(int feature)
{
switch (feature)
{
......@@ -142,55 +102,46 @@ vtkMySQLDatabase::IsSupported(int feature)
}
// ----------------------------------------------------------------------
bool
vtkMySQLDatabase::Open()
bool vtkMySQLDatabase::Open()
{
bool canOpen = true;
if (this->UserName == NULL)
{
vtkErrorMacro(<<"Open(): Username is null!");
canOpen = false;
}
if (this->Password == NULL)
{
vtkErrorMacro(<<"Open(): Password is null! For no password, use the string \"\".");
canOpen = false;
}
if (this->HostName == NULL)
{
vtkErrorMacro(<<"Open(): Hostname is null!");
canOpen = false;
}
if (this->DatabaseName == NULL)
if ( ! this->URL )
{
vtkWarningMacro(<<"Open(): Database name is null. This is permitted but highly discouraged.");
this->SetLastErrorText("Cannot open database because URL is null.");
vtkErrorMacro(<< this->GetLastErrorText());
return false;
}
if (this->IsOpen())
if ( this->IsOpen() )
{
vtkWarningMacro(<<"Open(): Database is already open.");