Skip to content

Commit

Permalink
Fix ogr and spatialite default values
Browse files Browse the repository at this point in the history
  • Loading branch information
elpaso committed Jan 27, 2020
1 parent 13681cc commit f259345
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 35 deletions.
14 changes: 6 additions & 8 deletions src/core/providers/ogr/qgsogrprovider.cpp
Expand Up @@ -1209,13 +1209,18 @@ void QgsOgrProvider::loadFields()
QString defaultValue = textEncoding()->toUnicode( OGR_Fld_GetDefault( fldDef ) );
if ( !defaultValue.isEmpty() && !OGR_Fld_IsDefaultDriverSpecific( fldDef ) )
{
if ( defaultValue.startsWith( '\'' ) )
{
defaultValue = defaultValue.remove( 0, 1 );
defaultValue.chop( 1 );
defaultValue.replace( QLatin1String( "''" ), QLatin1String( "'" ) );
}
mDefaultValues.insert( createdFields, defaultValue );
}

mAttributeFields.append( newField );
createdFields++;
}

}


Expand Down Expand Up @@ -1389,13 +1394,6 @@ QVariant QgsOgrProvider::defaultValue( int fieldId ) const
resultVar = QDate::currentDate();
else if ( defaultVal == QStringLiteral( "CURRENT_TIME" ) )
resultVar = QTime::currentTime();
else if ( defaultVal.startsWith( '\'' ) )
{
defaultVal = defaultVal.remove( 0, 1 );
defaultVal.chop( 1 );
defaultVal.replace( QLatin1String( "''" ), QLatin1String( "'" ) );
resultVar = defaultVal;
}

( void )mAttributeFields.at( fieldId ).convertCompatible( resultVar );
return resultVar;
Expand Down
66 changes: 49 additions & 17 deletions src/providers/spatialite/qgsspatialiteprovider.cpp
Expand Up @@ -956,19 +956,22 @@ void QgsSpatiaLiteProvider::insertDefaultValue( int fieldIndex, QString defaultV

if ( mAttributeFields.at( fieldIndex ).name() != mPrimaryKey || ( mAttributeFields.at( fieldIndex ).name() == mPrimaryKey && !mPrimaryKeyAutoIncrement ) )
{
bool ok;
switch ( mAttributeFields.at( fieldIndex ).type() )
{
case QVariant::LongLong:
defaultVariant = defaultVal.toLongLong();
defaultVariant = defaultVal.toLongLong( &ok );
break;

case QVariant::Double:
defaultVariant = defaultVal.toDouble();
defaultVariant = defaultVal.toDouble( &ok );
break;

default:
{
if ( defaultVal.startsWith( '\'' ) )
// Literal string?
ok = defaultVal.startsWith( '\'' );
if ( ok )
defaultVal = defaultVal.remove( 0, 1 );
if ( defaultVal.endsWith( '\'' ) )
defaultVal.chop( 1 );
Expand All @@ -978,14 +981,20 @@ void QgsSpatiaLiteProvider::insertDefaultValue( int fieldIndex, QString defaultV
break;
}
}

if ( ! ok ) // Must be a SQL clause
{
mDefaultValueClause.insert( fieldIndex, defaultVal );
}

}
mDefaultValues.insert( fieldIndex, defaultVariant );
mDefaultValues.insert( fieldIndex, defaultVal );
}
}

QString QgsSpatiaLiteProvider::defaultValueClause( int fieldIndex ) const
{
return mDefaultValues.value( fieldIndex, QString() ).toString();
return mDefaultValueClause.value( fieldIndex, QString() );
}

void QgsSpatiaLiteProvider::handleError( const QString &sql, char *errorMessage, bool rollback )
Expand Down Expand Up @@ -3962,7 +3971,7 @@ bool QgsSpatiaLiteProvider::addFeatures( QgsFeatureList &flist, Flags flags )
sqlite3_stmt *stmt = nullptr;
char *errMsg = nullptr;
bool toCommit = false;
QString values;
QString baseValues;
QString separator;
int ia, ret;
// SQL for single row
Expand All @@ -3978,19 +3987,20 @@ bool QgsSpatiaLiteProvider::addFeatures( QgsFeatureList &flist, Flags flags )
toCommit = true;

