Performance optimizations for database libraries.

This commit is contained in:
Alex Shvartzkop 2024-02-19 23:45:24 +03:00 committed by dsa-t
parent 3e26e7b646
commit e68df8e1d1
8 changed files with 106 additions and 54 deletions

View File

@ -448,7 +448,7 @@ bool DATABASE_CONNECTION::SelectOne( const std::string& aTable,
{ {
aResult[column] = fmt::format( "{:G}", results.get<double>( i ) ); aResult[column] = fmt::format( "{:G}", results.get<double>( i ) );
} }
catch( nanodbc::null_access_error& e ) catch( nanodbc::null_access_error& )
{ {
// Column was empty (null) // Column was empty (null)
aResult[column] = std::string(); aResult[column] = std::string();
@ -498,6 +498,8 @@ bool DATABASE_CONNECTION::SelectAll( const std::string& aTable, const std::strin
{ {
wxLogTrace( traceDatabase, wxT( "SelectAll: `%s` - cache hit" ), aTable ); wxLogTrace( traceDatabase, wxT( "SelectAll: `%s` - cache hit" ), aTable );
aResults.reserve( cacheEntry.size() );
for( auto &[ key, row ] : cacheEntry ) for( auto &[ key, row ] : cacheEntry )
aResults.emplace_back( row ); aResults.emplace_back( row );
@ -605,7 +607,7 @@ bool DATABASE_CONNECTION::SelectAll( const std::string& aTable, const std::strin
{ {
result[column] = fmt::format( "{:G}", results.get<double>( j ) ); result[column] = fmt::format( "{:G}", results.get<double>( j ) );
} }
catch( nanodbc::null_access_error& e ) catch( nanodbc::null_access_error& )
{ {
// Column was empty (null) // Column was empty (null)
result[column] = std::string(); result[column] = std::string();

View File

@ -32,6 +32,17 @@
const int dblibSchemaVersion = 1; const int dblibSchemaVersion = 1;
DATABASE_FIELD_MAPPING::DATABASE_FIELD_MAPPING( std::string aColumn, std::string aName,
bool aVisibleOnAdd, bool aVisibleInChooser,
bool aShowName, bool aInheritProperties ) :
column( aColumn ),
name( aName ), name_wx( aName.c_str(), wxConvUTF8 ), visible_on_add( aVisibleOnAdd ),
visible_in_chooser( aVisibleInChooser ), show_name( aShowName ),
inherit_properties( aInheritProperties )
{
}
DATABASE_LIB_SETTINGS::DATABASE_LIB_SETTINGS( const std::string& aFilename ) : DATABASE_LIB_SETTINGS::DATABASE_LIB_SETTINGS( const std::string& aFilename ) :
JSON_SETTINGS( aFilename, SETTINGS_LOC::NONE, dblibSchemaVersion ) JSON_SETTINGS( aFilename, SETTINGS_LOC::NONE, dblibSchemaVersion )
{ {
@ -113,11 +124,8 @@ DATABASE_LIB_SETTINGS::DATABASE_LIB_SETTINGS( const std::string& aFilename ) :
bool inherit = fetchOrDefault<bool>( fieldJson, "inherit_properties" ); bool inherit = fetchOrDefault<bool>( fieldJson, "inherit_properties" );
table.fields.emplace_back( table.fields.emplace_back(
DATABASE_FIELD_MAPPING( DATABASE_FIELD_MAPPING( column, name, visible_on_add,
{ visible_in_chooser, show_name, inherit ) );
column, name, visible_on_add, visible_in_chooser, show_name,
inherit
} ) );
} }
} }

View File

@ -313,40 +313,40 @@ wxString UnescapeString( const wxString& aSource )
} }
else else
{ {
token.append( ch ); token << ch;
} }
} }
if( !terminated ) if( !terminated )
{ {
newbuf.append( wxT( "{" ) + UnescapeString( token ) ); newbuf << wxT( "{" ) << UnescapeString( token );
} }
else if( prev == '$' || prev == '~' || prev == '^' || prev == '_' ) else if( prev == '$' || prev == '~' || prev == '^' || prev == '_' )
{ {
newbuf.append( wxT( "{" ) + UnescapeString( token ) + wxT( "}" ) ); newbuf << wxT( "{" ) << UnescapeString( token ) << wxT( "}" );
} }
else if( token == wxT( "dblquote" ) ) newbuf.append( wxT( "\"" ) ); else if( token == wxT( "dblquote" ) ) newbuf << wxT( "\"" );
else if( token == wxT( "quote" ) ) newbuf.append( wxT( "'" ) ); else if( token == wxT( "quote" ) ) newbuf << wxT( "'" );
else if( token == wxT( "lt" ) ) newbuf.append( wxT( "<" ) ); else if( token == wxT( "lt" ) ) newbuf << wxT( "<" );
else if( token == wxT( "gt" ) ) newbuf.append( wxT( ">" ) ); else if( token == wxT( "gt" ) ) newbuf << wxT( ">" );
else if( token == wxT( "backslash" ) ) newbuf.append( wxT( "\\" ) ); else if( token == wxT( "backslash" ) ) newbuf << wxT( "\\" );
else if( token == wxT( "slash" ) ) newbuf.append( wxT( "/" ) ); else if( token == wxT( "slash" ) ) newbuf << wxT( "/" );
else if( token == wxT( "bar" ) ) newbuf.append( wxT( "|" ) ); else if( token == wxT( "bar" ) ) newbuf << wxT( "|" );
else if( token == wxT( "comma" ) ) newbuf.append( wxT( "," ) ); else if( token == wxT( "comma" ) ) newbuf << wxT( "," );
else if( token == wxT( "colon" ) ) newbuf.append( wxT( ":" ) ); else if( token == wxT( "colon" ) ) newbuf << wxT( ":" );
else if( token == wxT( "space" ) ) newbuf.append( wxT( " " ) ); else if( token == wxT( "space" ) ) newbuf << wxT( " " );
else if( token == wxT( "dollar" ) ) newbuf.append( wxT( "$" ) ); else if( token == wxT( "dollar" ) ) newbuf << wxT( "$" );
else if( token == wxT( "tab" ) ) newbuf.append( wxT( "\t" ) ); else if( token == wxT( "tab" ) ) newbuf << wxT( "\t" );
else if( token == wxT( "return" ) ) newbuf.append( wxT( "\n" ) ); else if( token == wxT( "return" ) ) newbuf << wxT( "\n" );
else if( token == wxT( "brace" ) ) newbuf.append( wxT( "{" ) ); else if( token == wxT( "brace" ) ) newbuf << wxT( "{" );
else else
{ {
newbuf.append( wxT( "{" ) + UnescapeString( token ) + wxT( "}" ) ); newbuf << wxT( "{" ) << UnescapeString( token ) << wxT( "}" );
} }
} }
else else
{ {
newbuf.append( ch ); newbuf << ch;
} }
} }
@ -785,11 +785,14 @@ int StrNumCmp( const wxString& aString1, const wxString& aString2, bool aIgnoreC
// Any numerical comparisons to here are identical. // Any numerical comparisons to here are identical.
if( aIgnoreCase ) if( aIgnoreCase )
{ {
if( wxToupper( c1 ) < wxToupper( c2 ) ) if( c1 != c2 )
return -1; {
wxUniChar uc1 = wxToupper( c1 );
wxUniChar uc2 = wxToupper( c2 );
if( wxToupper( c1 ) > wxToupper( c2 ) ) if( uc1 != uc2 )
return 1; return uc1 < uc2 ? -1 : 1;
}
} }
else else
{ {

View File

@ -54,8 +54,16 @@ const wxString TEMPLATE_FIELDNAME::GetDefaultFieldName( int aFieldNdx, bool aTra
case FOOTPRINT_FIELD: return s_CanonicalFootprint; // The footprint for use with Pcbnew case FOOTPRINT_FIELD: return s_CanonicalFootprint; // The footprint for use with Pcbnew
case DATASHEET_FIELD: return s_CanonicalDatasheet; // Link to a datasheet for symbol case DATASHEET_FIELD: return s_CanonicalDatasheet; // Link to a datasheet for symbol
case DESCRIPTION_FIELD: return s_CanonicalDescription; // The symbol description case DESCRIPTION_FIELD: return s_CanonicalDescription; // The symbol description
default: return wxString::Format( wxT( "Field%d" ), aFieldNdx ); default: break;
} }
wxString str( wxS( "Field" ) );
#if wxUSE_UNICODE_WCHAR
str << std::to_wstring( aFieldNdx );
#else
str << std::to_string( aFieldNdx );
#endif
return str;
} }
switch( aFieldNdx ) switch( aFieldNdx )

