LibreOffice Module connectivity (master) 1
pq_databasemetadata.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*************************************************************************
3 *
4 * Effective License of whole file:
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License version 2.1, as published by the Free Software Foundation.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
18 * MA 02111-1307 USA
19 *
20 * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
21 *
22 * The Contents of this file are made available subject to the terms of
23 * the GNU Lesser General Public License Version 2.1
24 *
25 * Copyright: 2000 by Sun Microsystems, Inc.
26 *
27 * Contributor(s): Joerg Budischewski
28 *
29 * All parts contributed on or after August 2011:
30 *
31 * This Source Code Form is subject to the terms of the Mozilla Public
32 * License, v. 2.0. If a copy of the MPL was not distributed with this
33 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
34 *
35 * Some portions were adapted from JDBC PostgreSQL driver:
36 *
37 * Copyright (c) 2004-2008, PostgreSQL Global Development Group
38 *
39 * Licence of original JDBC driver code:
40 *
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions are met:
43 *
44 * 1. Redistributions of source code must retain the above copyright notice,
45 * this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright notice,
47 * this list of conditions and the following disclaimer in the documentation
48 * and/or other materials provided with the distribution.
49 * 3. Neither the name of the PostgreSQL Global Development Group nor the names
50 * of its contributors may be used to endorse or promote products derived
51 * from this software without specific prior written permission.
52 *
53 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
54 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
57 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
58 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
59 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
60 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
61 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
62 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
63 * POSSIBILITY OF SUCH DAMAGE.
64 *
65 ************************************************************************/
66
67#include <algorithm>
68#include <string_view>
69
70#include <sal/log.hxx>
72#include "pq_driver.hxx"
74#include "pq_statics.hxx"
75#include "pq_tools.hxx"
76
77#include <o3tl/string_view.hxx>
78#include <rtl/ustrbuf.hxx>
79#include <sal/macros.h>
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>
87#include <utility>
88
89using ::osl::MutexGuard;
90
91
92using namespace com::sun::star::sdbc;
93
96using com::sun::star::uno::Any;
97using com::sun::star::uno::UNO_QUERY;
98using com::sun::star::uno::UNO_QUERY_THROW;
99
100namespace pq_sdbc_driver
101{
102// These are pre-processor versions of KeyRule.idl declarations
103// These are inherited from JDBC, and thus won't change anytime soon.
104// Having them as pre-processor definitions allows to include them
105// into compile-time strings (through SAL_STRINGIFY), which can be passed to ASCII_STR.
106// That is without resorting to horrendous hacks in template meta-programming.
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
112// Ditto for Deferrability.idl
113#define DEFERRABILITY_INITIALLY_DEFERRED 5
114#define DEFERRABILITY_INITIALLY_IMMEDIATE 6
115#define DEFERRABILITY_NONE 7
116
119 css::uno::Reference< css::sdbc::XConnection > origin,
120 ConnectionSettings *pSettings )
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=?") )
125{
128}
129
131{
132 // TODO
133 return false;
134}
135
137{
138 return true;
139}
140
142{
143 // TODO
144 // LEM TODO: implement
145 return OUString();
146}
147
149{
150 return m_pSettings->user;
151}
152
154{
155 return false;
156}
157
158
160{
161 // Whether NULL values are considered, for sorting purposes, LARGER than any other value.
162 // Specification: http://download.oracle.com/javase/6/docs/api/java/sql/DatabaseMetaData.html#nullsAreSortedHigh()
163 // PostgreSQL behaviour: http://www.postgresql.org/docs/9.1/static/queries-order.html
164 return true;
165}
166
168{
169 return ! nullsAreSortedHigh();
170}
171
173{
174 return false;
175}
176
178{
179 return false;
180}
181
183{
184 return "PostgreSQL";
185}
186
188{
189 return OUString::createFromAscii( PQparameterStatus( m_pSettings->pConnection, "server_version" ) );
190}
192{
193 return "postgresql-sdbc";
194}
195
197{
199}
200
202{
203 return PQ_SDBC_MAJOR;
204}
205
207{
208 return PQ_SDBC_MINOR;
209}
210
212{
213 // LEM TODO:
214 // https://wiki.documentfoundation.org/Documentation/DevGuide/Database_Access#XDatabaseMetaData_Interface
215 // says "Returns true when the catalog name of the
216 // database should not appear in the DatasourceBrowser
217 // of LibreOffice API, otherwise false is returned."
218 // So, hmmm, think about it.
219 return false;
220}
221
223{
224 return false;
225}
226
228{
229 return false;
230}
231
233{
234 return false;
235}
236
238{
239 return true;
240}
241
242
244{
245 return false;
246}
247
248
250{
251 return true;
252}
253
255{
256 return false;
257}
258
259
261{
262 return false;
263}
264
265
267{
268 return false;
269}
270
271
273{
274 return "\"";
275}
276
278{
279 // In Java 6, this is all keywords that are not SQL:2003
280 // In Java 2 v1.4 and as per LibreOffice SDK doc, this is all keywords that are not SQL92
281 // I understand this to mean "reserved keywords" only.
282 // See http://www.postgresql.org/docs/current/static/sql-keywords-appendix.html
283 // LEM TODO: consider using pg_get_keywords(), filter on catcode
284 return
285 "ANALYSE,"
286 "ANALYZE,"
287 "ARRAY," //SQL:1999
288 "ASYMMETRIC," //SQL:2003
289 "BINARY," //SQL:1999
290 "CONCURRENTLY,"
291 "CURRENT_CATALOG," //SQL:2008
292 "CURRENT_ROLE," //SQL:1999
293 "CURRENT_SCHEMA," //SQL:2008
294 "DO,"
295 "FREEZE,"
296 "ILIKE,"
297 "ISNULL,"
298 "LIMIT," //SQL:1999; non-reserved in SQL:2003
299 "LOCALTIME," //SQL:1999
300 "LOCALTIMESTAMP," //SQL:1999
301 "NOTNULL,"
302 "OFFSET," //SQL:2008
303 "OVER," //SQL:2003
304 "PLACING," //non-reserved in SQL:2003
305 "RETURNING," //non-reserved in SQL:2008
306 "SIMILAR," //SQL:2003
307 "VARIADIC,"
308 "VERBOSE,"
309 "WINDOW" //SQL:2003
310 ;
311}
313{
314 // See https://www.postgresql.org/docs/9.1/static/functions-math.html
315 // LEM TODO: Err... https://wiki.documentfoundation.org/Documentation/DevGuide/Database_Access#Support_Scalar_Functions
316 // says this should be "Open Group CLI" names, not PostgreSQL names.
317 // Currently this is just a list of supported functions in PostgreSQL, with PostgreSQL names.
318 // And it is my job to map from Open Group CLI names/syntax to PostgreSQL names/syntax. Where? By parsing the SQL???
319 // Should look at what the JDBC driver is doing.
320 return
321 "abs,"
322 "cbrt,"
323 "ceil,"
324 "ceiling,"
325 "degrees,"
326 "div,"
327 "exp,"
328 "floor,"
329 "ln,"
330 "log,"
331 "mod,"
332 "pi,"
333 "power,"
334 "radians,"
335 "random,"
336 "round,"
337 "setseed,"
338 "sign,"
339 "sqrt,"
340 "trunc,"
341 "width_bucket,"
342 "acos,"
343 "asin,"
344 "atan,"
345 "atan2,"
346 "cos,"
347 "cot,"
348 "sin,"
349 "tan"
350 ;
351}
352
354{
355 // See http://www.postgresql.org/docs/9.1/static/functions-string.html
356 return
357 "bit_length,"
358 "char_length,"
359 "character_length,"
360 "lower,"
361 "octet_length,"
362 "overlay,"
363 "position,"
364 "substring,"
365 "trim,"
366 "upper,"
367 "ascii,"
368 "btrim,"
369 "chr,"
370 "concat,"
371 "concat_ws,"
372 "convert,"
373 "convert_from,"
374 "convert_to,"
375 "decode,"
376 "encode,"
377 "format,"
378 "initcap,"
379 "left,"
380 "length,"
381 "lpad,"
382 "ltrim,"
383 "md5,"
384 "pg_client_encoding,"
385 "quote_ident,"
386 "quote_literal,"
387 "quote_nullable,"
388 "regexp_matches,"
389 "regexp_replace,"
390 "regexp_split_to_array,"
391 "regexp_split_to_table,"
392 "repeat,"
393 "replace,"
394 "reverse,"
395 "right,"
396 "rpad,"
397 "rtrim,"
398 "split_part,"
399 "strpos,"
400 "substr,"
401 "to_ascii,"
402 "to_hex,"
403 "translate"
404 ;
405}
406
408{
409 // See http://www.postgresql.org/docs/9.1/static/functions-info.html
410 // and http://www.postgresql.org/docs/9.1/static/functions-admin.html
411 return
412 "current_catalog,"
413 "current_database,"
414 "current_query,"
415 "current_schema,"
416 "current_schemas,"
417 "current_user,"
418 "inet_client_addr,"
419 "inet_client_port,"
420 "inet_server_addr,"
421 "inet_server_port,"
422 "pg_backend_pid,"
423 "pg_conf_load_time,"
424 "pg_is_other_temp_schema,"
425 "pg_listening_channels,"
426 "pg_my_temp_schema,"
427 "pg_postmaster_start_time,"
428 "session_user,"
429 "user,"
430 "version,"
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,"
444 "pg_has_role,"
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,"
456 "format_type,"
457 "pg_describe_object,"
458 "pg_get_constraintdef,"
459 "pg_get_expr,"
460 "pg_get_functiondef,"
461 "pg_get_function_arguments,"
462 "pg_get_function_identity_arguments,"
463 "pg_get_function_result,"
464 "pg_get_indexdef,"
465 "pg_get_keywords,"
466 "pg_get_ruledef,"
467 "pg_get_serial_sequence,"
468 "pg_get_triggerdef,"
469 "pg_get_userbyid,"
470 "pg_get_viewdef,"
471 "pg_options_to_table,"
472 "pg_tablespace_databases,"
473 "pg_typeof,"
474 "col_description,"
475 "obj_description,"
476 "shobj_description,"
477 "txid_current,"
478 "txid_current_snapshot,"
479 "txid_snapshot_xip,"
480 "txid_snapshot_xmax,"
481 "txid_snapshot_xmin,"
482 "txid_visible_in_snapshot,"
483 "xmin,"
484 "xmax,"
485 "xip_list,"
486 "current_setting,"
487 "set_config,"
488 "pg_cancel_backend,"
489 "pg_reload_conf,"
490 "pg_rotate_logfile,"
491 "pg_terminate_backend,"
492 "pg_create_restore_point,"
493 "pg_current_xlog_insert_location,"
494 "pg_current_xlog_location,"
495 "pg_start_backup,"
496 "pg_stop_backup,"
497 "pg_switch_xlog,"
498 "pg_xlogfile_name,"
499 "pg_xlogfile_name_offset,"
500 "pg_is_in_recovery,"
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,"
507 "pg_column_size,"
508 "pg_database_size,"
509 "pg_indexes_size,"
510 "pg_relation_size,"
511 "pg_size_pretty,"
512 "pg_table_size,"
513 "pg_tablespace_size,"
514 "pg_tablespace_size,"
515 "pg_total_relation_size,"
516 "pg_relation_filenode,"
517 "pg_relation_filepath,"
518 "pg_ls_dir,"
519 "pg_read_file,"
520 "pg_read_binary_file,"
521 "pg_stat_file,"
522 "pg_advisory_lock,"
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,"
533 "pg_sleep"
534 ;
535}
537{
538 // TODO
539 return
540 "age,"
541 "age,"
542 "clock_timestamp,"
543 "current_date,"
544 "current_time,"
545 "current_timestamp,"
546 "date_part,"
547 "date_part,"
548 "date_trunc,"
549 "extract,"
550 "extract,"
551 "isfinite,"
552 "isfinite,"
553 "isfinite,"
554 "justify_days,"
555 "justify_hours,"
556 "justify_interval,"
557 "localtime,"
558 "localtimestamp,"
559 "now,"
560 "statement_timestamp,"
561 "timeofday,"
562 "transaction_timestamp,"
563 ;
564}
566{
567 return "\\";
568}
570{
571 return "$";
572}
573
575{
576 return true;
577}
578
580{
581 return true;
582}
583
585{
586 return true;
587}
588
590{
591 return true;
592}
593
595{
596 // LEM: this is specifically whether the "CONVERT" function is supported
597 // It seems that in PostgreSQL, that function is only for string encoding, so no.
598 return false;
599}
600
602{
603 return false;
604}
605
607{
608 // LEM: A correlation name is "bar" in "SELECT foo FROM qux [AS] bar WHERE ..."
609 return true;
610}
611
612
614{
615 return false;
616}
618{
619 return true;
620}
621
623{
624 return true;
625}
626
628{
629 return true;
630}
631
633{
634 return true;
635}
636
638{
639 return true;
640}
641
643{
644 return true;
645}
646
648{
649 return true;
650}
651
653{
654 // Allows multiple transactions open at once (on different connections!)
655 return true;
656}
657
659{
660 return true;
661}
662
663
665{
666 return true;
667}
668
670{
671 // LEM: jdbc driver says not, although the comments in it seem old
672 // fdo#45249 Base query design won't use any aggregate function
673 // (except COUNT(*) unless we say yes, so say yes.
674 // Actually, Base assumes *also* support for aggregate functions "collect, fusion, intersection"
675 // as soon as supportsCoreSQLGrammar() returns true.
676 // Those are *not* Core SQL, though. They are in optional feature S271 "Basic multiset support"
677 return true;
678}
679
681{
682 return false;
683}
684
686{
687 return true;
688}
689
691{
692 // LEM: jdbc driver says not, although the comments in it seem old
693 return false;
694}
695
697{
698 // LEM: jdbc driver says not, although the comments in it seem old
699 return false;
700}
701
703{
704 // LEM: jdbc driver says yes, although comment says they are not sure what this means...
705 return true;
706}
707
709{
710 return true;
711}
712
714{
715 return true;
716}
717
719{
720 return true;
721}
722
723
725{
726 return "SCHEMA";
727}
728
730{
731 return "function";
732}
733
735{
736 return "DATABASE";
737}
738
740{
741 return true;
742}
743
745{
746 return ".";
747}
748
750{
751 return true;
752}
753
755{
756 return true;
757}
758
760{
761 return true;
762}
763
765{
766 return true;
767}
768
770{
771 return true;
772}
773
775{
776 return false;
777}
778
780{
781 return false;
782}
783
785{
786 return false;
787}
788
789
791{
792 return false;
793}
794
795
797{
798 return false;
799}
800
801
802// LEM TODO: positioned (through cursor) updates and deletes seem
803// to be supported; see {UPDATE,DELETE} /table/ (...) WHERE CURRENT OF /cursor_name/" syntax
804// and http://www.postgresql.org/docs/9.1/static/view-pg-cursors.html
805// http://www.postgresql.org/docs/9.1/static/libpq-example.html actually uses a cursor :)
807{
808 // LEM: jdbc driver says not, although the comments in it seem old
809 return false;
810}
811
813{
814 // LEM: jdbc driver says not, although the comments in it seem old
815 return false;
816}
817
818
820{
821 return true;
822}
823
824
826{
827 return true;
828}
829
830
832{
833 return true;
834}
835
837{
838 return true;
839}
840
842{
843 return true;
844}
845
847{
848 // LEM: jdbc driver says yes, although comment says they don't know what this means...
849 return true;
850}
851
853{
854 return true;
855}
857{
858 return true;
859}
860
862{
863 return true;
864}
865
867{
868 return false;
869}
870
872{
873 return false;
874}
875
877{
878 return true;
879}
881{
882 return true;
883}
884
886{
887 return 0;
888}
889
891{
892 return 0;
893}
894
895// Copied / adapted / simplified from JDBC driver
896sal_Int32 DatabaseMetaData::getIntSetting(const OUString& settingName)
897{
898 MutexGuard guard( m_xMutex->GetMutex() );
899
900 Reference< XParameters > params(m_getIntSetting_stmt, UNO_QUERY_THROW );
901 params->setString(1, settingName );
903 Reference< XRow > xRow( rs , UNO_QUERY_THROW );
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);
908}
909
911{
912 if ( m_pSettings->maxNameLen == 0)
913 m_pSettings->maxNameLen = getIntSetting( "max_identifier_length" );
914 OSL_ENSURE(m_pSettings->maxNameLen, "postgresql-sdbc: maxNameLen is zero");
915 return m_pSettings->maxNameLen;
916}
917
919{
920 if ( m_pSettings->maxIndexKeys == 0)
921 m_pSettings->maxIndexKeys = getIntSetting("max_index_keys");
922 OSL_ENSURE(m_pSettings->maxIndexKeys, "postgresql-sdbc: maxIndexKeys is zero");
924}
925
927{
928 return getMaxNameLength();
929}
930
932{
933 return 0;
934}
935
937{
938 return getMaxIndexKeys();
939}
940
942{
943 return 0;
944}
945
947{
948 return 0;
949}
950
952{
953 return 1600;
954}
955
957{
958 // LEM: The JDBC driver returns an arbitrary 8192; truth is as much as OS / hardware supports
959 return 0;
960}
961
962sal_Int32 DatabaseMetaData::getMaxCursorNameLength( ) //TODO, don't know
963{
964 return getMaxNameLength();
965}
966
967sal_Int32 DatabaseMetaData::getMaxIndexLength( ) //TODO, don't know
968{
969 // LEM: that's the index itself, not its name
970 return 0;
971}
972
974{
975 return getMaxNameLength();
976}
977
979{
980 return getMaxNameLength();
981}
982
984{
985 return getMaxNameLength();
986}
987
989{
990 // jdbc driver says 1GB, but http://www.postgresql.org/about/ says 1.6TB
991 // and that 1GB is the maximum _field_ size
992 // The row limit does not fit into a sal_Int32
993 return 0;
994}
995
997{
998 // LEM: Err... PostgreSQL basically does not do BLOBs well
999 // In any case, BLOBs do not change the maximal row length AFAIK
1000 return true;
1001}
1002
1004{
1005 // LEM: actually, that would be 2^sizeof(size_t)-1
1006 // on the server? on the client (because of libpq)? minimum of the two? not sure
1007 // Anyway, big, so say unlimited.
1008 return 0;
1009}
1010
1011sal_Int32 DatabaseMetaData::getMaxStatements( ) //TODO, don't know
1012{
1013 return 0;
1014}
1015
1017{
1018 return getMaxNameLength();
1019}
1020
1022{
1023 return 0;
1024}
1025
1027{
1028 return getMaxNameLength();
1029}
1030
1032{
1033 return css::sdbc::TransactionIsolation::READ_COMMITTED;
1034}
1035
1037{
1038 return true;
1039}
1040
1042{
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)
1047 return true;
1048 else
1049 return false;
1050}
1051
1053{
1054 return true;
1055}
1056
1058{
1059 return false;
1060}
1061
1063{
1064 return false;
1065}
1066
1068{
1069 return false;
1070}
1071
1072css::uno::Reference< XResultSet > DatabaseMetaData::getProcedures(
1073 const css::uno::Any&,
1074 const OUString&,
1075 const OUString& )
1076{
1077// 1. PROCEDURE_CAT string =&gt; procedure catalog (may be NULL )
1078// 2. PROCEDURE_SCHEM string =&gt; procedure schema (may be NULL )
1079// 3. PROCEDURE_NAME string =&gt; procedure name
1080// 4. reserved for future use
1081// 5. reserved for future use
1082// 6. reserved for future use
1083// 7. REMARKS string =&gt; explanatory comment on the procedure
1084// 8. PROCEDURE_TYPE short =&gt; kind of procedure:
1085// * UNKNOWN - May return a result
1086// * NO - Does not return a result
1087// * RETURN - Returns a result
1088
1089// LEM TODO: implement
1090// LEM TODO: at least fake the columns, even if no row.
1091 MutexGuard guard( m_xMutex->GetMutex() );
1092 return new SequenceResultSet(
1093 m_xMutex, *this, std::vector< OUString >(), std::vector< std::vector< Any > > (), m_pSettings->tc );
1094}
1095
1096css::uno::Reference< XResultSet > DatabaseMetaData::getProcedureColumns(
1097 const css::uno::Any&,
1098 const OUString&,
1099 const OUString&,
1100 const OUString& )
1101{
1102 MutexGuard guard( m_xMutex->GetMutex() );
1103// LEM TODO: implement
1104// LEM TODO: at least fake the columns, even if no row.
1105 return new SequenceResultSet(
1106 m_xMutex, *this, std::vector< OUString >(), std::vector< std::vector< Any > >(), m_pSettings->tc );
1107}
1108
1109css::uno::Reference< XResultSet > DatabaseMetaData::getTables(
1110 const css::uno::Any&,
1111 const OUString& schemaPattern,
1112 const OUString& tableNamePattern,
1113 const css::uno::Sequence< OUString >& )
1114{
1115 Statics &statics = getStatics();
1116
1117 MutexGuard guard( m_xMutex->GetMutex() );
1118
1119 SAL_INFO("connectivity.postgresql", "DatabaseMetaData::getTables() got called with " << schemaPattern << "." << tableNamePattern);
1120
1121 // ignore catalog, as a single pq connection does not support multiple catalogs
1122
1123 // LEM TODO: this does not give the right column names, not the right number of columns, etc.
1124 // Take "inspiration" from JDBC driver
1125 // Ah, this is used to create a XResultSet manually... Try to do it directly in SQL
1126 Reference< XPreparedStatement > statement = m_origin->prepareStatement(
1127 "SELECT "
1128 "DISTINCT ON (pg_namespace.nspname, relname ) " // avoid duplicates (pg_settings !)
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 ? "
1135// "ORDER BY pg_namespace.nspname || relname"
1136 );
1137
1138 Reference< XParameters > parameters( statement, UNO_QUERY_THROW );
1139 parameters->setString( 1 , schemaPattern );
1140 parameters->setString( 2 , tableNamePattern );
1141
1142 Reference< XResultSet > rs = statement->executeQuery();
1143 Reference< XRow > xRow( rs, UNO_QUERY_THROW );
1144 std::vector< std::vector<Any> > vec;
1145
1146 while( rs->next() )
1147 {
1148 std::vector< Any > row( 5 );
1149
1150 row[0] <<= m_pSettings->catalog;
1151 row[1] <<= xRow->getString( 1 );
1152 row[2] <<= xRow->getString( 2 );
1153 OUString type = xRow->getString(3);
1154 if( type == "r" )
1155 {
1156 if( xRow->getString(1) == "pg_catalog" )
1157 {
1158 row[3] <<= statics.SYSTEM_TABLE;
1159 }
1160 else
1161 {
1162 row[3] <<= statics.TABLE;
1163 }
1164 }
1165 else if( type == "v" )
1166 {
1167 row[3] <<= statics.VIEW;
1168 }
1169 else
1170 {
1171 row[3] <<= statics.UNKNOWN;
1172 }
1173 row[4] <<= xRow->getString(4);
1174
1175 // no description in postgresql AFAIK
1176 vec.push_back( row );
1177 }
1178 Reference< XCloseable > closeable( statement, UNO_QUERY );
1179 if( closeable.is() )
1180 closeable->close();
1181
1182 return new SequenceResultSet(
1183 m_xMutex, *this, std::vector(statics.tablesRowNames), std::move(vec), m_pSettings->tc );
1184}
1185
1186namespace
1187{
1188 // sort no schema first, then "public", then normal schemas, then internal schemas
1189 int compare_schema(std::u16string_view nsA, std::u16string_view nsB)
1190 {
1191 if (nsA.empty())
1192 {
1193 return nsB.empty() ? 0 : -1;
1194 }
1195 else if (nsB.empty())
1196 {
1197 assert(!nsA.empty());
1198 return 1;
1199 }
1200 else if(nsA == u"public")
1201 {
1202 return (nsB == u"public") ? 0 : -1;
1203 }
1204 else if(nsB == u"public")
1205 {
1206 assert(nsA != u"public");
1207 return 1;
1208 }
1209 else if(o3tl::starts_with(nsA, u"pg_"))
1210 {
1211 if(o3tl::starts_with(nsB, u"pg_"))
1212 return nsA.compare(nsB);
1213 else
1214 return 1;
1215 }
1216 else if(o3tl::starts_with(nsB, u"pg_"))
1217 {
1218 return -1;
1219 }
1220 else
1221 {
1222 return nsA.compare(nsB);
1223 }
1224 }
1225
1226 struct SortInternalSchemasLastAndPublicFirst
1227 {
1228 bool operator () ( const std::vector< Any > & a, const std::vector< Any > & b )
1229 {
1230 OUString valueA;
1231 OUString valueB;
1232 a[0] >>= valueA;
1233 b[0] >>= valueB;
1234 return compare_schema(valueA, valueB) < 0;
1235 }
1236 };
1237}
1238
1239css::uno::Reference< XResultSet > DatabaseMetaData::getSchemas( )
1240{
1241 MutexGuard guard( m_xMutex->GetMutex() );
1242
1243 SAL_INFO("connectivity.postgresql", "DatabaseMetaData::getSchemas() got called");
1244
1245 // <b>TABLE_SCHEM</b> string =&amp;gt; schema name
1246 Reference< XStatement > statement = m_origin->createStatement();
1247 Reference< XResultSet > rs = statement->executeQuery(
1248 "SELECT nspname from pg_namespace" );
1249 // LEM TODO: look at JDBC driver and consider doing the same
1250 // in particular, excluding temporary schemas, but maybe better through pg_is_other_temp_schema(oid) OR == pg_my_temp_schema()
1251
1252 Reference< XRow > xRow( rs, UNO_QUERY_THROW );
1253 std::vector< std::vector<Any> > vec;
1254 while( rs->next() )
1255 {
1256 vec.push_back( { Any(xRow->getString(1)) } );
1257 }
1258
1259 // sort public first, sort internal schemas last, sort rest in alphabetic order
1260 std::sort( vec.begin(), vec.end(), SortInternalSchemasLastAndPublicFirst() );
1261
1262 Reference< XCloseable > closeable( statement, UNO_QUERY );
1263 if( closeable.is() )
1264 closeable->close();
1265 return new SequenceResultSet(
1266 m_xMutex, *this, std::vector(getStatics().schemaNames), std::move(vec), m_pSettings->tc );
1267}
1268
1269css::uno::Reference< XResultSet > DatabaseMetaData::getCatalogs( )
1270{
1271 // LEM TODO: return the current catalog like JDBC driver?
1272 // at least fake the columns, even if no content
1273 MutexGuard guard( m_xMutex->GetMutex() );
1274 return new SequenceResultSet(
1275 m_xMutex, *this, std::vector< OUString >(), std::vector< std::vector< Any > >(), m_pSettings->tc );
1276}
1277
1278css::uno::Reference< XResultSet > DatabaseMetaData::getTableTypes( )
1279{
1280 // LEM TODO: this can be made dynamic, see JDBC driver
1281 MutexGuard guard( m_xMutex->GetMutex() );
1282 return new SequenceResultSet(
1283 m_xMutex, *this, std::vector(getStatics().tableTypeNames), std::vector(getStatics().tableTypeData),
1284 m_pSettings->tc );
1285}
1286
1287
1290sal_Int32 typeNameToDataType( const OUString &typeName, std::u16string_view typtype )
1291{
1292// sal_Int32 ret = css::sdbc::DataType::DISTINCT;
1293 // map all unknown types to memo (longvarchar). This allows to show them in
1294 // string representation. Additionally, the edit-table-type-selection-box
1295 // is not so unusable anymore.
1296 sal_Int32 ret = css::sdbc::DataType::LONGVARCHAR;
1297 if( typtype == u"b" )
1298 {
1299 // as long as the OOo framework does not support arrays,
1300 // the user is better of with interpreting arrays as strings !
1301// if( typeName.getLength() && '_' == typeName[0] )
1302// {
1303// it's just a naming convention, but as long as we don't have anything better,
1304// we take it as granted
1305// ret = css::sdbc::DataType::ARRAY;
1306// }
1307 // base type
1308 Statics &statics = getStatics();
1309 BaseTypeMap::const_iterator ii = statics.baseTypeMap.find( typeName );
1310 if( ii != statics.baseTypeMap.end() )
1311 {
1312 ret = ii->second;
1313 }
1314 }
1315 else if( typtype == u"c" )
1316 {
1317 ret = css::sdbc::DataType::STRUCT;
1318 }
1319 else if( typtype == u"d" )
1320 {
1321 ret = css::sdbc::DataType::LONGVARCHAR;
1322 }
1323 return ret;
1324}
1325
1326namespace {
1327 bool isSystemColumn( sal_Int16 attnum )
1328 {
1329 return attnum <= 0;
1330 }
1331
1332 // is not exported by the postgres header
1333 const int PQ_VARHDRSZ = sizeof( sal_Int32 );
1334
1335 // Oh, quelle horreur
1336 // LEM TODO: Need to severely rewrite that!
1337 // should probably just "do the same" as ODBC or JDBC drivers...
1339 sal_Int32 dataType, sal_Int32 atttypmod, sal_Int32 *precision, sal_Int32 *scale )
1340 {
1341 if( atttypmod < PQ_VARHDRSZ )
1342 {
1343 *precision = 0;
1344 *scale = 0;
1345 }
1346 else
1347 {
1348 switch( dataType )
1349 {
1350 case css::sdbc::DataType::NUMERIC:
1351 case css::sdbc::DataType::DECIMAL:
1352 {
1353 *precision = ( ( atttypmod - PQ_VARHDRSZ ) >> 16 ) & 0xffff;
1354 *scale = (atttypmod - PQ_VARHDRSZ ) & 0xffff;
1355 break;
1356 }
1357 default:
1358 *precision = atttypmod - PQ_VARHDRSZ;
1359 *scale = 0;
1360 }
1361 }
1362 }
1363
1364 struct DatabaseTypeDescription
1365 {
1366 DatabaseTypeDescription()
1367 {}
1368 DatabaseTypeDescription( OUString name, OUString type ) :
1369 typeName(std::move( name )),
1370 typeType(std::move( type ))
1371 {}
1372 DatabaseTypeDescription( const DatabaseTypeDescription &source ) :
1373 typeName( source.typeName ),
1374 typeType( source.typeType )
1375 {}
1376 DatabaseTypeDescription & operator = ( const DatabaseTypeDescription & source )
1377 {
1378 typeName = source.typeName;
1379 typeType = source.typeType;
1380 return *this;
1381 }
1382 OUString typeName;
1383 OUString typeType;
1384 };
1385}
1386
1387typedef std::unordered_map
1388<
1389 sal_Int32,
1390 DatabaseTypeDescription
1392
1395 const Reference< XResultSet > &rs,
1396 const Reference< XStatement > &stmt )
1397{
1398 Reference< XRow > row( rs, UNO_QUERY_THROW );
1399 int domains = 0;
1400 OUStringBuffer queryBuf(128);
1401 queryBuf.append( "SELECT oid,typtype,typname FROM pg_TYPE WHERE " );
1402 while( rs->next() )
1403 {
1404 if( row->getString( 9 ) == "d" && oidMap.find( row->getInt( 12 ) ) == oidMap.end() )
1405 {
1406 oidMap[row->getInt(12)] = DatabaseTypeDescription();
1407 if( domains )
1408 queryBuf.append( " OR " );
1409 queryBuf.append( "oid = " + OUString::number( row->getInt(12 ) ) );
1410 domains ++;
1411 }
1412 }
1413 rs->beforeFirst();
1414
1415 if( domains )
1416 {
1417 Reference< XResultSet > rsDomain = stmt->executeQuery( queryBuf.makeStringAndClear() );
1418 row.set( rsDomain, UNO_QUERY_THROW );
1419 while( rsDomain->next() )
1420 {
1421 oidMap[row->getInt(1)] = DatabaseTypeDescription(row->getString(3), row->getString(2) );
1422 }
1423 disposeNoThrow( stmt );
1424 }
1425
1426}
1427
1428
1429css::uno::Reference< XResultSet > DatabaseMetaData::getColumns(
1430 const css::uno::Any&,
1431 const OUString& schemaPattern,
1432 const OUString& tableNamePattern,
1433 const OUString& columnNamePattern )
1434{
1435 // LEM TODO: review in comparison with JDBC driver
1436 Statics &statics = getStatics();
1437
1438 // continue !
1439 MutexGuard guard( m_xMutex->GetMutex() );
1440
1441 SAL_INFO("connectivity.postgresql", "DatabaseMetaData::getColumns() got called with "
1442 << schemaPattern << "." << tableNamePattern << "." << columnNamePattern);
1443
1444 // ignore catalog, as a single pq connection
1445 // does not support multiple catalogs anyway
1446 // We don't use information_schema.columns because it contains
1447 // only the columns the current user has any privilege over.
1448
1449 // 1. TABLE_CAT string => table catalog (may be NULL)
1450 // => not supported
1451 // 2. TABLE_SCHEM string => table schema (may be NULL)
1452 // => pg_namespace.nspname
1453 // 3. TABLE_NAME string => table name
1454 // => pg_class.relname
1455 // 4. COLUMN_NAME string => column name
1456 // => pg_attribute.attname
1457 // 5. DATA_TYPE short => SQL type from java.sql.Types
1458 // => pg_type.typname => sdbc.DataType
1459 // 6. TYPE_NAME string => Data source dependent type name, for a UDT the
1460 // type name is fully qualified
1461 // => pg_type.typname
1462 // 7. COLUMN_SIZE long => column size. For char or date types this is
1463 // the maximum number of characters, for numeric
1464 // or decimal types this is precision.
1465 // => pg_attribute.atttypmod
1466 // 8. BUFFER_LENGTH is not used.
1467 // => not used
1468 // 9. DECIMAL_DIGITS long => the number of fractional digits
1469 // => don't know ! TODO !
1470 // 10. NUM_PREC_RADIX long => Radix (typically either 10 or 2)
1471 // => TODO ??
1472 // 11. NULLABLE long => is NULL allowed?
1473 // NO_NULLS - might not allow NULL values
1474 // NULABLE - definitely allows NULL values
1475 // NULLABLE_UNKNOWN - nullability unknown
1476 // => pg_attribute.attnotnull
1477 // 12. REMARKS string => comment describing column (may be NULL )
1478 // => pg_description.description
1479 // 13. COLUMN_DEF string => default value (may be NULL)
1480 // => pg_type.typdefault
1481 // 14. SQL_DATA_TYPE long => unused
1482 // => empty
1483 // 15. SQL_DATETIME_SUB long => unused
1484 // => empty
1485 // 16. CHAR_OCTET_LENGTH long => for char types the maximum number of
1486 // bytes in the column
1487 // => pg_type.typlen
1488 // 17. ORDINAL_POSITION int => index of column in table (starting at 1)
1489 // pg_attribute.attnum
1490 // 18. IS_NULLABLE string => "NO" means column definitely does not allow
1491 // NULL values; "YES" means the column might
1492 // allow NULL values. An empty string means
1493 // nobody knows.
1494 // => pg_attribute.attnotnull
1495 OUString strDefaultValue = getColExprForDefaultSettingVal(m_pSettings);
1496 Reference< XPreparedStatement > statement = m_origin->prepareStatement(
1497 "SELECT pg_namespace.nspname, " // 1
1498 "pg_class.relname, " // 2
1499 "pg_attribute.attname, " // 3
1500 "pg_type.typname, " // 4
1501 "pg_attribute.atttypmod, " // 5
1502 "pg_attribute.attnotnull, " // 6
1503 "pg_type.typdefault, " // 7
1504 "pg_type.typtype, " // 8
1505 + strDefaultValue + // 9
1506 ",pg_description.description, " // 10
1507 "pg_type.typbasetype, " // 11
1508 "pg_attribute.attnum " // 12
1509 "FROM pg_class, "
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"
1521 );
1522
1523 Reference< XParameters > parameters( statement, UNO_QUERY_THROW );
1524 parameters->setString( 1 , schemaPattern );
1525 parameters->setString( 2 , tableNamePattern );
1526 parameters->setString( 3 , columnNamePattern );
1527
1528 Reference< XResultSet > rs = statement->executeQuery();
1529 Reference< XRow > xRow( rs, UNO_QUERY_THROW );
1530 std::vector< std::vector<Any> > vec;
1531
1533 Reference< XStatement > domainTypeStmt = m_origin->createStatement();
1534 columnMetaData2DatabaseTypeDescription( domainMap, rs, domainTypeStmt );
1535
1536 sal_uInt32 colNum(0);
1537 OUString sSchema( "#invalid#" );
1538 OUString sTable( "#invalid#" );
1539
1540 while( rs->next() )
1541 {
1542 if( ! isSystemColumn( xRow->getShort( 12 ) ) )
1543 {
1544 OUString sNewSchema( xRow->getString(1) );
1545 OUString sNewTable( xRow->getString(2) );
1546 if ( sNewSchema != sSchema || sNewTable != sTable )
1547 {
1548 colNum = 1;
1549 sSchema = sNewSchema;
1550 sTable = sNewTable;
1551 }
1552 else
1553 ++colNum;
1554 sal_Int32 precision, scale, type;
1555 std::vector< Any > row( 18 );
1556 row[0] <<= m_pSettings->catalog;
1557 row[1] <<= sNewSchema;
1558 row[2] <<= sNewTable;
1559 row[3] <<= xRow->getString(3);
1560 if( xRow->getString(8) == "d" )
1561 {
1562 DatabaseTypeDescription desc( domainMap[xRow->getInt(11)] );
1563 type = typeNameToDataType( desc.typeName, desc.typeType );
1564 }
1565 else
1566 {
1567 type = typeNameToDataType( xRow->getString(4), xRow->getString(8) );
1568 }
1569 extractPrecisionAndScale( type, xRow->getInt(5) , &precision, &scale );
1570 row[4] <<= type;
1571 row[5] <<= xRow->getString(4);
1572 row[6] <<= precision;
1573 // row[7] BUFFER_LENGTH not used
1574 row[8] <<= scale;
1575 // row[9] RADIX TODO
1576 if( xRow->getBoolean( 6 ) && ! isSystemColumn(xRow->getInt( 12 )) )
1577 {
1578 row[10] <<= OUString::number(css::sdbc::ColumnValue::NO_NULLS);
1579 row[17] <<= statics.NO;
1580 }
1581 else
1582 {
1583 row[10] <<= OUString::number(css::sdbc::ColumnValue::NULLABLE);
1584 row[17] <<= statics.YES;
1585 }
1586
1587 row[11] <<= xRow->getString( 10 ); // comment
1588 row[12] <<= xRow->getString( 9 ); // COLUMN_DEF = pg_type.typdefault
1589 // row[13] SQL_DATA_TYPE not used
1590 // row[14] SQL_DATETIME_SUB not used
1591 row[15] <<= precision;
1592 row[16] <<= colNum ;
1593
1594 vec.push_back( row );
1595 }
1596 }
1597 Reference< XCloseable > closeable( statement, UNO_QUERY );
1598 if( closeable.is() )
1599 closeable->close();
1600
1601 return new SequenceResultSet(
1602 m_xMutex, *this, std::vector(statics.columnRowNames), std::move(vec), m_pSettings->tc );
1603}
1604
1605css::uno::Reference< XResultSet > DatabaseMetaData::getColumnPrivileges(
1606 const css::uno::Any&,
1607 const OUString& schema,
1608 const OUString& table,
1609 const OUString& columnNamePattern )
1610{
1611 MutexGuard guard( m_xMutex->GetMutex() );
1612
1613 SAL_INFO("connectivity.postgresql", "DatabaseMetaData::getColumnPrivileges() got called with "
1614 << schema << "." << table << "." << columnNamePattern);
1615
1616 Reference< XParameters > parameters( m_getColumnPrivs_stmt, UNO_QUERY_THROW );
1617 parameters->setString( 1 , schema );
1618 parameters->setString( 2 , table );
1619 parameters->setString( 3 , columnNamePattern );
1620
1622
1623 return rs;
1624}
1625
1626css::uno::Reference< XResultSet > DatabaseMetaData::getTablePrivileges(
1627 const css::uno::Any&,
1628 const OUString& schemaPattern,
1629 const OUString& tableNamePattern )
1630{
1631 MutexGuard guard( m_xMutex->GetMutex() );
1632
1633 SAL_INFO("connectivity.postgresql", "DatabaseMetaData::getTablePrivileges() got called with "
1634 << schemaPattern << "." << tableNamePattern);
1635
1636 Reference< XParameters > parameters( m_getTablePrivs_stmt, UNO_QUERY_THROW );
1637 parameters->setString( 1 , schemaPattern );
1638 parameters->setString( 2 , tableNamePattern );
1639
1640 Reference< XResultSet > rs = m_getTablePrivs_stmt->executeQuery();
1641
1642 return rs;
1643}
1644
1645css::uno::Reference< XResultSet > DatabaseMetaData::getBestRowIdentifier(
1646 const css::uno::Any&,
1647 const OUString&,
1648 const OUString&,
1649 sal_Int32,
1650 sal_Bool )
1651{
1652 //LEM TODO: implement! See JDBC driver
1653 MutexGuard guard( m_xMutex->GetMutex() );
1654 return new SequenceResultSet(
1655 m_xMutex, *this, std::vector< OUString >(), std::vector< std::vector< Any > >(), m_pSettings->tc );
1656}
1657
1658css::uno::Reference< XResultSet > DatabaseMetaData::getVersionColumns(
1659 const css::uno::Any&,
1660 const OUString&,
1661 const OUString& )
1662{
1663 //LEM TODO: implement! See JDBC driver
1664 MutexGuard guard( m_xMutex->GetMutex() );
1665 return new SequenceResultSet(
1666 m_xMutex, *this, std::vector< OUString >(), std::vector< std::vector< Any > >(), m_pSettings->tc );
1667}
1668
1669css::uno::Reference< XResultSet > DatabaseMetaData::getPrimaryKeys(
1670 const css::uno::Any&,
1671 const OUString& schema,
1672 const OUString& table )
1673{
1674 //LEM TODO: review
1675 MutexGuard guard( m_xMutex->GetMutex() );
1676
1677// 1. TABLE_CAT string =&gt; table catalog (may be NULL )
1678// 2. TABLE_SCHEM string =&gt; table schema (may be NULL )
1679// 3. TABLE_NAME string =&gt; table name
1680// 4. COLUMN_NAME string =&gt; column name
1681// 5. KEY_SEQ short =&gt; sequence number within primary key
1682// 6. PK_NAME string =&gt; primary key name (may be NULL )
1683
1684 SAL_INFO("connectivity.postgresql", "DatabaseMetaData::getPrimaryKeys() got called with "
1685 << schema << "." << table);
1686
1687 Reference< XPreparedStatement > statement = m_origin->prepareStatement(
1688 "SELECT nmsp.nspname, "
1689 "cl.relname, "
1690 "con.conkey, "
1691 "con.conname, "
1692 "con.conrelid "
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 ?" );
1696
1697 Reference< XParameters > parameters( statement, UNO_QUERY_THROW );
1698 parameters->setString( 1 , schema );
1699 parameters->setString( 2 , table );
1700
1701 Reference< XResultSet > rs = statement->executeQuery();
1702 Reference< XRow > xRow( rs, UNO_QUERY_THROW );
1703 std::vector< std::vector<Any> > vec;
1704
1705 while( rs->next() )
1706 {
1707 std::vector< Any > row( 6 );
1708 row[0] <<= m_pSettings->catalog;
1709 row[1] <<= xRow->getString(1);
1710 row[2] <<= xRow->getString(2);
1711 OUString array = xRow->getString(3);
1712 row[4] <<= xRow->getString(5); // the relid
1713 row[5] <<= xRow->getString(4);
1714
1715 int i = 0;
1716 // now retrieve the columns information
1717 // unfortunately, postgresql does not allow array of variable size in
1718 // WHERE clauses (in the default installation), so we have to choose
1719 // this expensive and somewhat ugly way
1720 // annotation: postgresql shouldn't have chosen an array here, instead they
1721 // should have multiple rows per table
1722 // LEM: to transform an array into several rows, see unnest;
1723 // it is as simple as "SELECT foo, bar, unnest(qux) FROM ..."
1724 // where qux is the column that contains an array.
1725 while( array[i] && '}' != array[i] )
1726 {
1727 i++;
1728 int start = i;
1729 while( array[i] && array[i] != '}' && array[i] != ',' ) i++;
1730 row[3] <<= array.copy(start, i - start );
1731 vec.push_back( row );
1732 }
1733 }
1734
1735 {
1736 Reference< XCloseable > closeable( statement, UNO_QUERY );
1737 if( closeable.is() )
1738 closeable->close();
1739 }
1740
1741
1742 OUString lastTableOid;
1743 sal_Int32 index = 0;
1744 std::vector< std::vector< Any > > ret( vec.size() );
1745 int elements = 0;
1746 for (auto const& elem : vec)
1747 {
1748
1749 std::vector< Any > row = elem;
1750 OUString tableOid;
1751 OUString attnum;
1752
1753 row[4] >>= tableOid;
1754 row[3] >>= attnum;
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 = ?" );
1759
1760 parameters.set( statement, UNO_QUERY_THROW );
1761 parameters->setString( 1 , tableOid );
1762 parameters->setString( 2 , attnum );
1763
1764 rs = statement->executeQuery();
1765 xRow.set( rs, UNO_QUERY_THROW );
1766 if( rs->next() )
1767 {
1768 // column name
1769 row[3] <<= xRow->getString( 1 );
1770 if( tableOid != lastTableOid )
1771 index = 1;
1772 lastTableOid = tableOid;
1773 row[4] <<= OUString::number( index );
1774 index ++;
1775 }
1776 {
1777 Reference< XCloseable > closeable( statement, UNO_QUERY );
1778 if( closeable.is() )
1779 closeable->close();
1780 }
1781 ret[elements] = row;
1782 elements ++;
1783 }
1784 return new SequenceResultSet(
1785 m_xMutex, *this, std::vector(getStatics().primaryKeyNames), std::move(ret), m_pSettings->tc );
1786}
1787
1788// Copied / adapted / simplified from JDBC driver
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) \
1794 " ELSE NULL "
1795
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 " \
1802 SQL_CASE_KEYRULE \
1803 " END AS UPDATE_RULE, " \
1804 " CASE con.confdeltype " \
1805 SQL_CASE_KEYRULE \
1806 " END AS DELETE_RULE, " \
1807 " con.conname AS FK_NAME, pkic.relname AS PK_NAME, " \
1808 " CASE " \
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 " \
1813 "FROM " \
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 "
1820
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"
1827
1828#define SQL_GET_REFERENCES_NONE_NONE_NONE_NONE \
1829 SQL_GET_REFERENCES \
1830 SQL_GET_REFERENCES_ORDER_NO_PTABLE
1831
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
1836
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
1841
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
1847
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
1852
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
1857
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
1863
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
1869
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
1875
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
1882
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
1888
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
1894
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
1901
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
1908
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
1915
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
1923
1925{
1942}
1943
1945{
1946 OUStringBuffer sSQL(300);
1947 sSQL.append(
1948 " SELECT dp.TABLE_CAT, dp.TABLE_SCHEM, dp.TABLE_NAME, dp.GRANTOR, pr.rolname AS GRANTEE, dp.privilege, dp.is_grantable "
1949 " FROM ("
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");
1953 if ( PQserverVersion( m_pSettings->pConnection ) < 90200 )
1954 // information_schema.table_privileges does not fill in default ACLs when no ACL
1955 // assume default ACL is "owner has all privileges" and add it
1956 sSQL.append(
1957 " UNION "
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"
1964 " UNION ALL"
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");
1970 sSQL.append(
1971 " ) dp,"
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" );
1975
1976 m_getTablePrivs_stmt = m_origin->prepareStatement( sSQL.makeStringAndClear() );
1977
1978 sSQL.append(
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");
1983 if ( PQserverVersion( m_pSettings->pConnection ) < 90200 )
1984 // information_schema.table_privileges does not fill in default ACLs when no ACL
1985 // assume default ACL is "owner has all privileges" and add it
1986 sSQL.append(
1987 " UNION "
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"
1994 " UNION ALL"
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");
2000 sSQL.append(
2001 " ) dp,"
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" );
2005
2006 m_getColumnPrivs_stmt = m_origin->prepareStatement( sSQL.makeStringAndClear() );
2007}
2008
2009css::uno::Reference< XResultSet > DatabaseMetaData::getImportedExportedKeys(
2010 const Any& /* primaryCatalog */,
2011 const OUString& primarySchema,
2012 const OUString& primaryTable,
2013 const Any& /* foreignCatalog */,
2014 const OUString& foreignSchema,
2015 const OUString& foreignTable )
2016{
2017 unsigned int i = 0;
2018 if ( ! primarySchema.isEmpty() )
2019 i |= 0x01;
2020 if ( ! primaryTable.isEmpty() )
2021 i |= 0x02;
2022 if ( ! foreignSchema.isEmpty() )
2023 i |= 0x04;
2024 if ( ! foreignTable.isEmpty() )
2025 i |= 0x08;
2026
2028 Reference< XParameters > param ( stmt, UNO_QUERY_THROW );
2029
2030 unsigned int j = 1;
2031 if ( i & 0x01 )
2032 param->setString( j++, primarySchema );
2033 if ( i & 0x02 )
2034 param->setString( j++, primaryTable );
2035 if ( i & 0x04 )
2036 param->setString( j++, foreignSchema );
2037 if ( i & 0x08 )
2038 param->setString( j++, foreignTable );
2039
2040 Reference< XResultSet > rs = stmt->executeQuery();
2041
2042 return rs;
2043}
2044
2045
2046css::uno::Reference< XResultSet > DatabaseMetaData::getImportedKeys(
2047 const css::uno::Any& catalog,
2048 const OUString& schema,
2049 const OUString& table )
2050{
2051 return getImportedExportedKeys(Any(), OUString(), OUString(), catalog, schema, table);
2052}
2053
2054css::uno::Reference< XResultSet > DatabaseMetaData::getExportedKeys(
2055 const css::uno::Any& catalog,
2056 const OUString& schema,
2057 const OUString& table )
2058{
2059 return getImportedExportedKeys(catalog, schema, table, Any(), OUString(), OUString());
2060}
2061
2062css::uno::Reference< XResultSet > DatabaseMetaData::getCrossReference(
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 )
2069{
2070 return getImportedExportedKeys( primaryCatalog, primarySchema, primaryTable, foreignCatalog, foreignSchema, foreignTable );
2071}
2072
2073namespace
2074{
2075 struct TypeInfoByDataTypeSorter
2076 {
2077 bool operator () ( const std::vector< Any > & a, const std::vector< Any > & b )
2078 {
2079 OUString valueA;
2080 OUString valueB;
2081 a[1 /*DATA_TYPE*/] >>= valueA;
2082 b[1 /*DATA_TYPE*/] >>= valueB;
2083 if( valueB.toInt32() == valueA.toInt32() )
2084 {
2085 OUString nameA;
2086 OUString nameB;
2087 a[0 /*TYPE_NAME*/] >>= nameA;
2088 b[0 /*TYPE_NAME*/] >>= nameB;
2089 std::u16string_view nsA, tnA, nsB, tnB;
2090
2091 // parse typename into schema and typename
2092 sal_Int32 nIndex=0;
2093 nsA = o3tl::getToken(nameA, 0, '.', nIndex);
2094 if (nIndex<0)
2095 {
2096 tnA = nsA;
2097 nsA = std::u16string_view();
2098 }
2099 else
2100 {
2101 tnA = o3tl::getToken(nameA, 0, '.', nIndex);
2102 assert(nIndex < 0);
2103 }
2104
2105 nIndex=0;
2106 nsB = o3tl::getToken(nameB, 0, '.', nIndex);
2107 if (nIndex<0)
2108 {
2109 tnB = nsB;
2110 nsB = std::u16string_view();
2111 }
2112 else
2113 {
2114 tnB = o3tl::getToken(nameB, 0, '.', nIndex);
2115 assert(nIndex < 0);
2116 }
2117
2118 const int ns_comp = compare_schema(nsA, nsB);
2119 if(ns_comp == 0)
2120 {
2121 if(nsA.empty())
2122 {
2123 assert(nsB.empty());
2124 // within each type category, sort privileged choice first
2125 if( tnA == u"int4" || tnA == u"varchar" || tnA == u"char" || tnA == u"text")
2126 return true;
2127 if( tnB == u"int4" || tnB == u"varchar" || tnB == u"char" || tnB == u"text")
2128 return false;
2129 }
2130 return nameA.compareTo( nameB ) < 0;
2131 }
2132 else
2133 {
2134 return ns_comp < 0;
2135 }
2136 }
2137
2138 return valueA.toInt32() < valueB.toInt32();
2139 }
2140 };
2141
2142 sal_Int32 calcSearchable( sal_Int32 dataType )
2143 {
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;
2149
2150 return ret;
2151 }
2152
2153 sal_Int32 getMaxScale( sal_Int32 dataType )
2154 {
2155 // LEM TODO: review, see where used, see JDBC, ...
2156 sal_Int32 ret = 0;
2157 if( dataType == css::sdbc::DataType::NUMERIC )
2158 ret = 1000; // see pg-docs DataType/numeric
2159// else if( dataType == DataType::DOUBLE )
2160// ret = 308;
2161// else if( dataType == DataType::FLOAT )
2162// ret =
2163 return ret;
2164 }
2165
2166 OUString construct_full_typename(std::u16string_view ns, const OUString &tn)
2167 {
2168 if(ns.empty() || ns == u"pg_catalog")
2169 return tn;
2170 else
2171 return OUString::Concat(ns) + "." + tn;
2172 }
2173
2174 void pgTypeInfo2ResultSet(
2175 std::vector< std::vector<Any> > &vec,
2176 const Reference< XResultSet > &rs )
2177 {
2178 static const sal_Int32 TYPE_NAME = 0; // string Type name
2179 static const sal_Int32 DATA_TYPE = 1; // short SQL data type from java.sql.Types
2180 static const sal_Int32 PRECISION = 2; // long maximum precision
2181 static const sal_Int32 CREATE_PARAMS = 5; // string => parameters used in creating the type (may be NULL )
2182 static const sal_Int32 NULLABLE = 6; // short ==> can you use NULL for this type?
2183 // - NO_NULLS - does not allow NULL values
2184 // - NULLABLE - allows NULL values
2185 // - NULLABLE_UNKNOWN - nullability unknown
2186
2187 static const sal_Int32 CASE_SENSITIVE = 7; // boolean==> is it case sensitive
2188 static const sal_Int32 SEARCHABLE = 8; // short ==>; can you use
2189 // "WHERE" based on this type:
2190 // - NONE - No support
2191 // - CHAR - Only supported with WHERE .. LIKE
2192 // - BASIC - Supported except for WHERE .. LIKE
2193 // - FULL - Supported for all WHERE ..
2194 static const sal_Int32 UNSIGNED_ATTRIBUTE = 9; // boolean ==> is it unsigned?
2195 // FIXED_PREC_SCALE = 10; boolean ==> can it be a money value?
2196 static const sal_Int32 AUTO_INCREMENT = 11; // boolean ==> can it be used for
2197 // an auto-increment value?
2198 static const sal_Int32 MINIMUM_SCALE = 13; // short ==> minimum scale supported
2199 static const sal_Int32 MAXIMUM_SCALE = 14; // short ==> maximum scale supported
2200 static const sal_Int32 NUM_PREC_RADIX = 17; // long ==> usually 2 or 10
2201
2202 /* not filled so far
2203 3. LITERAL_PREFIX string ==> prefix used to quote a literal
2204 (may be <NULL/>)
2205 4. LITERAL_SUFFIX string ==> suffix used to quote a literal
2206 (may be <NULL/>)
2207 5. CREATE_PARAMS string ==> parameters used in creating the type (may be <NULL/>)
2208 12. LOCAL_TYPE_NAME string ==> localized version of type name (may be <NULL/>)
2209 15, SQL_DATA_TYPE long ==> unused
2210 16. SQL_DATETIME_SUB long ==> unused
2211 */
2212 Reference< XRow > xRow( rs, UNO_QUERY_THROW );
2213 while( rs->next() )
2214 {
2215 std::vector< Any > row(18);
2216
2217 sal_Int32 dataType =typeNameToDataType(xRow->getString(5),xRow->getString(2));
2218 sal_Int32 precision = xRow->getString(3).toInt32();
2219
2220 if( dataType == css::sdbc::DataType::CHAR ||
2221 ( dataType == css::sdbc::DataType::VARCHAR &&
2222 xRow->getString(TYPE_NAME+1).equalsIgnoreAsciiCase("varchar") ) )
2223 {
2224 // reflect varchar as varchar with upper limit !
2225 //NOTE: the sql spec requires varchar to have an upper limit, however
2226 // in postgresql the upper limit is optional, no limit means unlimited
2227 // length (=1GB).
2228 precision = 0x40000000; // about 1 GB, see character type docs in postgresql
2229 row[CREATE_PARAMS] <<= OUString("length");
2230 }
2231 else if( dataType == css::sdbc::DataType::NUMERIC )
2232 {
2233 precision = 1000;
2234 row[CREATE_PARAMS] <<= OUString("length, scale");
2235 }
2236
2237 row[TYPE_NAME] <<= construct_full_typename(xRow->getString(6), xRow->getString(1));
2238 row[DATA_TYPE] <<= OUString::number(dataType);
2239 row[PRECISION] <<= OUString::number( precision );
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"); // TODO
2250 else
2251 row[AUTO_INCREMENT] <<= OUString("0"); // TODO
2252 row[MINIMUM_SCALE] <<= OUString("0"); // TODO: what is this ?
2253 row[MAXIMUM_SCALE] <<= OUString::number( getMaxScale( dataType ) );
2254 row[NUM_PREC_RADIX] <<= OUString("10"); // TODO: what is this ?
2255 vec.push_back( row );
2256 }
2257 }
2258}
2259
2260
2261css::uno::Reference< XResultSet > DatabaseMetaData::getTypeInfo( )
2262{
2263 // Note: Indexes start at 0 (in the API doc, they start at 1)
2264 MutexGuard guard( m_xMutex->GetMutex() );
2265
2266 SAL_INFO("connectivity.postgresql", "DatabaseMetaData::getTypeInfo() got called");
2267
2268 Reference< XStatement > statement = m_origin->createStatement();
2269 Reference< XResultSet > rs = statement->executeQuery(
2270 "SELECT pg_type.typname AS typname," //1
2271 "pg_type.typtype AS typtype," //2
2272 "pg_type.typlen AS typlen," //3
2273 "pg_type.typnotnull AS typnotnull," //4
2274 "pg_type.typname AS typname, " //5
2275 "pg_namespace.nspname as typns " //6
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'"
2279 );
2280
2281 std::vector< std::vector<Any> > vec;
2282 pgTypeInfo2ResultSet( vec, rs );
2283
2284 // check for domain types
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 );
2295
2296 std::sort( vec.begin(), vec.end(), TypeInfoByDataTypeSorter() );
2297
2298 return new SequenceResultSet(
2299 m_xMutex,
2300 *this,
2301 std::vector(getStatics().typeinfoColumnNames),
2302 std::move(vec),
2303 m_pSettings->tc,
2304 &( getStatics().typeInfoMetaData ));
2305}
2306
2307
2308css::uno::Reference< XResultSet > DatabaseMetaData::getIndexInfo(
2309 const css::uno::Any& ,
2310 const OUString& schema,
2311 const OUString& table,
2312 sal_Bool unique,
2313 sal_Bool )
2314{
2315 //LEM TODO: review
2316 MutexGuard guard( m_xMutex->GetMutex() );
2317
2318 /*
2319 1. TABLE_CAT string -> table catalog (may be NULL )
2320 2. TABLE_SCHEM string -> table schema (may be NULL )
2321 3. TABLE_NAME string -> table name
2322 4. NON_UNIQUE boolean -> Can index values be non-unique?
2323 false when TYPE is tableIndexStatistic
2324 5. INDEX_QUALIFIER string -> index catalog (may be NULL );
2325 NULL when TYPE is tableIndexStatistic
2326 6. INDEX_NAME string -> index name; NULL when TYPE is tableIndexStatistic
2327 7. TYPE short -> index type:
2328 * 0 - this identifies table statistics that are returned
2329 in conjunction with a table's index descriptions
2330 * CLUSTERED - this is a clustered index
2331 * HASHED - this is a hashed index
2332 * OTHER - this is some other style of index
2333 8. ORDINAL_POSITION short -> column sequence number within index;
2334 zero when TYPE is tableIndexStatistic
2335 9. COLUMN_NAME string -> column name; NULL when TYPE is tableIndexStatistic
2336 10. ASC_OR_DESC string -> column sort sequence, "A"= ascending,
2337 "D" = descending, may be NULL if sort sequence
2338 is not supported; NULL when TYPE is tableIndexStatistic
2339 11. CARDINALITY long -> When TYPE is tableIndexStatistic, then this is
2340 the number of rows in the table; otherwise, it
2341 is the number of unique values in the index.
2342 12. PAGES long -> When TYPE is tableIndexStatistic then this is
2343 the number of pages used for the table, otherwise
2344 it is the number of pages used for the current index.
2345 13. FILTER_CONDITION string -> Filter condition, if any. (may be NULL )
2346
2347 */
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;
2353 // C_IS_PRIMARY = 6
2354 static const sal_Int32 C_COLUMNS = 7;
2355
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;
2363
2364 Reference< XPreparedStatement > stmt = m_origin->prepareStatement(
2365 "SELECT nspname, " // 1
2366 "pg_class.relname, " // 2
2367 "class2.relname, " // 3
2368 "indisclustered, " // 4
2369 "indisunique, " // 5
2370 "indisprimary, " // 6
2371 "indkey " // 7
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 = ?" );
2376
2377 Reference< XParameters > param ( stmt, UNO_QUERY_THROW );
2378 param->setString( 1, schema );
2379 param->setString( 2, table );
2380 Reference< XResultSet > rs = stmt->executeQuery();
2381 Reference< XRow > xRow ( rs, UNO_QUERY_THROW );
2382
2383 std::vector< std::vector<Any> > vec;
2384 while( rs->next() )
2385 {
2386 std::vector< sal_Int32 > columns = parseIntArray( xRow->getString(C_COLUMNS) );
2387 Reference< XPreparedStatement > columnsStmt = m_origin->prepareStatement(
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=?" );
2393 Reference< XParameters > paramColumn ( columnsStmt, UNO_QUERY_THROW );
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;
2401
2402 paramColumn->setString( C_SCHEMA, currentSchema );
2403 paramColumn->setString( C_TABLENAME, currentTable );
2404
2405 Reference< XResultSet > rsColumn = columnsStmt->executeQuery();
2406 Reference< XRow > rowColumn( rsColumn, UNO_QUERY_THROW );
2407 while( rsColumn->next() )
2408 {
2409 auto findIt = std::find( columns.begin(), columns.end(), rowColumn->getInt( 1 ) );
2410 if( findIt != columns.end() && ( ! isNonUnique || ! unique ) )
2411 {
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); // MSVC++ nonsense
2420 result[R_ORDINAL_POSITION] <<= nPos;
2421 vec.push_back( result );
2422 }
2423 }
2424 }
2425 return new SequenceResultSet(
2426 m_xMutex, *this, std::vector(getStatics().indexinfoColumnNames),
2427 std::move(vec),
2428 m_pSettings->tc );
2429}
2430
2432{
2433 if ( setType == css::sdbc::ResultSetType::SCROLL_SENSITIVE )
2434 return false;
2435 else
2436 return true;
2437}
2438
2440 sal_Int32 setType, sal_Int32 )
2441{
2442 if ( ! supportsResultSetType( setType ) )
2443 return false;
2444 else
2445 return true;
2446}
2447
2449{
2450 return true;
2451}
2452
2454{
2455 return true;
2456}
2457
2459{
2460 return true;
2461}
2462
2464{
2465 return false;
2466}
2467
2469{
2470 return false;
2471}
2472
2474{
2475 return false;
2476}
2477
2479{
2480 return false;
2481}
2482
2484{
2485 return false;
2486}
2488{
2489 return false;
2490}
2491
2493{
2494 return true;
2495}
2496
2497css::uno::Reference< XResultSet > DatabaseMetaData::getUDTs( const css::uno::Any&, const OUString&, const OUString&, const css::uno::Sequence< sal_Int32 >& )
2498{
2499 //LEM TODO: implement! See JDBC driver
2500 MutexGuard guard( m_xMutex->GetMutex() );
2501 return new SequenceResultSet(
2502 m_xMutex, *this, std::vector< OUString >(), std::vector< std::vector< Any > >(), m_pSettings->tc );
2503}
2504
2505css::uno::Reference< css::sdbc::XConnection > DatabaseMetaData::getConnection()
2506{
2507 return m_origin;
2508}
2509}
2510
2511/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
OptionalString sSchema
virtual sal_Bool SAL_CALL doesMaxRowSizeIncludeBlobs() override
virtual OUString SAL_CALL getSystemFunctions() override
virtual sal_Int32 SAL_CALL getMaxRowSize() override
virtual sal_Int32 SAL_CALL getDefaultTransactionIsolation() override
virtual sal_Bool SAL_CALL supportsOpenCursorsAcrossCommit() override
virtual OUString SAL_CALL getDatabaseProductVersion() override
virtual sal_Bool SAL_CALL supportsExtendedSQLGrammar() override
virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getProcedureColumns(const css::uno::Any &catalog, const OUString &schemaPattern, const OUString &procedureNamePattern, const OUString &columnNamePattern) override
virtual sal_Bool SAL_CALL supportsGroupBy() override
virtual sal_Bool SAL_CALL supportsIntegrityEnhancementFacility() override
virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getUDTs(const css::uno::Any &catalog, const OUString &schemaPattern, const OUString &typeNamePattern, const css::uno::Sequence< sal_Int32 > &types) override
virtual OUString SAL_CALL getIdentifierQuoteString() override
virtual sal_Bool SAL_CALL supportsANSI92EntryLevelSQL() override
virtual sal_Bool SAL_CALL supportsSchemasInIndexDefinitions() override
virtual sal_Bool SAL_CALL supportsMixedCaseIdentifiers() override
virtual sal_Bool SAL_CALL othersInsertsAreVisible(sal_Int32 setType) override
virtual sal_Int32 SAL_CALL getMaxColumnsInOrderBy() override
virtual sal_Bool SAL_CALL usesLocalFilePerTable() override
virtual sal_Bool SAL_CALL storesLowerCaseQuotedIdentifiers() override
virtual OUString SAL_CALL getURL() override
virtual sal_Int32 SAL_CALL getMaxTablesInSelect() override
css::uno::Reference< css::sdbc::XResultSet > getImportedExportedKeys(const css::uno::Any &primaryCatalog, const OUString &primarySchema, const OUString &primaryTable, const css::uno::Any &foreignCatalog, const OUString &foreignSchema, const OUString &foreignTable)
virtual sal_Bool SAL_CALL supportsOpenStatementsAcrossCommit() override
virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getCatalogs() override
virtual sal_Bool SAL_CALL supportsTransactionIsolationLevel(sal_Int32 level) override
virtual sal_Bool SAL_CALL deletesAreDetected(sal_Int32 setType) override
virtual sal_Bool SAL_CALL supportsCorrelatedSubqueries() override
virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getTables(const css::uno::Any &catalog, const OUString &schemaPattern, const OUString &tableNamePattern, const css::uno::Sequence< OUString > &types) override
virtual sal_Bool SAL_CALL supportsFullOuterJoins() override
virtual sal_Bool SAL_CALL nullsAreSortedAtStart() override
virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getColumnPrivileges(const css::uno::Any &catalog, const OUString &schema, const OUString &table, const OUString &columnNamePattern) override
::rtl::Reference< comphelper::RefCountedMutex > m_xMutex
virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getImportedKeys(const css::uno::Any &catalog, const OUString &schema, const OUString &table) override
virtual sal_Int32 SAL_CALL getMaxUserNameLength() override
virtual sal_Bool SAL_CALL ownUpdatesAreVisible(sal_Int32 setType) override
virtual sal_Int32 SAL_CALL getMaxColumnNameLength() override
virtual sal_Bool SAL_CALL storesLowerCaseIdentifiers() override
virtual sal_Bool SAL_CALL allProceduresAreCallable() override
virtual sal_Bool SAL_CALL othersUpdatesAreVisible(sal_Int32 setType) override
virtual sal_Bool SAL_CALL supportsResultSetConcurrency(sal_Int32 setType, sal_Int32 concurrency) override
virtual sal_Bool SAL_CALL dataDefinitionCausesTransactionCommit() override
virtual sal_Bool SAL_CALL supportsNonNullableColumns() override
virtual sal_Bool SAL_CALL supportsMultipleResultSets() override
virtual OUString SAL_CALL getCatalogTerm() override
virtual sal_Bool SAL_CALL supportsResultSetType(sal_Int32 setType) override
virtual sal_Bool SAL_CALL supportsTransactions() override
virtual sal_Bool SAL_CALL supportsMultipleTransactions() override
virtual sal_Bool SAL_CALL updatesAreDetected(sal_Int32 setType) override
virtual OUString SAL_CALL getDriverName() override
virtual sal_Bool SAL_CALL dataDefinitionIgnoredInTransactions() override
virtual OUString SAL_CALL getCatalogSeparator() override
virtual sal_Bool SAL_CALL supportsANSI92IntermediateSQL() override
virtual sal_Bool SAL_CALL supportsPositionedDelete() override
virtual sal_Bool SAL_CALL supportsConvert(sal_Int32 fromType, sal_Int32 toType) override
virtual sal_Int32 SAL_CALL getMaxCharLiteralLength() override
virtual OUString SAL_CALL getDatabaseProductName() override
virtual sal_Bool SAL_CALL supportsSchemasInProcedureCalls() override
virtual sal_Bool SAL_CALL usesLocalFiles() override
virtual sal_Bool SAL_CALL supportsTableCorrelationNames() override
virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getPrimaryKeys(const css::uno::Any &catalog, const OUString &schema, const OUString &table) override
virtual sal_Bool SAL_CALL supportsAlterTableWithDropColumn() override
virtual sal_Bool SAL_CALL supportsCoreSQLGrammar() override
virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getBestRowIdentifier(const css::uno::Any &catalog, const OUString &schema, const OUString &table, sal_Int32 scope, sal_Bool nullable) override
virtual sal_Bool SAL_CALL storesUpperCaseQuotedIdentifiers() override
virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getSchemas() override
css::uno::Reference< css::sdbc::XPreparedStatement > m_getReferences_stmt[16]
virtual sal_Bool SAL_CALL supportsDataManipulationTransactionsOnly() override
virtual sal_Bool SAL_CALL ownInsertsAreVisible(sal_Int32 setType) override
virtual sal_Bool SAL_CALL nullsAreSortedAtEnd() override
virtual sal_Int32 SAL_CALL getMaxCatalogNameLength() override
virtual sal_Bool SAL_CALL supportsANSI92FullSQL() override
virtual sal_Bool SAL_CALL nullsAreSortedHigh() override
virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getColumns(const css::uno::Any &catalog, const OUString &schemaPattern, const OUString &tableNamePattern, const OUString &columnNamePattern) override
virtual sal_Bool SAL_CALL supportsOuterJoins() override
virtual sal_Bool SAL_CALL supportsOrderByUnrelated() override
virtual OUString SAL_CALL getTimeDateFunctions() override
virtual sal_Int32 SAL_CALL getMaxIndexLength() override
virtual sal_Int32 SAL_CALL getMaxStatements() override
virtual OUString SAL_CALL getSearchStringEscape() override
virtual sal_Bool SAL_CALL othersDeletesAreVisible(sal_Int32 setType) override
virtual sal_Int32 SAL_CALL getDriverMinorVersion() override
virtual OUString SAL_CALL getNumericFunctions() override
virtual sal_Bool SAL_CALL supportsSchemasInTableDefinitions() override
virtual sal_Int32 SAL_CALL getMaxProcedureNameLength() override
virtual sal_Bool SAL_CALL supportsMinimumSQLGrammar() override
virtual sal_Bool SAL_CALL supportsPositionedUpdate() override
virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getTablePrivileges(const css::uno::Any &catalog, const OUString &schemaPattern, const OUString &tableNamePattern) override
virtual sal_Bool SAL_CALL supportsCatalogsInDataManipulation() override
virtual sal_Bool SAL_CALL supportsMixedCaseQuotedIdentifiers() override
virtual sal_Int32 SAL_CALL getMaxStatementLength() override
virtual sal_Bool SAL_CALL supportsLikeEscapeClause() override
virtual sal_Bool SAL_CALL supportsAlterTableWithAddColumn() override
sal_Int32 getIntSetting(const OUString &settingName)
virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getExportedKeys(const css::uno::Any &catalog, const OUString &schema, const OUString &table) override
virtual sal_Bool SAL_CALL nullPlusNonNullIsNull() override
virtual sal_Bool SAL_CALL supportsUnionAll() override
virtual sal_Bool SAL_CALL storesUpperCaseIdentifiers() override
virtual sal_Int32 SAL_CALL getMaxBinaryLiteralLength() override
virtual sal_Bool SAL_CALL supportsColumnAliasing() override
virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getTypeInfo() override
virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getCrossReference(const css::uno::Any &primaryCatalog, const OUString &primarySchema, const OUString &primaryTable, const css::uno::Any &foreignCatalog, const OUString &foreignSchema, const OUString &foreignTable) override
virtual sal_Bool SAL_CALL insertsAreDetected(sal_Int32 setType) override
css::uno::Reference< css::sdbc::XPreparedStatement > m_getIntSetting_stmt
virtual sal_Int32 SAL_CALL getMaxColumnsInTable() override
virtual sal_Bool SAL_CALL supportsCatalogsInTableDefinitions() override
virtual sal_Bool SAL_CALL ownDeletesAreVisible(sal_Int32 setType) override
virtual sal_Bool SAL_CALL supportsGroupByBeyondSelect() override
virtual sal_Bool SAL_CALL supportsBatchUpdates() override
virtual sal_Bool SAL_CALL supportsDataDefinitionAndDataManipulationTransactions() override
virtual sal_Bool SAL_CALL supportsCatalogsInProcedureCalls() override
virtual OUString SAL_CALL getUserName() override
virtual sal_Bool SAL_CALL supportsCatalogsInPrivilegeDefinitions() override
virtual sal_Bool SAL_CALL supportsSubqueriesInIns() override
virtual sal_Int32 SAL_CALL getMaxCursorNameLength() override
virtual sal_Bool SAL_CALL supportsSubqueriesInQuantifieds() override
virtual sal_Bool SAL_CALL allTablesAreSelectable() override
virtual sal_Bool SAL_CALL supportsOpenCursorsAcrossRollback() override
virtual sal_Int32 SAL_CALL getMaxConnections() override
virtual sal_Bool SAL_CALL isCatalogAtStart() override
virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getProcedures(const css::uno::Any &catalog, const OUString &schemaPattern, const OUString &procedureNamePattern) override
virtual sal_Int32 SAL_CALL getMaxSchemaNameLength() override
DatabaseMetaData(::rtl::Reference< comphelper::RefCountedMutex > reMutex, css::uno::Reference< css::sdbc::XConnection > origin, ConnectionSettings *pSettings)
virtual css::uno::Reference< css::sdbc::XConnection > SAL_CALL getConnection() override
virtual sal_Bool SAL_CALL storesMixedCaseIdentifiers() override
virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getIndexInfo(const css::uno::Any &catalog, const OUString &schema, const OUString &table, sal_Bool unique, sal_Bool approximate) override
virtual sal_Bool SAL_CALL supportsStoredProcedures() override
virtual sal_Bool SAL_CALL supportsSchemasInPrivilegeDefinitions() override
virtual OUString SAL_CALL getStringFunctions() override
virtual sal_Bool SAL_CALL supportsSubqueriesInComparisons() override
virtual sal_Int32 SAL_CALL getMaxTableNameLength() override
virtual sal_Bool SAL_CALL supportsLimitedOuterJoins() override
virtual sal_Bool SAL_CALL supportsTypeConversion() override
virtual sal_Bool SAL_CALL storesMixedCaseQuotedIdentifiers() override
css::uno::Reference< css::sdbc::XPreparedStatement > m_getColumnPrivs_stmt
virtual OUString SAL_CALL getProcedureTerm() override
virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getVersionColumns(const css::uno::Any &catalog, const OUString &schema, const OUString &table) override
virtual sal_Bool SAL_CALL nullsAreSortedLow() override
virtual sal_Bool SAL_CALL supportsSchemasInDataManipulation() override
virtual sal_Bool SAL_CALL supportsCatalogsInIndexDefinitions() override
virtual OUString SAL_CALL getSchemaTerm() override
virtual sal_Bool SAL_CALL supportsSubqueriesInExists() override
virtual sal_Bool SAL_CALL supportsGroupByUnrelated() override
virtual sal_Bool SAL_CALL supportsOpenStatementsAcrossRollback() override
virtual sal_Int32 SAL_CALL getMaxColumnsInGroupBy() override
virtual OUString SAL_CALL getDriverVersion() override
virtual sal_Int32 SAL_CALL getMaxColumnsInSelect() override
virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getTableTypes() override
virtual sal_Int32 SAL_CALL getMaxColumnsInIndex() override
css::uno::Reference< css::sdbc::XConnection > m_origin
virtual sal_Bool SAL_CALL supportsUnion() override
css::uno::Reference< css::sdbc::XPreparedStatement > m_getTablePrivs_stmt
virtual sal_Int32 SAL_CALL getDriverMajorVersion() override
virtual OUString SAL_CALL getSQLKeywords() override
virtual sal_Bool SAL_CALL supportsSelectForUpdate() override
virtual sal_Bool SAL_CALL supportsExpressionsInOrderBy() override
virtual sal_Bool SAL_CALL isReadOnly() override
virtual sal_Bool SAL_CALL supportsDifferentTableCorrelationNames() override
virtual OUString SAL_CALL getExtraNameCharacters() override
float u
sal_Int32 nIndex
uno_Any a
sal_uInt16 nPos
#define SAL_INFO(area, stream)
@ table
ns
int i
index
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)
Statics & getStatics()
Definition: pq_statics.cxx:112
std::vector< sal_Int32 > parseIntArray(const OUString &str)
Definition: pq_tools.cxx:691
void disposeNoThrow(const css::uno::Reference< css::uno::XInterface > &r)
Definition: pq_tools.cxx:235
OUString getColExprForDefaultSettingVal(ConnectionSettings const *settings)
Definition: pq_tools.cxx:836
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 SQL_GET_REFERENCES_SOME_SOME_NONE_NONE
#define SQL_GET_REFERENCES_SOME_SOME_NONE_SOME
OUString typeName
#define SQL_GET_REFERENCES_SOME_NONE_SOME_SOME
#define SQL_GET_REFERENCES_SOME_NONE_NONE_SOME
#define SQL_GET_REFERENCES_SOME_NONE_NONE_NONE
#define SQL_GET_REFERENCES_NONE_SOME_SOME_NONE
#define SQL_GET_REFERENCES_NONE_NONE_NONE_SOME
OUString typeType
#define SQL_GET_REFERENCES_SOME_NONE_SOME_NONE
#define SQL_GET_REFERENCES_SOME_SOME_SOME_NONE
#define SQL_GET_REFERENCES_NONE_NONE_SOME_NONE
#define SQL_GET_REFERENCES_NONE_SOME_NONE_SOME
#define SQL_GET_REFERENCES_SOME_SOME_SOME_SOME
#define SQL_GET_REFERENCES_NONE_NONE_NONE_NONE
#define SQL_GET_REFERENCES_NONE_NONE_SOME_SOME
#define SQL_GET_REFERENCES_NONE_SOME_NONE_NONE
#define SQL_GET_REFERENCES_NONE_SOME_SOME_SOME
#define PQ_SDBC_DRIVER_VERSION
Definition: pq_driver.hxx:53
sal_Int32 scale
Definition: pq_statics.cxx:62
sal_Int32 precision
Definition: pq_statics.cxx:61
OUString name
Definition: pq_statics.cxx:74
sal_Int32 type
Definition: pq_statics.cxx:60
css::uno::Reference< css::script::XTypeConverter > tc
std::vector< OUString > columnRowNames
Definition: pq_statics.hxx:219
std::vector< OUString > tablesRowNames
Definition: pq_statics.hxx:218
unsigned char sal_Bool
Any result