Skip to content

Commit

Permalink
Catch and fix uninitialized QStrings passed to SQL code.
Browse files Browse the repository at this point in the history
Most of Qt5 treats an uninitialized string and an empty string as the
same thing.  QSqlQuery doesn't, storing NULL for the former and "" for
the latter.  Add a new function for storing a non-null database field
that will store both of these QStrings as "".

Fixes #13420
  • Loading branch information
linuxdude42 committed Mar 6, 2019
1 parent 5de99ad commit fcc1aa5
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 9 deletions.
10 changes: 10 additions & 0 deletions mythtv/libs/libmythbase/mythdbcon.cpp
Expand Up @@ -866,6 +866,16 @@ void MSqlQuery::bindValue(const QString &placeholder, const QVariant &val)
QSqlQuery::bindValue(placeholder, val, QSql::In);
}

void MSqlQuery::bindValueNoNull(const QString &placeholder, const QVariant &val)
{
if ((val.type() == QVariant::String) && val.isNull())
{
QSqlQuery::bindValue(placeholder, QString(""), QSql::In);
return;
}
QSqlQuery::bindValue(placeholder, val, QSql::In);
}

void MSqlQuery::bindValues(const MSqlBindings &bindings)
{
MSqlBindings::const_iterator it;
Expand Down
16 changes: 16 additions & 0 deletions mythtv/libs/libmythbase/mythdbcon.h
Expand Up @@ -159,8 +159,24 @@ class MBASE_PUBLIC MSqlQuery : private QSqlQuery
/// \brief QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2
bool prepare(const QString &query);

/// \brief Add a single binding
void bindValue(const QString &placeholder, const QVariant &val);

/// \brief Add a single binding, taking care not to set a NULL value.
///
/// Most of Qt5 treats an uninitialized (i.e. null) string and an
/// empty string as the same thing, but not the QSqlQuery code.
/// This means that an uninitialized QString() and an explicitly
/// initialized to empty QString("") both represent an empty
/// string everywhere in Qt except in the QSqlQuery code. This
/// function adds the same behavior to SQL queries, by checking
/// and substituting a QString("") where necessary. This function
/// should be used for any database string field that has been
/// declared "NOT NULL" so that MythTV won't throw an errors
/// complaining about trying to set a NULL value in a SQL column
/// that's marked "non-NULL".
void bindValueNoNull(const QString &placeholder, const QVariant &val);

/// \brief Add all the bindings in the passed in bindings
void bindValues(const MSqlBindings &bindings);

Expand Down
18 changes: 9 additions & 9 deletions mythtv/libs/libmythtv/channelinfo.cpp
Expand Up @@ -323,26 +323,26 @@ bool ChannelInsertInfo::SaveScan(uint scanid, uint transportid) const
query.bindValue(":MPLEX_ID", m_db_mplexid);
query.bindValue(":SOURCE_ID", m_source_id);
query.bindValue(":CHANNEL_ID", m_channel_id);
query.bindValue(":CALLSIGN", m_callsign);
query.bindValue(":SERVICE_NAME", m_service_name);
query.bindValue(":CHAN_NUM", m_chan_num);
query.bindValueNoNull(":CALLSIGN", m_callsign);
query.bindValueNoNull(":SERVICE_NAME", m_service_name);
query.bindValueNoNull(":CHAN_NUM", m_chan_num);
query.bindValue(":SERVICE_ID", m_service_id);
query.bindValue(":ATSC_MAJOR_CHANNEL", m_atsc_major_channel);
query.bindValue(":ATSC_MINOR_CHANNEL", m_atsc_minor_channel);
query.bindValue(":USE_ON_AIR_GUIDE", m_use_on_air_guide);
query.bindValue(":HIDDEN", m_hidden);
query.bindValue(":HIDDEN_IN_GUIDE", m_hidden_in_guide);
query.bindValue(":FREQID", m_freqid);
query.bindValue(":ICON", m_icon);
query.bindValue(":TVFORMAT", m_format);
query.bindValue(":XMLTVID", m_xmltvid);
query.bindValueNoNull(":FREQID", m_freqid);
query.bindValueNoNull(":ICON", m_icon);
query.bindValueNoNull(":TVFORMAT", m_format);
query.bindValueNoNull(":XMLTVID", m_xmltvid);
query.bindValue(":PAT_TSID", m_pat_tsid);
query.bindValue(":VCT_TSID", m_vct_tsid);
query.bindValue(":VCT_CHAN_TSID", m_vct_chan_tsid);
query.bindValue(":SDT_TSID", m_sdt_tsid);
query.bindValue(":ORIG_NETID", m_orig_netid);
query.bindValue(":NETID", m_netid);
query.bindValue(":SI_STANDARD", m_si_standard);
query.bindValueNoNull(":SI_STANDARD", m_si_standard);
query.bindValue(":IN_CHANNELS_CONF", m_in_channels_conf);
query.bindValue(":IN_PAT", m_in_pat);
query.bindValue(":IN_PMT", m_in_pmt);
Expand All @@ -355,7 +355,7 @@ bool ChannelInsertInfo::SaveScan(uint scanid, uint transportid) const
query.bindValue(":IS_OPEBCABLE", m_is_opencable);
query.bindValue(":COULD_BE_OPENCABLE", m_could_be_opencable);
query.bindValue(":DECRYPTION_STATUS", m_decryption_status);
query.bindValue(":DEFAULT_AUTHORITY", m_default_authority);
query.bindValueNoNull(":DEFAULT_AUTHORITY", m_default_authority);

if (!query.exec())
{
Expand Down

0 comments on commit fcc1aa5

Please sign in to comment.