Line data Source code
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 : * Version: MPL 1.1 / GPLv3+ / LGPLv2.1+
32 : *
33 : * The contents of this file are subject to the Mozilla Public License Version
34 : * 1.1 (the "License"); you may not use this file except in compliance with
35 : * the License or as specified alternatively below. You may obtain a copy of
36 : * the License at http://www.mozilla.org/MPL/
37 : *
38 : * Software distributed under the License is distributed on an "AS IS" basis,
39 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
40 : * for the specific language governing rights and limitations under the
41 : * License.
42 : *
43 : * Major Contributor(s):
44 : * [ Copyright (C) 2011 Lionel Elie Mamane <lionel@mamane.lu> ]
45 : *
46 : * All Rights Reserved.
47 : *
48 : * For minor contributions see the git repository.
49 : *
50 : * Alternatively, the contents of this file may be used under the terms of
51 : * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
52 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPLv2.1+"),
53 : * in which case the provisions of the GPLv3+ or the LGPLv2.1+ are applicable
54 : * instead of those above.
55 : *
56 : * Some portions were adapted from JDBC PostgreSQL driver:
57 : *
58 : * Copyright (c) 2004-2008, PostgreSQL Global Development Group
59 : *
60 : * Licence of original JDBC driver code:
61 : *
62 : * Redistribution and use in source and binary forms, with or without
63 : * modification, are permitted provided that the following conditions are met:
64 : *
65 : * 1. Redistributions of source code must retain the above copyright notice,
66 : * this list of conditions and the following disclaimer.
67 : * 2. Redistributions in binary form must reproduce the above copyright notice,
68 : * this list of conditions and the following disclaimer in the documentation
69 : * and/or other materials provided with the distribution.
70 : * 3. Neither the name of the PostgreSQL Global Development Group nor the names
71 : * of its contributors may be used to endorse or promote products derived
72 : * from this software without specific prior written permission.
73 : *
74 : * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
75 : * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
76 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
77 : * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
78 : * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
79 : * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
80 : * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
81 : * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
82 : * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
83 : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
84 : * POSSIBILITY OF SUCH DAMAGE.
85 : *
86 : ************************************************************************/
87 :
88 : #include <algorithm>
89 : #include "pq_databasemetadata.hxx"
90 : #include "pq_driver.hxx"
91 : #include "pq_sequenceresultset.hxx"
92 : #include "pq_statics.hxx"
93 : #include "pq_tools.hxx"
94 :
95 : #include <rtl/ustrbuf.hxx>
96 :
97 : #include<com/sun/star/sdbc/TransactionIsolation.hpp>
98 : #include<com/sun/star/sdbc/ResultSetType.hpp>
99 : #include<com/sun/star/sdbc/XPreparedStatement.hpp>
100 : #include<com/sun/star/sdbc/XParameters.hpp>
101 : #include<com/sun/star/sdbc/DataType.hpp>
102 : #include<com/sun/star/sdbc/IndexType.hpp>
103 : #include<com/sun/star/sdbc/ColumnValue.hpp>
104 : #include<com/sun/star/sdbc/ColumnSearch.hpp>
105 : #include<com/sun/star/sdbc/KeyRule.hpp>
106 : #include<com/sun/star/sdbc/Deferrability.hpp>
107 :
108 : using ::osl::MutexGuard;
109 :
110 : using ::rtl::OUString;
111 :
112 : using namespace com::sun::star::sdbc;
113 :
114 : using com::sun::star::uno::RuntimeException;
115 : using com::sun::star::uno::Sequence;
116 :
117 : using com::sun::star::uno::Reference;
118 : using com::sun::star::uno::Sequence;
119 : using com::sun::star::uno::Any;
120 : using com::sun::star::uno::makeAny;
121 : using com::sun::star::uno::UNO_QUERY;
122 : using com::sun::star::uno::UNO_QUERY_THROW;
123 :
124 : namespace pq_sdbc_driver
125 : {
126 : typedef
127 : std::vector
128 : <
129 : com::sun::star::uno::Sequence< com::sun::star::uno::Any >,
130 : Allocator< com::sun::star::uno::Sequence< com::sun::star::uno::Any > >
131 : > SequenceAnyVector;
132 :
133 :
134 : #define ASCII_STR(x) OUString( RTL_CONSTASCII_USTRINGPARAM( x ) )
135 :
136 : #define QUOTEME(X) #X
137 : #define STRINGIFY(X) QUOTEME(X)
138 :
139 : // These are pre-processor versions of KeyRule.idl declarations
140 : // These are inherited from JDBC, and thus won't change anytime soon.
141 : // Having them as pre-processor definitions allows to include them
142 : // into compile-time strings (through STRINGIFY), which can be passed to ASCII_STR.
143 : // That is without resorting to horrendeous hacks in template meta-programming.
144 : #define KEYRULE_CASCADE 0
145 : #define KEYRULE_RESTRICT 1
146 : #define KEYRULE_SET_NULL 2
147 : #define KEYRULE_NO_ACTION 4
148 : #define KEYRULE_SET_DEFAULT 4
149 : // Ditto for Deferrability.idl
150 : #define DEFERRABILITY_INITIALLY_DEFERRED 5
151 : #define DEFERRABILITY_INITIALLY_IMMEDIATE 6
152 : #define DEFERRABILITY_NONE 7
153 :
154 : // alphabetically ordered !
155 : static const int PRIVILEGE_CREATE = 0x1;
156 : static const int PRIVILEGE_DELETE = 0x2;
157 : static const int PRIVILEGE_EXECUTE = 0x4;
158 : static const int PRIVILEGE_INSERT = 0x8;
159 : static const int PRIVILEGE_REFERENCES = 0x10;
160 : static const int PRIVILEGE_RULE = 0x20;
161 : static const int PRIVILEGE_SELECT = 0x40;
162 : static const int PRIVILEGE_TEMPORARY = 0x80;
163 : static const int PRIVILEGE_TRIGGER = 0x100;
164 : static const int PRIVILEGE_UPDATE = 0x200;
165 : static const int PRIVILEGE_USAGE = 0x400;
166 : static const int PRIVILEGE_MAX = PRIVILEGE_USAGE;
167 :
168 0 : void DatabaseMetaData::checkClosed()
169 : throw (SQLException, RuntimeException)
170 : {
171 0 : }
172 :
173 0 : DatabaseMetaData::DatabaseMetaData(
174 : const ::rtl::Reference< RefCountedMutex > & refMutex,
175 : const ::com::sun::star::uno::Reference< com::sun::star::sdbc::XConnection > & origin,
176 : ConnectionSettings *pSettings )
177 : : m_refMutex( refMutex ),
178 : m_pSettings( pSettings ),
179 : m_origin( origin ),
180 0 : m_getIntSetting_stmt ( m_origin->prepareStatement(ASCII_STR( "SELECT setting FROM pg_catalog.pg_settings WHERE name=?" )) )
181 : {
182 0 : init_getReferences_stmt();
183 0 : init_getPrivs_stmt();
184 0 : }
185 :
186 0 : sal_Bool DatabaseMetaData::allProceduresAreCallable( ) throw (SQLException, RuntimeException)
187 : {
188 : // TODO
189 0 : return sal_False;
190 : }
191 :
192 0 : sal_Bool DatabaseMetaData::allTablesAreSelectable( ) throw (SQLException, RuntimeException)
193 : {
194 0 : return sal_True;
195 : }
196 :
197 0 : OUString DatabaseMetaData::getURL( ) throw (SQLException, RuntimeException)
198 : {
199 : // TODO
200 : // LEM TODO: implement
201 0 : return OUString();
202 : }
203 :
204 0 : OUString DatabaseMetaData::getUserName( ) throw (SQLException, RuntimeException)
205 : {
206 0 : return m_pSettings->user;
207 : }
208 :
209 0 : sal_Bool DatabaseMetaData::isReadOnly( ) throw (SQLException, RuntimeException)
210 : {
211 0 : return sal_False;
212 : }
213 :
214 :
215 0 : sal_Bool DatabaseMetaData::nullsAreSortedHigh( ) throw (SQLException, RuntimeException)
216 : {
217 : // Whether NULL values are considered, for sorting purposes, LARGER than any other value.
218 : // Specification: http://download.oracle.com/javase/6/docs/api/java/sql/DatabaseMetaData.html#nullsAreSortedHigh()
219 : // PostgreSQL behaviour: http://www.postgresql.org/docs/9.1/static/queries-order.htlm
220 0 : return sal_True;
221 : }
222 :
223 0 : sal_Bool DatabaseMetaData::nullsAreSortedLow( ) throw (SQLException, RuntimeException)
224 : {
225 0 : return ! nullsAreSortedHigh();
226 : }
227 :
228 0 : sal_Bool DatabaseMetaData::nullsAreSortedAtStart( ) throw (SQLException, RuntimeException)
229 : {
230 0 : return sal_False;
231 : }
232 :
233 0 : sal_Bool DatabaseMetaData::nullsAreSortedAtEnd( ) throw (SQLException, RuntimeException)
234 : {
235 0 : return sal_False;
236 : }
237 :
238 0 : OUString DatabaseMetaData::getDatabaseProductName( ) throw (SQLException, RuntimeException)
239 : {
240 0 : return ASCII_STR("PostgreSQL");
241 : }
242 :
243 0 : OUString DatabaseMetaData::getDatabaseProductVersion( ) throw (SQLException, RuntimeException)
244 : {
245 0 : return rtl::OUString::createFromAscii( PQparameterStatus( m_pSettings->pConnection, "server_version" ) );
246 : }
247 0 : OUString DatabaseMetaData::getDriverName( ) throw (SQLException, RuntimeException)
248 : {
249 0 : return ASCII_STR( "postgresql-sdbc" );
250 : }
251 :
252 0 : OUString DatabaseMetaData::getDriverVersion( ) throw (SQLException, RuntimeException)
253 : {
254 0 : return ASCII_STR( PQ_SDBC_DRIVER_VERSION );
255 : }
256 :
257 0 : sal_Int32 DatabaseMetaData::getDriverMajorVersion( ) throw (RuntimeException)
258 : {
259 0 : return PQ_SDBC_MAJOR;
260 : }
261 :
262 0 : sal_Int32 DatabaseMetaData::getDriverMinorVersion( ) throw (RuntimeException)
263 : {
264 0 : return PQ_SDBC_MINOR;
265 : }
266 :
267 0 : sal_Bool DatabaseMetaData::usesLocalFiles( ) throw (SQLException, RuntimeException)
268 : {
269 : // LEM TODO:
270 : // http://wiki.services.openoffice.org/wiki/Documentation/DevGuide/Database/XDatabaseMetaData_Interface
271 : // says "Returns true when the catalog name of the
272 : // database should not appear in the DatasourceBrowser
273 : // of OpenOffice.org API, otherwise false is returned."
274 : // So, hmmm, think about it.
275 0 : return sal_False;
276 : }
277 :
278 0 : sal_Bool DatabaseMetaData::usesLocalFilePerTable( ) throw (SQLException, RuntimeException)
279 : {
280 0 : return sal_False;
281 : }
282 :
283 0 : sal_Bool DatabaseMetaData::supportsMixedCaseIdentifiers( ) throw (SQLException, RuntimeException)
284 : {
285 0 : return sal_False;
286 : }
287 :
288 0 : sal_Bool DatabaseMetaData::storesUpperCaseIdentifiers( ) throw (SQLException, RuntimeException)
289 : {
290 0 : return sal_False;
291 : }
292 :
293 0 : sal_Bool DatabaseMetaData::storesLowerCaseIdentifiers( ) throw (SQLException, RuntimeException)
294 : {
295 0 : return sal_True;
296 : }
297 :
298 :
299 0 : sal_Bool DatabaseMetaData::storesMixedCaseIdentifiers( ) throw (SQLException, RuntimeException)
300 : {
301 0 : return sal_False;
302 : }
303 :
304 :
305 0 : sal_Bool DatabaseMetaData::supportsMixedCaseQuotedIdentifiers( ) throw (SQLException, RuntimeException)
306 : {
307 0 : return sal_True;
308 : }
309 :
310 0 : sal_Bool DatabaseMetaData::storesUpperCaseQuotedIdentifiers( ) throw (SQLException, RuntimeException)
311 : {
312 0 : return sal_False;
313 : }
314 :
315 :
316 0 : sal_Bool DatabaseMetaData::storesLowerCaseQuotedIdentifiers( ) throw (SQLException, RuntimeException)
317 : {
318 0 : return sal_False;
319 : }
320 :
321 :
322 0 : sal_Bool DatabaseMetaData::storesMixedCaseQuotedIdentifiers( ) throw (SQLException, RuntimeException)
323 : {
324 0 : return sal_False;
325 : }
326 :
327 :
328 0 : OUString DatabaseMetaData::getIdentifierQuoteString( ) throw (SQLException, RuntimeException)
329 : {
330 0 : return ASCII_STR( "\"" );
331 : }
332 :
333 0 : OUString DatabaseMetaData::getSQLKeywords( ) throw (SQLException, RuntimeException)
334 : {
335 : // In Java 6, this is all keywords that are not SQL:2003
336 : // In Java 2 v1.4 and as per LibreOffice SDK doc, this is all keywords that are not SQL92
337 : // I understand this to mean "reserved keywords" only.
338 : // See http://www.postgresql.org/docs/current/static/sql-keywords-appendix.html
339 0 : return ASCII_STR(
340 : "ANALYSE,"
341 : "ANALYZE,"
342 : "ARRAY," //SQL:1999
343 : "ASYMMETRIC," //SQL:2003
344 : "BINARY," //SQL:1999
345 : "CONCURRENTLY,"
346 : "CURRENT_CATALOG," //SQL:2008
347 : "CURRENT_ROLE," //SQL:1999
348 : "CURRENT_SCHEMA," //SQL:2008
349 : "DO,"
350 : "FREEZE,"
351 : "ILIKE,"
352 : "ISNULL,"
353 : "LIMIT," //SQL:1999; non-reserved in SQL:2003
354 : "LOCALTIME," //SQL:1999
355 : "LOCALTIMESTAMP," //SQL:1999
356 : "NOTNULL,"
357 : "OFFSET," //SQL:2008
358 : "OVER," //SQL:2003
359 : "PLACING," //non-reserved in SQL:2003
360 : "RETURNING," //non-reserved in SQL:2008
361 : "SIMILAR," //SQL:2003
362 : "VARIADIC,"
363 : "VERBOSE,"
364 : "WINDOW" //SQL:2003
365 : );
366 : }
367 0 : OUString DatabaseMetaData::getNumericFunctions( ) throw (SQLException, RuntimeException)
368 : {
369 : // See http://www.postgresql.org/docs/9.1/static/functions-math.html
370 : // LEM TODO: Err... http://wiki.services.openoffice.org/wiki/Documentation/DevGuide/Database/Support_Scalar_Functions
371 : // says this should be "Open Group CLI" names, not PostgreSQL names.
372 : // Currently this is just a list of supported functions in PostgreSQL, with PostgreSQL names.
373 : // And it is my job to map from Open Group CLI names/syntax to PostgreSQL names/syntax. Where? By parsing the SQL???
374 : // Should look at what the JDBC driver is doing.
375 0 : return ASCII_STR(
376 : "abs,"
377 : "cbrt,"
378 : "ceil,"
379 : "ceiling,"
380 : "degrees,"
381 : "div,"
382 : "exp,"
383 : "floor,"
384 : "ln,"
385 : "log,"
386 : "mod,"
387 : "pi,"
388 : "power,"
389 : "radians,"
390 : "random,"
391 : "round,"
392 : "setseed,"
393 : "sign,"
394 : "sqrt,"
395 : "trunc,"
396 : "width_bucket,"
397 : "acos,"
398 : "asin,"
399 : "atan,"
400 : "atan2,"
401 : "cos,"
402 : "cot,"
403 : "sin,"
404 : "tan"
405 : );
406 : }
407 :
408 0 : OUString DatabaseMetaData::getStringFunctions( ) throw (SQLException, RuntimeException)
409 : {
410 : // See http://www.postgresql.org/docs/9.1/static/functions-string.html
411 0 : return ASCII_STR(
412 : "bit_length,"
413 : "char_length,"
414 : "character_length,"
415 : "lower,"
416 : "octet_length,"
417 : "overlay,"
418 : "position,"
419 : "substring,"
420 : "trim,"
421 : "upper,"
422 : "ascii,"
423 : "btrim,"
424 : "chr,"
425 : "concat,"
426 : "concat_ws,"
427 : "convert,"
428 : "convert_from,"
429 : "convert_to,"
430 : "decode,"
431 : "encode,"
432 : "foramt,"
433 : "initcap,"
434 : "left,"
435 : "length,"
436 : "lpad,"
437 : "ltrim,"
438 : "md5,"
439 : "pg_client_encoding,"
440 : "quote_ident,"
441 : "quote_literal,"
442 : "quote_nullable,"
443 : "regexp_matches,"
444 : "regexp_replace,"
445 : "regexp_split_to_array,"
446 : "regexp_split_to_table,"
447 : "repeat,"
448 : "replace,"
449 : "reverse,"
450 : "right,"
451 : "rpad,"
452 : "rtrim,"
453 : "split_part,"
454 : "strpos,"
455 : "substr,"
456 : "to_ascii,"
457 : "to_hex,"
458 : "translate"
459 : );
460 : }
461 :
462 0 : OUString DatabaseMetaData::getSystemFunctions( ) throw (SQLException, RuntimeException)
463 : {
464 : // See http://www.postgresql.org/docs/9.1/static/functions-info.html
465 : // and http://www.postgresql.org/docs/9.1/static/functions-admin.html
466 0 : return ASCII_STR(
467 : "current_catalog,"
468 : "current_database,"
469 : "current_query,"
470 : "current_schema,"
471 : "current_schemas,"
472 : "current_user,"
473 : "inet_client_addr,"
474 : "inet_client_port,"
475 : "inet_server_addr,"
476 : "inet_server_port,"
477 : "pg_backend_pid,"
478 : "pg_conf_load_time,"
479 : "pg_is_other_temp_schema,"
480 : "pg_listening_channels,"
481 : "pg_my_temp_schema,"
482 : "pg_postmaster_start_time,"
483 : "session_user,"
484 : "user,"
485 : "version,"
486 : "has_any_column_privilege,"
487 : "has_any_column_privilege,"
488 : "has_any_column_privilege,"
489 : "has_column_privilege,"
490 : "has_database_privilege,"
491 : "has_foreign_data_wrapper_privilege,"
492 : "has_function_privilege,"
493 : "has_language_privilege,"
494 : "has_schema_privilege,"
495 : "has_sequence_privilege,"
496 : "has_server_privilege,"
497 : "has_table_privilege,"
498 : "has_tablespace_privilege,"
499 : "pg_has_role,"
500 : "pg_collation_is_visible,"
501 : "pg_conversion_is_visible,"
502 : "pg_function_is_visible,"
503 : "pg_opclass_is_visible,"
504 : "pg_operator_is_visible,"
505 : "pg_table_is_visible,"
506 : "pg_ts_config_is_visible,"
507 : "pg_ts_dict_is_visible,"
508 : "pg_ts_parser_is_visible,"
509 : "pg_ts_template_is_visible,"
510 : "pg_type_is_visible,"
511 : "format_type,"
512 : "pg_describe_object,"
513 : "pg_get_constraintdef,"
514 : "pg_get_expr,"
515 : "pg_get_functiondef,"
516 : "pg_get_function_arguments,"
517 : "pg_get_function_identity_arguments,"
518 : "pg_get_function_result,"
519 : "pg_get_indexdef,"
520 : "pg_get_keywords,"
521 : "pg_get_ruledef,"
522 : "pg_get_serial_sequence,"
523 : "pg_get_triggerdef,"
524 : "pg_get_userbyid,"
525 : "pg_get_viewdef,"
526 : "pg_options_to_table,"
527 : "pg_tablespace_databases,"
528 : "pg_typeof,"
529 : "col_description,"
530 : "obj_description,"
531 : "shobj_description,"
532 : "txid_current,"
533 : "txid_current_snapshot,"
534 : "txid_snapshot_xip,"
535 : "txid_snapshot_xmax,"
536 : "txid_snapshot_xmin,"
537 : "txid_visible_in_snapshot,"
538 : "xmin,"
539 : "xmax,"
540 : "xip_list,"
541 : "current_setting,"
542 : "set_config,"
543 : "pg_cancel_backend,"
544 : "pg_reload_conf,"
545 : "pg_rotate_logfile,"
546 : "pg_terminate_backend,"
547 : "pg_create_restore_point,"
548 : "pg_current_xlog_insert_location,"
549 : "pg_current_xlog_location,"
550 : "pg_start_backup,"
551 : "pg_stop_backup,"
552 : "pg_switch_xlog,"
553 : "pg_xlogfile_name,"
554 : "pg_xlogfile_name_offset,"
555 : "pg_is_in_recovery,"
556 : "pg_last_xlog_receive_location,"
557 : "pg_last_xlog_replay_location,"
558 : "pg_last_xact_replay_timestamp,"
559 : "pg_is_xlog_replay_paused,"
560 : "pg_xlog_replay_pause,"
561 : "pg_xlog_replay_resume,"
562 : "pg_column_size,"
563 : "pg_database_size,"
564 : "pg_indexes_size,"
565 : "pg_relation_size,"
566 : "pg_size_pretty,"
567 : "pg_table_size,"
568 : "pg_tablespace_size,"
569 : "pg_tablespace_size,"
570 : "pg_total_relation_size,"
571 : "pg_relation_filenode,"
572 : "pg_relation_filepath,"
573 : "pg_ls_dir,"
574 : "pg_read_file,"
575 : "pg_read_binary_file,"
576 : "pg_stat_file,"
577 : "pg_advisory_lock,"
578 : "pg_advisory_lock_shared,"
579 : "pg_advisory_unlock,"
580 : "pg_advisory_unlock_all,"
581 : "pg_advisory_unlock_shared,"
582 : "pg_advisory_xact_lock,"
583 : "pg_advisory_xact_lock_shared,"
584 : "pg_try_advisory_lock,"
585 : "pg_try_advisory_lock_shared,"
586 : "pg_try_advisory_xact_lock,"
587 : "pg_try_advisory_xact_lock_shared,"
588 : "pg_sleep"
589 : );
590 : }
591 0 : OUString DatabaseMetaData::getTimeDateFunctions( ) throw (SQLException, RuntimeException)
592 : {
593 : // TODO
594 0 : return ASCII_STR(
595 : "age,"
596 : "age,"
597 : "clock_timestamp,"
598 : "current_date,"
599 : "current_time,"
600 : "current_timestamp,"
601 : "date_part,"
602 : "date_part,"
603 : "date_trunc,"
604 : "extract,"
605 : "extract,"
606 : "isfinite,"
607 : "isfinite,"
608 : "isfinite,"
609 : "justify_days,"
610 : "justify_hours,"
611 : "justify_interval,"
612 : "localtime,"
613 : "localtimestamp,"
614 : "now,"
615 : "statement_timestamp,"
616 : "timeofday,"
617 : "transaction_timestamp,"
618 : );
619 : }
620 0 : OUString DatabaseMetaData::getSearchStringEscape( ) throw (SQLException, RuntimeException)
621 : {
622 0 : return ASCII_STR( "\\" );
623 : }
624 0 : OUString DatabaseMetaData::getExtraNameCharacters( ) throw (SQLException, RuntimeException)
625 : {
626 0 : return ASCII_STR( "$" );
627 : }
628 :
629 0 : sal_Bool DatabaseMetaData::supportsAlterTableWithAddColumn( ) throw (SQLException, RuntimeException)
630 : {
631 0 : return sal_True;
632 : }
633 :
634 0 : sal_Bool DatabaseMetaData::supportsAlterTableWithDropColumn( ) throw (SQLException, RuntimeException)
635 : {
636 0 : return sal_True;
637 : }
638 :
639 0 : sal_Bool DatabaseMetaData::supportsColumnAliasing( ) throw (SQLException, RuntimeException)
640 : {
641 0 : return sal_True;
642 : }
643 :
644 0 : sal_Bool DatabaseMetaData::nullPlusNonNullIsNull( ) throw (SQLException, RuntimeException)
645 : {
646 0 : return sal_True;
647 : }
648 :
649 0 : sal_Bool DatabaseMetaData::supportsTypeConversion( ) throw (SQLException, RuntimeException)
650 : {
651 : // LEM: this is specifically whether the "CONVERT" function is supported
652 : // It seems that in PostgreSQL, that function is only for string encoding, so no.
653 0 : return sal_False;
654 : }
655 :
656 0 : sal_Bool DatabaseMetaData::supportsConvert( sal_Int32 fromType, sal_Int32 toType ) throw (SQLException, RuntimeException)
657 : {
658 : (void) fromType; (void) toType;
659 0 : return sal_False;
660 : }
661 :
662 0 : sal_Bool DatabaseMetaData::supportsTableCorrelationNames( ) throw (SQLException, RuntimeException)
663 : {
664 : // LEM: A correlation name is "bar" in "SELECT foo FROM qux [AS] bar WHERE ..."
665 0 : return sal_True;
666 : }
667 :
668 :
669 0 : sal_Bool DatabaseMetaData::supportsDifferentTableCorrelationNames( ) throw (SQLException, RuntimeException)
670 : {
671 0 : return sal_False;
672 : }
673 0 : sal_Bool DatabaseMetaData::supportsExpressionsInOrderBy( ) throw (SQLException, RuntimeException)
674 : {
675 0 : return sal_True;
676 : }
677 :
678 0 : sal_Bool DatabaseMetaData::supportsOrderByUnrelated( ) throw (SQLException, RuntimeException)
679 : {
680 0 : return sal_True;
681 : }
682 :
683 0 : sal_Bool DatabaseMetaData::supportsGroupBy( ) throw (SQLException, RuntimeException)
684 : {
685 0 : return sal_True;
686 : }
687 :
688 0 : sal_Bool DatabaseMetaData::supportsGroupByUnrelated( ) throw (SQLException, RuntimeException)
689 : {
690 0 : return sal_True;
691 : }
692 :
693 0 : sal_Bool DatabaseMetaData::supportsGroupByBeyondSelect( ) throw (SQLException, RuntimeException)
694 : {
695 0 : return sal_True;
696 : }
697 :
698 0 : sal_Bool DatabaseMetaData::supportsLikeEscapeClause( ) throw (SQLException, RuntimeException)
699 : {
700 0 : return sal_True;
701 : }
702 :
703 0 : sal_Bool DatabaseMetaData::supportsMultipleResultSets( ) throw (SQLException, RuntimeException)
704 : {
705 0 : return sal_True;
706 : }
707 :
708 0 : sal_Bool DatabaseMetaData::supportsMultipleTransactions( ) throw (SQLException, RuntimeException)
709 : {
710 : // Allows multiple transactions open at once (on different connections!)
711 0 : return sal_True;
712 : }
713 :
714 0 : sal_Bool DatabaseMetaData::supportsNonNullableColumns( ) throw (SQLException, RuntimeException)
715 : {
716 0 : return sal_True;
717 : }
718 :
719 :
720 0 : sal_Bool DatabaseMetaData::supportsMinimumSQLGrammar( ) throw (SQLException, RuntimeException)
721 : {
722 0 : return sal_True;
723 : }
724 :
725 0 : sal_Bool DatabaseMetaData::supportsCoreSQLGrammar( ) throw (SQLException, RuntimeException)
726 : {
727 : // LEM: jdbc driver says not, although the comments in it seem old
728 : // fdo#45249 Base query design won't use any aggregate function
729 : // (except COUNT(*) unless we say yes, so say yes.
730 : // Actually, Base assumes *also* support for aggregate functions "collect, fusion, intersection"
731 : // as soon as supportsCoreSQLGrammar() returns true.
732 : // Those are *not* Core SQL, though. They are in optional feature S271 "Basic multiset support"
733 0 : return sal_True;
734 : }
735 :
736 0 : sal_Bool DatabaseMetaData::supportsExtendedSQLGrammar( ) throw (SQLException, RuntimeException)
737 : {
738 0 : return sal_False;
739 : }
740 :
741 0 : sal_Bool DatabaseMetaData::supportsANSI92EntryLevelSQL( ) throw (SQLException, RuntimeException)
742 : {
743 0 : return sal_True;
744 : }
745 :
746 0 : sal_Bool DatabaseMetaData::supportsANSI92IntermediateSQL( ) throw (SQLException, RuntimeException)
747 : {
748 : // LEM: jdbc driver says not, although the comments in it seem old
749 0 : return sal_False;
750 : }
751 :
752 0 : sal_Bool DatabaseMetaData::supportsANSI92FullSQL( ) throw (SQLException, RuntimeException)
753 : {
754 : // LEM: jdbc driver says not, although the comments in it seem old
755 0 : return sal_False;
756 : }
757 :
758 0 : sal_Bool DatabaseMetaData::supportsIntegrityEnhancementFacility( ) throw (SQLException, RuntimeException)
759 : {
760 : // LEM: jdbc driver says yes, although comment says they are not sure what this means...
761 0 : return sal_True;
762 : }
763 :
764 0 : sal_Bool DatabaseMetaData::supportsOuterJoins( ) throw (SQLException, RuntimeException)
765 : {
766 0 : return sal_True;
767 : }
768 :
769 0 : sal_Bool DatabaseMetaData::supportsFullOuterJoins( ) throw (SQLException, RuntimeException)
770 : {
771 0 : return sal_True;
772 : }
773 :
774 0 : sal_Bool DatabaseMetaData::supportsLimitedOuterJoins( ) throw (SQLException, RuntimeException)
775 : {
776 0 : return sal_True;
777 : }
778 :
779 :
780 0 : OUString DatabaseMetaData::getSchemaTerm( ) throw (SQLException, RuntimeException)
781 : {
782 0 : return ASCII_STR( "SCHEMA" );
783 : }
784 :
785 0 : OUString DatabaseMetaData::getProcedureTerm( ) throw (SQLException, RuntimeException)
786 : {
787 0 : return ASCII_STR( "function" );
788 : }
789 :
790 0 : OUString DatabaseMetaData::getCatalogTerm( ) throw (SQLException, RuntimeException)
791 : {
792 0 : return ASCII_STR( "DATABASE" );
793 : }
794 :
795 0 : sal_Bool DatabaseMetaData::isCatalogAtStart( ) throw (SQLException, RuntimeException)
796 : {
797 :
798 0 : return sal_True;
799 : }
800 :
801 0 : OUString DatabaseMetaData::getCatalogSeparator( ) throw (SQLException, RuntimeException)
802 : {
803 0 : return ASCII_STR( "." );
804 : }
805 :
806 0 : sal_Bool DatabaseMetaData::supportsSchemasInDataManipulation( ) throw (SQLException, RuntimeException)
807 : {
808 0 : return sal_True;
809 : }
810 :
811 0 : sal_Bool DatabaseMetaData::supportsSchemasInProcedureCalls( ) throw (SQLException, RuntimeException)
812 : {
813 0 : return sal_True;
814 : }
815 :
816 0 : sal_Bool DatabaseMetaData::supportsSchemasInTableDefinitions( ) throw (SQLException, RuntimeException)
817 : {
818 0 : return sal_True;
819 : }
820 :
821 0 : sal_Bool DatabaseMetaData::supportsSchemasInIndexDefinitions( ) throw (SQLException, RuntimeException)
822 : {
823 0 : return sal_True;
824 : }
825 :
826 0 : sal_Bool DatabaseMetaData::supportsSchemasInPrivilegeDefinitions( ) throw (SQLException, RuntimeException)
827 : {
828 0 : return sal_True;
829 : }
830 :
831 0 : sal_Bool DatabaseMetaData::supportsCatalogsInDataManipulation( ) throw (SQLException, RuntimeException)
832 : {
833 0 : return sal_False;
834 : }
835 :
836 0 : sal_Bool DatabaseMetaData::supportsCatalogsInProcedureCalls( ) throw (SQLException, RuntimeException)
837 : {
838 0 : return sal_False;
839 : }
840 :
841 0 : sal_Bool DatabaseMetaData::supportsCatalogsInTableDefinitions( ) throw (SQLException, RuntimeException)
842 : {
843 0 : return sal_False;
844 : }
845 :
846 :
847 0 : sal_Bool DatabaseMetaData::supportsCatalogsInIndexDefinitions( ) throw (SQLException, RuntimeException)
848 : {
849 0 : return sal_False;
850 : }
851 :
852 :
853 0 : sal_Bool DatabaseMetaData::supportsCatalogsInPrivilegeDefinitions( ) throw (SQLException, RuntimeException)
854 : {
855 0 : return sal_False;
856 : }
857 :
858 :
859 : // LEM TODO: positioned (through cursor) updates and deletes seem
860 : // to be supported; see {UPDATE,DELETE} /table/ (...) WHERE CURRENT OF /cursor_name/" syntax
861 : // and http://www.postgresql.org/docs/9.1/static/view-pg-cursors.html
862 : // http://www.postgresql.org/docs/9.1/static/libpq-example.html actually uses a cursor :)
863 0 : sal_Bool DatabaseMetaData::supportsPositionedDelete( ) throw (SQLException, RuntimeException)
864 : {
865 : // LEM: jdbc driver says not, although the comments in it seem old
866 0 : return sal_False;
867 : }
868 :
869 0 : sal_Bool DatabaseMetaData::supportsPositionedUpdate( ) throw (SQLException, RuntimeException)
870 : {
871 : // LEM: jdbc driver says not, although the comments in it seem old
872 0 : return sal_False;
873 : }
874 :
875 :
876 0 : sal_Bool DatabaseMetaData::supportsSelectForUpdate( ) throw (SQLException, RuntimeException)
877 : {
878 0 : return sal_True;
879 : }
880 :
881 :
882 0 : sal_Bool DatabaseMetaData::supportsStoredProcedures( ) throw (SQLException, RuntimeException)
883 : {
884 0 : return sal_True;
885 : }
886 :
887 :
888 0 : sal_Bool DatabaseMetaData::supportsSubqueriesInComparisons( ) throw (SQLException, RuntimeException)
889 : {
890 0 : return sal_True;
891 : }
892 :
893 0 : sal_Bool DatabaseMetaData::supportsSubqueriesInExists( ) throw (SQLException, RuntimeException)
894 : {
895 0 : return sal_True;
896 : }
897 :
898 0 : sal_Bool DatabaseMetaData::supportsSubqueriesInIns( ) throw (SQLException, RuntimeException)
899 : {
900 0 : return sal_True;
901 : }
902 :
903 0 : sal_Bool DatabaseMetaData::supportsSubqueriesInQuantifieds( ) throw (SQLException, RuntimeException)
904 : {
905 : // LEM: jdbc driver says yes, although comment says they don't know what this means...
906 0 : return sal_True;
907 : }
908 :
909 0 : sal_Bool DatabaseMetaData::supportsCorrelatedSubqueries( ) throw (SQLException, RuntimeException)
910 : {
911 0 : return sal_True;
912 : }
913 0 : sal_Bool DatabaseMetaData::supportsUnion( ) throw (SQLException, RuntimeException)
914 : {
915 0 : return sal_True;
916 : }
917 :
918 0 : sal_Bool DatabaseMetaData::supportsUnionAll( ) throw (SQLException, RuntimeException)
919 : {
920 0 : return sal_True;
921 : }
922 :
923 0 : sal_Bool DatabaseMetaData::supportsOpenCursorsAcrossCommit( ) throw (SQLException, RuntimeException)
924 : {
925 0 : return sal_False;
926 : }
927 :
928 0 : sal_Bool DatabaseMetaData::supportsOpenCursorsAcrossRollback( ) throw (SQLException, RuntimeException)
929 : {
930 0 : return sal_False;
931 : }
932 :
933 0 : sal_Bool DatabaseMetaData::supportsOpenStatementsAcrossCommit( ) throw (SQLException, RuntimeException)
934 : {
935 0 : return sal_True;
936 : }
937 0 : sal_Bool DatabaseMetaData::supportsOpenStatementsAcrossRollback( ) throw (SQLException, RuntimeException)
938 : {
939 0 : return sal_True;
940 : }
941 :
942 0 : sal_Int32 DatabaseMetaData::getMaxBinaryLiteralLength( ) throw (SQLException, RuntimeException)
943 : {
944 0 : return 0;
945 : }
946 :
947 0 : sal_Int32 DatabaseMetaData::getMaxCharLiteralLength( ) throw (SQLException, RuntimeException)
948 : {
949 0 : return 0;
950 : }
951 :
952 : // Copied / adapted / simplified from JDBC driver
953 0 : sal_Int32 DatabaseMetaData::getIntSetting(OUString settingName)
954 : throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
955 : {
956 0 : MutexGuard guard( m_refMutex->mutex );
957 :
958 0 : Reference< XParameters > params(m_getIntSetting_stmt, UNO_QUERY_THROW );
959 0 : params->setString(1, settingName );
960 0 : Reference< XResultSet > rs = m_getIntSetting_stmt->executeQuery();
961 0 : Reference< XRow > xRow( rs , UNO_QUERY_THROW );
962 0 : OSL_VERIFY(rs->next());
963 : OSL_ENSURE(rs->isFirst(), "postgresql-sdbc DatabaseMetaData getIntSetting not on first row");
964 : OSL_ENSURE(rs->isLast(), "postgresql-sdbc DatabaseMetaData getIntSetting not on last row");
965 0 : return xRow->getInt(1);
966 : }
967 :
968 0 : sal_Int32 DatabaseMetaData::getMaxNameLength()
969 : throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
970 : {
971 0 : if ( m_pSettings->maxNameLen == 0)
972 0 : m_pSettings->maxNameLen = getIntSetting( ASCII_STR("max_identifier_length") );
973 : OSL_ENSURE(m_pSettings->maxNameLen, "postgresql-sdbc: maxNameLen is zero");
974 0 : return m_pSettings->maxNameLen;
975 : }
976 :
977 0 : sal_Int32 DatabaseMetaData::getMaxIndexKeys()
978 : throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
979 : {
980 0 : if ( m_pSettings->maxIndexKeys == 0)
981 0 : m_pSettings->maxIndexKeys = getIntSetting(ASCII_STR("max_index_keys"));
982 : OSL_ENSURE(m_pSettings->maxIndexKeys, "postgresql-sdbc: maxIndexKeys is zero");
983 0 : return m_pSettings->maxIndexKeys;
984 : }
985 :
986 0 : sal_Int32 DatabaseMetaData::getMaxColumnNameLength( ) throw (SQLException, RuntimeException)
987 : {
988 0 : return getMaxNameLength();
989 : }
990 :
991 0 : sal_Int32 DatabaseMetaData::getMaxColumnsInGroupBy( ) throw (SQLException, RuntimeException)
992 : {
993 0 : return 0;
994 : }
995 :
996 0 : sal_Int32 DatabaseMetaData::getMaxColumnsInIndex( ) throw (SQLException, RuntimeException)
997 : {
998 0 : return getMaxIndexKeys();
999 : }
1000 :
1001 0 : sal_Int32 DatabaseMetaData::getMaxColumnsInOrderBy( ) throw (SQLException, RuntimeException)
1002 : {
1003 0 : return 0;
1004 : }
1005 :
1006 0 : sal_Int32 DatabaseMetaData::getMaxColumnsInSelect( ) throw (SQLException, RuntimeException)
1007 : {
1008 0 : return 0;
1009 : }
1010 :
1011 0 : sal_Int32 DatabaseMetaData::getMaxColumnsInTable( ) throw (SQLException, RuntimeException)
1012 : {
1013 0 : return 1600;
1014 : }
1015 :
1016 0 : sal_Int32 DatabaseMetaData::getMaxConnections( ) throw (SQLException, RuntimeException)
1017 : {
1018 : // LEM: The JDBC driver returns an arbitrary 8192; truth is as much as OS / hardware supports
1019 0 : return 0;
1020 : }
1021 :
1022 0 : sal_Int32 DatabaseMetaData::getMaxCursorNameLength( ) throw (SQLException, RuntimeException) //TODO, don't know
1023 : {
1024 0 : return getMaxNameLength();
1025 : }
1026 :
1027 0 : sal_Int32 DatabaseMetaData::getMaxIndexLength( ) throw (SQLException, RuntimeException) //TODO, don't know
1028 : {
1029 : // LEM: that's the index itself, not its name
1030 0 : return 0;
1031 : }
1032 :
1033 0 : sal_Int32 DatabaseMetaData::getMaxSchemaNameLength( ) throw (SQLException, RuntimeException)
1034 : {
1035 0 : return getMaxNameLength();
1036 : }
1037 :
1038 0 : sal_Int32 DatabaseMetaData::getMaxProcedureNameLength( ) throw (SQLException, RuntimeException)
1039 : {
1040 0 : return getMaxNameLength();
1041 : }
1042 :
1043 0 : sal_Int32 DatabaseMetaData::getMaxCatalogNameLength( ) throw (SQLException, RuntimeException)
1044 : {
1045 0 : return getMaxNameLength();
1046 : }
1047 :
1048 0 : sal_Int32 DatabaseMetaData::getMaxRowSize( ) throw (SQLException, RuntimeException)
1049 : {
1050 : // jdbc driver says 1GB, but http://www.postgresql.org/about/ says 1.6TB
1051 : // and that 1GB is the maximum _field_ size
1052 : // The row limit does not fit into a sal_Int32
1053 0 : return 0;
1054 : }
1055 :
1056 0 : sal_Bool DatabaseMetaData::doesMaxRowSizeIncludeBlobs( ) throw (SQLException, RuntimeException)
1057 : {
1058 : // LEM: Err... PostgreSQL basically does not do BLOBs well
1059 : // In any case, BLOBs do not change the maximal row length AFAIK
1060 0 : return sal_True;
1061 : }
1062 :
1063 0 : sal_Int32 DatabaseMetaData::getMaxStatementLength( ) throw (SQLException, RuntimeException)
1064 : {
1065 : // LEM: actually, that would be 2^sizeof(size_t)-1
1066 : // on the server? on the client (because of libpq)? minimum of the two? not sure
1067 : // Anyway, big, so say unlimited.
1068 0 : return 0;
1069 : }
1070 :
1071 0 : sal_Int32 DatabaseMetaData::getMaxStatements( ) throw (SQLException, RuntimeException) //TODO, don't know
1072 : {
1073 0 : return 0;
1074 : }
1075 :
1076 0 : sal_Int32 DatabaseMetaData::getMaxTableNameLength( ) throw (SQLException, RuntimeException)
1077 : {
1078 0 : return getMaxNameLength();
1079 : }
1080 :
1081 0 : sal_Int32 DatabaseMetaData::getMaxTablesInSelect( ) throw (SQLException, RuntimeException)
1082 : {
1083 0 : return 0;
1084 : }
1085 :
1086 0 : sal_Int32 DatabaseMetaData::getMaxUserNameLength( ) throw (SQLException, RuntimeException)
1087 : {
1088 0 : return getMaxNameLength();
1089 : }
1090 :
1091 0 : sal_Int32 DatabaseMetaData::getDefaultTransactionIsolation( ) throw (SQLException, RuntimeException)
1092 : {
1093 0 : return com::sun::star::sdbc::TransactionIsolation::READ_COMMITTED;
1094 : }
1095 :
1096 0 : sal_Bool DatabaseMetaData::supportsTransactions( ) throw (SQLException, RuntimeException)
1097 : {
1098 0 : return sal_True;
1099 : }
1100 :
1101 0 : sal_Bool DatabaseMetaData::supportsTransactionIsolationLevel( sal_Int32 level ) throw (SQLException, RuntimeException)
1102 : {
1103 0 : if ( level == com::sun::star::sdbc::TransactionIsolation::READ_COMMITTED
1104 : || level == com::sun::star::sdbc::TransactionIsolation::SERIALIZABLE
1105 : || level == com::sun::star::sdbc::TransactionIsolation::READ_UNCOMMITTED
1106 : || level == com::sun::star::sdbc::TransactionIsolation::REPEATABLE_READ)
1107 0 : return sal_True;
1108 : else
1109 0 : return sal_False;
1110 : }
1111 :
1112 0 : sal_Bool DatabaseMetaData::supportsDataDefinitionAndDataManipulationTransactions( )
1113 : throw (SQLException, RuntimeException)
1114 : {
1115 0 : return sal_True;
1116 : }
1117 :
1118 0 : sal_Bool DatabaseMetaData::supportsDataManipulationTransactionsOnly( ) throw (SQLException, RuntimeException)
1119 : {
1120 0 : return sal_False;
1121 : }
1122 :
1123 0 : sal_Bool DatabaseMetaData::dataDefinitionCausesTransactionCommit( ) throw (SQLException, RuntimeException)
1124 : {
1125 0 : return sal_False;
1126 : }
1127 :
1128 0 : sal_Bool DatabaseMetaData::dataDefinitionIgnoredInTransactions( ) throw (SQLException, RuntimeException)
1129 : {
1130 0 : return sal_False;
1131 : }
1132 :
1133 0 : ::com::sun::star::uno::Reference< XResultSet > DatabaseMetaData::getProcedures(
1134 : const ::com::sun::star::uno::Any& catalog,
1135 : const OUString& schemaPattern,
1136 : const OUString& procedureNamePattern ) throw (SQLException, RuntimeException)
1137 : {
1138 : (void) catalog; (void) schemaPattern; (void) procedureNamePattern;
1139 : // 1. PROCEDURE_CAT string => procedure catalog (may be NULL )
1140 : // 2. PROCEDURE_SCHEM string => procedure schema (may be NULL )
1141 : // 3. PROCEDURE_NAME string => procedure name
1142 : // 4. reserved for future use
1143 : // 5. reserved for future use
1144 : // 6. reserved for future use
1145 : // 7. REMARKS string => explanatory comment on the procedure
1146 : // 8. PROCEDURE_TYPE short => kind of procedure:
1147 : // * UNKNOWN - May return a result
1148 : // * NO - Does not return a result
1149 : // * RETURN - Returns a result
1150 :
1151 : // LEM TODO: implement
1152 : // LEM TODO: at least fake the columns, even if no row.
1153 0 : MutexGuard guard( m_refMutex->mutex );
1154 0 : checkClosed();
1155 : return new SequenceResultSet(
1156 0 : m_refMutex, *this, Sequence< OUString >(), Sequence< Sequence< Any > > (), m_pSettings->tc );
1157 : }
1158 :
1159 0 : ::com::sun::star::uno::Reference< XResultSet > DatabaseMetaData::getProcedureColumns(
1160 : const ::com::sun::star::uno::Any& catalog,
1161 : const OUString& schemaPattern,
1162 : const OUString& procedureNamePattern,
1163 : const OUString& columnNamePattern ) throw (SQLException, RuntimeException)
1164 : {
1165 : (void) catalog; (void) schemaPattern; (void) procedureNamePattern; (void) columnNamePattern;
1166 0 : MutexGuard guard( m_refMutex->mutex );
1167 0 : checkClosed();
1168 : // LEM TODO: implement
1169 : // LEM TODO: at least fake the columns, even if no row.
1170 : return new SequenceResultSet(
1171 0 : m_refMutex, *this, Sequence< OUString >(), Sequence< Sequence< Any > > (), m_pSettings->tc );
1172 : }
1173 :
1174 0 : ::com::sun::star::uno::Reference< XResultSet > DatabaseMetaData::getTables(
1175 : const ::com::sun::star::uno::Any& catalog,
1176 : const OUString& schemaPattern,
1177 : const OUString& tableNamePattern,
1178 : const ::com::sun::star::uno::Sequence< OUString >& types )
1179 : throw (SQLException, RuntimeException)
1180 : {
1181 : (void) catalog; (void) types;
1182 0 : Statics &statics = getStatics();
1183 :
1184 0 : MutexGuard guard( m_refMutex->mutex );
1185 0 : checkClosed();
1186 :
1187 0 : if( isLog( m_pSettings, LogLevel::INFO ) )
1188 : {
1189 0 : rtl::OUStringBuffer buf( 128 );
1190 0 : buf.appendAscii( "DatabaseMetaData::getTables got called with " );
1191 0 : buf.append( schemaPattern );
1192 0 : buf.appendAscii( "." );
1193 0 : buf.append( tableNamePattern );
1194 0 : log( m_pSettings, LogLevel::INFO, buf.makeStringAndClear() );
1195 : }
1196 : // ignore catalog, as a single pq connection does not support multiple catalogs
1197 :
1198 : // LEM TODO: this does not give the right column names, not the right number of columns, etc.
1199 : // Take "inspiration" from JDBC driver
1200 : // Ah, this is used to create a XResultSet manually... Try to do it directly in SQL
1201 0 : Reference< XPreparedStatement > statement = m_origin->prepareStatement(
1202 : ASCII_STR(
1203 : "SELECT "
1204 : "DISTINCT ON (pg_namespace.nspname, relname ) " // avoid duplicates (pg_settings !)
1205 : "pg_namespace.nspname, relname, relkind, pg_description.description "
1206 : "FROM pg_namespace, pg_class LEFT JOIN pg_description ON pg_class.oid = pg_description.objoid "
1207 : "WHERE relnamespace = pg_namespace.oid "
1208 : "AND ( relkind = 'r' OR relkind = 'v') "
1209 : "AND pg_namespace.nspname LIKE ? "
1210 : "AND relname LIKE ? "
1211 : // "ORDER BY pg_namespace.nspname || relname"
1212 0 : ) );
1213 :
1214 0 : Reference< XParameters > parameters( statement, UNO_QUERY_THROW );
1215 0 : parameters->setString( 1 , schemaPattern );
1216 0 : parameters->setString( 2 , tableNamePattern );
1217 :
1218 0 : Reference< XResultSet > rs = statement->executeQuery();
1219 0 : Reference< XRow > xRow( rs, UNO_QUERY_THROW );
1220 0 : SequenceAnyVector vec;
1221 :
1222 0 : while( rs->next() )
1223 : {
1224 0 : Sequence< Any > row( 5 );
1225 :
1226 0 : row[0] <<= m_pSettings->catalog;
1227 0 : row[1] <<= xRow->getString( 1 );
1228 0 : row[2] <<= xRow->getString( 2 );
1229 0 : OUString type = xRow->getString(3);
1230 0 : if( 0 == type.compareToAscii( "r" ) )
1231 : {
1232 0 : if( 0 == xRow->getString(1).compareToAscii( "pg_catalog" ) )
1233 : {
1234 0 : row[3] <<= statics.SYSTEM_TABLE;
1235 : }
1236 : else
1237 : {
1238 0 : row[3] <<= statics.TABLE;
1239 : }
1240 : }
1241 0 : else if( 0 == type.compareToAscii( "v" ) )
1242 : {
1243 0 : row[3] <<= statics.VIEW;
1244 : }
1245 : else
1246 : {
1247 0 : row[3] <<= statics.UNKNOWN;
1248 : }
1249 0 : row[4] <<= xRow->getString(4);
1250 :
1251 : // no description in postgresql AFAIK
1252 0 : vec.push_back( row );
1253 0 : }
1254 0 : Reference< XCloseable > closeable( statement, UNO_QUERY );
1255 0 : if( closeable.is() )
1256 0 : closeable->close();
1257 :
1258 : return new SequenceResultSet(
1259 0 : m_refMutex, *this, statics.tablesRowNames, sequence_of_vector(vec), m_pSettings->tc );
1260 : }
1261 :
1262 : struct SortInternalSchemasLastAndPublicFirst
1263 : {
1264 0 : bool operator () ( const Sequence< Any > & a, const Sequence< Any > & b )
1265 : {
1266 0 : OUString valueA;
1267 0 : OUString valueB;
1268 0 : a[0] >>= valueA;
1269 0 : b[0] >>= valueB;
1270 0 : bool ret = false;
1271 0 : if( valueA.compareToAscii( RTL_CONSTASCII_STRINGPARAM( "public" ) ) == 0 )
1272 : {
1273 0 : ret = true;
1274 : }
1275 0 : else if( valueB.compareToAscii( RTL_CONSTASCII_STRINGPARAM( "public" ) ) == 0 )
1276 : {
1277 0 : ret = false;
1278 : }
1279 0 : else if( valueA.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "pg_" ) ) &&
1280 0 : valueB.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "pg_" ) ) )
1281 : {
1282 0 : ret = valueA.compareTo( valueB ) < 0; // sorts equal !
1283 : }
1284 0 : else if( valueA.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "pg_" ) ))
1285 : {
1286 0 : ret = false; // sorts last !
1287 : }
1288 0 : else if( valueB.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "pg_" ) ) )
1289 : {
1290 0 : ret = true; // sorts first !
1291 : }
1292 : else
1293 : {
1294 0 : ret = (valueA.compareTo( valueB ) < 0);
1295 : }
1296 0 : return ret;
1297 : }
1298 : };
1299 :
1300 0 : ::com::sun::star::uno::Reference< XResultSet > DatabaseMetaData::getSchemas( )
1301 : throw (SQLException, RuntimeException)
1302 : {
1303 0 : MutexGuard guard( m_refMutex->mutex );
1304 0 : checkClosed();
1305 :
1306 0 : if( isLog( m_pSettings, LogLevel::INFO ) )
1307 : {
1308 0 : log( m_pSettings, LogLevel::INFO, "DatabaseMetaData::getSchemas() got called" );
1309 : }
1310 : // <b>TABLE_SCHEM</b> string =&gt; schema name
1311 0 : Reference< XStatement > statement = m_origin->createStatement();
1312 0 : Reference< XResultSet > rs = statement->executeQuery(
1313 0 : ASCII_STR("SELECT nspname from pg_namespace") );
1314 : // LEM TODO: look at JDBC driver and consider doing the same
1315 : // in particular, excluding temporary schemas, but maybe better through pg_is_other_temp_schema(oid) OR == pg_my_temp_schema()
1316 :
1317 0 : Reference< XRow > xRow( rs, UNO_QUERY_THROW );
1318 0 : SequenceAnyVector vec;
1319 0 : while( rs->next() )
1320 : {
1321 0 : Sequence<Any> row(1);
1322 0 : row[0] <<= xRow->getString(1);
1323 0 : vec.push_back( row );
1324 0 : }
1325 :
1326 : // sort public first, sort internal schemas last, sort rest in alphabetic order
1327 0 : std::sort( vec.begin(), vec.end(), SortInternalSchemasLastAndPublicFirst() );
1328 :
1329 0 : Reference< XCloseable > closeable( statement, UNO_QUERY );
1330 0 : if( closeable.is() )
1331 0 : closeable->close();
1332 : return new SequenceResultSet(
1333 0 : m_refMutex, *this, getStatics().schemaNames, sequence_of_vector(vec), m_pSettings->tc );
1334 : }
1335 :
1336 0 : ::com::sun::star::uno::Reference< XResultSet > DatabaseMetaData::getCatalogs( )
1337 : throw (SQLException, RuntimeException)
1338 : {
1339 : // LEM TODO: return the current catalog like JDBC driver?
1340 : // at least fake the columns, even if no content
1341 0 : MutexGuard guard( m_refMutex->mutex );
1342 0 : checkClosed();
1343 : return new SequenceResultSet(
1344 0 : m_refMutex, *this, Sequence< OUString >(), Sequence< Sequence< Any > > (), m_pSettings->tc );
1345 : }
1346 :
1347 0 : ::com::sun::star::uno::Reference< XResultSet > DatabaseMetaData::getTableTypes( )
1348 : throw (SQLException, RuntimeException)
1349 : {
1350 : // LEM TODO: this can be made dynamic, see JDBC driver
1351 0 : MutexGuard guard( m_refMutex->mutex );
1352 0 : checkClosed();
1353 : return new SequenceResultSet(
1354 0 : m_refMutex, *this, getStatics().tableTypeNames, getStatics().tableTypeData,
1355 0 : m_pSettings->tc );
1356 : }
1357 :
1358 :
1359 : /** returns the constant from sdbc.DataType
1360 : */
1361 0 : sal_Int32 typeNameToDataType( const OUString &typeName, const OUString &typtype )
1362 : {
1363 : // sal_Int32 ret = com::sun::star::sdbc::DataType::DISTINCT;
1364 : // map all unknown types to memo (longvarchar). This allows to show them in
1365 : // string representation. Additionally, the edit-table-type-selection-box
1366 : // is not so unuseable anymore.
1367 0 : sal_Int32 ret = com::sun::star::sdbc::DataType::LONGVARCHAR;
1368 0 : if( 0 == typtype.compareToAscii( "b" ) )
1369 : {
1370 : // as long as the OOo framework does not support arrays,
1371 : // the user is better of with interpreting arrays as strings !
1372 : // if( typeName.getLength() && '_' == typeName[0] )
1373 : // {
1374 : // its just a naming convention, but as long as we don't have anything better,
1375 : // we take it as granted
1376 : // ret = com::sun::star::sdbc::DataType::ARRAY;
1377 : // }
1378 : // base type
1379 0 : Statics &statics = getStatics();
1380 0 : BaseTypeMap::iterator ii = statics.baseTypeMap.find( typeName );
1381 0 : if( ii != statics.baseTypeMap.end() )
1382 : {
1383 0 : ret = ii->second;
1384 : }
1385 : }
1386 0 : else if( 0 == typtype.compareToAscii( "c" ) )
1387 : {
1388 0 : ret = com::sun::star::sdbc::DataType::STRUCT;
1389 : }
1390 0 : else if( 0 == typtype.compareToAscii( "d" ) )
1391 : {
1392 0 : ret = com::sun::star::sdbc::DataType::LONGVARCHAR;
1393 : }
1394 0 : return ret;
1395 : }
1396 :
1397 : namespace {
1398 0 : inline bool isSystemColumn( sal_Int16 attnum )
1399 : {
1400 0 : return attnum <= 0;
1401 : }
1402 : }
1403 :
1404 : // is not exported by the postgres header
1405 : const static int PQ_VARHDRSZ = sizeof( sal_Int32 );
1406 :
1407 : // Oh, quelle horreur
1408 : // LEM TODO: Need to severely rewrite that!
1409 : // should probably just "do the same" as ODBC or JDBC drivers...
1410 0 : static void extractPrecisionAndScale(
1411 : sal_Int32 dataType, sal_Int32 atttypmod, sal_Int32 *precision, sal_Int32 *scale )
1412 : {
1413 0 : if( atttypmod < PQ_VARHDRSZ )
1414 : {
1415 0 : *precision = 0;
1416 0 : *scale = 0;
1417 : }
1418 : else
1419 : {
1420 0 : switch( dataType )
1421 : {
1422 : case com::sun::star::sdbc::DataType::NUMERIC:
1423 : case com::sun::star::sdbc::DataType::DECIMAL:
1424 : {
1425 0 : *precision = ( ( atttypmod - PQ_VARHDRSZ ) >> 16 ) & 0xffff;
1426 0 : *scale = (atttypmod - PQ_VARHDRSZ ) & 0xffff;
1427 0 : break;
1428 : }
1429 : default:
1430 0 : *precision = atttypmod - PQ_VARHDRSZ;
1431 0 : *scale = 0;
1432 : }
1433 : }
1434 0 : }
1435 :
1436 0 : struct DatabaseTypeDescription
1437 : {
1438 0 : DatabaseTypeDescription()
1439 0 : {}
1440 0 : DatabaseTypeDescription( const OUString &name, const OUString & type ) :
1441 : typeName( name ),
1442 0 : typeType( type )
1443 0 : {}
1444 0 : DatabaseTypeDescription( const DatabaseTypeDescription &source ) :
1445 : typeName( source.typeName ),
1446 0 : typeType( source.typeType )
1447 0 : {}
1448 0 : DatabaseTypeDescription & operator = ( const DatabaseTypeDescription & source )
1449 : {
1450 0 : typeName = source.typeName;
1451 0 : typeType = source.typeType;
1452 0 : return *this;
1453 : }
1454 : OUString typeName;
1455 : OUString typeType;
1456 : };
1457 :
1458 : typedef ::boost::unordered_map
1459 : <
1460 : sal_Int32,
1461 : DatabaseTypeDescription,
1462 : ::boost::hash< sal_Int32 >,
1463 : ::std::equal_to< sal_Int32 >,
1464 : Allocator< ::std::pair< sal_Int32, DatabaseTypeDescription > >
1465 : > Oid2DatabaseTypeDescriptionMap;
1466 :
1467 0 : static void columnMetaData2DatabaseTypeDescription(
1468 : Oid2DatabaseTypeDescriptionMap &oidMap,
1469 : const Reference< XResultSet > &rs,
1470 : const Reference< XStatement > &stmt )
1471 : {
1472 0 : Reference< XRow > row( rs, UNO_QUERY_THROW );
1473 0 : int domains = 0;
1474 0 : rtl::OUStringBuffer queryBuf(128);
1475 0 : queryBuf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "SELECT oid,typtype,typname FROM pg_TYPE WHERE " ) );
1476 0 : while( rs->next() )
1477 : {
1478 0 : if( row->getString( 9 ) == "d" && oidMap.find( row->getInt( 12 ) ) == oidMap.end() )
1479 : {
1480 0 : oidMap[row->getInt(12)] = DatabaseTypeDescription();
1481 0 : if( domains )
1482 0 : queryBuf.appendAscii( " OR " );
1483 0 : queryBuf.appendAscii( "oid = " );
1484 0 : queryBuf.append( row->getInt(12 ), 10 );
1485 0 : domains ++;
1486 : }
1487 : }
1488 0 : rs->beforeFirst();
1489 :
1490 0 : if( domains )
1491 : {
1492 0 : Reference< XResultSet > rsDomain = stmt->executeQuery( queryBuf.makeStringAndClear() );
1493 0 : row = Reference< XRow >( rsDomain, UNO_QUERY_THROW );
1494 0 : while( rsDomain->next() )
1495 : {
1496 0 : oidMap[row->getInt(1)] = DatabaseTypeDescription(row->getString(3), row->getString(2) );
1497 : }
1498 0 : disposeNoThrow( stmt );
1499 0 : }
1500 :
1501 0 : }
1502 :
1503 :
1504 :
1505 0 : ::com::sun::star::uno::Reference< XResultSet > DatabaseMetaData::getColumns(
1506 : const ::com::sun::star::uno::Any& catalog,
1507 : const OUString& schemaPattern,
1508 : const OUString& tableNamePattern,
1509 : const OUString& columnNamePattern ) throw (SQLException, RuntimeException)
1510 : {
1511 : (void) catalog;
1512 : // LEM TODO: review in comparison with JDBC driver
1513 0 : Statics &statics = getStatics();
1514 :
1515 : // continue !
1516 0 : MutexGuard guard( m_refMutex->mutex );
1517 0 : checkClosed();
1518 :
1519 0 : if( isLog( m_pSettings, LogLevel::INFO ) )
1520 : {
1521 0 : rtl::OUStringBuffer buf( 128 );
1522 0 : buf.appendAscii( "DatabaseMetaData::getColumns got called with " );
1523 0 : buf.append( schemaPattern );
1524 0 : buf.appendAscii( "." );
1525 0 : buf.append( tableNamePattern );
1526 0 : buf.appendAscii( "." );
1527 0 : buf.append( columnNamePattern );
1528 0 : log( m_pSettings, LogLevel::INFO, buf.makeStringAndClear() );
1529 : }
1530 :
1531 : // ignore catalog, as a single pq connection
1532 : // does not support multiple catalogs anyway
1533 : // We don't use information_schema.columns because it contains
1534 : // only the columns the current user has any privilege over.
1535 :
1536 : // 1. TABLE_CAT string => table catalog (may be NULL)
1537 : // => not supported
1538 : // 2. TABLE_SCHEM string => table schema (may be NULL)
1539 : // => pg_namespace.nspname
1540 : // 3. TABLE_NAME string => table name
1541 : // => pg_class.relname
1542 : // 4. COLUMN_NAME string => column name
1543 : // => pg_attribure.attname
1544 : // 5. DATA_TYPE short => SQL type from java.sql.Types
1545 : // => pg_type.typname => sdbc.DataType
1546 : // 6. TYPE_NAME string => Data source dependent type name, for a UDT the
1547 : // type name is fully qualified
1548 : // => pg_type.typname
1549 : // 7. COLUMN_SIZE long => column size. For char or date types this is
1550 : // the maximum number of characters, for numeric
1551 : // or decimal types this is precision.
1552 : // => pg_attribute.atttypmod
1553 : // 8. BUFFER_LENGTH is not used.
1554 : // => not used
1555 : // 9. DECIMAL_DIGITS long => the number of fractional digits
1556 : // => don't know ! TODO !
1557 : // 10. NUM_PREC_RADIX long => Radix (typically either 10 or 2)
1558 : // => TODO ??
1559 : // 11. NULLABLE long => is NULL allowed?
1560 : // NO_NULLS - might not allow NULL values
1561 : // NULABLE - definitely allows NULL values
1562 : // NULLABLE_UNKNOWN - nullability unknown
1563 : // => pg_attribute.attnotnull
1564 : // 12. REMARKS string => comment describing column (may be NULL )
1565 : // => pg_description.description
1566 : // 13. COLUMN_DEF string => default value (may be NULL)
1567 : // => pg_type.typdefault
1568 : // 14. SQL_DATA_TYPE long => unused
1569 : // => empty
1570 : // 15. SQL_DATETIME_SUB long => unused
1571 : // => empty
1572 : // 16. CHAR_OCTET_LENGTH long => for char types the maximum number of
1573 : // bytes in the column
1574 : // => pg_type.typlen
1575 : // 17. ORDINAL_POSITION int => index of column in table (starting at 1)
1576 : // pg_attribute.attnum
1577 : // 18. IS_NULLABLE string => "NO" means column definitely does not allow
1578 : // NULL values; "YES" means the column might
1579 : // allow NULL values. An empty string means
1580 : // nobody knows.
1581 : // => pg_attribute.attnotnull
1582 :
1583 0 : Reference< XPreparedStatement > statement = m_origin->prepareStatement(
1584 : ASCII_STR(
1585 :
1586 : "SELECT pg_namespace.nspname, " // 1
1587 : "pg_class.relname, " // 2
1588 : "pg_attribute.attname, " // 3
1589 : "pg_type.typname, " // 4
1590 : "pg_attribute.atttypmod, " // 5
1591 : "pg_attribute.attnotnull, " // 6
1592 : "pg_type.typdefault, " // 7
1593 : "pg_type.typtype, " // 8
1594 : "pg_attrdef.adsrc, " // 9
1595 : "pg_description.description, " // 10
1596 : "pg_type.typbasetype, " // 11
1597 : "pg_attribute.attnum " // 12
1598 : "FROM pg_class, "
1599 : "pg_attribute LEFT JOIN pg_attrdef ON pg_attribute.attrelid = pg_attrdef.adrelid AND pg_attribute.attnum = pg_attrdef.adnum "
1600 : "LEFT JOIN pg_description ON pg_attribute.attrelid = pg_description.objoid AND pg_attribute.attnum=pg_description.objsubid,"
1601 : " pg_type, pg_namespace "
1602 : "WHERE pg_attribute.attrelid = pg_class.oid "
1603 : "AND pg_attribute.atttypid = pg_type.oid "
1604 : "AND pg_class.relnamespace = pg_namespace.oid "
1605 : "AND NOT pg_attribute.attisdropped "
1606 : "AND pg_namespace.nspname LIKE ? "
1607 : "AND pg_class.relname LIKE ? "
1608 : "AND pg_attribute.attname LIKE ? "
1609 : "ORDER BY pg_namespace.nspname, pg_class.relname, pg_attribute.attnum"
1610 0 : ) );
1611 :
1612 0 : Reference< XParameters > parameters( statement, UNO_QUERY_THROW );
1613 0 : parameters->setString( 1 , schemaPattern );
1614 0 : parameters->setString( 2 , tableNamePattern );
1615 0 : parameters->setString( 3 , columnNamePattern );
1616 :
1617 0 : Reference< XResultSet > rs = statement->executeQuery();
1618 0 : Reference< XRow > xRow( rs, UNO_QUERY_THROW );
1619 0 : SequenceAnyVector vec;
1620 :
1621 0 : Oid2DatabaseTypeDescriptionMap domainMap;
1622 0 : Reference< XStatement > domainTypeStmt = m_origin->createStatement();
1623 0 : columnMetaData2DatabaseTypeDescription( domainMap, rs, domainTypeStmt );
1624 :
1625 0 : sal_uInt32 colNum(0);
1626 0 : OUString sSchema( ASCII_STR("#invalid#") );
1627 0 : OUString sTable( ASCII_STR("#invalid#") );
1628 :
1629 0 : while( rs->next() )
1630 : {
1631 0 : if( m_pSettings->showSystemColumns || ! isSystemColumn( xRow->getShort( 12 ) ) )
1632 : {
1633 0 : OUString sNewSchema( xRow->getString(1) );
1634 0 : OUString sNewTable( xRow->getString(2) );
1635 0 : if ( sNewSchema != sSchema || sNewTable != sTable )
1636 : {
1637 0 : colNum = 1;
1638 0 : sSchema = sNewSchema;
1639 0 : sTable = sNewTable;
1640 : }
1641 : else
1642 0 : ++colNum;
1643 : sal_Int32 precision, scale, type;
1644 0 : Sequence< Any > row( 18 );
1645 0 : row[0] <<= m_pSettings->catalog;
1646 0 : row[1] <<= sNewSchema;
1647 0 : row[2] <<= sNewTable;
1648 0 : row[3] <<= xRow->getString(3);
1649 0 : if( xRow->getString(8) == "d" )
1650 : {
1651 0 : DatabaseTypeDescription desc( domainMap[xRow->getInt(11)] );
1652 0 : type = typeNameToDataType( desc.typeName, desc.typeType );
1653 : }
1654 : else
1655 : {
1656 0 : type = typeNameToDataType( xRow->getString(4), xRow->getString(8) );
1657 : }
1658 0 : extractPrecisionAndScale( type, xRow->getInt(5) , &precision, &scale );
1659 0 : row[4] <<= type;
1660 0 : row[5] <<= xRow->getString(4);
1661 0 : row[6] <<= precision;
1662 : // row[7] BUFFER_LENGTH not used
1663 0 : row[8] <<= scale;
1664 : // row[9] RADIX TODO
1665 0 : if( xRow->getBoolean( 6 ) && ! isSystemColumn(xRow->getInt( 12 )) )
1666 : {
1667 0 : row[10] <<= OUString::valueOf(com::sun::star::sdbc::ColumnValue::NO_NULLS);
1668 0 : row[17] <<= statics.NO;
1669 : }
1670 : else
1671 : {
1672 0 : row[10] <<= OUString::valueOf(com::sun::star::sdbc::ColumnValue::NULLABLE);
1673 0 : row[17] <<= statics.YES;
1674 : }
1675 :
1676 0 : row[11] <<= xRow->getString( 10 ); // comment
1677 0 : row[12] <<= xRow->getString( 9 ); // COLUMN_DEF = pg_type.typdefault
1678 : // row[13] SQL_DATA_TYPE not used
1679 : // row[14] SQL_DATETIME_SUB not used
1680 0 : row[15] <<= precision;
1681 0 : row[16] <<= colNum ;
1682 :
1683 0 : vec.push_back( row );
1684 : }
1685 : }
1686 0 : Reference< XCloseable > closeable( statement, UNO_QUERY );
1687 0 : if( closeable.is() )
1688 0 : closeable->close();
1689 :
1690 : return new SequenceResultSet(
1691 0 : m_refMutex, *this, statics.columnRowNames, sequence_of_vector(vec), m_pSettings->tc );
1692 : }
1693 :
1694 0 : ::com::sun::star::uno::Reference< XResultSet > DatabaseMetaData::getColumnPrivileges(
1695 : const ::com::sun::star::uno::Any& catalog,
1696 : const OUString& schema,
1697 : const OUString& table,
1698 : const OUString& columnNamePattern ) throw (SQLException, RuntimeException)
1699 : {
1700 : (void) catalog;
1701 :
1702 0 : MutexGuard guard( m_refMutex->mutex );
1703 0 : checkClosed();
1704 :
1705 0 : if( isLog( m_pSettings, LogLevel::INFO ) )
1706 : {
1707 0 : rtl::OUStringBuffer buf( 128 );
1708 0 : buf.appendAscii( "DatabaseMetaData::getColumnPrivileges got called with " );
1709 0 : buf.append( schema );
1710 0 : buf.appendAscii( "." );
1711 0 : buf.append( table );
1712 0 : buf.appendAscii( "." );
1713 0 : buf.append( columnNamePattern );
1714 0 : log( m_pSettings, LogLevel::INFO, buf.makeStringAndClear() );
1715 : }
1716 :
1717 0 : Reference< XParameters > parameters( m_getColumnPrivs_stmt, UNO_QUERY_THROW );
1718 0 : parameters->setString( 1 , schema );
1719 0 : parameters->setString( 2 , table );
1720 0 : parameters->setString( 3 , columnNamePattern );
1721 :
1722 0 : Reference< XResultSet > rs = m_getColumnPrivs_stmt->executeQuery();
1723 :
1724 0 : return rs;
1725 : }
1726 :
1727 0 : ::com::sun::star::uno::Reference< XResultSet > DatabaseMetaData::getTablePrivileges(
1728 : const ::com::sun::star::uno::Any& catalog,
1729 : const OUString& schemaPattern,
1730 : const OUString& tableNamePattern ) throw (SQLException, RuntimeException)
1731 : {
1732 : (void) catalog;
1733 0 : MutexGuard guard( m_refMutex->mutex );
1734 0 : checkClosed();
1735 :
1736 0 : if( isLog( m_pSettings, LogLevel::INFO ) )
1737 : {
1738 0 : rtl::OUStringBuffer buf( 128 );
1739 0 : buf.appendAscii( "DatabaseMetaData::getTablePrivileges got called with " );
1740 0 : buf.append( schemaPattern );
1741 0 : buf.appendAscii( "." );
1742 0 : buf.append( tableNamePattern );
1743 0 : log( m_pSettings, LogLevel::INFO, buf.makeStringAndClear() );
1744 : }
1745 :
1746 0 : Reference< XParameters > parameters( m_getTablePrivs_stmt, UNO_QUERY_THROW );
1747 0 : parameters->setString( 1 , schemaPattern );
1748 0 : parameters->setString( 2 , tableNamePattern );
1749 :
1750 0 : Reference< XResultSet > rs = m_getTablePrivs_stmt->executeQuery();
1751 :
1752 0 : return rs;
1753 : }
1754 :
1755 0 : ::com::sun::star::uno::Reference< XResultSet > DatabaseMetaData::getBestRowIdentifier(
1756 : const ::com::sun::star::uno::Any& catalog,
1757 : const OUString& schema,
1758 : const OUString& table,
1759 : sal_Int32 scope,
1760 : sal_Bool nullable ) throw (SQLException, RuntimeException)
1761 : {
1762 : (void) catalog; (void) schema; (void) table; (void) scope; (void) nullable;
1763 : //LEM TODO: implement! See JDBC driver
1764 0 : MutexGuard guard( m_refMutex->mutex );
1765 0 : checkClosed();
1766 : return new SequenceResultSet(
1767 0 : m_refMutex, *this, Sequence< OUString >(), Sequence< Sequence< Any > > (), m_pSettings->tc );
1768 : }
1769 :
1770 0 : ::com::sun::star::uno::Reference< XResultSet > DatabaseMetaData::getVersionColumns(
1771 : const ::com::sun::star::uno::Any& catalog,
1772 : const OUString& schema,
1773 : const OUString& table ) throw (SQLException, RuntimeException)
1774 : {
1775 : (void) catalog; (void) schema; (void) table;
1776 : //LEM TODO: implement! See JDBC driver
1777 0 : MutexGuard guard( m_refMutex->mutex );
1778 0 : checkClosed();
1779 : return new SequenceResultSet(
1780 0 : m_refMutex, *this, Sequence< OUString >(), Sequence< Sequence< Any > > (), m_pSettings->tc );
1781 : }
1782 :
1783 0 : ::com::sun::star::uno::Reference< XResultSet > DatabaseMetaData::getPrimaryKeys(
1784 : const ::com::sun::star::uno::Any& catalog,
1785 : const OUString& schema,
1786 : const OUString& table ) throw (SQLException, RuntimeException)
1787 : {
1788 : (void) catalog;
1789 : //LEM TODO: review
1790 0 : MutexGuard guard( m_refMutex->mutex );
1791 0 : checkClosed();
1792 :
1793 : // 1. TABLE_CAT string => table catalog (may be NULL )
1794 : // 2. TABLE_SCHEM string => table schema (may be NULL )
1795 : // 3. TABLE_NAME string => table name
1796 : // 4. COLUMN_NAME string => column name
1797 : // 5. KEY_SEQ short => sequence number within primary key
1798 : // 6. PK_NAME string => primary key name (may be NULL )
1799 :
1800 0 : if( isLog( m_pSettings, LogLevel::INFO ) )
1801 : {
1802 0 : rtl::OUStringBuffer buf( 128 );
1803 0 : buf.appendAscii( "DatabaseMetaData::getPrimaryKeys got called with " );
1804 0 : buf.append( schema );
1805 0 : buf.appendAscii( "." );
1806 0 : buf.append( table );
1807 0 : log( m_pSettings, LogLevel::INFO, buf.makeStringAndClear() );
1808 : }
1809 :
1810 0 : Reference< XPreparedStatement > statement = m_origin->prepareStatement(
1811 : ASCII_STR(
1812 : "SELECT nmsp.nspname, "
1813 : "cl.relname, "
1814 : "con.conkey, "
1815 : "con.conname, "
1816 : "con.conrelid "
1817 : "FROM pg_constraint as con,pg_class as cl, pg_namespace as nmsp "
1818 : "WHERE con.connamespace = nmsp.oid AND con.conrelid = cl.oid AND con.contype = 'p' "
1819 0 : "AND nmsp.nspname LIKE ? AND cl.relname LIKE ?" ) );
1820 :
1821 0 : Reference< XParameters > parameters( statement, UNO_QUERY_THROW );
1822 0 : parameters->setString( 1 , schema );
1823 0 : parameters->setString( 2 , table );
1824 :
1825 0 : Reference< XResultSet > rs = statement->executeQuery();
1826 0 : Reference< XRow > xRow( rs, UNO_QUERY_THROW );
1827 0 : SequenceAnyVector vec;
1828 :
1829 0 : while( rs->next() )
1830 : {
1831 0 : Sequence< Any > row( 6 );
1832 0 : row[0] <<= m_pSettings->catalog;
1833 0 : row[1] <<= xRow->getString(1); //
1834 0 : row[2] <<= xRow->getString(2);
1835 0 : OUString array = xRow->getString(3);
1836 0 : row[4] <<= xRow->getString(5); // the relid
1837 0 : row[5] <<= xRow->getString(4);
1838 :
1839 0 : int i = 0;
1840 : // now retrieve the columns information
1841 : // unfortunately, postgresql does not allow array of variable size in
1842 : // WHERE clauses (in the default installation), so we have to choose
1843 : // this expensive and somewhat ugly way
1844 : // annotation: postgresql shouldn't have choosen an array here, instead they
1845 : // should have multiple rows per table
1846 : // LEM: to transform an array into several rows, see unnest;
1847 : // it is as simple as "SELECT foo, bar, unnest(qux) FROM ..."
1848 : // where qux is the column that contains an array.
1849 0 : while( array[i] && '}' != array[i] )
1850 : {
1851 0 : i++;
1852 0 : int start = i;
1853 0 : while( array[i] && array[i] != '}' && array[i] != ',' ) i++;
1854 0 : row[3] <<= OUString( &array.getStr()[start], i - start );
1855 0 : vec.push_back( row );
1856 : }
1857 0 : }
1858 :
1859 : {
1860 0 : Reference< XCloseable > closeable( statement, UNO_QUERY );
1861 0 : if( closeable.is() )
1862 0 : closeable->close();
1863 : }
1864 :
1865 :
1866 0 : SequenceAnyVector::iterator ii = vec.begin();
1867 0 : OUString lastTableOid;
1868 0 : sal_Int32 index = 0;
1869 0 : Sequence< Sequence< Any > > ret( vec.size() );
1870 0 : int elements = 0;
1871 0 : for( ; ii != vec.end() ; ++ ii )
1872 : {
1873 :
1874 0 : Sequence< Any > row = *ii;
1875 0 : OUString tableOid;
1876 0 : OUString attnum;
1877 :
1878 0 : row[4] >>= tableOid;
1879 0 : row[3] >>= attnum;
1880 0 : statement = m_origin->prepareStatement(
1881 : ASCII_STR(
1882 : "SELECT att.attname FROM "
1883 : "pg_attribute AS att, pg_class AS cl WHERE "
1884 0 : "att.attrelid = ? AND att.attnum = ?" ));
1885 :
1886 0 : parameters = Reference< XParameters >( statement, UNO_QUERY_THROW );
1887 0 : parameters->setString( 1 , tableOid );
1888 0 : parameters->setString( 2 , attnum );
1889 :
1890 0 : rs = statement->executeQuery();
1891 0 : xRow = Reference< XRow >( rs, UNO_QUERY_THROW );
1892 0 : if( rs->next() )
1893 : {
1894 : // column name
1895 0 : row[3] <<= xRow->getString( 1 );
1896 0 : if( tableOid != lastTableOid )
1897 0 : index = 1;
1898 0 : lastTableOid = tableOid;
1899 0 : row[4] <<= OUString::valueOf( index );
1900 0 : index ++;
1901 : }
1902 : {
1903 0 : Reference< XCloseable > closeable( statement, UNO_QUERY );
1904 0 : if( closeable.is() )
1905 0 : closeable->close();
1906 : }
1907 0 : ret[elements] = row;
1908 0 : elements ++;
1909 0 : }
1910 : return new SequenceResultSet(
1911 0 : m_refMutex, *this, getStatics().primaryKeyNames, ret , m_pSettings->tc );
1912 : }
1913 :
1914 : // Copied / adapted / simplified from JDBC driver
1915 : #define SQL_CASE_KEYRULE " WHEN 'c' THEN " STRINGIFY(KEYRULE_CASCADE) \
1916 : " WHEN 'n' THEN " STRINGIFY(KEYRULE_SET_NULL) \
1917 : " WHEN 'd' THEN " STRINGIFY(KEYRULE_SET_DEFAULT) \
1918 : " WHEN 'r' THEN " STRINGIFY(KEYRULE_RESTRICT) \
1919 : " WHEN 'a' THEN " STRINGIFY(KEYRULE_NO_ACTION) \
1920 : " ELSE NULL "
1921 :
1922 : #define SQL_GET_REFERENCES \
1923 : "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) " \
1924 : "SELECT NULL::text AS PKTABLE_CAT, pkn.nspname AS PKTABLE_SCHEM, pkc.relname AS PKTABLE_NAME, pka.attname AS PKCOLUMN_NAME, " \
1925 : " NULL::text AS FKTABLE_CAT, fkn.nspname AS FKTABLE_SCHEM, fkc.relname AS FKTABLE_NAME, fka.attname AS FKCOLUMN_NAME, " \
1926 : " con.conkeyseq AS KEY_SEQ, " \
1927 : " CASE con.confupdtype " \
1928 : SQL_CASE_KEYRULE \
1929 : " END AS UPDATE_RULE, " \
1930 : " CASE con.confdeltype " \
1931 : SQL_CASE_KEYRULE \
1932 : " END AS DELETE_RULE, " \
1933 : " con.conname AS FK_NAME, pkic.relname AS PK_NAME, " \
1934 : " CASE " \
1935 : " WHEN con.condeferrable AND con.condeferred THEN " STRINGIFY(DEFERRABILITY_INITIALLY_DEFERRED) \
1936 : " WHEN con.condeferrable THEN " STRINGIFY(DEFERRABILITY_INITIALLY_IMMEDIATE) \
1937 : " ELSE " STRINGIFY(DEFERRABILITY_NONE) \
1938 : " END AS DEFERRABILITY " \
1939 : "FROM " \
1940 : " pg_catalog.pg_namespace pkn, pg_catalog.pg_class pkc, pg_catalog.pg_attribute pka, " \
1941 : " pg_catalog.pg_namespace fkn, pg_catalog.pg_class fkc, pg_catalog.pg_attribute fka, " \
1942 : " con, pg_catalog.pg_depend dep, pg_catalog.pg_class pkic " \
1943 : "WHERE pkn.oid = pkc.relnamespace AND pkc.oid = pka.attrelid AND pka.attnum = con.confkey AND con.confrelid = pkc.oid " \
1944 : " AND fkn.oid = fkc.relnamespace AND fkc.oid = fka.attrelid AND fka.attnum = con.conkey AND con.conrelid = fkc.oid " \
1945 : " 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 "
1946 :
1947 : #define SQL_GET_REFERENCES_PSCHEMA " AND pkn.nspname = ? "
1948 : #define SQL_GET_REFERENCES_PTABLE " AND pkc.relname = ? "
1949 : #define SQL_GET_REFERENCES_FSCHEMA " AND fkn.nspname = ? "
1950 : #define SQL_GET_REFERENCES_FTABLE " AND fkc.relname = ? "
1951 : #define SQL_GET_REFERENCES_ORDER_SOME_PTABLE "ORDER BY fkn.nspname, fkc.relname, conkeyseq"
1952 : #define SQL_GET_REFERENCES_ORDER_NO_PTABLE "ORDER BY pkn.nspname, pkc.relname, conkeyseq"
1953 :
1954 : #define SQL_GET_REFERENCES_NONE_NONE_NONE_NONE \
1955 : SQL_GET_REFERENCES \
1956 : SQL_GET_REFERENCES_ORDER_NO_PTABLE
1957 :
1958 : #define SQL_GET_REFERENCES_SOME_NONE_NONE_NONE \
1959 : SQL_GET_REFERENCES \
1960 : SQL_GET_REFERENCES_PSCHEMA \
1961 : SQL_GET_REFERENCES_ORDER_NO_PTABLE
1962 :
1963 : #define SQL_GET_REFERENCES_NONE_SOME_NONE_NONE \
1964 : SQL_GET_REFERENCES \
1965 : SQL_GET_REFERENCES_PTABLE \
1966 : SQL_GET_REFERENCES_ORDER_SOME_PTABLE
1967 :
1968 : #define SQL_GET_REFERENCES_SOME_SOME_NONE_NONE \
1969 : SQL_GET_REFERENCES \
1970 : SQL_GET_REFERENCES_PSCHEMA \
1971 : SQL_GET_REFERENCES_PTABLE \
1972 : SQL_GET_REFERENCES_ORDER_SOME_PTABLE
1973 :
1974 : #define SQL_GET_REFERENCES_NONE_NONE_SOME_NONE \
1975 : SQL_GET_REFERENCES \
1976 : SQL_GET_REFERENCES_FSCHEMA \
1977 : SQL_GET_REFERENCES_ORDER_NO_PTABLE
1978 :
1979 : #define SQL_GET_REFERENCES_NONE_NONE_NONE_SOME \
1980 : SQL_GET_REFERENCES \
1981 : SQL_GET_REFERENCES_FTABLE \
1982 : SQL_GET_REFERENCES_ORDER_NO_PTABLE
1983 :
1984 : #define SQL_GET_REFERENCES_NONE_NONE_SOME_SOME \
1985 : SQL_GET_REFERENCES \
1986 : SQL_GET_REFERENCES_FSCHEMA \
1987 : SQL_GET_REFERENCES_FTABLE \
1988 : SQL_GET_REFERENCES_ORDER_NO_PTABLE
1989 :
1990 : #define SQL_GET_REFERENCES_SOME_NONE_SOME_NONE \
1991 : SQL_GET_REFERENCES \
1992 : SQL_GET_REFERENCES_PSCHEMA \
1993 : SQL_GET_REFERENCES_FSCHEMA \
1994 : SQL_GET_REFERENCES_ORDER_NO_PTABLE
1995 :
1996 : #define SQL_GET_REFERENCES_SOME_NONE_NONE_SOME \
1997 : SQL_GET_REFERENCES \
1998 : SQL_GET_REFERENCES_PSCHEMA \
1999 : SQL_GET_REFERENCES_FTABLE \
2000 : SQL_GET_REFERENCES_ORDER_NO_PTABLE
2001 :
2002 : #define SQL_GET_REFERENCES_SOME_NONE_SOME_SOME \
2003 : SQL_GET_REFERENCES \
2004 : SQL_GET_REFERENCES_PSCHEMA \
2005 : SQL_GET_REFERENCES_FSCHEMA \
2006 : SQL_GET_REFERENCES_FTABLE \
2007 : SQL_GET_REFERENCES_ORDER_NO_PTABLE
2008 :
2009 : #define SQL_GET_REFERENCES_NONE_SOME_SOME_NONE \
2010 : SQL_GET_REFERENCES \
2011 : SQL_GET_REFERENCES_PTABLE \
2012 : SQL_GET_REFERENCES_FSCHEMA \
2013 : SQL_GET_REFERENCES_ORDER_SOME_PTABLE
2014 :
2015 : #define SQL_GET_REFERENCES_NONE_SOME_NONE_SOME \
2016 : SQL_GET_REFERENCES \
2017 : SQL_GET_REFERENCES_PTABLE \
2018 : SQL_GET_REFERENCES_FTABLE \
2019 : SQL_GET_REFERENCES_ORDER_SOME_PTABLE
2020 :
2021 : #define SQL_GET_REFERENCES_NONE_SOME_SOME_SOME \
2022 : SQL_GET_REFERENCES \
2023 : SQL_GET_REFERENCES_PTABLE \
2024 : SQL_GET_REFERENCES_FSCHEMA \
2025 : SQL_GET_REFERENCES_FTABLE \
2026 : SQL_GET_REFERENCES_ORDER_SOME_PTABLE
2027 :
2028 : #define SQL_GET_REFERENCES_SOME_SOME_SOME_NONE \
2029 : SQL_GET_REFERENCES \
2030 : SQL_GET_REFERENCES_PSCHEMA \
2031 : SQL_GET_REFERENCES_PTABLE \
2032 : SQL_GET_REFERENCES_FSCHEMA \
2033 : SQL_GET_REFERENCES_ORDER_SOME_PTABLE
2034 :
2035 : #define SQL_GET_REFERENCES_SOME_SOME_NONE_SOME \
2036 : SQL_GET_REFERENCES \
2037 : SQL_GET_REFERENCES_PSCHEMA \
2038 : SQL_GET_REFERENCES_PTABLE \
2039 : SQL_GET_REFERENCES_FTABLE \
2040 : SQL_GET_REFERENCES_ORDER_SOME_PTABLE
2041 :
2042 : #define SQL_GET_REFERENCES_SOME_SOME_SOME_SOME \
2043 : SQL_GET_REFERENCES \
2044 : SQL_GET_REFERENCES_PSCHEMA \
2045 : SQL_GET_REFERENCES_PTABLE \
2046 : SQL_GET_REFERENCES_FSCHEMA \
2047 : SQL_GET_REFERENCES_FTABLE \
2048 : SQL_GET_REFERENCES_ORDER_SOME_PTABLE
2049 :
2050 0 : void DatabaseMetaData::init_getReferences_stmt ()
2051 : {
2052 0 : m_getReferences_stmt[0] = m_origin->prepareStatement(ASCII_STR( SQL_GET_REFERENCES_NONE_NONE_NONE_NONE ));
2053 0 : m_getReferences_stmt[1] = m_origin->prepareStatement(ASCII_STR( SQL_GET_REFERENCES_SOME_NONE_NONE_NONE ));
2054 0 : m_getReferences_stmt[2] = m_origin->prepareStatement(ASCII_STR( SQL_GET_REFERENCES_NONE_SOME_NONE_NONE ));
2055 0 : m_getReferences_stmt[3] = m_origin->prepareStatement(ASCII_STR( SQL_GET_REFERENCES_SOME_SOME_NONE_NONE ));
2056 0 : m_getReferences_stmt[4] = m_origin->prepareStatement(ASCII_STR( SQL_GET_REFERENCES_NONE_NONE_SOME_NONE ));
2057 0 : m_getReferences_stmt[5] = m_origin->prepareStatement(ASCII_STR( SQL_GET_REFERENCES_SOME_NONE_SOME_NONE ));
2058 0 : m_getReferences_stmt[6] = m_origin->prepareStatement(ASCII_STR( SQL_GET_REFERENCES_NONE_SOME_SOME_NONE ));
2059 0 : m_getReferences_stmt[7] = m_origin->prepareStatement(ASCII_STR( SQL_GET_REFERENCES_SOME_SOME_SOME_NONE ));
2060 0 : m_getReferences_stmt[8] = m_origin->prepareStatement(ASCII_STR( SQL_GET_REFERENCES_NONE_NONE_NONE_SOME ));
2061 0 : m_getReferences_stmt[9] = m_origin->prepareStatement(ASCII_STR( SQL_GET_REFERENCES_SOME_NONE_NONE_SOME ));
2062 0 : m_getReferences_stmt[10] = m_origin->prepareStatement(ASCII_STR( SQL_GET_REFERENCES_NONE_SOME_NONE_SOME ));
2063 0 : m_getReferences_stmt[11] = m_origin->prepareStatement(ASCII_STR( SQL_GET_REFERENCES_SOME_SOME_NONE_SOME ));
2064 0 : m_getReferences_stmt[12] = m_origin->prepareStatement(ASCII_STR( SQL_GET_REFERENCES_NONE_NONE_SOME_SOME ));
2065 0 : m_getReferences_stmt[13] = m_origin->prepareStatement(ASCII_STR( SQL_GET_REFERENCES_SOME_NONE_SOME_SOME ));
2066 0 : m_getReferences_stmt[14] = m_origin->prepareStatement(ASCII_STR( SQL_GET_REFERENCES_NONE_SOME_SOME_SOME ));
2067 0 : m_getReferences_stmt[15] = m_origin->prepareStatement(ASCII_STR( SQL_GET_REFERENCES_SOME_SOME_SOME_SOME ));
2068 0 : }
2069 :
2070 0 : void DatabaseMetaData::init_getPrivs_stmt ()
2071 : {
2072 0 : rtl::OUStringBuffer sSQL(300);
2073 : sSQL.append( ASCII_STR(
2074 : " SELECT dp.TABLE_CAT, dp.TABLE_SCHEM, dp.TABLE_NAME, dp.GRANTOR, pr.rolname AS GRANTEE, dp.privilege, dp.is_grantable "
2075 : " FROM ("
2076 : " SELECT table_catalog AS TABLE_CAT, table_schema AS TABLE_SCHEM, table_name,"
2077 : " grantor, grantee, privilege_type AS PRIVILEGE, is_grantable"
2078 0 : " FROM information_schema.table_privileges") );
2079 0 : if ( PQserverVersion( m_pSettings->pConnection ) < 90200 )
2080 : // information_schema.table_privileges does not fill in default ACLs when no ACL
2081 : // assume default ACL is "owner has all privileges" and add it
2082 : sSQL.append( ASCII_STR(
2083 : " UNION "
2084 : " SELECT current_database() AS TABLE_CAT, pn.nspname AS TABLE_SCHEM, c.relname AS TABLE_NAME,"
2085 : " ro.rolname AS GRANTOR, rg.rolname AS GRANTEE, p.privilege, 'YES' AS is_grantable"
2086 : " FROM pg_catalog.pg_class c,"
2087 : " (VALUES ('SELECT'), ('INSERT'), ('UPDATE'), ('DELETE'), ('TRUNCATE'), ('REFERENCES'), ('TRIGGER')) p (privilege),"
2088 : " pg_catalog.pg_roles ro,"
2089 : " ( SELECT oid, rolname FROM pg_catalog.pg_roles"
2090 : " UNION ALL"
2091 : " VALUES (0::oid, 'PUBLIC')"
2092 : " ) AS rg (oid, rolname),"
2093 : " pg_catalog.pg_namespace pn"
2094 : " WHERE c.relkind IN ('r', 'v') AND c.relacl IS NULL AND pg_has_role(rg.oid, c.relowner, 'USAGE')"
2095 0 : " AND c.relowner=ro.oid AND c.relnamespace = pn.oid") );
2096 : sSQL.append( ASCII_STR(
2097 : " ) dp,"
2098 : " (SELECT oid, rolname FROM pg_catalog.pg_roles UNION ALL VALUES (0, 'PUBLIC')) pr"
2099 : " WHERE table_schem LIKE ? AND table_name LIKE ? AND (dp.grantee = 'PUBLIC' OR pg_has_role(pr.oid, dp.grantee, 'USAGE'))"
2100 0 : " ORDER BY table_schem, table_name, privilege" ) );
2101 :
2102 0 : m_getTablePrivs_stmt = m_origin->prepareStatement( sSQL.makeStringAndClear() );
2103 :
2104 : sSQL.append( ASCII_STR(
2105 : " 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 ("
2106 : " SELECT table_catalog AS TABLE_CAT, table_schema AS TABLE_SCHEM, table_name, column_name,"
2107 : " grantor, grantee, privilege_type AS PRIVILEGE, is_grantable"
2108 0 : " FROM information_schema.column_privileges") );
2109 0 : if ( PQserverVersion( m_pSettings->pConnection ) < 90200 )
2110 : // information_schema.table_privileges does not fill in default ACLs when no ACL
2111 : // assume default ACL is "owner has all privileges" and add it
2112 : sSQL.append( ASCII_STR(
2113 : " UNION "
2114 : " SELECT current_database() AS TABLE_CAT, pn.nspname AS TABLE_SCHEM, c.relname AS TABLE_NAME, a.attname AS column_name,"
2115 : " ro.rolname AS GRANTOR, rg.rolname AS GRANTEE, p.privilege, 'YES' AS is_grantable"
2116 : " FROM pg_catalog.pg_class c, pg_catalog.pg_attribute a,"
2117 : " (VALUES ('SELECT'), ('INSERT'), ('UPDATE'), ('REFERENCES')) p (privilege),"
2118 : " pg_catalog.pg_roles ro,"
2119 : " ( SELECT oid, rolname FROM pg_catalog.pg_roles"
2120 : " UNION ALL"
2121 : " VALUES (0::oid, 'PUBLIC')"
2122 : " ) AS rg (oid, rolname),"
2123 : " pg_catalog.pg_namespace pn"
2124 : " WHERE c.relkind IN ('r', 'v') AND c.relacl IS NULL AND pg_has_role(rg.oid, c.relowner, 'USAGE')"
2125 0 : " AND c.relowner=ro.oid AND c.relnamespace = pn.oid AND a.attrelid = c.oid AND a.attnum > 0") );
2126 : sSQL.append( ASCII_STR(
2127 : " ) dp,"
2128 : " (SELECT oid, rolname FROM pg_catalog.pg_roles UNION ALL VALUES (0, 'PUBLIC')) pr"
2129 : " WHERE table_schem = ? AND table_name = ? AND column_name LIKE ? AND (dp.grantee = 'PUBLIC' OR pg_has_role(pr.oid, dp.grantee, 'USAGE'))"
2130 0 : " ORDER BY column_name, privilege" ) );
2131 :
2132 0 : m_getColumnPrivs_stmt = m_origin->prepareStatement( sSQL.makeStringAndClear() );
2133 0 : }
2134 :
2135 0 : ::com::sun::star::uno::Reference< XResultSet > DatabaseMetaData::getImportedExportedKeys(
2136 : const Any& /* primaryCatalog */,
2137 : const OUString& primarySchema,
2138 : const OUString& primaryTable,
2139 : const Any& /* foreignCatalog */,
2140 : const OUString& foreignSchema,
2141 : const OUString& foreignTable ) throw (SQLException, RuntimeException)
2142 : {
2143 0 : unsigned int i = 0;
2144 0 : if ( ! primarySchema.isEmpty() )
2145 0 : i |= 0x01;
2146 0 : if ( ! primaryTable.isEmpty() )
2147 0 : i |= 0x02;
2148 0 : if ( ! foreignSchema.isEmpty() )
2149 0 : i |= 0x04;
2150 0 : if ( ! foreignTable.isEmpty() )
2151 0 : i |= 0x08;
2152 :
2153 0 : Reference< XPreparedStatement > stmt = m_getReferences_stmt[i];
2154 0 : Reference< XParameters > param ( stmt, UNO_QUERY_THROW );
2155 :
2156 0 : unsigned int j = 1;
2157 0 : if ( i & 0x01 )
2158 0 : param->setString( j++, primarySchema );
2159 0 : if ( i & 0x02 )
2160 0 : param->setString( j++, primaryTable );
2161 0 : if ( i & 0x04 )
2162 0 : param->setString( j++, foreignSchema );
2163 0 : if ( i & 0x08 )
2164 0 : param->setString( j++, foreignTable );
2165 :
2166 0 : Reference< XResultSet > rs = stmt->executeQuery();
2167 :
2168 0 : return rs;
2169 : }
2170 :
2171 :
2172 0 : ::com::sun::star::uno::Reference< XResultSet > DatabaseMetaData::getImportedKeys(
2173 : const ::com::sun::star::uno::Any& catalog,
2174 : const OUString& schema,
2175 : const OUString& table ) throw (SQLException, RuntimeException)
2176 : {
2177 0 : return getImportedExportedKeys(Any(), OUString(), OUString(), catalog, schema, table);
2178 : }
2179 :
2180 0 : ::com::sun::star::uno::Reference< XResultSet > DatabaseMetaData::getExportedKeys(
2181 : const ::com::sun::star::uno::Any& catalog,
2182 : const OUString& schema,
2183 : const OUString& table ) throw (SQLException, RuntimeException)
2184 : {
2185 0 : return getImportedExportedKeys(catalog, schema, table, Any(), OUString(), OUString());
2186 : }
2187 :
2188 0 : ::com::sun::star::uno::Reference< XResultSet > DatabaseMetaData::getCrossReference(
2189 : const ::com::sun::star::uno::Any& primaryCatalog,
2190 : const OUString& primarySchema,
2191 : const OUString& primaryTable,
2192 : const ::com::sun::star::uno::Any& foreignCatalog,
2193 : const OUString& foreignSchema,
2194 : const OUString& foreignTable ) throw (SQLException, RuntimeException)
2195 : {
2196 0 : return getImportedExportedKeys( primaryCatalog, primarySchema, primaryTable, foreignCatalog, foreignSchema, foreignTable );
2197 : }
2198 :
2199 :
2200 : struct TypeInfoByDataTypeSorter
2201 : {
2202 0 : bool operator () ( const Sequence< Any > & a, const Sequence< Any > & b )
2203 : {
2204 0 : OUString valueA;
2205 0 : OUString valueB;
2206 0 : a[1 /*DATA_TYPE*/] >>= valueA;
2207 0 : b[1 /*DATA_TYPE*/] >>= valueB;
2208 0 : if( valueB.toInt32() == valueA.toInt32() )
2209 : {
2210 0 : OUString nameA;
2211 0 : OUString nameB;
2212 0 : a[0 /*TYPE_NAME*/] >>= nameA;
2213 0 : b[0 /*TYPE_NAME*/] >>= nameB;
2214 0 : if( nameA.compareToAscii( RTL_CONSTASCII_STRINGPARAM( "int4" ) ) == 0 )
2215 0 : return 1;
2216 0 : if( nameB.compareToAscii( RTL_CONSTASCII_STRINGPARAM( "int4" ) ) == 0 )
2217 0 : return 0;
2218 0 : return nameA.compareTo( nameB ) < 0;
2219 : }
2220 :
2221 0 : return valueA.toInt32() < valueB.toInt32();
2222 : // sal_Int32 valueA;
2223 : // sal_Int32 valueB;
2224 : // a[1 /*DATA_TYPE*/] >>= valueA;
2225 : // b[1 /*DATA_TYPE*/] >>= valueB;
2226 : // if( valueB == valueA )
2227 : // {
2228 : // OUString nameA;
2229 : // OUString nameB;
2230 : // a[0 /*TYPE_NAME*/] >>= nameA;
2231 : // b[0 /*TYPE_NAME*/] >>= nameB;
2232 : // return nameA.compareTo( nameB ) < 0;
2233 : // }
2234 :
2235 : // return valueA < valueB;
2236 : }
2237 : };
2238 :
2239 0 : static sal_Int32 calcSearchable( sal_Int32 dataType )
2240 : {
2241 0 : sal_Int32 ret = com::sun::star::sdbc::ColumnSearch::FULL;
2242 0 : if( com::sun::star::sdbc::DataType::BINARY == dataType ||
2243 : com::sun::star::sdbc::DataType::VARBINARY == dataType ||
2244 : com::sun::star::sdbc::DataType::LONGVARBINARY == dataType )
2245 0 : ret = com::sun::star::sdbc::ColumnSearch::NONE;
2246 :
2247 0 : return ret;
2248 : }
2249 :
2250 0 : static sal_Int32 getMaxScale( sal_Int32 dataType )
2251 : {
2252 : // LEM TODO: review, see where used, see JDBC, ...
2253 0 : sal_Int32 ret = 0;
2254 0 : if( dataType == com::sun::star::sdbc::DataType::NUMERIC )
2255 0 : ret = 1000; // see pg-docs DataType/numeric
2256 : // else if( dataType == DataType::DOUBLE )
2257 : // ret = 308;
2258 : // else if( dataType == DataType::FLOAT )
2259 : // ret =
2260 0 : return ret;
2261 : }
2262 :
2263 :
2264 : struct RawType
2265 : {
2266 : const char * typeName;
2267 : const char * createParam;
2268 : sal_Int32 sdbcType;
2269 : sal_Int32 precision;
2270 : sal_Int32 nullable;
2271 : bool caseSensitive;
2272 : sal_Int32 searchable;
2273 : };
2274 :
2275 0 : static void pgTypeInfo2ResultSet(
2276 : SequenceAnyVector &vec,
2277 : const Reference< XResultSet > &rs )
2278 : {
2279 : static const sal_Int32 TYPE_NAME = 0; // string Type name
2280 : static const sal_Int32 DATA_TYPE = 1; // short SQL data type from java.sql.Types
2281 : static const sal_Int32 PRECISION = 2; // long maximum precision
2282 : static const sal_Int32 CREATE_PARAMS = 5; // string => parameters used in creating the type (may be NULL )
2283 : static const sal_Int32 NULLABLE = 6; // short ==> can you use NULL for this type?
2284 : // - NO_NULLS - does not allow NULL values
2285 : // - NULLABLE - allows NULL values
2286 : // - NULLABLE_UNKNOWN - nullability unknown
2287 :
2288 : static const sal_Int32 CASE_SENSITIVE = 7; // boolean==> is it case sensitive
2289 : static const sal_Int32 SEARCHABLE = 8; // short ==>; can you use
2290 : // "WHERE" based on this type:
2291 : // - NONE - No support
2292 : // - CHAR - Only supported with WHERE .. LIKE
2293 : // - BASIC - Supported except for WHERE .. LIKE
2294 : // - FULL - Supported for all WHERE ..
2295 : static const sal_Int32 UNSIGNED_ATTRIBUTE = 9; // boolean ==> is it unsigned?
2296 : static const sal_Int32 FIXED_PREC_SCALE = 10; // boolean ==> can it be a money value?
2297 : static const sal_Int32 AUTO_INCREMENT = 11; // boolean ==> can it be used for
2298 : // an auto-increment value?
2299 : static const sal_Int32 MINIMUM_SCALE = 13; // short ==> minimum scale supported
2300 : static const sal_Int32 MAXIMUM_SCALE = 14; // short ==> maximum scale supported
2301 : static const sal_Int32 NUM_PREC_RADIX = 17; // long ==> usually 2 or 10
2302 :
2303 : /* not filled so far
2304 : 3. LITERAL_PREFIX string ==> prefix used to quote a literal
2305 : (may be <NULL/>)
2306 : 4, LITERAL_SUFFIX string ==> suffix used to quote a literal
2307 : (may be <NULL/>)
2308 : 5. CREATE_PARAMS string ==> parameters used in creating thw type (may be <NULL/>)
2309 : 12. LOCAL_TYPE_NAME string ==> localized version of type name (may be <NULL/>)
2310 : 15, SQL_DATA_TYPE long ==> unused
2311 : 16. SQL_DATETIME_SUB long ==> unused
2312 : */
2313 0 : Reference< XRow > xRow( rs, UNO_QUERY_THROW );
2314 0 : while( rs->next() )
2315 : {
2316 0 : Sequence< Any > row(18);
2317 :
2318 0 : sal_Int32 dataType =typeNameToDataType(xRow->getString(5),xRow->getString(2));
2319 0 : sal_Int32 precision = xRow->getString(3).toInt32();
2320 :
2321 0 : if( dataType == com::sun::star::sdbc::DataType::CHAR ||
2322 : ( dataType == com::sun::star::sdbc::DataType::VARCHAR &&
2323 0 : xRow->getString(TYPE_NAME+1).equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("varchar")) ) )
2324 : {
2325 : // reflect varchar as varchar with upper limit !
2326 : //NOTE: the sql spec requires varchar to have an upper limit, however
2327 : // in postgresql the upper limit is optional, no limit means unlimited
2328 : // length (=1GB).
2329 0 : precision = 0x40000000; // about 1 GB, see character type docs in postgresql
2330 0 : row[CREATE_PARAMS] <<= ASCII_STR( "length" );
2331 : }
2332 0 : else if( dataType == com::sun::star::sdbc::DataType::NUMERIC )
2333 : {
2334 0 : precision = 1000;
2335 0 : row[CREATE_PARAMS] <<= ASCII_STR( "length, scale" );
2336 : }
2337 :
2338 0 : row[TYPE_NAME] <<= xRow->getString(1);
2339 0 : row[DATA_TYPE] <<= OUString::valueOf(dataType);
2340 0 : row[PRECISION] <<= OUString::valueOf( precision );
2341 0 : sal_Int32 nullable = xRow->getBoolean(4) ?
2342 : com::sun::star::sdbc::ColumnValue::NO_NULLS :
2343 0 : com::sun::star::sdbc::ColumnValue::NULLABLE;
2344 0 : row[NULLABLE] <<= OUString::valueOf(nullable);
2345 0 : row[CASE_SENSITIVE] <<= OUString::valueOf((sal_Int32)1);
2346 0 : row[SEARCHABLE] <<= OUString::valueOf( calcSearchable( dataType ) );
2347 0 : row[UNSIGNED_ATTRIBUTE] <<= ASCII_STR( "0" ); //
2348 0 : if( com::sun::star::sdbc::DataType::INTEGER == dataType ||
2349 : com::sun::star::sdbc::DataType::BIGINT == dataType )
2350 0 : row[AUTO_INCREMENT] <<= ASCII_STR( "1" ); // TODO
2351 : else
2352 0 : row[AUTO_INCREMENT] <<= ASCII_STR( "0" ); // TODO
2353 0 : row[MINIMUM_SCALE] <<= ASCII_STR( "0" ); // TODO: what is this ?
2354 0 : row[MAXIMUM_SCALE] <<= OUString::valueOf( getMaxScale( dataType ) );
2355 0 : row[NUM_PREC_RADIX] <<= ASCII_STR( "10" ); // TODO: what is this ?
2356 : (void)FIXED_PREC_SCALE;
2357 0 : vec.push_back( row );
2358 0 : }
2359 :
2360 0 : }
2361 :
2362 :
2363 0 : ::com::sun::star::uno::Reference< XResultSet > DatabaseMetaData::getTypeInfo( )
2364 : throw (SQLException, RuntimeException)
2365 : {
2366 : // Note: Indexes start at 0 (in the API doc, they start at 1)
2367 0 : MutexGuard guard( m_refMutex->mutex );
2368 0 : checkClosed();
2369 :
2370 0 : if( isLog( m_pSettings, LogLevel::INFO ) )
2371 : {
2372 0 : log( m_pSettings, LogLevel::INFO, "DatabaseMetaData::getTypeInfo() got called" );
2373 : }
2374 :
2375 0 : Reference< XStatement > statement = m_origin->createStatement();
2376 0 : Reference< XResultSet > rs = statement->executeQuery(
2377 : ASCII_STR(
2378 : "SELECT pg_type.typname AS typname," //1
2379 : "pg_type.typtype AS typtype," //2
2380 : "pg_type.typlen AS typlen," //3
2381 : "pg_type.typnotnull AS typnotnull," //4
2382 : "pg_type.typname AS typname " //5
2383 : "FROM pg_type "
2384 : "WHERE pg_type.typtype = 'b' "
2385 : "OR pg_type.typtype = 'p'"
2386 0 : ) );
2387 :
2388 0 : SequenceAnyVector vec;
2389 0 : pgTypeInfo2ResultSet( vec, rs );
2390 :
2391 : // check for domain types
2392 0 : rs = statement->executeQuery(
2393 : ASCII_STR(
2394 : "SELECT t1.typname as typname,"
2395 : "t2.typtype AS typtype,"
2396 : "t2.typlen AS typlen,"
2397 : "t2.typnotnull AS typnotnull,"
2398 : "t2.typname as realtypname "
2399 : "FROM pg_type as t1 LEFT JOIN pg_type AS t2 ON t1.typbasetype=t2.oid "
2400 0 : "WHERE t1.typtype = 'd'" ) );
2401 0 : pgTypeInfo2ResultSet( vec, rs );
2402 :
2403 0 : std::sort( vec.begin(), vec.end(), TypeInfoByDataTypeSorter() );
2404 :
2405 : return new SequenceResultSet(
2406 : m_refMutex,
2407 : *this,
2408 0 : getStatics().typeinfoColumnNames,
2409 : sequence_of_vector(vec),
2410 : m_pSettings->tc,
2411 0 : &( getStatics().typeInfoMetaData ));
2412 : }
2413 :
2414 :
2415 0 : static sal_Int32 seqContains( const Sequence< sal_Int32 > &seq, sal_Int32 value )
2416 : {
2417 0 : sal_Int32 ret = -1;
2418 0 : for( int i = 0; i < seq.getLength(); i ++ )
2419 : {
2420 0 : if( seq[i] == value )
2421 : {
2422 0 : ret = i;
2423 0 : break;
2424 : }
2425 : }
2426 0 : return ret;
2427 : }
2428 :
2429 0 : ::com::sun::star::uno::Reference< XResultSet > DatabaseMetaData::getIndexInfo(
2430 : const ::com::sun::star::uno::Any& catalog,
2431 : const OUString& schema,
2432 : const OUString& table,
2433 : sal_Bool unique,
2434 : sal_Bool approximate ) throw (SQLException, RuntimeException)
2435 : {
2436 : (void) catalog; (void) approximate;
2437 : //LEM TODO: review
2438 0 : MutexGuard guard( m_refMutex->mutex );
2439 0 : checkClosed();
2440 :
2441 : /*
2442 : 1. TABLE_CAT string -> table catalog (may be NULL )
2443 : 2. TABLE_SCHEM string -> table schema (may be NULL )
2444 : 3. TABLE_NAME string -> table name
2445 : 4. NON_UNIQUE boolean -> Can index values be non-unique?
2446 : false when TYPE is tableIndexStatistic
2447 : 5. INDEX_QUALIFIER string -> index catalog (may be NULL );
2448 : NULL when TYPE is tableIndexStatistic
2449 : 6. INDEX_NAME string -> index name; NULL when TYPE is tableIndexStatistic
2450 : 7. TYPE short -> index type:
2451 : * 0 - this identifies table statistics that are returned
2452 : in conjuction with a table's index descriptions
2453 : * CLUSTERED - this is a clustered index
2454 : * HASHED - this is a hashed index
2455 : * OTHER - this is some other style of index
2456 : 8. ORDINAL_POSITION short -> column sequence number within index;
2457 : zero when TYPE is tableIndexStatistic
2458 : 9. COLUMN_NAME string -> column name; NULL when TYPE is tableIndexStatistic
2459 : 10. ASC_OR_DESC string -> column sort sequence, "A"= ascending,
2460 : "D" = descending, may be NULL if sort sequence
2461 : is not supported; NULL when TYPE is tableIndexStatistic
2462 : 11. CARDINALITY long -> When TYPE is tableIndexStatistic, then this is
2463 : the number of rows in the table; otherwise, it
2464 : is the number of unique values in the index.
2465 : 12. PAGES long -> When TYPE is tableIndexStatisic then this is
2466 : the number of pages used for the table, otherwise
2467 : it is the number of pages used for the current index.
2468 : 13. FILTER_CONDITION string -> Filter condition, if any. (may be NULL )
2469 :
2470 : */
2471 : static const sal_Int32 C_SCHEMA = 1;
2472 : static const sal_Int32 C_TABLENAME = 2;
2473 : static const sal_Int32 C_INDEXNAME = 3;
2474 : static const sal_Int32 C_IS_CLUSTERED = 4;
2475 : static const sal_Int32 C_IS_UNIQUE = 5;
2476 : static const sal_Int32 C_IS_PRIMARY = 6;
2477 : static const sal_Int32 C_COLUMNS = 7;
2478 :
2479 : static const sal_Int32 R_TABLE_SCHEM = 1;
2480 : static const sal_Int32 R_TABLE_NAME = 2;
2481 : static const sal_Int32 R_NON_UNIQUE = 3;
2482 : static const sal_Int32 R_INDEX_NAME = 5;
2483 : static const sal_Int32 R_TYPE = 6;
2484 : static const sal_Int32 R_ORDINAL_POSITION = 7;
2485 : static const sal_Int32 R_COLUMN_NAME = 8;
2486 :
2487 0 : Reference< XPreparedStatement > stmt = m_origin->prepareStatement(
2488 : ASCII_STR(
2489 : "SELECT nspname, " // 1
2490 : "pg_class.relname, " // 2
2491 : "class2.relname, " // 3
2492 : "indisclustered, " // 4
2493 : "indisunique, " // 5
2494 : "indisprimary, " // 6
2495 : "indkey " // 7
2496 : "FROM pg_index INNER JOIN pg_class ON indrelid = pg_class.oid "
2497 : "INNER JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid "
2498 : "INNER JOIN pg_class as class2 ON pg_index.indexrelid = class2.oid "
2499 0 : "WHERE nspname = ? AND pg_class.relname = ?" ) );
2500 :
2501 0 : Reference< XParameters > param ( stmt, UNO_QUERY_THROW );
2502 0 : param->setString( 1, schema );
2503 0 : param->setString( 2, table );
2504 0 : Reference< XResultSet > rs = stmt->executeQuery();
2505 0 : Reference< XRow > xRow ( rs, UNO_QUERY_THROW );
2506 :
2507 0 : SequenceAnyVector vec;
2508 0 : while( rs->next() )
2509 : {
2510 0 : Sequence< sal_Int32 > columns = parseIntArray( xRow->getString(C_COLUMNS) );
2511 0 : Reference< XPreparedStatement > columnsStmt = m_origin->prepareStatement(
2512 : ASCII_STR(
2513 : "SELECT attnum, attname "
2514 : "FROM pg_attribute "
2515 : " INNER JOIN pg_class ON attrelid = pg_class.oid "
2516 : " INNER JOIN pg_namespace ON pg_class.relnamespace=pg_namespace.oid "
2517 0 : " WHERE pg_namespace.nspname=? AND pg_class.relname=?" ) );
2518 0 : Reference< XParameters > paramColumn ( columnsStmt, UNO_QUERY_THROW );
2519 0 : OUString currentSchema = xRow->getString( C_SCHEMA );
2520 0 : OUString currentTable = xRow->getString( C_TABLENAME );
2521 0 : OUString currentIndexName = xRow->getString( C_INDEXNAME );
2522 0 : sal_Bool isNonUnique = ! xRow->getBoolean( C_IS_UNIQUE );
2523 0 : sal_Bool isPrimary = xRow->getBoolean( C_IS_PRIMARY );
2524 : (void)isPrimary;
2525 0 : sal_Int32 indexType = xRow->getBoolean( C_IS_CLUSTERED ) ?
2526 : com::sun::star::sdbc::IndexType::CLUSTERED :
2527 0 : com::sun::star::sdbc::IndexType::HASHED;
2528 :
2529 0 : paramColumn->setString( C_SCHEMA, currentSchema );
2530 0 : paramColumn->setString( C_TABLENAME, currentTable );
2531 :
2532 0 : Reference< XResultSet > rsColumn = columnsStmt->executeQuery();
2533 0 : Reference< XRow > rowColumn( rsColumn, UNO_QUERY_THROW );
2534 0 : while( rsColumn->next() )
2535 : {
2536 0 : sal_Int32 pos = seqContains( columns, rowColumn->getInt( 1 ) );
2537 0 : if( pos >= 0 && ( ! isNonUnique || ! unique ) )
2538 : {
2539 0 : Sequence< Any > result( 13 );
2540 0 : result[R_TABLE_SCHEM] = makeAny(currentSchema);
2541 0 : result[R_TABLE_NAME] = makeAny(currentTable);
2542 0 : result[R_INDEX_NAME] = makeAny(currentIndexName);
2543 0 : result[R_NON_UNIQUE] =
2544 0 : Any( &isNonUnique, getBooleanCppuType() );
2545 0 : result[R_TYPE] = makeAny( indexType );
2546 0 : result[R_COLUMN_NAME] = makeAny( rowColumn->getString(2) );
2547 0 : sal_Int32 nPos = ((sal_Int32)pos+1); // MSVC++ nonsense
2548 0 : result[R_ORDINAL_POSITION] = makeAny( nPos );
2549 0 : vec.push_back( result );
2550 : }
2551 : }
2552 0 : }
2553 : return new SequenceResultSet(
2554 0 : m_refMutex, *this, getStatics().indexinfoColumnNames,
2555 : sequence_of_vector(vec),
2556 0 : m_pSettings->tc );
2557 : }
2558 :
2559 0 : sal_Bool DatabaseMetaData::supportsResultSetType( sal_Int32 setType )
2560 : throw (SQLException, RuntimeException)
2561 : {
2562 0 : if ( setType == com::sun::star::sdbc::ResultSetType::SCROLL_SENSITIVE )
2563 0 : return sal_False;
2564 : else
2565 0 : return sal_True;
2566 : }
2567 :
2568 0 : sal_Bool DatabaseMetaData::supportsResultSetConcurrency(
2569 : sal_Int32 setType, sal_Int32 concurrency ) throw (SQLException, RuntimeException)
2570 : {
2571 : (void) concurrency;
2572 0 : if ( ! supportsResultSetType( setType ) )
2573 0 : return sal_False;
2574 : else
2575 0 : return sal_True;
2576 : }
2577 :
2578 0 : sal_Bool DatabaseMetaData::ownUpdatesAreVisible( sal_Int32 /* setType */ ) throw (SQLException, RuntimeException)
2579 : {
2580 0 : return sal_True;
2581 : }
2582 :
2583 0 : sal_Bool DatabaseMetaData::ownDeletesAreVisible( sal_Int32 /* setType */ ) throw (SQLException, RuntimeException)
2584 : {
2585 0 : return sal_True;
2586 : }
2587 :
2588 0 : sal_Bool DatabaseMetaData::ownInsertsAreVisible( sal_Int32 /* setType */ ) throw (SQLException, RuntimeException)
2589 : {
2590 0 : return sal_True;
2591 : }
2592 :
2593 0 : sal_Bool DatabaseMetaData::othersUpdatesAreVisible( sal_Int32 /* setType */ ) throw (SQLException, RuntimeException)
2594 : {
2595 0 : return sal_False;
2596 : }
2597 :
2598 0 : sal_Bool DatabaseMetaData::othersDeletesAreVisible( sal_Int32 /* setType */ ) throw (SQLException, RuntimeException)
2599 : {
2600 0 : return sal_False;
2601 : }
2602 :
2603 0 : sal_Bool DatabaseMetaData::othersInsertsAreVisible( sal_Int32 /* setType */ ) throw (SQLException, RuntimeException)
2604 : {
2605 0 : return sal_False;
2606 : }
2607 :
2608 0 : sal_Bool DatabaseMetaData::updatesAreDetected( sal_Int32 /* setType */ ) throw (SQLException, RuntimeException)
2609 : {
2610 0 : return sal_False;
2611 : }
2612 :
2613 0 : sal_Bool DatabaseMetaData::deletesAreDetected( sal_Int32 /* setType */ ) throw (SQLException, RuntimeException)
2614 : {
2615 0 : return sal_False;
2616 : }
2617 0 : sal_Bool DatabaseMetaData::insertsAreDetected( sal_Int32 /* setType */ ) throw (SQLException, RuntimeException)
2618 : {
2619 0 : return sal_False;
2620 : }
2621 :
2622 0 : sal_Bool DatabaseMetaData::supportsBatchUpdates( ) throw (SQLException, RuntimeException)
2623 : {
2624 0 : return sal_True;
2625 : }
2626 :
2627 0 : ::com::sun::star::uno::Reference< XResultSet > DatabaseMetaData::getUDTs( const ::com::sun::star::uno::Any& catalog, const OUString& schemaPattern, const OUString& typeNamePattern, const ::com::sun::star::uno::Sequence< sal_Int32 >& types ) throw (SQLException, RuntimeException)
2628 : {
2629 : (void) catalog; (void) schemaPattern; (void) typeNamePattern; (void) types;
2630 : //LEM TODO: implement! See JDBC driver
2631 0 : MutexGuard guard( m_refMutex->mutex );
2632 0 : checkClosed();
2633 : return new SequenceResultSet(
2634 0 : m_refMutex, *this, Sequence< OUString >(), Sequence< Sequence< Any > > (), m_pSettings->tc );
2635 : }
2636 :
2637 0 : ::com::sun::star::uno::Reference< com::sun::star::sdbc::XConnection > DatabaseMetaData::getConnection()
2638 : throw (SQLException, RuntimeException)
2639 : {
2640 0 : return m_origin;
2641 : }
2642 : }
|