78#include <rtl/ustrbuf.hxx>
80#include <com/sun/star/sdbc/TransactionIsolation.hpp>
81#include <com/sun/star/sdbc/ResultSetType.hpp>
82#include <com/sun/star/sdbc/XParameters.hpp>
83#include <com/sun/star/sdbc/DataType.hpp>
84#include <com/sun/star/sdbc/IndexType.hpp>
85#include <com/sun/star/sdbc/ColumnValue.hpp>
86#include <com/sun/star/sdbc/ColumnSearch.hpp>
89using ::osl::MutexGuard;
96using com::sun::star::uno::Any;
97using com::sun::star::uno::UNO_QUERY;
98using com::sun::star::uno::UNO_QUERY_THROW;
107#define KEYRULE_CASCADE 0
108#define KEYRULE_RESTRICT 1
109#define KEYRULE_SET_NULL 2
110#define KEYRULE_NO_ACTION 4
111#define KEYRULE_SET_DEFAULT 4
113#define DEFERRABILITY_INITIALLY_DEFERRED 5
114#define DEFERRABILITY_INITIALLY_IMMEDIATE 6
115#define DEFERRABILITY_NONE 7
119 css::uno::Reference< css::sdbc::XConnection > origin,
121 : m_xMutex(
std::move( refMutex )),
122 m_pSettings( pSettings ),
123 m_origin(
std::move( origin )),
124 m_getIntSetting_stmt ( m_origin->prepareStatement(
"SELECT setting FROM pg_catalog.pg_settings WHERE name=?") )
193 return "postgresql-sdbc";
203 return PQ_SDBC_MAJOR;
208 return PQ_SDBC_MINOR;
384 "pg_client_encoding,"
390 "regexp_split_to_array,"
391 "regexp_split_to_table,"
424 "pg_is_other_temp_schema,"
425 "pg_listening_channels,"
427 "pg_postmaster_start_time,"
431 "has_any_column_privilege,"
432 "has_any_column_privilege,"
433 "has_any_column_privilege,"
434 "has_column_privilege,"
435 "has_database_privilege,"
436 "has_foreign_data_wrapper_privilege,"
437 "has_function_privilege,"
438 "has_language_privilege,"
439 "has_schema_privilege,"
440 "has_sequence_privilege,"
441 "has_server_privilege,"
442 "has_table_privilege,"
443 "has_tablespace_privilege,"
445 "pg_collation_is_visible,"
446 "pg_conversion_is_visible,"
447 "pg_function_is_visible,"
448 "pg_opclass_is_visible,"
449 "pg_operator_is_visible,"
450 "pg_table_is_visible,"
451 "pg_ts_config_is_visible,"
452 "pg_ts_dict_is_visible,"
453 "pg_ts_parser_is_visible,"
454 "pg_ts_template_is_visible,"
455 "pg_type_is_visible,"
457 "pg_describe_object,"
458 "pg_get_constraintdef,"
460 "pg_get_functiondef,"
461 "pg_get_function_arguments,"
462 "pg_get_function_identity_arguments,"
463 "pg_get_function_result,"
467 "pg_get_serial_sequence,"
471 "pg_options_to_table,"
472 "pg_tablespace_databases,"
478 "txid_current_snapshot,"
480 "txid_snapshot_xmax,"
481 "txid_snapshot_xmin,"
482 "txid_visible_in_snapshot,"
491 "pg_terminate_backend,"
492 "pg_create_restore_point,"
493 "pg_current_xlog_insert_location,"
494 "pg_current_xlog_location,"
499 "pg_xlogfile_name_offset,"
501 "pg_last_xlog_receive_location,"
502 "pg_last_xlog_replay_location,"
503 "pg_last_xact_replay_timestamp,"
504 "pg_is_xlog_replay_paused,"
505 "pg_xlog_replay_pause,"
506 "pg_xlog_replay_resume,"
513 "pg_tablespace_size,"
514 "pg_tablespace_size,"
515 "pg_total_relation_size,"
516 "pg_relation_filenode,"
517 "pg_relation_filepath,"
520 "pg_read_binary_file,"
523 "pg_advisory_lock_shared,"
524 "pg_advisory_unlock,"
525 "pg_advisory_unlock_all,"
526 "pg_advisory_unlock_shared,"
527 "pg_advisory_xact_lock,"
528 "pg_advisory_xact_lock_shared,"
529 "pg_try_advisory_lock,"
530 "pg_try_advisory_lock_shared,"
531 "pg_try_advisory_xact_lock,"
532 "pg_try_advisory_xact_lock_shared,"
560 "statement_timestamp,"
562 "transaction_timestamp,"
898 MutexGuard guard(
m_xMutex->GetMutex() );
901 params->setString(1, settingName );
904 OSL_VERIFY(rs->next());
905 OSL_ENSURE(rs->isFirst(),
"postgresql-sdbc DatabaseMetaData getIntSetting not on first row");
906 OSL_ENSURE(rs->isLast(),
"postgresql-sdbc DatabaseMetaData getIntSetting not on last row");
907 return xRow->getInt(1);
1033 return css::sdbc::TransactionIsolation::READ_COMMITTED;
1043 if ( level == css::sdbc::TransactionIsolation::READ_COMMITTED
1044 || level == css::sdbc::TransactionIsolation::SERIALIZABLE
1045 || level == css::sdbc::TransactionIsolation::READ_UNCOMMITTED
1046 || level == css::sdbc::TransactionIsolation::REPEATABLE_READ)
1073 const css::uno::Any&,
1091 MutexGuard guard(
m_xMutex->GetMutex() );
1093 m_xMutex, *
this, std::vector< OUString >(), std::vector< std::vector< Any > > (),
m_pSettings->
tc );
1097 const css::uno::Any&,
1102 MutexGuard guard(
m_xMutex->GetMutex() );
1110 const css::uno::Any&,
1111 const OUString& schemaPattern,
1112 const OUString& tableNamePattern,
1113 const css::uno::Sequence< OUString >& )
1117 MutexGuard guard(
m_xMutex->GetMutex() );
1119 SAL_INFO(
"connectivity.postgresql",
"DatabaseMetaData::getTables() got called with " << schemaPattern <<
"." << tableNamePattern);
1128 "DISTINCT ON (pg_namespace.nspname, relname ) "
1129 "pg_namespace.nspname, relname, relkind, pg_description.description "
1130 "FROM pg_namespace, pg_class LEFT JOIN pg_description ON pg_class.oid = pg_description.objoid "
1131 "WHERE relnamespace = pg_namespace.oid "
1132 "AND ( relkind = 'r' OR relkind = 'v') "
1133 "AND pg_namespace.nspname LIKE ? "
1134 "AND relname LIKE ? "
1139 parameters->setString( 1 , schemaPattern );
1140 parameters->setString( 2 , tableNamePattern );
1144 std::vector< std::vector<Any> > vec;
1148 std::vector< Any > row( 5 );
1151 row[1] <<= xRow->getString( 1 );
1152 row[2] <<= xRow->getString( 2 );
1153 OUString
type = xRow->getString(3);
1156 if( xRow->getString(1) ==
"pg_catalog" )
1162 row[3] <<= statics.
TABLE;
1165 else if(
type ==
"v" )
1167 row[3] <<= statics.
VIEW;
1173 row[4] <<= xRow->getString(4);
1176 vec.push_back( row );
1179 if( closeable.is() )
1189 int compare_schema(std::u16string_view nsA, std::u16string_view nsB)
1193 return nsB.empty() ? 0 : -1;
1195 else if (nsB.empty())
1197 assert(!nsA.empty());
1200 else if(nsA == u
"public")
1202 return (nsB == u
"public") ? 0 : -1;
1204 else if(nsB == u
"public")
1206 assert(nsA != u
"public");
1212 return nsA.compare(nsB);
1222 return nsA.compare(nsB);
1226 struct SortInternalSchemasLastAndPublicFirst
1228 bool operator () (
const std::vector< Any > & a,
const std::vector< Any > & b )
1234 return compare_schema(valueA, valueB) < 0;
1241 MutexGuard guard(
m_xMutex->GetMutex() );
1243 SAL_INFO(
"connectivity.postgresql",
"DatabaseMetaData::getSchemas() got called");
1248 "SELECT nspname from pg_namespace" );
1253 std::vector< std::vector<Any> > vec;
1256 vec.push_back( {
Any(xRow->getString(1)) } );
1260 std::sort( vec.begin(), vec.end(), SortInternalSchemasLastAndPublicFirst() );
1263 if( closeable.is() )
1273 MutexGuard guard(
m_xMutex->GetMutex() );
1281 MutexGuard guard(
m_xMutex->GetMutex() );
1296 sal_Int32 ret = css::sdbc::DataType::LONGVARCHAR;
1297 if( typtype ==
u"b" )
1315 else if( typtype ==
u"c" )
1317 ret = css::sdbc::DataType::STRUCT;
1319 else if( typtype ==
u"d" )
1321 ret = css::sdbc::DataType::LONGVARCHAR;
1327 bool isSystemColumn( sal_Int16 attnum )
1339 sal_Int32 dataType, sal_Int32 atttypmod, sal_Int32 *
precision, sal_Int32 *
scale )
1350 case css::sdbc::DataType::NUMERIC:
1351 case css::sdbc::DataType::DECIMAL:
1364 struct DatabaseTypeDescription
1366 DatabaseTypeDescription()
1368 DatabaseTypeDescription( OUString
name, OUString
type ) :
1372 DatabaseTypeDescription(
const DatabaseTypeDescription &source ) :
1376 DatabaseTypeDescription & operator = (
const DatabaseTypeDescription & source )
1387typedef std::unordered_map
1390 DatabaseTypeDescription
1400 OUStringBuffer queryBuf(128);
1401 queryBuf.append(
"SELECT oid,typtype,typname FROM pg_TYPE WHERE " );
1404 if( row->getString( 9 ) ==
"d" && oidMap.find( row->getInt( 12 ) ) == oidMap.end() )
1406 oidMap[row->getInt(12)] = DatabaseTypeDescription();
1408 queryBuf.append(
" OR " );
1409 queryBuf.append(
"oid = " + OUString::number( row->getInt(12 ) ) );
1418 row.set( rsDomain, UNO_QUERY_THROW );
1419 while( rsDomain->next() )
1421 oidMap[row->getInt(1)] = DatabaseTypeDescription(row->getString(3), row->getString(2) );
1430 const css::uno::Any&,
1431 const OUString& schemaPattern,
1432 const OUString& tableNamePattern,
1433 const OUString& columnNamePattern )
1439 MutexGuard guard(
m_xMutex->GetMutex() );
1441 SAL_INFO(
"connectivity.postgresql",
"DatabaseMetaData::getColumns() got called with "
1442 << schemaPattern <<
"." << tableNamePattern <<
"." << columnNamePattern);
1497 "SELECT pg_namespace.nspname, "
1498 "pg_class.relname, "
1499 "pg_attribute.attname, "
1501 "pg_attribute.atttypmod, "
1502 "pg_attribute.attnotnull, "
1503 "pg_type.typdefault, "
1506 ",pg_description.description, "
1507 "pg_type.typbasetype, "
1508 "pg_attribute.attnum "
1510 "pg_attribute LEFT JOIN pg_attrdef ON pg_attribute.attrelid = pg_attrdef.adrelid AND pg_attribute.attnum = pg_attrdef.adnum "
1511 "LEFT JOIN pg_description ON pg_attribute.attrelid = pg_description.objoid AND pg_attribute.attnum=pg_description.objsubid,"
1512 " pg_type, pg_namespace "
1513 "WHERE pg_attribute.attrelid = pg_class.oid "
1514 "AND pg_attribute.atttypid = pg_type.oid "
1515 "AND pg_class.relnamespace = pg_namespace.oid "
1516 "AND NOT pg_attribute.attisdropped "
1517 "AND pg_namespace.nspname LIKE ? "
1518 "AND pg_class.relname LIKE ? "
1519 "AND pg_attribute.attname LIKE ? "
1520 "ORDER BY pg_namespace.nspname, pg_class.relname, pg_attribute.attnum"
1524 parameters->setString( 1 , schemaPattern );
1525 parameters->setString( 2 , tableNamePattern );
1526 parameters->setString( 3 , columnNamePattern );
1530 std::vector< std::vector<Any> > vec;
1536 sal_uInt32 colNum(0);
1537 OUString
sSchema(
"#invalid#" );
1538 OUString sTable(
"#invalid#" );
1542 if( ! isSystemColumn( xRow->getShort( 12 ) ) )
1544 OUString sNewSchema( xRow->getString(1) );
1545 OUString sNewTable( xRow->getString(2) );
1546 if ( sNewSchema !=
sSchema || sNewTable != sTable )
1555 std::vector< Any > row( 18 );
1557 row[1] <<= sNewSchema;
1558 row[2] <<= sNewTable;
1559 row[3] <<= xRow->getString(3);
1560 if( xRow->getString(8) ==
"d" )
1562 DatabaseTypeDescription desc( domainMap[xRow->getInt(11)] );
1571 row[5] <<= xRow->getString(4);
1576 if( xRow->getBoolean( 6 ) && ! isSystemColumn(xRow->getInt( 12 )) )
1578 row[10] <<= OUString::number(css::sdbc::ColumnValue::NO_NULLS);
1579 row[17] <<= statics.
NO;
1583 row[10] <<= OUString::number(css::sdbc::ColumnValue::NULLABLE);
1584 row[17] <<= statics.
YES;
1587 row[11] <<= xRow->getString( 10 );
1588 row[12] <<= xRow->getString( 9 );
1592 row[16] <<= colNum ;
1594 vec.push_back( row );
1598 if( closeable.is() )
1606 const css::uno::Any&,
1607 const OUString& schema,
1608 const OUString& table,
1609 const OUString& columnNamePattern )
1611 MutexGuard guard(
m_xMutex->GetMutex() );
1613 SAL_INFO(
"connectivity.postgresql",
"DatabaseMetaData::getColumnPrivileges() got called with "
1614 << schema <<
"." <<
table <<
"." << columnNamePattern);
1617 parameters->setString( 1 , schema );
1618 parameters->setString( 2 ,
table );
1619 parameters->setString( 3 , columnNamePattern );
1627 const css::uno::Any&,
1628 const OUString& schemaPattern,
1629 const OUString& tableNamePattern )
1631 MutexGuard guard(
m_xMutex->GetMutex() );
1633 SAL_INFO(
"connectivity.postgresql",
"DatabaseMetaData::getTablePrivileges() got called with "
1634 << schemaPattern <<
"." << tableNamePattern);
1637 parameters->setString( 1 , schemaPattern );
1638 parameters->setString( 2 , tableNamePattern );
1646 const css::uno::Any&,
1653 MutexGuard guard(
m_xMutex->GetMutex() );
1659 const css::uno::Any&,
1664 MutexGuard guard(
m_xMutex->GetMutex() );
1670 const css::uno::Any&,
1671 const OUString& schema,
1672 const OUString& table )
1675 MutexGuard guard(
m_xMutex->GetMutex() );
1684 SAL_INFO(
"connectivity.postgresql",
"DatabaseMetaData::getPrimaryKeys() got called with "
1685 << schema <<
"." <<
table);
1688 "SELECT nmsp.nspname, "
1693 "FROM pg_constraint as con,pg_class as cl, pg_namespace as nmsp "
1694 "WHERE con.connamespace = nmsp.oid AND con.conrelid = cl.oid AND con.contype = 'p' "
1695 "AND nmsp.nspname LIKE ? AND cl.relname LIKE ?" );
1698 parameters->setString( 1 , schema );
1699 parameters->setString( 2 ,
table );
1703 std::vector< std::vector<Any> > vec;
1707 std::vector< Any > row( 6 );
1709 row[1] <<= xRow->getString(1);
1710 row[2] <<= xRow->getString(2);
1711 OUString array = xRow->getString(3);
1712 row[4] <<= xRow->getString(5);
1713 row[5] <<= xRow->getString(4);
1725 while( array[
i] &&
'}' != array[
i] )
1729 while( array[
i] && array[
i] !=
'}' && array[
i] !=
',' )
i++;
1731 vec.push_back( row );
1737 if( closeable.is() )
1742 OUString lastTableOid;
1743 sal_Int32
index = 0;
1744 std::vector< std::vector< Any > > ret( vec.size() );
1746 for (
auto const& elem : vec)
1749 std::vector< Any > row = elem;
1753 row[4] >>= tableOid;
1755 statement =
m_origin->prepareStatement(
1756 "SELECT att.attname FROM "
1757 "pg_attribute AS att, pg_class AS cl WHERE "
1758 "att.attrelid = ? AND att.attnum = ?" );
1760 parameters.set( statement, UNO_QUERY_THROW );
1761 parameters->setString( 1 , tableOid );
1762 parameters->setString( 2 , attnum );
1764 rs = statement->executeQuery();
1765 xRow.set( rs, UNO_QUERY_THROW );
1769 row[3] <<= xRow->getString( 1 );
1770 if( tableOid != lastTableOid )
1772 lastTableOid = tableOid;
1773 row[4] <<= OUString::number(
index );
1778 if( closeable.is() )
1781 ret[elements] = row;
1789#define SQL_CASE_KEYRULE " WHEN 'c' THEN " SAL_STRINGIFY(KEYRULE_CASCADE) \
1790 " WHEN 'n' THEN " SAL_STRINGIFY(KEYRULE_SET_NULL) \
1791 " WHEN 'd' THEN " SAL_STRINGIFY(KEYRULE_SET_DEFAULT) \
1792 " WHEN 'r' THEN " SAL_STRINGIFY(KEYRULE_RESTRICT) \
1793 " WHEN 'a' THEN " SAL_STRINGIFY(KEYRULE_NO_ACTION) \
1796#define SQL_GET_REFERENCES \
1797 "WITH con AS (SELECT oid, conname, contype, condeferrable, condeferred, conrelid, confrelid, confupdtype, confdeltype, generate_subscripts(conkey,1) AS conkeyseq, unnest(conkey) AS conkey , unnest(confkey) AS confkey FROM pg_catalog.pg_constraint) " \
1798 "SELECT NULL::text AS PKTABLE_CAT, pkn.nspname AS PKTABLE_SCHEM, pkc.relname AS PKTABLE_NAME, pka.attname AS PKCOLUMN_NAME, " \
1799 " NULL::text AS FKTABLE_CAT, fkn.nspname AS FKTABLE_SCHEM, fkc.relname AS FKTABLE_NAME, fka.attname AS FKCOLUMN_NAME, " \
1800 " con.conkeyseq AS KEY_SEQ, " \
1801 " CASE con.confupdtype " \
1803 " END AS UPDATE_RULE, " \
1804 " CASE con.confdeltype " \
1806 " END AS DELETE_RULE, " \
1807 " con.conname AS FK_NAME, pkic.relname AS PK_NAME, " \
1809 " WHEN con.condeferrable AND con.condeferred THEN " SAL_STRINGIFY(DEFERRABILITY_INITIALLY_DEFERRED) \
1810 " WHEN con.condeferrable THEN " SAL_STRINGIFY(DEFERRABILITY_INITIALLY_IMMEDIATE) \
1811 " ELSE " SAL_STRINGIFY(DEFERRABILITY_NONE) \
1812 " END AS DEFERRABILITY " \
1814 " pg_catalog.pg_namespace pkn, pg_catalog.pg_class pkc, pg_catalog.pg_attribute pka, " \
1815 " pg_catalog.pg_namespace fkn, pg_catalog.pg_class fkc, pg_catalog.pg_attribute fka, " \
1816 " con, pg_catalog.pg_depend dep, pg_catalog.pg_class pkic " \
1817 "WHERE pkn.oid = pkc.relnamespace AND pkc.oid = pka.attrelid AND pka.attnum = con.confkey AND con.confrelid = pkc.oid " \
1818 " AND fkn.oid = fkc.relnamespace AND fkc.oid = fka.attrelid AND fka.attnum = con.conkey AND con.conrelid = fkc.oid " \
1819 " AND con.contype = 'f' AND con.oid = dep.objid AND pkic.oid = dep.refobjid AND pkic.relkind = 'i' AND dep.classid = 'pg_constraint'::regclass::oid AND dep.refclassid = 'pg_class'::regclass::oid "
1821#define SQL_GET_REFERENCES_PSCHEMA " AND pkn.nspname = ? "
1822#define SQL_GET_REFERENCES_PTABLE " AND pkc.relname = ? "
1823#define SQL_GET_REFERENCES_FSCHEMA " AND fkn.nspname = ? "
1824#define SQL_GET_REFERENCES_FTABLE " AND fkc.relname = ? "
1825#define SQL_GET_REFERENCES_ORDER_SOME_PTABLE "ORDER BY fkn.nspname, fkc.relname, conkeyseq"
1826#define SQL_GET_REFERENCES_ORDER_NO_PTABLE "ORDER BY pkn.nspname, pkc.relname, conkeyseq"
1828#define SQL_GET_REFERENCES_NONE_NONE_NONE_NONE \
1829 SQL_GET_REFERENCES \
1830 SQL_GET_REFERENCES_ORDER_NO_PTABLE
1832#define SQL_GET_REFERENCES_SOME_NONE_NONE_NONE \
1833 SQL_GET_REFERENCES \
1834 SQL_GET_REFERENCES_PSCHEMA \
1835 SQL_GET_REFERENCES_ORDER_NO_PTABLE
1837#define SQL_GET_REFERENCES_NONE_SOME_NONE_NONE \
1838 SQL_GET_REFERENCES \
1839 SQL_GET_REFERENCES_PTABLE \
1840 SQL_GET_REFERENCES_ORDER_SOME_PTABLE
1842#define SQL_GET_REFERENCES_SOME_SOME_NONE_NONE \
1843 SQL_GET_REFERENCES \
1844 SQL_GET_REFERENCES_PSCHEMA \
1845 SQL_GET_REFERENCES_PTABLE \
1846 SQL_GET_REFERENCES_ORDER_SOME_PTABLE
1848#define SQL_GET_REFERENCES_NONE_NONE_SOME_NONE \
1849 SQL_GET_REFERENCES \
1850 SQL_GET_REFERENCES_FSCHEMA \
1851 SQL_GET_REFERENCES_ORDER_NO_PTABLE
1853#define SQL_GET_REFERENCES_NONE_NONE_NONE_SOME \
1854 SQL_GET_REFERENCES \
1855 SQL_GET_REFERENCES_FTABLE \
1856 SQL_GET_REFERENCES_ORDER_NO_PTABLE
1858#define SQL_GET_REFERENCES_NONE_NONE_SOME_SOME \
1859 SQL_GET_REFERENCES \
1860 SQL_GET_REFERENCES_FSCHEMA \
1861 SQL_GET_REFERENCES_FTABLE \
1862 SQL_GET_REFERENCES_ORDER_NO_PTABLE
1864#define SQL_GET_REFERENCES_SOME_NONE_SOME_NONE \
1865 SQL_GET_REFERENCES \
1866 SQL_GET_REFERENCES_PSCHEMA \
1867 SQL_GET_REFERENCES_FSCHEMA \
1868 SQL_GET_REFERENCES_ORDER_NO_PTABLE
1870#define SQL_GET_REFERENCES_SOME_NONE_NONE_SOME \
1871 SQL_GET_REFERENCES \
1872 SQL_GET_REFERENCES_PSCHEMA \
1873 SQL_GET_REFERENCES_FTABLE \
1874 SQL_GET_REFERENCES_ORDER_NO_PTABLE
1876#define SQL_GET_REFERENCES_SOME_NONE_SOME_SOME \
1877 SQL_GET_REFERENCES \
1878 SQL_GET_REFERENCES_PSCHEMA \
1879 SQL_GET_REFERENCES_FSCHEMA \
1880 SQL_GET_REFERENCES_FTABLE \
1881 SQL_GET_REFERENCES_ORDER_NO_PTABLE
1883#define SQL_GET_REFERENCES_NONE_SOME_SOME_NONE \
1884 SQL_GET_REFERENCES \
1885 SQL_GET_REFERENCES_PTABLE \
1886 SQL_GET_REFERENCES_FSCHEMA \
1887 SQL_GET_REFERENCES_ORDER_SOME_PTABLE
1889#define SQL_GET_REFERENCES_NONE_SOME_NONE_SOME \
1890 SQL_GET_REFERENCES \
1891 SQL_GET_REFERENCES_PTABLE \
1892 SQL_GET_REFERENCES_FTABLE \
1893 SQL_GET_REFERENCES_ORDER_SOME_PTABLE
1895#define SQL_GET_REFERENCES_NONE_SOME_SOME_SOME \
1896 SQL_GET_REFERENCES \
1897 SQL_GET_REFERENCES_PTABLE \
1898 SQL_GET_REFERENCES_FSCHEMA \
1899 SQL_GET_REFERENCES_FTABLE \
1900 SQL_GET_REFERENCES_ORDER_SOME_PTABLE
1902#define SQL_GET_REFERENCES_SOME_SOME_SOME_NONE \
1903 SQL_GET_REFERENCES \
1904 SQL_GET_REFERENCES_PSCHEMA \
1905 SQL_GET_REFERENCES_PTABLE \
1906 SQL_GET_REFERENCES_FSCHEMA \
1907 SQL_GET_REFERENCES_ORDER_SOME_PTABLE
1909#define SQL_GET_REFERENCES_SOME_SOME_NONE_SOME \
1910 SQL_GET_REFERENCES \
1911 SQL_GET_REFERENCES_PSCHEMA \
1912 SQL_GET_REFERENCES_PTABLE \
1913 SQL_GET_REFERENCES_FTABLE \
1914 SQL_GET_REFERENCES_ORDER_SOME_PTABLE
1916#define SQL_GET_REFERENCES_SOME_SOME_SOME_SOME \
1917 SQL_GET_REFERENCES \
1918 SQL_GET_REFERENCES_PSCHEMA \
1919 SQL_GET_REFERENCES_PTABLE \
1920 SQL_GET_REFERENCES_FSCHEMA \
1921 SQL_GET_REFERENCES_FTABLE \
1922 SQL_GET_REFERENCES_ORDER_SOME_PTABLE
1946 OUStringBuffer sSQL(300);
1948 " SELECT dp.TABLE_CAT, dp.TABLE_SCHEM, dp.TABLE_NAME, dp.GRANTOR, pr.rolname AS GRANTEE, dp.privilege, dp.is_grantable "
1950 " SELECT table_catalog AS TABLE_CAT, table_schema AS TABLE_SCHEM, table_name,"
1951 " grantor, grantee, privilege_type AS PRIVILEGE, is_grantable"
1952 " FROM information_schema.table_privileges");
1958 " SELECT current_database() AS TABLE_CAT, pn.nspname AS TABLE_SCHEM, c.relname AS TABLE_NAME,"
1959 " ro.rolname AS GRANTOR, rg.rolname AS GRANTEE, p.privilege, 'YES' AS is_grantable"
1960 " FROM pg_catalog.pg_class c,"
1961 " (VALUES ('SELECT'), ('INSERT'), ('UPDATE'), ('DELETE'), ('TRUNCATE'), ('REFERENCES'), ('TRIGGER')) p (privilege),"
1962 " pg_catalog.pg_roles ro,"
1963 " ( SELECT oid, rolname FROM pg_catalog.pg_roles"
1965 " VALUES (0::oid, 'PUBLIC')"
1966 " ) AS rg (oid, rolname),"
1967 " pg_catalog.pg_namespace pn"
1968 " WHERE c.relkind IN ('r', 'v') AND c.relacl IS NULL AND pg_has_role(rg.oid, c.relowner, 'USAGE')"
1969 " AND c.relowner=ro.oid AND c.relnamespace = pn.oid");
1972 " (SELECT oid, rolname FROM pg_catalog.pg_roles UNION ALL VALUES (0, 'PUBLIC')) pr"
1973 " WHERE table_schem LIKE ? AND table_name LIKE ? AND (dp.grantee = 'PUBLIC' OR pg_has_role(pr.oid, dp.grantee, 'USAGE'))"
1974 " ORDER BY table_schem, table_name, privilege" );
1979 " SELECT dp.TABLE_CAT, dp.TABLE_SCHEM, dp.TABLE_NAME, dp.COLUMN_NAME, dp.GRANTOR, pr.rolname AS GRANTEE, dp.PRIVILEGE, dp.IS_GRANTABLE FROM ("
1980 " SELECT table_catalog AS TABLE_CAT, table_schema AS TABLE_SCHEM, table_name, column_name,"
1981 " grantor, grantee, privilege_type AS PRIVILEGE, is_grantable"
1982 " FROM information_schema.column_privileges");
1988 " SELECT current_database() AS TABLE_CAT, pn.nspname AS TABLE_SCHEM, c.relname AS TABLE_NAME, a.attname AS column_name,"
1989 " ro.rolname AS GRANTOR, rg.rolname AS GRANTEE, p.privilege, 'YES' AS is_grantable"
1990 " FROM pg_catalog.pg_class c, pg_catalog.pg_attribute a,"
1991 " (VALUES ('SELECT'), ('INSERT'), ('UPDATE'), ('REFERENCES')) p (privilege),"
1992 " pg_catalog.pg_roles ro,"
1993 " ( SELECT oid, rolname FROM pg_catalog.pg_roles"
1995 " VALUES (0::oid, 'PUBLIC')"
1996 " ) AS rg (oid, rolname),"
1997 " pg_catalog.pg_namespace pn"
1998 " WHERE c.relkind IN ('r', 'v') AND c.relacl IS NULL AND pg_has_role(rg.oid, c.relowner, 'USAGE')"
1999 " AND c.relowner=ro.oid AND c.relnamespace = pn.oid AND a.attrelid = c.oid AND a.attnum > 0");
2002 " (SELECT oid, rolname FROM pg_catalog.pg_roles UNION ALL VALUES (0, 'PUBLIC')) pr"
2003 " WHERE table_schem = ? AND table_name = ? AND column_name LIKE ? AND (dp.grantee = 'PUBLIC' OR pg_has_role(pr.oid, dp.grantee, 'USAGE'))"
2004 " ORDER BY column_name, privilege" );
2011 const OUString& primarySchema,
2012 const OUString& primaryTable,
2014 const OUString& foreignSchema,
2015 const OUString& foreignTable )
2018 if ( ! primarySchema.isEmpty() )
2020 if ( ! primaryTable.isEmpty() )
2022 if ( ! foreignSchema.isEmpty() )
2024 if ( ! foreignTable.isEmpty() )
2032 param->setString( j++, primarySchema );
2034 param->setString( j++, primaryTable );
2036 param->setString( j++, foreignSchema );
2038 param->setString( j++, foreignTable );
2047 const css::uno::Any& catalog,
2048 const OUString& schema,
2049 const OUString& table )
2055 const css::uno::Any& catalog,
2056 const OUString& schema,
2057 const OUString& table )
2063 const css::uno::Any& primaryCatalog,
2064 const OUString& primarySchema,
2065 const OUString& primaryTable,
2066 const css::uno::Any& foreignCatalog,
2067 const OUString& foreignSchema,
2068 const OUString& foreignTable )
2070 return getImportedExportedKeys( primaryCatalog, primarySchema, primaryTable, foreignCatalog, foreignSchema, foreignTable );
2075 struct TypeInfoByDataTypeSorter
2077 bool operator () (
const std::vector< Any > & a,
const std::vector< Any > & b )
2083 if( valueB.toInt32() == valueA.toInt32() )
2089 std::u16string_view nsA, tnA, nsB, tnB;
2097 nsA = std::u16string_view();
2110 nsB = std::u16string_view();
2118 const int ns_comp = compare_schema(nsA, nsB);
2123 assert(nsB.empty());
2125 if( tnA == u
"int4" || tnA == u
"varchar" || tnA == u
"char" || tnA == u
"text")
2127 if( tnB == u
"int4" || tnB == u
"varchar" || tnB == u
"char" || tnB == u
"text")
2130 return nameA.compareTo( nameB ) < 0;
2138 return valueA.toInt32() < valueB.toInt32();
2142 sal_Int32 calcSearchable( sal_Int32 dataType )
2144 sal_Int32 ret = css::sdbc::ColumnSearch::FULL;
2145 if( css::sdbc::DataType::BINARY == dataType ||
2146 css::sdbc::DataType::VARBINARY == dataType ||
2147 css::sdbc::DataType::LONGVARBINARY == dataType )
2148 ret = css::sdbc::ColumnSearch::NONE;
2153 sal_Int32 getMaxScale( sal_Int32 dataType )
2157 if( dataType == css::sdbc::DataType::NUMERIC )
2166 OUString construct_full_typename(std::u16string_view ns,
const OUString &tn)
2168 if(
ns.empty() || ns == u
"pg_catalog")
2171 return OUString::Concat(ns) +
"." + tn;
2174 void pgTypeInfo2ResultSet(
2175 std::vector< std::vector<Any> > &vec,
2178 static const sal_Int32 TYPE_NAME = 0;
2179 static const sal_Int32 DATA_TYPE = 1;
2181 static const sal_Int32 CREATE_PARAMS = 5;
2182 static const sal_Int32 NULLABLE = 6;
2187 static const sal_Int32 CASE_SENSITIVE = 7;
2188 static const sal_Int32 SEARCHABLE = 8;
2194 static const sal_Int32 UNSIGNED_ATTRIBUTE = 9;
2196 static const sal_Int32 AUTO_INCREMENT = 11;
2198 static const sal_Int32 MINIMUM_SCALE = 13;
2199 static const sal_Int32 MAXIMUM_SCALE = 14;
2200 static const sal_Int32 NUM_PREC_RADIX = 17;
2215 std::vector< Any > row(18);
2218 sal_Int32
precision = xRow->getString(3).toInt32();
2220 if( dataType == css::sdbc::DataType::CHAR ||
2221 ( dataType == css::sdbc::DataType::VARCHAR &&
2222 xRow->getString(TYPE_NAME+1).equalsIgnoreAsciiCase(
"varchar") ) )
2229 row[CREATE_PARAMS] <<= OUString(
"length");
2231 else if( dataType == css::sdbc::DataType::NUMERIC )
2234 row[CREATE_PARAMS] <<= OUString(
"length, scale");
2237 row[TYPE_NAME] <<= construct_full_typename(xRow->getString(6), xRow->getString(1));
2238 row[DATA_TYPE] <<= OUString::number(dataType);
2240 sal_Int32 nullable = xRow->getBoolean(4) ?
2241 css::sdbc::ColumnValue::NO_NULLS :
2242 css::sdbc::ColumnValue::NULLABLE;
2243 row[NULLABLE] <<= OUString::number(nullable);
2244 row[CASE_SENSITIVE] <<= OUString::number(1);
2245 row[SEARCHABLE] <<= OUString::number( calcSearchable( dataType ) );
2246 row[UNSIGNED_ATTRIBUTE] <<= OUString(
"0");
2247 if( css::sdbc::DataType::INTEGER == dataType ||
2248 css::sdbc::DataType::BIGINT == dataType )
2249 row[AUTO_INCREMENT] <<= OUString(
"1");
2251 row[AUTO_INCREMENT] <<= OUString(
"0");
2252 row[MINIMUM_SCALE] <<= OUString(
"0");
2253 row[MAXIMUM_SCALE] <<= OUString::number( getMaxScale( dataType ) );
2254 row[NUM_PREC_RADIX] <<= OUString(
"10");
2255 vec.push_back( row );
2264 MutexGuard guard(
m_xMutex->GetMutex() );
2266 SAL_INFO(
"connectivity.postgresql",
"DatabaseMetaData::getTypeInfo() got called");
2270 "SELECT pg_type.typname AS typname,"
2271 "pg_type.typtype AS typtype,"
2272 "pg_type.typlen AS typlen,"
2273 "pg_type.typnotnull AS typnotnull,"
2274 "pg_type.typname AS typname, "
2275 "pg_namespace.nspname as typns "
2276 "FROM pg_type LEFT JOIN pg_namespace ON pg_type.typnamespace=pg_namespace.oid "
2277 "WHERE pg_type.typtype = 'b' "
2278 "OR pg_type.typtype = 'p'"
2281 std::vector< std::vector<Any> > vec;
2282 pgTypeInfo2ResultSet( vec, rs );
2285 rs = statement->executeQuery(
2286 "SELECT t1.typname as typname,"
2287 "t2.typtype AS typtype,"
2288 "t2.typlen AS typlen,"
2289 "t2.typnotnull AS typnotnull,"
2290 "t2.typname as realtypname, "
2291 "pg_namespace.nspname as typns "
2292 "FROM pg_type as t1 LEFT JOIN pg_type AS t2 ON t1.typbasetype=t2.oid LEFT JOIN pg_namespace ON t1.typnamespace=pg_namespace.oid "
2293 "WHERE t1.typtype = 'd'" );
2294 pgTypeInfo2ResultSet( vec, rs );
2296 std::sort( vec.begin(), vec.end(), TypeInfoByDataTypeSorter() );
2301 std::vector(
getStatics().typeinfoColumnNames),
2309 const css::uno::Any& ,
2310 const OUString& schema,
2311 const OUString& table,
2316 MutexGuard guard(
m_xMutex->GetMutex() );
2348 static const sal_Int32 C_SCHEMA = 1;
2349 static const sal_Int32 C_TABLENAME = 2;
2350 static const sal_Int32 C_INDEXNAME = 3;
2351 static const sal_Int32 C_IS_CLUSTERED = 4;
2352 static const sal_Int32 C_IS_UNIQUE = 5;
2354 static const sal_Int32 C_COLUMNS = 7;
2356 static const sal_Int32 R_TABLE_SCHEM = 1;
2357 static const sal_Int32 R_TABLE_NAME = 2;
2358 static const sal_Int32 R_NON_UNIQUE = 3;
2359 static const sal_Int32 R_INDEX_NAME = 5;
2360 static const sal_Int32 R_TYPE = 6;
2361 static const sal_Int32 R_ORDINAL_POSITION = 7;
2362 static const sal_Int32 R_COLUMN_NAME = 8;
2366 "pg_class.relname, "
2372 "FROM pg_index INNER JOIN pg_class ON indrelid = pg_class.oid "
2373 "INNER JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid "
2374 "INNER JOIN pg_class as class2 ON pg_index.indexrelid = class2.oid "
2375 "WHERE nspname = ? AND pg_class.relname = ?" );
2378 param->setString( 1, schema );
2379 param->setString( 2,
table );
2383 std::vector< std::vector<Any> > vec;
2386 std::vector< sal_Int32 > columns =
parseIntArray( xRow->getString(C_COLUMNS) );
2388 "SELECT attnum, attname "
2389 "FROM pg_attribute "
2390 " INNER JOIN pg_class ON attrelid = pg_class.oid "
2391 " INNER JOIN pg_namespace ON pg_class.relnamespace=pg_namespace.oid "
2392 " WHERE pg_namespace.nspname=? AND pg_class.relname=?" );
2394 OUString currentSchema = xRow->getString( C_SCHEMA );
2395 OUString currentTable = xRow->getString( C_TABLENAME );
2396 OUString currentIndexName = xRow->getString( C_INDEXNAME );
2397 bool isNonUnique = ! xRow->getBoolean( C_IS_UNIQUE );
2398 sal_Int32 indexType = xRow->getBoolean( C_IS_CLUSTERED ) ?
2399 css::sdbc::IndexType::CLUSTERED :
2400 css::sdbc::IndexType::HASHED;
2402 paramColumn->setString( C_SCHEMA, currentSchema );
2403 paramColumn->setString( C_TABLENAME, currentTable );
2407 while( rsColumn->next() )
2409 auto findIt = std::find( columns.begin(), columns.end(), rowColumn->getInt( 1 ) );
2410 if( findIt != columns.end() && ( ! isNonUnique || ! unique ) )
2412 std::vector< Any >
result( 13 );
2413 result[R_TABLE_SCHEM] <<= currentSchema;
2414 result[R_TABLE_NAME] <<= currentTable;
2415 result[R_INDEX_NAME] <<= currentIndexName;
2416 result[R_NON_UNIQUE] <<= isNonUnique;
2417 result[R_TYPE] <<= indexType;
2418 result[R_COLUMN_NAME] <<= rowColumn->getString(2);
2419 sal_Int32
nPos =
static_cast<sal_Int32
>(findIt - columns.begin() +1);
2433 if ( setType == css::sdbc::ResultSetType::SCROLL_SENSITIVE )
2440 sal_Int32 setType, sal_Int32 )
2497css::uno::Reference< XResultSet >
DatabaseMetaData::getUDTs(
const css::uno::Any&,
const OUString&,
const OUString&,
const css::uno::Sequence< sal_Int32 >& )
2500 MutexGuard guard(
m_xMutex->GetMutex() );
#define SAL_INFO(area, stream)
constexpr bool starts_with(std::basic_string_view< charT, traits > sv, std::basic_string_view< charT, traits > x) noexcept
std::basic_string_view< charT, traits > getToken(std::basic_string_view< charT, traits > sv, charT delimiter, std::size_t &position)
std::vector< sal_Int32 > parseIntArray(const OUString &str)
void disposeNoThrow(const css::uno::Reference< css::uno::XInterface > &r)
OUString getColExprForDefaultSettingVal(ConnectionSettings const *settings)
static void columnMetaData2DatabaseTypeDescription(Oid2DatabaseTypeDescriptionMap &oidMap, const Reference< XResultSet > &rs, const Reference< XStatement > &stmt)
std::unordered_map< sal_Int32, DatabaseTypeDescription > Oid2DatabaseTypeDescriptionMap
static void extractPrecisionAndScale(sal_Int32 atttypmod, sal_Int32 *precision, sal_Int32 *scale)
sal_Int32 typeNameToDataType(const OUString &typeName, std::u16string_view typtype)
returns the constant from sdbc.DataType
#define PQ_SDBC_DRIVER_VERSION
css::uno::Reference< css::script::XTypeConverter > tc
std::vector< OUString > columnRowNames
std::vector< OUString > tablesRowNames