22#include <unordered_set> 
   24#include <wx/datetime.h> 
   27#include <boost/algorithm/string.hpp> 
   42        SCH_IO( wxS( 
"Database library" ) ),
 
 
   58                                          const wxString&   aLibraryPath,
 
   59                                          const std::map<std::string, UTF8>* aProperties )
 
   61    std::vector<LIB_SYMBOL*> symbols;
 
   65        aSymbolNameList.Add( symbol->GetName() );
 
 
   70                                          const wxString&           aLibraryPath,
 
   71                                          const std::map<std::string, UTF8>*         aProperties )
 
   73    wxCHECK_RET( 
m_adapter, 
"Database plugin missing library manager adapter handle!" );
 
   87        if( !powerSymbolsOnly || symbol->
IsPower() )
 
   88            aSymbolList.emplace_back( symbol );
 
 
   94                                         const wxString&   aAliasName,
 
   95                                         const std::map<std::string, UTF8>* aProperties )
 
   97    wxCHECK_MSG( 
m_adapter, 
nullptr, 
"Database plugin missing library manager adapter handle!" );
 
  115    std::string tableName;
 
  116    std::string symbolName( aAliasName.ToUTF8() );
 
  122        tableName = sanitizedIt->second.first;
 
  123        symbolName = sanitizedIt->second.second;
 
  129        if( aAliasName.Contains( 
'/' ) )
 
  131            tableName = std::string( aAliasName.BeforeFirst( 
'/' ).ToUTF8() );
 
  132            symbolName = std::string( aAliasName.AfterFirst( 
'/' ).ToUTF8() );
 
  136    std::vector<const DATABASE_LIB_TABLE*> tablesToTry;
 
  140        if( tableIter.
name == tableName )
 
  141            tablesToTry.emplace_back( &tableIter );
 
  144    if( tablesToTry.empty() )
 
  146        wxLogTrace( 
traceDatabase, wxT( 
"LoadSymbol: table '%s' not found in config" ), tableName );
 
  155        if( 
m_conn->SelectOne( 
table->table, std::make_pair( 
table->key_col, symbolName ),
 
  159            wxLogTrace( 
traceDatabase, wxT( 
"LoadSymbol: SelectOne (%s, %s) found in %s" ),
 
  164            wxLogTrace( 
traceDatabase, wxT( 
"LoadSymbol: SelectOne (%s, %s) failed for table %s" ),
 
  169    wxCHECK( foundTable, 
nullptr );
 
 
  181    std::set<wxString> tableNames;
 
  185        if( tableNames.count( tableIter.
name ) )
 
  188        aNames.emplace_back( tableIter.
name );
 
  189        tableNames.insert( tableIter.
name );
 
 
  203               std::back_inserter( aNames ) );
 
 
  214    if( aErrorMsg && ( !
m_conn || !
m_conn->IsConnected() ) )
 
 
  223    long long currentTimestampSeconds = wxDateTime::Now().GetValue().GetValue() / 1000;
 
  231    std::map<wxString, std::unique_ptr<LIB_SYMBOL>> newSymbolCache;
 
  232    std::map<wxString, std::pair<std::string, std::string>> newSanitizedNameMap;
 
  236        std::vector<DATABASE_CONNECTION::ROW> results;
 
  240            if( !
m_conn->GetLastError().empty() )
 
  242                wxString msg = wxString::Format( 
_( 
"Error reading database table %s: %s" ),
 
  255            std::string rawName = std::any_cast<std::string>( 
result[
table.key_col] );
 
  257            std::string sanitizedKey = sanitizedName.
c_str();
 
  258            std::string prefix = 
table.name.empty() ? 
"" : fmt::format( 
"{}/", 
table.name );
 
  259            std::string sanitizedDisplayName = fmt::format( 
"{}{}", prefix, sanitizedKey );
 
  260            wxString    
name( sanitizedDisplayName );
 
  262            newSanitizedNameMap[
name] = std::make_pair( 
table.name, rawName );
 
  267                newSymbolCache[symbol->GetName()] = std::move( symbol );
 
 
  285                    wxString msg = wxString::Format(
 
  286                        _( 
"Could not load database library: settings file %s missing or invalid" ),
 
  295        std::string 
path( aSettingsPath.ToUTF8() );
 
  308        wxASSERT_MSG( aSettingsPath == 
m_settings->GetFilename(),
 
  309                      "Path changed for database library without re-initializing plugin!" );
 
  313        wxLogTrace( 
traceDatabase, wxT( 
"ensureSettings: no settings but no valid path!" ) );
 
 
  320    wxCHECK_RET( 
m_settings, 
"Call ensureSettings before ensureConnection!" );
 
  326        wxString msg = wxString::Format(
 
  327                    _( 
"Could not load database library: could not connect to database %s (%s)" ),
 
 
  337    wxCHECK_RET( 
m_settings, 
"Call ensureSettings before connect()!" );
 
  344        if( 
m_settings->m_Source.connection_string.empty() )
 
  353            std::string cs = 
m_settings->m_Source.connection_string;
 
  354            std::string basePath( wxFileName( 
m_settings->GetFilename() ).GetPath().ToUTF8() );
 
  358            boost::replace_all( cs, 
"${CWD}", basePath );
 
  360            m_conn = std::make_unique<DATABASE_CONNECTION>( cs, 
m_settings->m_Source.timeout );
 
  363        if( !
m_conn->IsConnected() )
 
  372            std::set<std::string> columns;
 
  374            columns.insert( boost::to_lower_copy( tableIter.
key_col ) );
 
  375            columns.insert( boost::to_lower_copy( tableIter.
footprints_col ) );
 
  376            columns.insert( boost::to_lower_copy( tableIter.
symbols_col ) );
 
  386                columns.insert( boost::to_lower_copy( field.
column ) );
 
  388            m_conn->CacheTableInfo( tableIter.
table, columns );
 
 
  400        bool val = std::any_cast<bool>( aVal );
 
  403    catch( 
const std::bad_any_cast& )
 
  409        int val = std::any_cast<int>( aVal );
 
  410        return static_cast<bool>( val );
 
  412    catch( 
const std::bad_any_cast& )
 
  418        wxString strval( std::any_cast<std::string>( aVal ).c_str(), wxConvUTF8 );
 
  420        if( strval.IsEmpty() )
 
  425        for( 
const auto& trueVal : { wxS( 
"true" ), wxS( 
"yes" ), wxS( 
"y" ), wxS( 
"1" ) } )
 
  427            if( strval.Matches( trueVal ) )
 
  431        for( 
const auto& falseVal : { wxS( 
"false" ), wxS( 
"no" ), wxS( 
"n" ), wxS( 
"0" ) } )
 
  433            if( strval.Matches( falseVal ) )
 
  437    catch( 
const std::bad_any_cast& )
 
 
  449    std::unique_ptr<LIB_SYMBOL> symbol = 
nullptr;
 
  456        std::string symbolIdStr = std::any_cast<std::string>( aRow.at( aTable.
symbols_col ) );
 
  458        symbolId.
Parse( std::any_cast<std::string>( aRow.at( aTable.
symbols_col ) ) );
 
  461            originalSymbol = 
m_adapter->LoadSymbol( symbolId );
 
  465            wxLogTrace( 
traceDatabase, wxT( 
"loadSymbolFromRow: found original symbol '%s'" ),
 
  467            symbol.reset( originalSymbol->
Duplicate() );
 
  468            symbol->SetSourceLibId( symbolId );
 
  472            wxLogTrace( 
traceDatabase, wxT( 
"loadSymboFromRow: source symbol id '%s' is invalid, " 
  473                                            "will create empty symbol" ), symbolIdStr );
 
  477            wxLogTrace( 
traceDatabase, wxT( 
"loadSymboFromRow: source symbol '%s' not found, " 
  478                                            "will create empty symbol" ), symbolIdStr );
 
  486        symbol.reset( 
new LIB_SYMBOL( aSymbolName ) );
 
  490        symbol->SetName( aSymbolName );
 
  493    LIB_ID libId = symbol->GetLibId();
 
  495    symbol->SetLibId( libId );
 
  496    wxArrayString footprintsList;
 
  500        std::string footprints = std::any_cast<std::string>( aRow.at( aTable.
footprints_col ) );
 
  502        wxString footprintsStr = wxString( footprints.c_str(), wxConvUTF8 );
 
  503        wxStringTokenizer tokenizer( footprintsStr, 
";\t\r\n", wxTOKEN_STRTOK );
 
  505        while( tokenizer.HasMoreTokens() )
 
  506            footprintsList.Add( tokenizer.GetNextToken() );
 
  508        if( footprintsList.size() > 0 )
 
  509            symbol->GetFootprintField().SetText( footprintsList[0] );
 
  513        wxLogTrace( 
traceDatabase, wxT( 
"loadSymboFromRow: footprint field %s not found." ),
 
  522        symbol->SetDescription( value );
 
  527        wxString value( std::any_cast<std::string>( aRow.at( aTable.
properties.
keywords ) ).c_str(),
 
  529        symbol->SetKeyWords( value );
 
  538        footprintsList.push_back( value );
 
  541    symbol->SetFPFilters( footprintsList );
 
  550            symbol->SetExcludedFromSim( *val );
 
  554            wxLogTrace( 
traceDatabase, wxT( 
"loadSymbolFromRow: exclude_from_sim value for %s " 
  555                                            "could not be cast to a boolean" ), aSymbolName );
 
  566            symbol->SetExcludedFromBoard( *val );
 
  570            wxLogTrace( 
traceDatabase, wxT( 
"loadSymbolFromRow: exclude_from_board value for %s " 
  571                                            "could not be cast to a boolean" ), aSymbolName );
 
  582            symbol->SetExcludedFromBOM( *val );
 
  586            wxLogTrace( 
traceDatabase, wxT( 
"loadSymbolFromRow: exclude_from_bom value for %s " 
  587                                            "could not be cast to a boolean" ), aSymbolName );
 
  591    std::vector<SCH_FIELD*> fields;
 
  592    symbol->GetFields( fields );
 
  594    std::unordered_map<wxString, SCH_FIELD*> fieldsMap;
 
  597        fieldsMap[field->GetName()] = field;
 
  599    static const wxString c_valueFieldName( wxS( 
"Value" ) );
 
  600    static const wxString c_datasheetFieldName( wxS( 
"Datasheet" ) );
 
  604        if( !aRow.count( mapping.
column ) )
 
  606            wxLogTrace( 
traceDatabase, wxT( 
"loadSymbolFromRow: field %s not found in result" ),
 
  615            strValue = std::any_cast<std::string>( aRow.at( mapping.
column ) );
 
  617        catch( std::bad_any_cast& )
 
  621        wxString value( 
strValue.c_str(), wxConvUTF8 );
 
  623        if( mapping.
name_wx == c_valueFieldName )
 
  625            SCH_FIELD& field = symbol->GetValueField();
 
  635        else if( mapping.
name_wx == c_datasheetFieldName )
 
  637            SCH_FIELD& field = symbol->GetDatasheetField();
 
  655        if( fieldsMap.count( mapping.
name_wx ) )
 
  657            field = fieldsMap[mapping.
name_wx];
 
  664            fieldsMap[mapping.
name_wx] = field;
 
  677            symbol->AddDrawItem( field, 
false );
 
  685    symbol->GetDrawItems().sort();
 
 
std::map< std::string, std::any > ROW
 
Dialog helper object to sit in the inheritance tree between wxDialog and any class written by wxFormB...
 
virtual void SetVisible(bool aVisible)
 
A logical library item identifier and consists of various portions much like a URI.
 
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
 
bool IsValid() const
Check if this LID_ID is valid.
 
void SetSubLibraryName(const UTF8 &aName)
 
static UTF8 FixIllegalChars(const UTF8 &aLibItemName, bool aLib)
Replace illegal LIB_ID item name characters with underscores '_'.
 
Define a library symbol object.
 
bool IsPower() const override
 
virtual LIB_SYMBOL * Duplicate() const
Create a copy of a LIB_SYMBOL and assigns unique KIIDs to the copy and its children.
 
void SetAutoAdded(bool aAutoAdded)
 
void SetName(const wxString &aName)
 
void SetText(const wxString &aText) override
 
void SetNameShown(bool aShown=true)
 
void EnumerateSymbolLib(wxArrayString &aSymbolNameList, const wxString &aLibraryPath, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Populate a list of LIB_SYMBOL alias names contained within the library aLibraryPath.
 
std::unique_ptr< DATABASE_CONNECTION > m_conn
Generally will be null if no valid connection is established.
 
void GetDefaultSymbolFields(std::vector< wxString > &aNames) override
Retrieves a list of (custom) field names that should be shown by default for this library in the symb...
 
void ensureSettings(const wxString &aSettingsPath)
 
bool TestConnection(wxString *aErrorMsg=nullptr)
 
std::map< wxString, std::unique_ptr< LIB_SYMBOL > > m_nameToSymbolcache
 
std::map< wxString, std::pair< std::string, std::string > > m_sanitizedNameMap
 
std::set< wxString > m_defaultShownFields
 
virtual ~SCH_IO_DATABASE()
 
void GetSubLibraryNames(std::vector< wxString > &aNames) override
Retrieves a list of sub-libraries in this library.
 
std::unique_ptr< DATABASE_LIB_SETTINGS > m_settings
 
static std::optional< bool > boolFromAny(const std::any &aVal)
 
SYMBOL_LIBRARY_ADAPTER * m_adapter
 
long long m_cacheTimestamp
 
DIALOG_SHIM * CreateConfigurationDialog(wxWindow *aParent) override
 
void GetAvailableSymbolFields(std::vector< wxString > &aNames) override
Retrieves a list of (custom) field names that are present on symbols in this library.
 
std::unique_ptr< LIB_SYMBOL > loadSymbolFromRow(const wxString &aSymbolName, const DATABASE_LIB_TABLE &aTable, const DATABASE_CONNECTION::ROW &aRow)
 
std::set< wxString > m_customFields
 
LIB_SYMBOL * LoadSymbol(const wxString &aLibraryPath, const wxString &aAliasName, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Load a LIB_SYMBOL object having aPartName from the aLibraryPath containing a library format that this...
 
SCH_IO(const wxString &aName)
 
static const char * PropPowerSymsOnly
 
An 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to and fro...
 
const char * c_str() const
 
const char *const traceDatabase
 
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
 
static std::string strValue(double aValue)
 
bool visible_in_chooser
Whether the column is shown by default in the chooser.
 
std::string column
Database column name.
 
bool inherit_properties
Whether or not to inherit properties from symbol field.
 
bool visible_on_add
Whether to show the field when placing the symbol.
 
bool show_name
Whether or not to show the field name as well as its value.
 
wxString name_wx
KiCad field name (converted)
 
A database library table will be mapped to a sub-library provided by the database library entry in th...
 
std::string key_col
Unique key column name (will form part of the LIB_ID)
 
std::string name
KiCad library nickname (will form part of the LIB_ID)
 
std::string symbols_col
Column name containing KiCad symbol refs.
 
std::string footprints_col
Column name containing KiCad footprint refs.
 
std::vector< DATABASE_FIELD_MAPPING > fields
 
std::string table
Database table to pull content from.
 
MAPPABLE_SYMBOL_PROPERTIES properties
 
std::string footprint_filters
 
std::string exclude_from_sim
 
std::string exclude_from_board
 
std::string exclude_from_bom
 
@ USER
The field ID hasn't been set yet; field is invalid.
 
wxString result
Test unit parsing edge cases and error handling.