3

I would like to list the names of all schemas of PostGIS in a given DB called DB-1 in PyQGIS. My attempt was inspired by : Getting table names from PostGIS database in PyQGIS

from PyQt5.QtSql import *
db = QSqlDatabase.addDatabase("QPSQL");
db.setHostName("localhost");
db.setDatabaseName("DB-1");
db.setUserName("postgres");
db.setPassword("postgres");
db.open();
names=db.schemas(QSql.Schemas)
print names

it results :

Traceback (most recent call last):
 File "C:\OSGeo4W\apps\Python39\lib\code.py", line 90, in runcode
 exec(code, self.locals)
 File "<input>", line 1, in <module>
 File "<string>", line 8, in <module>
AttributeError: 'QSqlDatabase' object has no attribute 'schemas'

I think the issues is there : names=db.schemas( QSql.Schemas). Is there any other attribute that could do the job?

ThomasG77
31.7k1 gold badge56 silver badges96 bronze badges
asked Oct 29, 2021 at 12:08
4
  • 2
    Any interest in doing this using only PyQGIS? Commented Oct 29, 2021 at 19:03
  • 1
    @GermánCarrillo yes I would prefer a solution only in PyQGIS to be honest. Commented Oct 29, 2021 at 20:01
  • 1
    Made a pure PyQGIS answer Commented Oct 29, 2021 at 23:59
  • 1
    Thank you Thomas, I was about to do the same. Commented Oct 30, 2021 at 0:06

2 Answers 2

4

You can use the following recipe as it does not involve any third party library like psycopg2 as there is a native support for what you want in PyQGIS.

md = QgsProviderRegistry.instance().providerMetadata('postgres')
# Approach 1 without using existing connection
uri = QgsDataSourceUri()
uri.setConnection("localhost", "5432", "DB-1", "postgres", "postgres")
conn1 = md.createConnection(uri.uri(), {})
print(conn1.schemas())
# Approach 2 using existing connection (declared in "Data Source manager | PostgreSQL")
conn2 = md.createConnection('DB-1')
print(conn2.schemas())

Edit due to question in question :)

You may try to check if database exists going through the postgres database (that always exists in a PostgreSQL instance)

md = QgsProviderRegistry.instance().providerMetadata('postgres')
uri = QgsDataSourceUri()
# Important to keep postgres as 3rd argument or will not work
uri.setConnection("localhost", "5432", "postgres", "your_user", "your_password")
conn_postgres_db = md.createConnection(uri.uri(), {})
db_name_to_check = 'db_name_to_test'
sql_test_db_exists = f"""
select exists(
 SELECT datname FROM pg_catalog.pg_database WHERE lower(datname) = lower('{db_name_to_check}')
);
"""
result = conn_postgres_db.executeSql(sql_test_db_exists)
if result[0][0]:
 print('Present')
else:
 print('Absent')
answered Oct 29, 2021 at 23:56
2
  • 1
    it works, but if the dabase BD-1 doesn't exist a form appears. Is there anyway to check if the database BD-1 exist before print(conn2.schemas()) ? Commented Oct 31, 2021 at 11:49
  • 2
    Did not find out an approach with PyQGIS directly so going through PostgreSQL way. Maybe there is a better approach but did not found it... Commented Oct 31, 2021 at 13:37
2

You could use psycopg2 and do a simple query on information_schema.schemata:

import psycopg2
db_conn = psycopg2.connect(host='localhost', port=5432, dbname='DB-1', user='postgres', password='postgres')
db_cursor = db_conn.cursor()
query = "select schema_name from information_schema.schemata"
db_cursor.execute(query)
schemata = list(db_cursor.fetchall())
schemata = [''.join(i) for i in schemata] # tuples to string-list
print(schemata)
answered Oct 29, 2021 at 16:51

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.