diff --git a/src/core/qgsvirtuallayerdefinition.cpp b/src/core/qgsvirtuallayerdefinition.cpp index 6cec8d651844..81d274faecc8 100644 --- a/src/core/qgsvirtuallayerdefinition.cpp +++ b/src/core/qgsvirtuallayerdefinition.cpp @@ -146,7 +146,7 @@ QgsVirtualLayerDefinition QgsVirtualLayerDefinition::fromUrl( const QUrl &url ) QString fieldType( reField.cap( 2 ) ); if ( fieldType == QLatin1String( "int" ) ) { - fields.append( QgsField( fieldName, QVariant::Int, fieldType ) ); + fields.append( QgsField( fieldName, QVariant::LongLong, fieldType ) ); } else if ( fieldType == QLatin1String( "real" ) ) { @@ -293,7 +293,10 @@ QUrl QgsVirtualLayerDefinition::toUrl() const const auto constFields = fields(); for ( const QgsField &f : constFields ) { - if ( f.type() == QVariant::Int ) + if ( f.type() == QVariant::Int + || f.type() == QVariant::UInt + || f.type() == QVariant::Bool + || f.type() == QVariant::LongLong ) urlQuery.addQueryItem( QStringLiteral( "field" ), f.name() + ":int" ); else if ( f.type() == QVariant::Double ) urlQuery.addQueryItem( QStringLiteral( "field" ), f.name() + ":real" ); diff --git a/src/providers/virtual/qgsvirtuallayerqueryparser.cpp b/src/providers/virtual/qgsvirtuallayerqueryparser.cpp index 5c04fdf3644d..ebd10f76f229 100644 --- a/src/providers/virtual/qgsvirtuallayerqueryparser.cpp +++ b/src/providers/virtual/qgsvirtuallayerqueryparser.cpp @@ -82,7 +82,7 @@ namespace QgsVirtualLayerQueryParser ColumnDef def; def.setName( column ); if ( type == QLatin1String( "int" ) ) - def.setScalarType( QVariant::Int ); + def.setScalarType( QVariant::LongLong ); else if ( type == QLatin1String( "real" ) ) def.setScalarType( QVariant::Double ); else if ( type == QLatin1String( "text" ) ) @@ -111,7 +111,7 @@ namespace QgsVirtualLayerQueryParser // the type declared by one of the virtual tables // or null if ( columnType == QLatin1String( "int" ) ) - d.setScalarType( QVariant::Int ); + d.setScalarType( QVariant::LongLong ); else if ( columnType == QLatin1String( "real" ) ) d.setScalarType( QVariant::Double ); else if ( columnType == QLatin1String( "text" ) ) @@ -223,7 +223,7 @@ namespace QgsVirtualLayerQueryParser switch ( type ) { case SQLITE_INTEGER: - tableDef[colIdx].setScalarType( QVariant::Int ); + tableDef[colIdx].setScalarType( QVariant::LongLong ); break; case SQLITE_FLOAT: tableDef[colIdx].setScalarType( QVariant::Double ); diff --git a/src/providers/virtual/qgsvirtuallayersqlitemodule.cpp b/src/providers/virtual/qgsvirtuallayersqlitemodule.cpp index cb42fc56deb1..20e080ee822a 100644 --- a/src/providers/virtual/qgsvirtuallayersqlitemodule.cpp +++ b/src/providers/virtual/qgsvirtuallayersqlitemodule.cpp @@ -695,11 +695,13 @@ int vtableColumn( sqlite3_vtab_cursor *cursor, sqlite3_context *ctxt, int idx ) switch ( v.type() ) { case QVariant::Int: - case QVariant::UInt: case QVariant::Bool: + // read signed integer sqlite3_result_int( ctxt, v.toInt() ); break; + case QVariant::UInt: case QVariant::LongLong: + // read 64 bits signed integer (or 32 bits unsigned one) sqlite3_result_int64( ctxt, v.toLongLong() ); break; case QVariant::Double: diff --git a/tests/src/python/test_provider_virtual.py b/tests/src/python/test_provider_virtual.py index e16915eb2bfd..53da4aee3926 100644 --- a/tests/src/python/test_provider_virtual.py +++ b/tests/src/python/test_provider_virtual.py @@ -610,14 +610,14 @@ def test_sql3(self): l4 = QgsVectorLayer("?query=%s" % query, "tt", "virtual", QgsVectorLayer.LayerOptions(False)) self.assertEqual(l4.isValid(), True) self.assertEqual(l4.dataProvider().fields().at(0).name(), "count(*)") - self.assertEqual(l4.dataProvider().fields().at(0).type(), QVariant.Int) + self.assertEqual(l4.dataProvider().fields().at(0).type(), QVariant.LongLong) def test_sql_field_types(self): query = toPercent("SELECT 42 as t, 'ok'||'ok' as t2, GeomFromText('') as t3, 3.14*2 as t4") l4 = QgsVectorLayer("?query=%s" % query, "tt", "virtual", QgsVectorLayer.LayerOptions(False)) self.assertEqual(l4.isValid(), True) self.assertEqual(l4.dataProvider().fields().at(0).name(), "t") - self.assertEqual(l4.dataProvider().fields().at(0).type(), QVariant.Int) + self.assertEqual(l4.dataProvider().fields().at(0).type(), QVariant.LongLong) self.assertEqual(l4.dataProvider().fields().at(1).name(), "t2") self.assertEqual(l4.dataProvider().fields().at(1).type(), QVariant.String) self.assertEqual(l4.dataProvider().fields().at(2).name(), "t3") @@ -635,7 +635,7 @@ def test_sql_field_types(self): self.assertEqual(l4.dataProvider().fields().at(1).name(), "t2") self.assertEqual(l4.dataProvider().fields().at(1).type(), QVariant.String) self.assertEqual(l4.dataProvider().fields().at(2).name(), "t4") - self.assertEqual(l4.dataProvider().fields().at(2).type(), QVariant.Int) + self.assertEqual(l4.dataProvider().fields().at(2).type(), QVariant.LongLong) self.assertEqual(l4.dataProvider().wkbType(), 4) # multipoint # test value types (!= from declared column types) @@ -1326,6 +1326,32 @@ def test_bool_fields(self): QgsProject.instance().removeMapLayer(ml.id()) + def test_int64(self): + """ + Test that 64 bits integer doesn't generate an integer overflow + """ + bigint = 2262000000 + + ml = QgsVectorLayer('NoGeometry?crs=epsg:4326&field=fldlonglong:long', + 'test_bigint', 'memory') + provider = ml.dataProvider() + feat = QgsFeature(ml.fields()) + feat.setAttribute('fldlonglong', bigint) + provider.addFeatures([feat]) + + self.assertEqual(ml.isValid(), True) + QgsProject.instance().addMapLayer(ml) + + df = QgsVirtualLayerDefinition() + df.setQuery('select * from test_bigint') + vl = QgsVectorLayer(df.toString(), "testq", "virtual") + self.assertEqual(len(vl.fields()), 1) + field = vl.fields()[0] + self.assertEqual(field.type(), QVariant.LongLong) + self.assertTrue(vl.isValid()) + feat = next(vl.getFeatures()) + self.assertEqual(feat.attribute('fldlonglong'), bigint) + if __name__ == '__main__': unittest.main() diff --git a/tests/src/python/test_qgsvirtuallayerdefinition.py b/tests/src/python/test_qgsvirtuallayerdefinition.py index be05cb7e497c..812e2e7f4dce 100644 --- a/tests/src/python/test_qgsvirtuallayerdefinition.py +++ b/tests/src/python/test_qgsvirtuallayerdefinition.py @@ -80,9 +80,10 @@ def test1(self): f.append(QgsField("f", QVariant.Double)) f.append(QgsField("s", QVariant.String)) d.setFields(f) + f2 = QgsVirtualLayerDefinition.fromUrl(d.toUrl()).fields() self.assertEqual(f[0].name(), f2[0].name()) - self.assertEqual(f[0].type(), f2[0].type()) + self.assertEqual(f2[0].type(), QVariant.LongLong) self.assertEqual(f[1].name(), f2[1].name()) self.assertEqual(f[1].type(), f2[1].type()) self.assertEqual(f[2].name(), f2[2].name())