View File

@ -568,6 +568,9 @@ LIB_SYMBOL* SCH_IO_DATABASE::loadSymbolFromRow( const wxString& aSymbolName,
for( LIB_FIELD* field : fields ) for( LIB_FIELD* field : fields )
fieldsMap[field->GetName()] = field; fieldsMap[field->GetName()] = field;
static const wxString c_valueFieldName( wxS( "Value" ) );
static const wxString c_datasheetFieldName( wxS( "Datasheet" ) );
for( const DATABASE_FIELD_MAPPING& mapping : aTable.fields ) for( const DATABASE_FIELD_MAPPING& mapping : aTable.fields )
{ {
if( !aRow.count( mapping.column ) ) if( !aRow.count( mapping.column ) )
@ -577,7 +580,7 @@ LIB_SYMBOL* SCH_IO_DATABASE::loadSymbolFromRow( const wxString& aSymbolName,
continue; continue;
} }
std:: string strValue; std::string strValue;
try try
{ {
@ -589,7 +592,7 @@ LIB_SYMBOL* SCH_IO_DATABASE::loadSymbolFromRow( const wxString& aSymbolName,
wxString value( strValue.c_str(), wxConvUTF8 ); wxString value( strValue.c_str(), wxConvUTF8 );
if( mapping.name == wxT( "Value" ) ) if( mapping.name_wx == c_valueFieldName )
{ {
LIB_FIELD& field = symbol->GetValueField(); LIB_FIELD& field = symbol->GetValueField();
field.SetText( value ); field.SetText( value );
@ -601,7 +604,7 @@ LIB_SYMBOL* SCH_IO_DATABASE::loadSymbolFromRow( const wxString& aSymbolName,
} }
continue; continue;
} }
else if( mapping.name == wxT( "Datasheet" ) ) else if( mapping.name_wx == c_datasheetFieldName )
{ {
LIB_FIELD& field = symbol->GetDatasheetField(); LIB_FIELD& field = symbol->GetDatasheetField();
field.SetText( value ); field.SetText( value );
@ -621,16 +624,16 @@ LIB_SYMBOL* SCH_IO_DATABASE::loadSymbolFromRow( const wxString& aSymbolName,
LIB_FIELD* field; LIB_FIELD* field;
bool isNew = false; bool isNew = false;
if( fieldsMap.count( mapping.name ) ) if( fieldsMap.count( mapping.name_wx ) )
{ {
field = fieldsMap[mapping.name]; field = fieldsMap[mapping.name_wx];
} }
else else
{ {
field = new LIB_FIELD( symbol->GetNextAvailableFieldId() ); field = new LIB_FIELD( symbol->GetNextAvailableFieldId() );
field->SetName( mapping.name ); field->SetName( mapping.name_wx );
isNew = true; isNew = true;
fieldsMap[mapping.name] = field; fieldsMap[mapping.name_wx] = field;
} }
if( !mapping.inherit_properties || isNew ) if( !mapping.inherit_properties || isNew )
@ -643,13 +646,15 @@ LIB_SYMBOL* SCH_IO_DATABASE::loadSymbolFromRow( const wxString& aSymbolName,
field->SetText( value ); field->SetText( value );
if( isNew ) if( isNew )
symbol->AddField( field ); symbol->AddDrawItem( field, false );
m_customFields.insert( mapping.name ); m_customFields.insert( mapping.name_wx );
if( mapping.visible_in_chooser ) if( mapping.visible_in_chooser )
m_defaultShownFields.insert( mapping.name ); m_defaultShownFields.insert( mapping.name_wx );
} }
symbol->GetDrawItems().sort();
return symbol; return symbol;
} }

View File

@ -1644,12 +1644,21 @@ void SIM_MODEL::MigrateSimModel( T_symbol& aSymbol, const PROJECT* aProject )
wxString prefix = aSymbol.GetPrefix(); wxString prefix = aSymbol.GetPrefix();
T_field* valueField = aSymbol.FindField( wxT( "Value" ) ); T_field* valueField = aSymbol.FindField( wxT( "Value" ) );
std::vector<LIB_PIN*> sourcePins = aSymbol.GetAllLibPins(); std::vector<LIB_PIN*> sourcePins = aSymbol.GetAllLibPins();
bool sourcePinsSorted = false;
std::sort( sourcePins.begin(), sourcePins.end(), auto lazySortSourcePins = [&sourcePins, &sourcePinsSorted]()
[]( const LIB_PIN* lhs, const LIB_PIN* rhs ) {
{ if( !sourcePinsSorted )
return StrNumCmp( lhs->GetNumber(), rhs->GetNumber(), true ) < 0; {
} ); std::sort( sourcePins.begin(), sourcePins.end(),
[]( const LIB_PIN* lhs, const LIB_PIN* rhs )
{
return StrNumCmp( lhs->GetNumber(), rhs->GetNumber(), true ) < 0;
} );
}
sourcePinsSorted = true;
};
FIELD_INFO deviceInfo; FIELD_INFO deviceInfo;
FIELD_INFO modelInfo; FIELD_INFO modelInfo;
@ -1740,6 +1749,8 @@ void SIM_MODEL::MigrateSimModel( T_symbol& aSymbol, const PROJECT* aProject )
wxStringSplit( legacyPins->GetText(), pinIndexes, ' ' ); wxStringSplit( legacyPins->GetText(), pinIndexes, ' ' );
lazySortSourcePins();
if( isPassive && pinIndexes.size() == 2 && sourcePins.size() == 2 ) if( isPassive && pinIndexes.size() == 2 && sourcePins.size() == 2 )
{ {
if( pinIndexes[0] == wxT( "2" ) ) if( pinIndexes[0] == wxT( "2" ) )
@ -1800,6 +1811,8 @@ void SIM_MODEL::MigrateSimModel( T_symbol& aSymbol, const PROJECT* aProject )
model = model.BeforeFirst( ' ', &modelLineParams ); model = model.BeforeFirst( ' ', &modelLineParams );
modelInfo.m_Text = model; modelInfo.m_Text = model;
lazySortSourcePins();
SIM_LIBRARY::MODEL simModel = libMgr.CreateModel( lib, model.ToStdString(), SIM_LIBRARY::MODEL simModel = libMgr.CreateModel( lib, model.ToStdString(),
emptyFields, sourcePins, reporter ); emptyFields, sourcePins, reporter );
@ -1873,6 +1886,8 @@ void SIM_MODEL::MigrateSimModel( T_symbol& aSymbol, const PROJECT* aProject )
if( pinMapInfo.IsEmpty() ) if( pinMapInfo.IsEmpty() )
{ {
lazySortSourcePins();
// Generate a default pin map from the SIM_MODEL's pins // Generate a default pin map from the SIM_MODEL's pins
simModel->createPins( sourcePins ); simModel->createPins( sourcePins );
pinMapInfo.m_Text = wxString( simModel->Serializer().GeneratePins() ); pinMapInfo.m_Text = wxString( simModel->Serializer().GeneratePins() );
@ -1979,7 +1994,10 @@ void SIM_MODEL::MigrateSimModel( T_symbol& aSymbol, const PROJECT* aProject )
// the default pin map from the symbol's pins. // the default pin map from the symbol's pins.
if( pinMapInfo.IsEmpty() ) if( pinMapInfo.IsEmpty() )
{
lazySortSourcePins();
pinMapInfo.m_Text = generateDefaultPinMapFromSymbol( sourcePins ); pinMapInfo.m_Text = generateDefaultPinMapFromSymbol( sourcePins );
}
} }
if( !pinMapInfo.IsEmpty() ) if( !pinMapInfo.IsEmpty() )

View File

@ -163,13 +163,15 @@ bool SYMBOL_TREE_MODEL_ADAPTER::AddLibraries( const std::vector<wxString>& aNick
if( !parentDesc.IsEmpty() ) if( !parentDesc.IsEmpty() )
desc = wxString::Format( wxT( "%s (%s)" ), parentDesc, lib ); desc = wxString::Format( wxT( "%s (%s)" ), parentDesc, lib );
UTF8 utf8Lib( lib );
std::vector<LIB_SYMBOL*> symbols; std::vector<LIB_SYMBOL*> symbols;
std::copy_if( libSymbols.begin(), libSymbols.end(), std::copy_if( libSymbols.begin(), libSymbols.end(),
std::back_inserter( symbols ), std::back_inserter( symbols ),
[&lib]( LIB_SYMBOL* aSym ) [&utf8Lib]( LIB_SYMBOL* aSym )
{ {
return lib.IsSameAs( aSym->GetLibId().GetSubLibraryName() ); return utf8Lib == aSym->GetLibId().GetSubLibraryName();
} ); } );
addFunc( name, symbols, desc ); addFunc( name, symbols, desc );

View File

@ -22,6 +22,7 @@
#define KICAD_DATABASE_LIB_SETTINGS_H #define KICAD_DATABASE_LIB_SETTINGS_H
#include <settings/json_settings.h> #include <settings/json_settings.h>
#include <wx/string.h>
enum class DATABASE_SOURCE_TYPE enum class DATABASE_SOURCE_TYPE
@ -44,12 +45,17 @@ struct DATABASE_SOURCE
struct DATABASE_FIELD_MAPPING struct DATABASE_FIELD_MAPPING
{ {
std::string column; ///< Database column name const std::string column; ///< Database column name
std::string name; ///< KiCad field name const std::string name; ///< KiCad field name
bool visible_on_add; ///< Whether to show the field when placing the symbol const wxString name_wx; ///< KiCad field name (converted)
bool visible_in_chooser; ///< Whether the column is shown by default in the chooser const 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 const bool visible_in_chooser; ///< Whether the column is shown by default in the chooser
bool inherit_properties; ///< Whether or not to inherit properties from symbol field const bool show_name; ///< Whether or not to show the field name as well as its value
const bool inherit_properties; ///< Whether or not to inherit properties from symbol field
explicit DATABASE_FIELD_MAPPING( std::string aColumn, std::string aName, bool aVisibleOnAdd,
bool aVisibleInChooser, bool aShowName,
bool aInheritProperties );
}; };