1 Star 0 Fork 0

devstone/VTK

加入 Gitee
与超过 1400万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
vtkSQLDatabase.cxx 18.88 KB
一键复制 编辑 原始数据 按行查看 历史
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665
/*=========================================================================
Program: Visualization Toolkit
Module: vtkSQLDatabase.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
/*-------------------------------------------------------------------------
Copyright 2008 Sandia Corporation.
Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
the U.S. Government retains certain rights in this software.
-------------------------------------------------------------------------*/
#include "vtkToolkits.h"
#include "vtkInformationObjectBaseKey.h"
#include "vtkSQLDatabase.h"
#include "vtkSQLQuery.h"
#include "vtkSQLDatabaseSchema.h"
#include "vtkSQLiteDatabase.h"
#include "vtkCriticalSection.h"
#include "vtkObjectFactory.h"
#include "vtkStdString.h"
#include <vtksys/SystemTools.hxx>
#include <sstream>
class vtkSQLDatabase::vtkCallbackVector :
public std::vector<vtkSQLDatabase::CreateFunction>
{
public:
vtkSQLDatabase* CreateFromURL(const char* URL)
{
iterator iter;
for (iter = this->begin(); iter != this->end(); ++iter)
{
vtkSQLDatabase* db =(*(*iter))(URL);
if (db)
{
return db;
}
}
return nullptr;
}
};
vtkSQLDatabase::vtkCallbackVector* vtkSQLDatabase::Callbacks = nullptr;
// Ensures that there are no leaks when the application exits.
class vtkSQLDatabaseCleanup
{
public:
inline void Use()
{
};
~vtkSQLDatabaseCleanup()
{
vtkSQLDatabase::UnRegisterAllCreateFromURLCallbacks();
}
};
// Used to clean up the Callbacks
static vtkSQLDatabaseCleanup vtkCleanupSQLDatabaseGlobal;
vtkInformationKeyMacro(vtkSQLDatabase, DATABASE, ObjectBase);
// ----------------------------------------------------------------------
vtkSQLDatabase::vtkSQLDatabase()
{
}
// ----------------------------------------------------------------------
vtkSQLDatabase::~vtkSQLDatabase()
{
}
// ----------------------------------------------------------------------
void vtkSQLDatabase::RegisterCreateFromURLCallback(
vtkSQLDatabase::CreateFunction func)
{
if (!vtkSQLDatabase::Callbacks)
{
vtkCleanupSQLDatabaseGlobal.Use();
vtkSQLDatabase::Callbacks = new vtkCallbackVector();
}
vtkSQLDatabase::Callbacks->push_back(func);
}
// ----------------------------------------------------------------------
void vtkSQLDatabase::UnRegisterCreateFromURLCallback(
vtkSQLDatabase::CreateFunction func)
{
if (vtkSQLDatabase::Callbacks)
{
vtkSQLDatabase::vtkCallbackVector::iterator iter;
for (iter = vtkSQLDatabase::Callbacks->begin();
iter != vtkSQLDatabase::Callbacks->end(); ++iter)
{
if ((*iter) == func)
{
vtkSQLDatabase::Callbacks->erase(iter);
break;
}
}
}
}
// ----------------------------------------------------------------------
void vtkSQLDatabase::UnRegisterAllCreateFromURLCallbacks()
{
delete vtkSQLDatabase::Callbacks;
vtkSQLDatabase::Callbacks = nullptr;
}
// ----------------------------------------------------------------------
void vtkSQLDatabase::PrintSelf(ostream &os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
}
// ----------------------------------------------------------------------
vtkStdString vtkSQLDatabase::GetColumnSpecification( vtkSQLDatabaseSchema* schema,
int tblHandle,
int colHandle )
{
std::ostringstream queryStr;
queryStr << schema->GetColumnNameFromHandle( tblHandle, colHandle );
// Figure out column type
int colType = schema->GetColumnTypeFromHandle( tblHandle, colHandle );
vtkStdString colTypeStr;
switch ( static_cast<vtkSQLDatabaseSchema::DatabaseColumnType>( colType ) )
{
case vtkSQLDatabaseSchema::SERIAL:
colTypeStr = "INTEGER";
break;
case vtkSQLDatabaseSchema::SMALLINT:
colTypeStr = "INTEGER";
break;
case vtkSQLDatabaseSchema::INTEGER:
colTypeStr = "INTEGER";
break;
case vtkSQLDatabaseSchema::BIGINT:
colTypeStr = "INTEGER";
break;
case vtkSQLDatabaseSchema::VARCHAR:
colTypeStr = "VARCHAR";
break;
case vtkSQLDatabaseSchema::TEXT:
colTypeStr = "VARCHAR";
break;
case vtkSQLDatabaseSchema::REAL:
colTypeStr = "FLOAT";
break;
case vtkSQLDatabaseSchema::DOUBLE:
colTypeStr = "DOUBLE";
break;
case vtkSQLDatabaseSchema::BLOB:
colTypeStr = "";
break;
case vtkSQLDatabaseSchema::TIME:
colTypeStr = "TIME";
break;
case vtkSQLDatabaseSchema::DATE:
colTypeStr = "DATE";
break;
case vtkSQLDatabaseSchema::TIMESTAMP:
colTypeStr = "TIMESTAMP";
break;
}
if ( !colTypeStr.empty() )
{
queryStr << " " << colTypeStr;
}
else // if ( colTypeStr.size() )
{
vtkGenericWarningMacro( "Unable to get column specification: unsupported data type " << colType );
return vtkStdString();
}
// Decide whether size is allowed, required, or unused
int colSizeType = 0;
switch ( static_cast<vtkSQLDatabaseSchema::DatabaseColumnType>( colType ) )
{
case vtkSQLDatabaseSchema::SERIAL:
colSizeType = 0;
break;
case vtkSQLDatabaseSchema::SMALLINT:
colSizeType = 1;
break;
case vtkSQLDatabaseSchema::INTEGER:
colSizeType = 1;
break;
case vtkSQLDatabaseSchema::BIGINT:
colSizeType = 1;
break;
case vtkSQLDatabaseSchema::VARCHAR:
colSizeType = -1;
break;
case vtkSQLDatabaseSchema::TEXT:
colSizeType = -1;
break;
case vtkSQLDatabaseSchema::REAL:
colSizeType = 0;
break;
case vtkSQLDatabaseSchema::DOUBLE:
colSizeType = 0;
break;
case vtkSQLDatabaseSchema::BLOB:
colSizeType = 0;
break;
case vtkSQLDatabaseSchema::TIME:
colSizeType = 0;
break;
case vtkSQLDatabaseSchema::DATE:
colSizeType = 0;
break;
case vtkSQLDatabaseSchema::TIMESTAMP:
colSizeType = 0;
break;
}
// Specify size if allowed or required
if ( colSizeType )
{
int colSize = schema->GetColumnSizeFromHandle( tblHandle, colHandle );
// IF size is provided but absurd,
// OR, if size is required but not provided OR absurd,
// THEN assign the default size.
if ( ( colSize < 0 ) || ( colSizeType == -1 && colSize < 1 ) )
{
colSize = VTK_SQL_DEFAULT_COLUMN_SIZE;
}
// At this point, we have either a valid size if required, or a possibly null valid size
// if not required. Thus, skip sizing in the latter case.
if ( colSize > 0 )
{
queryStr << "(" << colSize << ")";
}
}
vtkStdString attStr = schema->GetColumnAttributesFromHandle( tblHandle, colHandle );
if ( !attStr.empty() )
{
queryStr << " " << attStr;
}
return queryStr.str();
}
// ----------------------------------------------------------------------
vtkStdString vtkSQLDatabase::GetIndexSpecification( vtkSQLDatabaseSchema* schema,
int tblHandle,
int idxHandle,
bool& skipped )
{
vtkStdString queryStr;
int idxType = schema->GetIndexTypeFromHandle( tblHandle, idxHandle );
switch ( idxType )
{
case vtkSQLDatabaseSchema::PRIMARY_KEY:
queryStr = ", PRIMARY KEY ";
skipped = false;
break;
case vtkSQLDatabaseSchema::UNIQUE:
queryStr = ", UNIQUE ";
skipped = false;
break;
case vtkSQLDatabaseSchema::INDEX:
// Not supported within a CREATE TABLE statement by all SQL backends:
// must be created later with a CREATE INDEX statement
queryStr = "CREATE INDEX ";
skipped = true;
break;
default:
return vtkStdString();
}
// No index_name for PRIMARY KEYs nor UNIQUEs
if ( skipped )
{
queryStr += schema->GetIndexNameFromHandle( tblHandle, idxHandle );
}
// CREATE INDEX <index name> ON <table name> syntax
if ( skipped )
{
queryStr += " ON ";
queryStr += schema->GetTableNameFromHandle( tblHandle );
}
queryStr += " (";
// Loop over all column names of the index
int numCnm = schema->GetNumberOfColumnNamesInIndex( tblHandle, idxHandle );
if ( numCnm < 0 )
{
vtkGenericWarningMacro( "Unable to get index specification: index has incorrect number of columns " << numCnm );
return vtkStdString();
}
bool firstCnm = true;
for ( int cnmHandle = 0; cnmHandle < numCnm; ++ cnmHandle )
{
if ( firstCnm )
{
firstCnm = false;
}
else
{
queryStr += ",";
}
queryStr += schema->GetIndexColumnNameFromHandle( tblHandle, idxHandle, cnmHandle );
}
queryStr += ")";
return queryStr;
}
// ----------------------------------------------------------------------
vtkStdString vtkSQLDatabase::GetTriggerSpecification( vtkSQLDatabaseSchema* schema,
int tblHandle,
int trgHandle )
{
vtkStdString queryStr = "CREATE TRIGGER ";
queryStr += schema->GetTriggerNameFromHandle( tblHandle, trgHandle );
int trgType = schema->GetTriggerTypeFromHandle( tblHandle, trgHandle );
// odd types: AFTER, even types: BEFORE
if ( trgType % 2 )
{
queryStr += " AFTER ";
}
else
{
queryStr += " BEFORE ";
}
// 0/1: INSERT, 2/3: UPDATE, 4/5: DELETE
if ( trgType > 1 )
{
if ( trgType > 3 )
{
queryStr += "DELETE ON ";
}
else // if ( trgType > 3 )
{
queryStr += "UPDATE ON ";
}
}
else // if ( trgType > 1 )
{
queryStr += "INSERT ON ";
}
queryStr += schema->GetTableNameFromHandle( tblHandle );
queryStr += " ";
queryStr += schema->GetTriggerActionFromHandle( tblHandle, trgHandle );
return queryStr;
}
// ----------------------------------------------------------------------
vtkSQLDatabase* vtkSQLDatabase::CreateFromURL( const char* URL )
{
std::string urlstr( URL ? URL : "" );
std::string protocol;
std::string username;
std::string unused;
std::string hostname;
std::string dataport;
std::string database;
std::string dataglom;
vtkSQLDatabase* db = nullptr;
static vtkSimpleCriticalSection dbURLCritSec;
dbURLCritSec.Lock();
// SQLite is a bit special so lets get that out of the way :)
if ( ! vtksys::SystemTools::ParseURLProtocol( urlstr, protocol, dataglom ))
{
vtkGenericWarningMacro( "Invalid URL (no protocol found): \"" << urlstr.c_str() << "\"" );
dbURLCritSec.Unlock();
return nullptr;
}
if ( protocol == "sqlite" )
{
db = vtkSQLiteDatabase::New();
db->ParseURL( URL );
dbURLCritSec.Unlock();
return db;
}
// Okay now for all the other database types get more detailed info
if ( ! vtksys::SystemTools::ParseURL( urlstr, protocol, username,
unused, hostname, dataport, database) )
{
vtkGenericWarningMacro( "Invalid URL (other components missing): \"" << urlstr.c_str() << "\"" );
dbURLCritSec.Unlock();
return nullptr;
}
// Now try to look at registered callback to try and find someone who can
// provide us with the required implementation.
if (!db && vtkSQLDatabase::Callbacks)
{
db = vtkSQLDatabase::Callbacks->CreateFromURL( URL );
}
if ( ! db )
{
vtkGenericWarningMacro( "Unsupported protocol: " << protocol.c_str() );
}
dbURLCritSec.Unlock();
return db;
}
// ----------------------------------------------------------------------
bool vtkSQLDatabase::EffectSchema( vtkSQLDatabaseSchema* schema, bool dropIfExists )
{
if ( ! this->IsOpen() )
{
vtkGenericWarningMacro( "Unable to effect the schema: no database is open" );
return false;
}
// Instantiate an empty query and begin the transaction.
vtkSQLQuery* query = this->GetQueryInstance();
if ( ! query->BeginTransaction() )
{
vtkGenericWarningMacro( "Unable to effect the schema: unable to begin transaction" );
return false;
}
// Loop over preamble statements of the schema and execute them only if they are relevant
int numPre = schema->GetNumberOfPreambles();
for ( int preHandle = 0; preHandle < numPre; ++ preHandle )
{
// Don't execute if the statement is not for this backend
const char* preBackend = schema->GetPreambleBackendFromHandle( preHandle );
if ( strcmp( preBackend, VTK_SQL_ALLBACKENDS ) && strcmp( preBackend, this->GetClassName() ) )
{
continue;
}
vtkStdString preStr = schema->GetPreambleActionFromHandle( preHandle );
query->SetQuery( preStr );
if ( ! query->Execute() )
{
vtkGenericWarningMacro( "Unable to effect the schema: unable to execute query.\nDetails: "
<< query->GetLastErrorText() );
query->RollbackTransaction();
query->Delete();
return false;
}
}
// Loop over all tables of the schema and create them
int numTbl = schema->GetNumberOfTables();
for ( int tblHandle = 0; tblHandle < numTbl; ++ tblHandle )
{
// Construct the CREATE TABLE query for this table
vtkStdString queryStr( "CREATE TABLE " );
queryStr += this->GetTablePreamble( dropIfExists );
queryStr += schema->GetTableNameFromHandle( tblHandle );
queryStr += " (";
// Loop over all columns of the current table
int numCol = schema->GetNumberOfColumnsInTable( tblHandle );
if ( numCol < 0 )
{
query->RollbackTransaction();
query->Delete();
return false;
}
bool firstCol = true;
for ( int colHandle = 0; colHandle < numCol; ++ colHandle )
{
if ( ! firstCol )
{
queryStr += ", ";
}
else // ( ! firstCol )
{
firstCol = false;
}
// Get column creation syntax (backend-dependent)
vtkStdString colStr = this->GetColumnSpecification( schema, tblHandle, colHandle );
if ( !colStr.empty() )
{
queryStr += colStr;
}
else // if ( colStr.size() )
{
query->RollbackTransaction();
query->Delete();
return false;
}
}
// Check out number of indices
int numIdx = schema->GetNumberOfIndicesInTable( tblHandle );
if ( numIdx < 0 )
{
query->RollbackTransaction();
query->Delete();
return false;
}
// In case separate INDEX statements are needed (backend-specific)
std::vector<vtkStdString> idxStatements;
bool skipped = false;
// Loop over all indices of the current table
for ( int idxHandle = 0; idxHandle < numIdx; ++ idxHandle )
{
// Get index creation syntax (backend-dependent)
vtkStdString idxStr = this->GetIndexSpecification( schema, tblHandle, idxHandle, skipped );
if ( !idxStr.empty() )
{
if ( skipped )
{
// Must create this index later
idxStatements.push_back( idxStr );
continue;
}
else // if ( skipped )
{
queryStr += idxStr;
}
}
else // if ( idxStr.size() )
{
query->RollbackTransaction();
query->Delete();
return false;
}
}
queryStr += ")";
// Add options to the end of the CREATE TABLE statement
int numOpt = schema->GetNumberOfOptionsInTable( tblHandle );
if ( numOpt < 0 )
{
query->RollbackTransaction();
query->Delete();
return false;
}
for ( int optHandle = 0; optHandle < numOpt; ++ optHandle )
{
vtkStdString optBackend = schema->GetOptionBackendFromHandle( tblHandle, optHandle );
if ( strcmp( optBackend, VTK_SQL_ALLBACKENDS ) && strcmp( optBackend, this->GetClassName() ) )
{
continue;
}
queryStr += " ";
queryStr += schema->GetOptionTextFromHandle( tblHandle, optHandle );
}
// Execute the CREATE TABLE query
query->SetQuery( queryStr );
if ( ! query->Execute() )
{
vtkGenericWarningMacro( "Unable to effect the schema: unable to execute query.\nDetails: "
<< query->GetLastErrorText() );
query->RollbackTransaction();
query->Delete();
return false;
}
// Execute separate CREATE INDEX statements if needed
for ( std::vector<vtkStdString>::iterator it = idxStatements.begin();
it != idxStatements.end(); ++ it )
{
query->SetQuery( *it );
if ( ! query->Execute() )
{
vtkGenericWarningMacro( "Unable to effect the schema: unable to execute query.\nDetails: "
<< query->GetLastErrorText() );
query->RollbackTransaction();
query->Delete();
return false;
}
}
// Check out number of triggers
int numTrg = schema->GetNumberOfTriggersInTable( tblHandle );
if ( numTrg < 0 )
{
query->RollbackTransaction();
query->Delete();
return false;
}
// Construct CREATE TRIGGER statements only if they are supported by the backend at hand
if ( numTrg && IsSupported( VTK_SQL_FEATURE_TRIGGERS ) )
{
// Loop over all triggers of the current table
for ( int trgHandle = 0; trgHandle < numTrg; ++ trgHandle )
{
// Don't execute if the trigger is not for this backend
const char* trgBackend = schema->GetTriggerBackendFromHandle( tblHandle, trgHandle );
if ( strcmp( trgBackend, VTK_SQL_ALLBACKENDS ) && strcmp( trgBackend, this->GetClassName() ) )
{
continue;
}
// Get trigger creation syntax (backend-dependent)
vtkStdString trgStr = this->GetTriggerSpecification( schema, tblHandle, trgHandle );
// If not empty, execute query
if ( !trgStr.empty() )
{
query->SetQuery( vtkStdString( trgStr ) );
if ( ! query->Execute() )
{
vtkGenericWarningMacro( "Unable to effect the schema: unable to execute query.\nDetails: "
<< query->GetLastErrorText() );
query->RollbackTransaction();
query->Delete();
return false;
}
}
else // if ( trgStr.size() )
{
query->RollbackTransaction();
query->Delete();
return false;
}
}
}
// If triggers are specified but not supported, don't quit, but let the user know it
else if ( numTrg )
{
vtkGenericWarningMacro( "Triggers are not supported by this SQL backend; ignoring them." );
}
} // for ( int tblHandle = 0; tblHandle < numTbl; ++ tblHandle )
// Commit the transaction.
if ( ! query->CommitTransaction() )
{
vtkGenericWarningMacro( "Unable to effect the schema: unable to commit transaction.\nDetails: "
<< query->GetLastErrorText() );
query->Delete();
return false;
}
query->Delete();
return true;
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C++
1
https://gitee.com/devstone/VTK.git
git@gitee.com:devstone/VTK.git
devstone
VTK
VTK
master

搜索帮助