2

I have been trying to programmatically save the styles of a number of layers to my postgres database using the following code:

for layer in QgsProject.instance().mapLayers().values():
    lyr_name = layer.name()
    layer.saveStyleToDatabase(
        f'oszs_outdoor_{lyr_name}', 
        f'Style (outdoor) for {lyr_name} layer', 
        True, 
        'uiFileContent'
    )

but keep getting this error:

Unable to save layer style. It's not possible to insert a new record into the style table. Maybe this is due to table permissions (user=postgres). Please contact your database administrator.

I have had a look at the PostGIS error message and get the following message on all the attempts:

[ERROR: syntax error at or near "(" LINE 1: ...leSLD,useAsDefault,description,owner,type,XMLPARSE(DOCUMENT ... ^ ]

I have noticed when copying the full message across to a text editor, the INSERT INTO and the VALUES don't seem to match up when it comes to the last few columns. The start and end lines of the SQL script looks like this:

Start (where the syntax error is):

INSERT INTO layer_styles(f_table_catalog,f_table_schema,f_table_name,f_geometry_column,styleName,styleQML,styleSLD,useAsDefault,description,owner,type,XMLPARSE(DOCUMENT 'uiFileContent'))

End:

),true,'Style Outdoor for woodland layer',CURRENT_USER,,ui'Unknown geometry');

The 'ui' value does not appear to be in the right place. Has anyone else experienced this error? Does the error message show exactly what was commited to the postgres DB? Is there something that I am doing wrong or is it something that should be raised as an issue?

I can save the styles manually by using the properties tab on each of the layers individually, but I was hoping to create a process to run through them automatically given the large number of layers and multiple styles I want to save.

1 Answer 1

4

You need to change 'uiFileContent' to ''. The role of uiFileContent is to provide the name of the Qt Designer UI file if you are using a custom form (see https://github.com/qgis/QGIS/blob/2d1aa68f0d044f2aced7ebeca8d2fa6b754ac970/src/gui/vector/qgsvectorlayersavestyledialog.cpp#L171 to see from code where my affirmation comes from). If you don't have one, the code will look for it and fails.

so, change

for layer in QgsProject.instance().mapLayers().values():
    lyr_name = layer.name()
    layer.saveStyleToDatabase(
        f'oszs_outdoor_{lyr_name}', 
        f'Style (outdoor) for {lyr_name} layer', 
        True, 
        'uiFileContent'
    )

to

for layer in QgsProject.instance().mapLayers().values():
    lyr_name = layer.name()
    # If you don't test before if there is already an existing style
    # with the same name, QGIS will open a GUI asking you if you want
    # to overwrite
    if f'oszs_outdoor_{lyr_name}' not in layer.listStylesInDatabase()[2]:
        layer.saveStyleToDatabase(
            f'oszs_outdoor_{lyr_name}', 
            f'Style (outdoor) for {lyr_name} layer', 
            True, 
            ''
        )
1
  • Thank you so much for that, it worked perfectly. Is there anyway of setting the 'type' to the geometry type of the layer or will it always add it as 'Unknown Geomtry'? I can create a function that runs after the save to DB that updates the layer_styles table based on the feature type, but it would be good if it was done in the saveStyleToDatabase function.
    – nevets
    Apr 26, 2021 at 6:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.