[FEATURE] Detect literal default values for spatialite provider

This commit is contained in:
Nyall Dawson 2016-11-07 14:33:44 +10:00
parent 1fea20de50
commit 0ae610c5e3
3 changed files with 66 additions and 1 deletions

View File

@ -684,6 +684,7 @@ void QgsSpatiaLiteProvider::loadFieldsAbstractInterface( gaiaVectorLayerPtr lyr
mAttributeFields.clear();
mPrimaryKey.clear(); // cazzo cazzo cazzo
mPrimaryKeyAttrs.clear();
mDefaultValues.clear();
gaiaLayerAttributeFieldPtr fld = lyr->First;
if ( !fld )
@ -729,6 +730,8 @@ void QgsSpatiaLiteProvider::loadFieldsAbstractInterface( gaiaVectorLayerPtr lyr
for ( int i = 1; i <= rows; i++ )
{
QString name = QString::fromUtf8( results[( i * columns ) + 1] );
insertDefaultValue( i - 1, QString::fromUtf8( results[( i * columns ) + 4] ) );
QString pk = results[( i * columns ) + 5];
QString type = results[( i * columns ) + 2];
type = type.toLower();
@ -870,6 +873,37 @@ error:
}
void QgsSpatiaLiteProvider::insertDefaultValue( int fieldIndex, QString defaultVal )
{
if ( !defaultVal.isEmpty() )
{
QVariant defaultVariant;
switch ( mAttributeFields.at( fieldIndex ).type() )
{
case QVariant::LongLong:
defaultVariant = defaultVal.toLongLong();
break;
case QVariant::Double:
defaultVariant = defaultVal.toDouble();
break;
default:
{
if ( defaultVal.startsWith( '\'' ) )
defaultVal = defaultVal.remove( 0, 1 );
if ( defaultVal.endsWith( '\'' ) )
defaultVal.chop( 1 );
defaultVal.replace( "''", "'" );
defaultVariant = defaultVal;
break;
}
}
mDefaultValues.insert( fieldIndex, defaultVariant );
}
}
void QgsSpatiaLiteProvider::loadFields()
{
int ret;
@ -884,6 +918,7 @@ void QgsSpatiaLiteProvider::loadFields()
QString sql;
mAttributeFields.clear();
mDefaultValues.clear();
if ( !mIsQuery )
{
@ -921,6 +956,8 @@ void QgsSpatiaLiteProvider::loadFields()
const TypeSubType fieldType = getVariantType( type );
mAttributeFields.append( QgsField( name, fieldType.first, type, 0, 0, QString(), fieldType.second ) );
}
insertDefaultValue( i - 1, QString::fromUtf8( results[( i * columns ) + 4] ) );
}
}
sqlite3_free_table( results );
@ -3820,8 +3857,10 @@ bool QgsSpatiaLiteProvider::addFeatures( QgsFeatureList & flist )
}
else if ( type == QVariant::String )
{
QString stringVal = v.toString();
// binding a TEXT value
QByteArray ba = v.toString().toUtf8();
QByteArray ba = stringVal.toUtf8();
sqlite3_bind_text( stmt, ++ia, ba.constData(), ba.size(), SQLITE_TRANSIENT );
}
else if ( type == QVariant::StringList || type == QVariant::List )
@ -4229,6 +4268,11 @@ QgsVectorDataProvider::Capabilities QgsSpatiaLiteProvider::capabilities() const
return mEnabledCapabilities;
}
QVariant QgsSpatiaLiteProvider::defaultValue( int fieldId ) const
{
return mDefaultValues.value( fieldId, QVariant() );
}
void QgsSpatiaLiteProvider::closeDb()
{
// trying to close the SQLite DB

View File

@ -165,6 +165,8 @@ class QgsSpatiaLiteProvider: public QgsVectorDataProvider
//! Returns a bitmask containing the supported capabilities
QgsVectorDataProvider::Capabilities capabilities() const override;
QVariant defaultValue( int fieldId ) const override;
/** The SpatiaLite provider does its own transforms so we return
* true for the following three functions to indicate that transforms
* should not be handled by the QgsCoordinateTransform object. See the
@ -338,6 +340,9 @@ class QgsSpatiaLiteProvider: public QgsVectorDataProvider
//! Name of the geometry column in the table
QString mGeometryColumn;
//! Map of field index to default value
QMap<int, QVariant> mDefaultValues;
//! Name of the SpatialIndex table
QString mIndexTable;
@ -448,6 +453,8 @@ class QgsSpatiaLiteProvider: public QgsVectorDataProvider
void fetchConstraints();
void insertDefaultValue( int fieldIndex, QString defaultVal );
enum GEOS_3D
{
GEOS_3D_POINT = -2147483647,

View File

@ -139,6 +139,10 @@ class TestQgsSpatialiteProvider(unittest.TestCase, ProviderTestCase):
sql = "CREATE TABLE test_constraints(id INTEGER PRIMARY KEY, num INTEGER NOT NULL, desc TEXT UNIQUE, desc2 TEXT, num2 INTEGER NOT NULL UNIQUE)"
cur.execute(sql)
# simple table with defaults
sql = "CREATE TABLE test_defaults (id INTEGER NOT NULL PRIMARY KEY, name TEXT DEFAULT 'qgis ''is good', number INTEGER DEFAULT 5, number2 REAL DEFAULT 5.7, no_default REAL)"
cur.execute(sql)
cur.execute("COMMIT")
con.close()
@ -461,6 +465,16 @@ class TestQgsSpatialiteProvider(unittest.TestCase, ProviderTestCase):
self.assertTrue(vl.commitChanges())
def testDefaultValues(self):
l = QgsVectorLayer("dbname=%s table='test_defaults' key='id'" % self.dbname, "test_defaults", "spatialite")
self.assertTrue(l.isValid())
self.assertEqual(l.dataProvider().defaultValue(1), "qgis 'is good")
self.assertEqual(l.dataProvider().defaultValue(2), 5)
self.assertEqual(l.dataProvider().defaultValue(3), 5.7)
self.assertFalse(l.dataProvider().defaultValue(4))
if __name__ == '__main__':
unittest.main()