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