QString baseSql { QStringLiteral( "INSERT INTO %1(" ).arg( QgsSqliteUtils::quotedIdentifier( mTableName ) ) };
values = QStringLiteral( ") VALUES (" );
baseValues = QStringLiteral( ") VALUES (" );
separator.clear();

if ( !mGeometryColumn.isEmpty() )
{
baseSql += separator + QgsSqliteUtils::quotedIdentifier( mGeometryColumn );
values += separator + geomParam();
baseValues += separator + geomParam();
separator = ',';
}

for ( QgsFeatureList::iterator feature = flist.begin(); feature != flist.end(); ++feature )
{

QString values { baseValues };
sql = baseSql;

// looping on each feature to insert
Expand All @@ -4001,7 +4011,7 @@ bool QgsSpatiaLiteProvider::addFeatures( QgsFeatureList &flist, Flags flags )

for ( int i = 0; i < attributevec.count(); ++i )
{
if ( mDefaultValues.contains( i ) && defaultValue( i ) == attributevec.at( i ).toString() )
if ( mDefaultValues.contains( i ) && mDefaultValues.value( i ) == attributevec.at( i ).toString() )
{
defaultIndexes.push_back( i );
continue;
Expand Down Expand Up @@ -4125,7 +4135,7 @@ bool QgsSpatiaLiteProvider::addFeatures( QgsFeatureList &flist, Flags flags )
// performing actual row insert
ret = sqlite3_step( stmt );

qDebug() << sqlite3_expanded_sql( stmt );
sqlite3_finalize( stmt );

if ( ret == SQLITE_DONE || ret == SQLITE_ROW )
{
Expand All @@ -4145,14 +4155,13 @@ bool QgsSpatiaLiteProvider::addFeatures( QgsFeatureList &flist, Flags flags )
break;
}
}
} // prepared statement

sqlite3_finalize( stmt );
if ( ret == SQLITE_DONE || ret == SQLITE_ROW )
{
ret = sqlite3_exec( mSqliteHandle, "COMMIT", nullptr, nullptr, &errMsg );
}

if ( ret == SQLITE_DONE || ret == SQLITE_ROW )
{
ret = sqlite3_exec( mSqliteHandle, "COMMIT", nullptr, nullptr, &errMsg );
}
} // prepared statement
} // BEGIN statement

if ( ret != SQLITE_OK )
Expand Down Expand Up @@ -4552,7 +4561,30 @@ QgsVectorDataProvider::Capabilities QgsSpatiaLiteProvider::capabilities() const

QVariant QgsSpatiaLiteProvider::defaultValue( int fieldId ) const
{
return mDefaultValues.value( fieldId, QVariant() );
if ( fieldId < 0 || fieldId >= mAttributeFields.count() )
return QVariant();

QString defaultVal = mDefaultValues.value( fieldId, QString() );
if ( defaultVal.isEmpty() )
return QVariant();

QVariant resultVar = defaultVal;
if ( defaultVal == QStringLiteral( "CURRENT_TIMESTAMP" ) )
resultVar = QDateTime::currentDateTime();
else if ( defaultVal == QStringLiteral( "CURRENT_DATE" ) )
resultVar = QDate::currentDate();
else if ( defaultVal == QStringLiteral( "CURRENT_TIME" ) )
resultVar = QTime::currentTime();
else if ( defaultVal.startsWith( '\'' ) )
{
defaultVal = defaultVal.remove( 0, 1 );
defaultVal.chop( 1 );
defaultVal.replace( QLatin1String( "''" ), QLatin1String( "'" ) );
resultVar = defaultVal;
}

( void )mAttributeFields.at( fieldId ).convertCompatible( resultVar );
return resultVar;
}

bool QgsSpatiaLiteProvider::skipConstraintCheck( int fieldIndex, QgsFieldConstraints::Constraint constraint, const QVariant &value ) const
Expand Down
5 changes: 4 additions & 1 deletion src/providers/spatialite/qgsspatialiteprovider.h
Expand Up @@ -221,6 +221,9 @@ class QgsSpatiaLiteProvider: public QgsVectorDataProvider

QgsFields mAttributeFields;

//! Map of field index to default value SQL fragments
QMap<int, QString> mDefaultValueClause;

//! Flag indicating if the layer data source is a valid SpatiaLite layer
bool mValid = false;

