Add support for no-geometry layer styles with Oracle provider

This commit is contained in:
Jacky Volpes 2022-04-22 15:02:49 +02:00 committed by Julien Cabieces
parent 4c88bc54b0
commit 292bf5982a
3 changed files with 149 additions and 89 deletions

View File

@ -117,8 +117,9 @@ if [ ${RUN_ORACLE:-"NO"} == "YES" ]; then
echo "${bold}Load Oracle database...🙏${endbold}"
export ORACLE_HOST="oracle"
export QGIS_ORACLETEST_DBNAME="${ORACLE_HOST}/XEPDB1"
export QGIS_ORACLETEST_DB="host=${QGIS_ORACLETEST_DBNAME} port=1521 user='QGIS' password='qgis'"
export ORACLE_PDB="XEPDB1"
export QGIS_ORACLETEST_DBNAME="${ORACLE_HOST}/${ORACLE_PDB}"
export QGIS_ORACLETEST_DB="host=${ORACLE_HOST} dbname=${ORACLE_PDB} port=1521 user='QGIS' password='qgis'"
echo "Wait a moment while loading Oracle database."
COUNT=0

View File

@ -3393,23 +3393,29 @@ bool QgsOracleProviderMetadata::styleExists( const QString &uri, const QString &
else if ( qry.value( 0 ).toInt() == 0 )
{
// layer styles table does not exist
conn->disconnect();
return false;
}
if ( !qry.prepare( QStringLiteral( "SELECT id,stylename FROM layer_styles"
" WHERE f_table_catalog=?"
" AND f_table_schema=?"
" AND f_table_name=?"
" AND f_geometry_column=?"
" AND styleName=?" ) ) ||
!(
qry.addBindValue( dsUri.database() ),
qry.addBindValue( dsUri.schema() ),
qry.addBindValue( dsUri.table() ),
qry.addBindValue( dsUri.geometryColumn() ),
qry.addBindValue( styleId.isEmpty() ? dsUri.table() : styleId ),
qry.exec()
) )
if ( !qry.prepare( "SELECT id,stylename FROM layer_styles"
" WHERE f_table_catalog=?"
" AND f_table_schema=?"
" AND f_table_name=?"
" AND f_geometry_column" +
QString( dsUri.geometryColumn().isNull() ? " IS NULL" : "=?" ) +
" AND styleName=?" ) )
{
errorCause = QObject::tr( "Could not prepare select [%1]" ).arg( qry.lastError().text() );
conn->disconnect();
return false;
}
qry.addBindValue( dsUri.database() );
qry.addBindValue( dsUri.schema() );
qry.addBindValue( dsUri.table() );
if ( !dsUri.geometryColumn().isNull() )
qry.addBindValue( dsUri.geometryColumn() );
qry.addBindValue( styleId.isEmpty() ? dsUri.table() : styleId );
if ( !qry.exec() )
{
errorCause = QObject::tr( "Unable to check style existence [%1]" ).arg( qry.lastError().text() );
conn->disconnect();
@ -3461,7 +3467,7 @@ bool QgsOracleProviderMetadata::saveStyle( const QString &uri,
"f_table_catalog VARCHAR2(30) NOT NULL,"
"f_table_schema VARCHAR2(30) NOT NULL,"
"f_table_name VARCHAR2(30) NOT NULL,"
"f_geometry_column VARCHAR2(30) NOT NULL,"
"f_geometry_column VARCHAR2(30),"
"stylename VARCHAR2(2047),"
"styleqml CLOB,"
"stylesld CLOB,"
@ -3480,21 +3486,25 @@ bool QgsOracleProviderMetadata::saveStyle( const QString &uri,
int id;
QString sql;
if ( !qry.prepare( QStringLiteral( "SELECT id,stylename FROM layer_styles"
" WHERE f_table_catalog=?"
" AND f_table_schema=?"
" AND f_table_name=?"
" AND f_geometry_column=?"
" AND styleName=?" ) ) ||
!(
qry.addBindValue( dsUri.database() ),
qry.addBindValue( dsUri.schema() ),
qry.addBindValue( dsUri.table() ),
qry.addBindValue( dsUri.geometryColumn() ),
qry.addBindValue( styleName.isEmpty() ? dsUri.table() : styleName ),
qry.exec()
) )
if ( !qry.prepare( "SELECT id,stylename FROM layer_styles"
" WHERE f_table_catalog=?"
" AND f_table_schema=?"
" AND f_table_name=?"
" AND f_geometry_column" +
QString( dsUri.geometryColumn().isNull() ? " IS NULL" : "=?" ) +
" AND styleName=?" ) )
{
errCause = QObject::tr( "Could not prepare select [%1]" ).arg( qry.lastError().text() );
conn->disconnect();
return false;
}
qry.addBindValue( dsUri.database() );
qry.addBindValue( dsUri.schema() );
qry.addBindValue( dsUri.table() );
if ( !dsUri.geometryColumn().isNull() )
qry.addBindValue( dsUri.geometryColumn() );
qry.addBindValue( styleName.isEmpty() ? dsUri.table() : styleName );
if ( !qry.exec() )
{
errCause = QObject::tr( "Unable to check style existence [%1]" ).arg( qry.lastError().text() );
conn->disconnect();
@ -3622,21 +3632,29 @@ QString QgsOracleProviderMetadata::loadStyle( const QString &uri, QString &errCa
conn->disconnect();
return QString();
}
else if ( !qry.prepare( QStringLiteral( "SELECT styleQML FROM ("
"SELECT styleQML"
" FROM layer_styles"
" WHERE f_table_catalog=?"
" AND f_table_schema=?"
" AND f_table_name=?"
" AND f_geometry_column=?"
" ORDER BY useAsDefault DESC"
") WHERE rownum=1" ) ) ||
!(
qry.addBindValue( dsUri.database() ),
qry.addBindValue( dsUri.schema() ),
qry.addBindValue( dsUri.table() ),
qry.addBindValue( dsUri.geometryColumn() ),
qry.exec() ) )
if ( !qry.prepare( "SELECT styleQML FROM ("
"SELECT styleQML"
" FROM layer_styles"
" WHERE f_table_catalog=?"
" AND f_table_schema=?"
" AND f_table_name=?"
" AND f_geometry_column" +
QString( dsUri.geometryColumn().isNull() ? " IS NULL" : "=?" ) +
" ORDER BY useAsDefault DESC"
") WHERE rownum=1" ) )
{
errCause = QObject::tr( "Could not prepare select [%1]" ).arg( qry.lastError().text() );
conn->disconnect();
return QString();
}
qry.addBindValue( dsUri.database() );
qry.addBindValue( dsUri.schema() );
qry.addBindValue( dsUri.table() );
if ( !dsUri.geometryColumn().isNull() )
qry.addBindValue( dsUri.geometryColumn() );
if ( !qry.exec() )
{
errCause = QObject::tr( "Could not retrieve style [%1]" ).arg( qry.lastError().text() );
}
@ -3671,60 +3689,73 @@ int QgsOracleProviderMetadata::listStyles( const QString &uri,
QSqlQuery qry( *conn );
int res = -1;
if ( !qry.exec( "SELECT count(*) FROM user_tables WHERE table_name='LAYER_STYLES'" ) || !qry.next() )
{
errCause = QObject::tr( "Could not verify existence of layer style table [%1]" ).arg( qry.lastError().text() );
conn->disconnect();
return -1;
}
else if ( qry.value( 0 ).toInt() == 0 )
if ( qry.value( 0 ).toInt() == 0 )
{
errCause = QObject::tr( "Layer style table does not exist [%1]" ).arg( qry.value( 0 ).toString() );
conn->disconnect();
return -1;
}
else
if ( !qry.prepare( "SELECT id,styleName,description FROM layer_styles WHERE f_table_catalog=? AND f_table_schema=? AND f_table_name=? AND f_geometry_column"
+ QString( dsUri.geometryColumn().isNull() ? " IS NULL" : "=?" ) ) )
{
if ( !qry.prepare( QStringLiteral( "SELECT id,styleName,description FROM layer_styles WHERE f_table_catalog=? AND f_table_schema=? AND f_table_name=? AND f_geometry_column=?" ) ) ||
!(
qry.addBindValue( dsUri.database() ),
qry.addBindValue( dsUri.schema() ),
qry.addBindValue( dsUri.table() ),
qry.addBindValue( dsUri.geometryColumn() ),
qry.exec() ) )
{
errCause = QObject::tr( "No style for layer found" );
}
else
{
res = 0;
while ( qry.next() )
{
ids << qry.value( 0 ).toString();
names << qry.value( 1 ).toString();
descriptions << qry.value( 2 ).toString();
res++;
}
errCause = QObject::tr( "Could not prepare select [%1]" ).arg( qry.lastError().text() );
conn->disconnect();
return -1;
}
qry.addBindValue( dsUri.database() );
qry.addBindValue( dsUri.schema() );
qry.addBindValue( dsUri.table() );
if ( !dsUri.geometryColumn().isNull() )
qry.addBindValue( dsUri.geometryColumn() );
if ( !qry.exec() )
{
conn->disconnect();
errCause = QObject::tr( "No style for layer found" );
return -1;
}
qry.finish();
int res = 0;
while ( qry.next() )
{
ids << qry.value( 0 ).toString();
names << qry.value( 1 ).toString();
descriptions << qry.value( 2 ).toString();
res++;
}
if ( qry.prepare( QStringLiteral( "SELECT id,styleName,description FROM layer_styles WHERE NOT (f_table_catalog=? AND f_table_schema=? AND f_table_name=? AND f_geometry_column=?) ORDER BY update_time DESC" ) ) &&
(
qry.addBindValue( dsUri.database() ),
qry.addBindValue( dsUri.schema() ),
qry.addBindValue( dsUri.table() ),
qry.addBindValue( dsUri.geometryColumn() ),
qry.exec() ) )
{
while ( qry.next() )
{
ids << qry.value( 0 ).toString();
names << qry.value( 1 ).toString();
descriptions << qry.value( 2 ).toString();
}
}
qry.finish();
if ( !qry.prepare( "SELECT id,styleName,description FROM layer_styles WHERE NOT (f_table_catalog=? AND f_table_schema=? AND f_table_name=? AND f_geometry_column"
+ QString( dsUri.geometryColumn().isNull() ? " IS NULL" : "=?" )
+ ") ORDER BY update_time DESC" ) )
{
errCause = QObject::tr( "Could not prepare select [%1]" ).arg( qry.lastError().text() );
conn->disconnect();
return -1;
}
qry.addBindValue( dsUri.database() );
qry.addBindValue( dsUri.schema() );
qry.addBindValue( dsUri.table() );
if ( !dsUri.geometryColumn().isNull() )
qry.addBindValue( dsUri.geometryColumn() );
if ( qry.exec() )
{
while ( qry.next() )
{
ids << qry.value( 0 ).toString();
names << qry.value( 1 ).toString();
descriptions << qry.value( 2 ).toString();
}
}
conn->disconnect();
return res;
}

View File

@ -30,7 +30,8 @@ from qgis.core import (
QgsField,
QgsFields,
QgsCoordinateReferenceSystem,
QgsProjUtils
QgsProjUtils,
QgsProviderRegistry
)
from qgis.PyQt.QtCore import QDate, QTime, QDateTime, QVariant
@ -49,7 +50,7 @@ class TestPyQgsOracleProvider(unittest.TestCase, ProviderTestCase):
@classmethod
def setUpClass(cls):
"""Run before all tests"""
cls.dbconn = "host=localhost/XEPDB1 port=1521 user='QGIS' password='qgis'"
cls.dbconn = "host=localhost dbname=XEPDB1 port=1521 user='QGIS' password='qgis'"
if 'QGIS_ORACLETEST_DB' in os.environ:
cls.dbconn = os.environ['QGIS_ORACLETEST_DB']
# Create test layers
@ -308,6 +309,33 @@ class TestPyQgsOracleProvider(unittest.TestCase, ProviderTestCase):
fid += 1
self.check_geom(multipoints_z, fid, 'MultiPointZ ((1 2 7),(3 4 8))')
def testLayerStyles(self):
# Table without geometry column
vl_no_geom = QgsVectorLayer(
self.dbconn + ' sslmode=disable key=\'id\' table="QGIS"."DATE_TIMES" sql=', 'test', 'oracle')
# Save layer styles
self.assertEqual(self.vl.saveStyleToDatabase("mystyle", "the best", True, "something.ui"), "")
self.assertEqual(vl_no_geom.saveStyleToDatabase("my_other_style", "the very best", True, "else.ui"), "")
# Verify presence of styles in database
res, err = QgsProviderRegistry.instance().styleExists('oracle', self.vl.source(), 'mystyle')
self.assertTrue(res)
self.assertFalse(err)
res, err = QgsProviderRegistry.instance().styleExists('oracle', vl_no_geom.source(), 'my_other_style')
self.assertTrue(res)
self.assertFalse(err)
# Verify listing and loading of styles
self.assertEqual(self.vl.listStylesInDatabase(), (1, ['0', '1'], ['mystyle', 'my_other_style'], ['the best', 'the very best'], ''))
_, res = self.vl.loadNamedStyle(self.vl.source())
self.assertTrue(res)
self.assertEqual(vl_no_geom.listStylesInDatabase(), (1, ['1', '0'], ['my_other_style', 'mystyle'], ['the very best', 'the best'], ''))
_, res = vl_no_geom.loadNamedStyle(vl_no_geom.source())
self.assertTrue(res)
self.execSQLCommand('DROP TABLE "QGIS"."LAYER_STYLES"')
def testCurves(self):
vl = QgsVectorLayer('%s table="QGIS"."LINE_DATA" (GEOM) srid=4326 type=LINESTRING sql=' %
(self.dbconn), "testlines", "oracle")