Expand Down Expand Up @@ -264,7 +267,7 @@ class QgsSpatiaLiteProvider: public QgsVectorDataProvider
QString mGeometryColumn;

//! Map of field index to default value
QMap<int, QVariant> mDefaultValues;
QMap<int, QString> mDefaultValues;

//! Name of the SpatialIndex table
QString mIndexTable;
Expand Down
12 changes: 7 additions & 5 deletions tests/src/python/test_provider_ogr.py
Expand Up @@ -630,10 +630,11 @@ def testSpatialiteDefaultValues(self):
sql = """
CREATE TABLE test_table (
id integer primary key autoincrement,
comment text,
comment TEXT,
created_at_01 text DEFAULT (datetime('now','localtime')),
created_at_02 text DEFAULT CURRENT_TIMESTAMP,
anumber INTEGER DEFAULT 123
anumber INTEGER DEFAULT 123,
atext TEXT default 'My default'
)
"""
cur.execute(sql)
Expand All @@ -644,8 +645,8 @@ def testSpatialiteDefaultValues(self):
self.assertTrue(vl.isValid())
feature = QgsFeature(vl.fields())
for idx in range(vl.fields().count()):
default = vl.dataProvider().defaultValueClause(idx)
if default != '':
default = vl.dataProvider().defaultValue(idx)
if default is not None:
feature.setAttribute(idx, default)
else:
feature.setAttribute(idx, 'A comment')
Expand All @@ -660,10 +661,11 @@ def testSpatialiteDefaultValues(self):
vl2 = QgsVectorLayer(dbname + '|layername=test_table', 'test_table', 'ogr')
self.assertTrue(vl2.isValid())
feature = next(vl2.getFeatures())
self.assertEqual(feature.attribute(1), 'A comment')
self.assertTrue(feature.attribute(2).startswith(now.strftime('%Y-%m-%d')))
self.assertTrue(feature.attribute(3).startswith(now.strftime('%Y-%m-%d')))
self.assertEqual(feature.attribute(4), 123)
self.assertEqual(feature.attribute(1), 'A comment')
self.assertEqual(feature.attribute(5), 'My default')


if __name__ == '__main__':
Expand Down
11 changes: 7 additions & 4 deletions tests/src/python/test_provider_spatialite.py
Expand Up @@ -1166,7 +1166,7 @@ def testSpatialiteDefaultValues(self):

# Create the test table

dbname = os.path.join(tempfile.gettempdir(), "test.sqlite")
dbname = os.path.join(tempfile.gettempdir(), "test_default_values.sqlite")
if os.path.exists(dbname):
os.remove(dbname)
con = spatialite_connect(dbname, isolation_level=None)
Expand All @@ -1182,7 +1182,8 @@ def testSpatialiteDefaultValues(self):
comment text,
created_at_01 text DEFAULT (datetime('now','localtime')),
created_at_02 text DEFAULT CURRENT_TIMESTAMP,
anumber INTEGER DEFAULT 123
anumber INTEGER DEFAULT 123,
atext TEXT default 'My default'
)
"""
cur.execute(sql)
Expand All @@ -1193,8 +1194,8 @@ def testSpatialiteDefaultValues(self):
self.assertTrue(vl.isValid())
feature = QgsFeature(vl.fields())
for idx in range(vl.fields().count()):
default = vl.dataProvider().defaultValueClause(idx)
if default != '':
default = vl.dataProvider().defaultValue(idx)
if default is not None:
feature.setAttribute(idx, default)
else:
feature.setAttribute(idx, 'A comment')
Expand All @@ -1209,9 +1210,11 @@ def testSpatialiteDefaultValues(self):
vl2 = QgsVectorLayer("dbname='%s' table='test_table'" % dbname, 'test_table', 'spatialite')
self.assertTrue(vl2.isValid())
feature = next(vl2.getFeatures())
self.assertEqual(feature.attribute(1), 'A comment')
self.assertTrue(feature.attribute(2).startswith(now.strftime('%Y-%m-%d')))
self.assertTrue(feature.attribute(3).startswith(now.strftime('%Y-%m-%d')))
self.assertEqual(feature.attribute(4), 123)
self.assertEqual(feature.attribute(5), 'My default')


if __name__ == '__main__':
Expand Down

0 comments on commit f259345

Please sign in to comment.