summaryrefslogtreecommitdiffstats
path: root/connectivity/qa/connectivity
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
commited5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch)
tree7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /connectivity/qa/connectivity
parentInitial commit. (diff)
downloadlibreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz
libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'connectivity/qa/connectivity')
-rw-r--r--connectivity/qa/connectivity/ado/DriverTest.cxx141
-rw-r--r--connectivity/qa/connectivity/ado/TS001018407.mdbbin0 -> 2789376 bytes
-rw-r--r--connectivity/qa/connectivity/commontools/FValue_test.cxx366
-rw-r--r--connectivity/qa/connectivity/mysql/mysql.cxx502
-rw-r--r--connectivity/qa/connectivity/resource/sharedresources_test.cxx106
-rw-r--r--connectivity/qa/connectivity/tools/AbstractDatabase.java207
-rw-r--r--connectivity/qa/connectivity/tools/CRMDatabase.java277
-rw-r--r--connectivity/qa/connectivity/tools/CsvDatabase.java31
-rw-r--r--connectivity/qa/connectivity/tools/DataSource.java150
-rw-r--r--connectivity/qa/connectivity/tools/DatabaseAccess.java50
-rw-r--r--connectivity/qa/connectivity/tools/DbaseDatabase.java32
-rw-r--r--connectivity/qa/connectivity/tools/FlatFileDatabase.java74
-rw-r--r--connectivity/qa/connectivity/tools/HsqlColumnDescriptor.java75
-rw-r--r--connectivity/qa/connectivity/tools/HsqlDatabase.java202
-rw-r--r--connectivity/qa/connectivity/tools/HsqlTableDescriptor.java93
-rw-r--r--connectivity/qa/connectivity/tools/QueryDefinition.java49
-rw-r--r--connectivity/qa/connectivity/tools/RowSet.java288
-rw-r--r--connectivity/qa/connectivity/tools/sdb/Connection.java80
18 files changed, 2723 insertions, 0 deletions
diff --git a/connectivity/qa/connectivity/ado/DriverTest.cxx b/connectivity/qa/connectivity/ado/DriverTest.cxx
new file mode 100644
index 000000000..abe4da67b
--- /dev/null
+++ b/connectivity/qa/connectivity/ado/DriverTest.cxx
@@ -0,0 +1,141 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <test/bootstrapfixture.hxx>
+
+#include "ado/AConnection.hxx"
+#include "ado/ADatabaseMetaData.hxx"
+#include "ado/ADriver.hxx"
+#include "ado/AStatement.hxx"
+#include "ado/ACallableStatement.hxx"
+#include "ado/APreparedStatement.hxx"
+#include "ado/ACatalog.hxx"
+#include <com/sun/star/sdbc/ColumnValue.hpp>
+#include <com/sun/star/sdbc/TransactionIsolation.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <cppuhelper/typeprovider.hxx>
+#include <connectivity/dbexception.hxx>
+#include <osl/file.hxx>
+#include "strings.hrc"
+
+
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::uno;
+
+namespace connectivity::ado {
+
+
+class AdoDriverTest: public test::BootstrapFixture
+{
+public:
+ AdoDriverTest() : test::BootstrapFixture(false, false) {};
+
+ void test_metadata();
+ void test_select_default_all();
+
+ virtual void setUp();
+ virtual void tearDown();
+
+ CPPUNIT_TEST_SUITE(AdoDriverTest);
+
+ CPPUNIT_TEST(test_metadata);
+ CPPUNIT_TEST(test_select_default_all);
+ CPPUNIT_TEST_SUITE_END();
+
+private:
+ Reference<XInterface> m_xAdoComponent;
+ Reference<XConnection> m_xConnection;
+};
+
+void AdoDriverTest::setUp()
+{
+ test::BootstrapFixture::setUp();
+ m_xAdoComponent = getMultiServiceFactory()->createInstance("com.sun.star.comp.sdbc.ado.ODriver");
+ CPPUNIT_ASSERT_MESSAGE("no ado component!", m_xAdoComponent.is());
+
+ OUString url = "sdbc:ado:access:PROVIDER=Microsoft.Jet.OLEDB.4.0;DATA SOURCE=" +
+ m_directories.getPathFromWorkdir(u"/CppunitTest/TS001018407.mdb");
+
+ Sequence< PropertyValue > info;
+ Reference< XDriver> xDriver(m_xAdoComponent, UNO_QUERY);
+ if (!xDriver.is())
+ {
+ CPPUNIT_ASSERT_MESSAGE("cannot connect to ado driver!", xDriver.is());
+ }
+
+ m_xConnection = xDriver->connect(url, info);
+ if (!m_xConnection.is())
+ {
+ CPPUNIT_ASSERT_MESSAGE("cannot connect to students data source!", m_xConnection.is());
+ }
+}
+
+void AdoDriverTest::tearDown()
+{
+ m_xAdoComponent = 0;
+ test::BootstrapFixture::tearDown();
+}
+
+void AdoDriverTest::test_metadata()
+{
+ Reference< XDatabaseMetaData > xDatabaseMetaData = m_xConnection->getMetaData();
+ if (!xDatabaseMetaData.is())
+ {
+ CPPUNIT_ASSERT_MESSAGE("cannot retrieve meta data!", xDatabaseMetaData.is());
+ }
+
+ const Any catalog;
+ static const OUStringLiteral schemaPattern = u"%";
+ static const OUStringLiteral tableNamePattern = u"%";
+ const Sequence< OUString > types;
+
+ Reference< XResultSet > xResultSet =
+ xDatabaseMetaData->getTables(catalog, schemaPattern, tableNamePattern, types);
+ if (!xResultSet.is())
+ {
+ CPPUNIT_ASSERT_MESSAGE("cannot retrieve tables!", xResultSet.is());
+ }
+}
+
+void AdoDriverTest::test_select_default_all()
+{
+ static const OUStringLiteral sql = u"select \"FirstName\" from \"Students\" ORDER BY \"FirstName\"";
+ Reference< XPreparedStatement > xStatement = m_xConnection->prepareStatement(sql);
+ if (!xStatement.is())
+ {
+ CPPUNIT_ASSERT_MESSAGE("cannot create prepared statement!", xStatement.is());
+ }
+
+ Reference< XResultSet > xResultSet = xStatement->executeQuery();
+ if (!xResultSet.is())
+ {
+ CPPUNIT_ASSERT_MESSAGE("cannot execute sql statement!", xResultSet.is());
+ }
+
+ Reference< XRow > xDelegatorRow(xResultSet, UNO_QUERY);
+ if (!xDelegatorRow.is())
+ {
+ CPPUNIT_ASSERT_MESSAGE("cannot extract row from result set!", xDelegatorRow.is());
+ }
+
+ sal_Bool result = xResultSet->first();
+ CPPUNIT_ASSERT_MESSAGE("fetch first row failed!", result);
+/*
+ OUString mail = xDelegatorRow->getString(1);
+ CPPUNIT_ASSERT_MESSAGE("first row is not john@doe.org!", mail.equalsAscii("john@doe.org"));
+*/
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(AdoDriverTest);
+
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/connectivity/qa/connectivity/ado/TS001018407.mdb b/connectivity/qa/connectivity/ado/TS001018407.mdb
new file mode 100644
index 000000000..abe9f5ee3
--- /dev/null
+++ b/connectivity/qa/connectivity/ado/TS001018407.mdb
Binary files differ
diff --git a/connectivity/qa/connectivity/commontools/FValue_test.cxx b/connectivity/qa/connectivity/commontools/FValue_test.cxx
new file mode 100644
index 000000000..b6f0e3658
--- /dev/null
+++ b/connectivity/qa/connectivity/commontools/FValue_test.cxx
@@ -0,0 +1,366 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <test/bootstrapfixture.hxx>
+
+#include <connectivity/FValue.hxx>
+#include <com/sun/star/sdbc/DataType.hpp>
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::uno;
+
+namespace connectivity::commontools {
+
+class FValueTest: public test::BootstrapFixture
+{
+public:
+ FValueTest() : test::BootstrapFixture(false, false) {};
+
+ void test_Bool();
+
+ void test_Int8();
+
+ void test_Int16();
+ void test_uInt16();
+
+ void test_Int32();
+ void test_uInt32();
+
+ void test_Int64();
+ void test_uInt64();
+
+ void test_float();
+ void test_double();
+
+ void test_bool_getString();
+ void test_bit_getString();
+
+ void test_bool_creation();
+
+ CPPUNIT_TEST_SUITE(FValueTest);
+
+ CPPUNIT_TEST(test_Bool);
+
+ CPPUNIT_TEST(test_Int8);
+
+ CPPUNIT_TEST(test_Int16);
+ CPPUNIT_TEST(test_uInt16);
+
+ CPPUNIT_TEST(test_Int32);
+ CPPUNIT_TEST(test_uInt32);
+
+ CPPUNIT_TEST(test_Int64);
+ CPPUNIT_TEST(test_uInt64);
+
+ CPPUNIT_TEST(test_float);
+ CPPUNIT_TEST(test_double);
+
+ CPPUNIT_TEST(test_bool_getString);
+ CPPUNIT_TEST(test_bit_getString);
+ CPPUNIT_TEST(test_bool_creation);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void FValueTest::test_Bool()
+{
+ bool src_Bool = true;
+ ORowSetValue v(src_Bool);
+ bool trg_Bool = v.getBool();
+
+ std::cerr << "src_Bool: " << src_Bool << std::endl;
+ std::cerr << "trg_Bool: " << trg_Bool << std::endl;
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("bool conversion to ORowSetValue didn't work", trg_Bool, src_Bool);
+
+ Any any_Bool = v.makeAny();
+ ORowSetValue t;
+ t.fill(any_Bool);
+ trg_Bool = t.getBool();
+
+ std::cerr << "trg_Bool: " << trg_Bool << std::endl;
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("bool conversion from Any didn't work", trg_Bool, src_Bool);
+}
+
+void FValueTest::test_Int8()
+{
+ sal_Int8 src_salInt8 = 127;
+ ORowSetValue v(src_salInt8);
+ sal_Int8 trg_salInt8 = v.getInt8();
+
+ std::cerr << "src_salInt8: " << static_cast<short>(src_salInt8) << std::endl;
+ std::cerr << "trg_salInt8: " << static_cast<short>(trg_salInt8) << std::endl;
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int8 conversion to ORowSetValue didn't work", trg_salInt8, src_salInt8);
+
+ Any any_Int8 = v.makeAny();
+ ORowSetValue t;
+ t.fill(any_Int8);
+ trg_salInt8 = t.getInt8();
+
+ std::cerr << "trg_salInt8: " << static_cast<short>(trg_salInt8) << std::endl;
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int8 conversion from Any didn't work", trg_salInt8, src_salInt8);
+}
+
+void FValueTest::test_Int16()
+{
+ sal_Int16 src_salInt16 = -10001;
+ ORowSetValue v(src_salInt16);
+ sal_Int16 trg_salInt16 = v.getInt16();
+
+ std::cerr << "src_salInt16: " << src_salInt16 << std::endl;
+ std::cerr << "trg_salInt16: " << trg_salInt16 << std::endl;
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int16 conversion to ORowSetValue didn't work", trg_salInt16, src_salInt16);
+
+ Any any_Int16 = v.makeAny();
+ ORowSetValue t;
+ t.fill(any_Int16);
+ trg_salInt16 = t.getInt16();
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int16 conversion from Any didn't work", trg_salInt16, src_salInt16);
+}
+
+void FValueTest::test_uInt16()
+{
+ sal_uInt16 src_saluInt16 = 10001;
+ ORowSetValue v(src_saluInt16);
+ sal_uInt16 trg_saluInt16 = v.getUInt16();
+
+ std::cerr << "src_saluInt16: " << src_saluInt16 << std::endl;
+ std::cerr << "trg_saluInt16: " << trg_saluInt16 << std::endl;
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt16 conversion to ORowSetValue didn't work", trg_saluInt16, src_saluInt16);
+
+ Any any_uInt16 = v.makeAny();
+ ORowSetValue t;
+ t.fill(any_uInt16);
+ trg_saluInt16 = t.getUInt16();
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt16 conversion from Any didn't work", trg_saluInt16, src_saluInt16);
+}
+
+void FValueTest::test_Int32()
+{
+ sal_Int32 src_salInt32 = -10000001;
+ ORowSetValue v(src_salInt32);
+ sal_Int32 trg_salInt32 = v.getInt32();
+
+ std::cerr << "src_salInt32: " << src_salInt32 << std::endl;
+ std::cerr << "trg_salInt32: " << trg_salInt32 << std::endl;
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int32 conversion to ORowSetValue didn't work", trg_salInt32, src_salInt32);
+
+ Any any_Int32 = v.makeAny();
+ ORowSetValue t;
+ t.fill(any_Int32);
+ trg_salInt32 = t.getInt32();
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int32 conversion from Any didn't work", trg_salInt32, src_salInt32);
+}
+
+void FValueTest::test_uInt32()
+{
+ sal_uInt32 src_saluInt32 = 100000001;
+ ORowSetValue v(src_saluInt32);
+ sal_uInt32 trg_saluInt32 = v.getUInt32();
+
+ std::cerr << "src_saluInt32: " << src_saluInt32 << std::endl;
+ std::cerr << "trg_saluInt32: " << trg_saluInt32 << std::endl;
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt32 conversion to ORowSetValue didn't work", trg_saluInt32, src_saluInt32);
+
+ Any any_uInt32 = v.makeAny();
+ ORowSetValue t;
+ t.fill(any_uInt32);
+ trg_saluInt32 = t.getUInt32();
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt32 conversion from Any didn't work", trg_saluInt32, src_saluInt32);
+}
+
+void FValueTest::test_Int64()
+{
+ sal_Int64 src_salInt64 = -1000000000000000001LL;
+ ORowSetValue v(src_salInt64);
+ sal_Int64 trg_salInt64 = v.getLong();
+
+ std::cerr << "src_salInt64: " << src_salInt64 << std::endl;
+ std::cerr << "trg_salInt64: " << trg_salInt64 << std::endl;
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int64 conversion to ORowSetValue didn't work", trg_salInt64, src_salInt64);
+
+ Any any_Int64 = v.makeAny();
+ ORowSetValue t;
+ t.fill(any_Int64);
+ trg_salInt64 = t.getLong();
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int64 conversion from Any didn't work", trg_salInt64, src_salInt64);
+}
+
+void FValueTest::test_uInt64()
+{
+ sal_uInt64 src_saluInt64 = 10000000000000000001ULL;
+ ORowSetValue v(src_saluInt64);
+ sal_uInt64 trg_saluInt64 = v.getULong();
+
+ std::cerr << "src_saluInt64: " << src_saluInt64 << std::endl;
+ std::cerr << "trg_saluInt64: " << trg_saluInt64 << std::endl;
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt64 conversion to ORowSetValue didn't work", trg_saluInt64, src_saluInt64);
+
+ Any any_uInt64 = v.makeAny();
+ ORowSetValue t;
+ t.fill(any_uInt64);
+ trg_saluInt64 = t.getULong();
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt64 conversion from Any didn't work", trg_saluInt64, src_saluInt64);
+}
+
+void FValueTest::test_float()
+{
+ float src_float = 1.234f;
+ ORowSetValue v(src_float);
+ float trg_float = v.getFloat();
+
+ std::cerr << "src_float: " << src_float << std::endl;
+ std::cerr << "trg_float: " << trg_float << std::endl;
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("float conversion to ORowSetValue didn't work", trg_float, src_float);
+
+ Any any_float = v.makeAny();
+ ORowSetValue t;
+ t.fill(any_float);
+ trg_float = t.getFloat();
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("float conversion from Any didn't work", trg_float, src_float);
+}
+
+void FValueTest::test_double()
+{
+ double src_double = 1.23456789;
+ ORowSetValue v(src_double);
+ double trg_double = v.getDouble();
+
+ std::cerr << "src_double: " << src_double << std::endl;
+ std::cerr << "trg_double: " << trg_double << std::endl;
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("double conversion to ORowSetValue didn't work", trg_double, src_double);
+
+ Any any_double = v.makeAny();
+ ORowSetValue t;
+ t.fill(any_double);
+ trg_double = t.getDouble();
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("double conversion from Any didn't work", trg_double, src_double);
+}
+
+void FValueTest::test_bool_getString()
+{
+ bool src_bool_1 = true;
+ ORowSetValue v_1(src_bool_1);
+ OUString trg_bool_1 = v_1.getString();
+
+ std::cerr << "src_bool_1: " << src_bool_1 << std::endl;
+ std::cerr << "trg_bool_1: " << trg_bool_1 << std::endl;
+
+ CPPUNIT_ASSERT_MESSAGE("ORowSetValue bool to string conversion didn't work", bool(trg_bool_1 == "true"));
+
+ bool src_bool_0 = false;
+ ORowSetValue v_0(src_bool_0);
+ OUString trg_bool_0 = v_0.getString();
+
+ std::cerr << "src_bool_0: " << src_bool_0 << std::endl;
+ std::cerr << "trg_bool_0: " << trg_bool_0 << std::endl;
+
+ CPPUNIT_ASSERT_MESSAGE("ORowSetValue bool to string conversion didn't work", bool(trg_bool_0 == "false"));
+}
+
+void FValueTest::test_bit_getString()
+{
+ bool src_bool_1 = true;
+ ORowSetValue v_1(src_bool_1);
+ v_1.setTypeKind(DataType::BIT);
+ OUString trg_bool_1 = v_1.getString();
+
+ std::cerr << "src_bit_1: " << src_bool_1 << std::endl;
+ std::cerr << "trg_bit_1: " << trg_bool_1 << std::endl;
+
+ CPPUNIT_ASSERT_MESSAGE("ORowSetValue bit to string conversion didn't work", bool(trg_bool_1 == "1"));
+
+ bool src_bool_0 = false;
+ ORowSetValue v_0(src_bool_0);
+ v_0.setTypeKind(DataType::BIT);
+ OUString trg_bool_0 = v_0.getString();
+
+ std::cerr << "src_bit_0: " << src_bool_0 << std::endl;
+ std::cerr << "trg_bit_0: " << trg_bool_0 << std::endl;
+
+ CPPUNIT_ASSERT_MESSAGE("ORowSetValue bit to string conversion didn't work", bool(trg_bool_0 == "0"));
+}
+
+void FValueTest::test_bool_creation()
+{
+ ORowSetValue vTrue(true);
+ ORowSetValue vFalse(false);
+
+ {
+ ORowSetValue v(OUString("1"));
+ v.setTypeKind(DataType::BOOLEAN);
+ CPPUNIT_ASSERT_MESSAGE("ORowSetValue bool creation from string didn't work", bool(v == vTrue));
+ }
+
+ {
+ ORowSetValue v(OUString("0"));
+ v.setTypeKind(DataType::BOOLEAN);
+ CPPUNIT_ASSERT_MESSAGE("ORowSetValue bool creation from string didn't work", bool(v == vFalse));
+ }
+
+ {
+ ORowSetValue v(OUString("true"));
+ v.setTypeKind(DataType::BOOLEAN);
+ CPPUNIT_ASSERT_MESSAGE("ORowSetValue bool creation from string didn't work", bool(v == vTrue));
+ }
+
+ {
+ ORowSetValue v(OUString("tRuE"));
+ v.setTypeKind(DataType::BOOLEAN);
+ CPPUNIT_ASSERT_MESSAGE("ORowSetValue bool creation from string didn't work", bool(v == vTrue));
+ }
+
+ {
+ ORowSetValue v(OUString("false"));
+ v.setTypeKind(DataType::BOOLEAN);
+ CPPUNIT_ASSERT_MESSAGE("ORowSetValue bool creation from string didn't work", bool(v == vFalse));
+ }
+
+ {
+ ORowSetValue v(OUString("0"));
+ v.setTypeKind(DataType::BOOLEAN);
+ CPPUNIT_ASSERT_MESSAGE("ORowSetValue bool creation from string didn't work", bool(v == vFalse));
+ }
+
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(FValueTest);
+
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/qa/connectivity/mysql/mysql.cxx b/connectivity/qa/connectivity/mysql/mysql.cxx
new file mode 100644
index 000000000..4b1a9a4e4
--- /dev/null
+++ b/connectivity/qa/connectivity/mysql/mysql.cxx
@@ -0,0 +1,502 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <test/bootstrapfixture.hxx>
+
+#include <com/sun/star/sdb/XOfficeDatabaseDocument.hpp>
+#include <com/sun/star/sdbc/XColumnLocate.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdbc/XResultSet.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaData.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/sdbc/XParameters.hpp>
+#include <com/sun/star/sdbc/XStatement.hpp>
+#include <com/sun/star/sdbc/XDriver.hpp>
+
+#include <com/sun/star/util/DateTime.hpp>
+#include <comphelper/propertysequence.hxx>
+#include <svtools/miscopt.hxx>
+#include <osl/process.h>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+
+class MysqlTestDriver : public test::BootstrapFixture
+{
+private:
+ OUString m_sUrl;
+ Reference<XInterface> m_xMysqlcComponent;
+ Reference<XDriver> m_xDriver;
+ Sequence<PropertyValue> m_infos;
+
+public:
+ MysqlTestDriver()
+ : test::BootstrapFixture(false, false)
+ {
+ }
+ virtual void setUp() override;
+ virtual void tearDown() override;
+ void testDBConnection();
+ void testCreateAndDropTable();
+ void testIntegerInsertAndQuery();
+ void testDBPositionChange();
+ void testMultipleResultsets();
+ void testDBMetaData();
+ void testTimestampField();
+ void testNumericConversionPrepared();
+ void testPreparedStmtIsAfterLast();
+ void testGetStringFromBloColumnb();
+
+ CPPUNIT_TEST_SUITE(MysqlTestDriver);
+ CPPUNIT_TEST(testDBConnection);
+ CPPUNIT_TEST(testCreateAndDropTable);
+ CPPUNIT_TEST(testIntegerInsertAndQuery);
+ CPPUNIT_TEST(testMultipleResultsets);
+ CPPUNIT_TEST(testDBMetaData);
+ CPPUNIT_TEST(testTimestampField);
+ CPPUNIT_TEST(testNumericConversionPrepared);
+ CPPUNIT_TEST(testPreparedStmtIsAfterLast);
+ CPPUNIT_TEST(testGetStringFromBloColumnb);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void MysqlTestDriver::tearDown()
+{
+ Reference<XConnection> xConnection = m_xDriver->connect(m_sUrl, m_infos);
+ if (!xConnection.is())
+ {
+ CPPUNIT_ASSERT_MESSAGE("cannot connect to data source!", xConnection.is());
+ }
+ uno::Reference<XStatement> xStatement = xConnection->createStatement();
+ CPPUNIT_ASSERT(xStatement.is());
+ xStatement->executeUpdate("DROP TABLE IF EXISTS myTestTable");
+ xStatement->executeUpdate("DROP TABLE IF EXISTS otherTable");
+ test::BootstrapFixture::tearDown();
+}
+
+void MysqlTestDriver::setUp()
+{
+ test::BootstrapFixture::setUp();
+
+ /* Get URL from environment variable. This test suite should run only when
+ * there is a URL given. This is because it can be used for testing connection to
+ * external databases as well.
+ *
+ * Example URL:
+ * username/password@sdbc:mysql:mysqlc:localhost:3306/testdatabase
+ */
+ osl_getEnvironment(OUString("CONNECTIVITY_TEST_MYSQL_DRIVER").pData, &m_sUrl.pData);
+ m_xMysqlcComponent
+ = getMultiServiceFactory()->createInstance("com.sun.star.comp.sdbc.mysqlc.MysqlCDriver");
+ CPPUNIT_ASSERT_MESSAGE("no mysqlc component!", m_xMysqlcComponent.is());
+
+ // set user name and password
+ sal_Int32 nPer = m_sUrl.indexOf("/");
+ OUString sUsername = m_sUrl.copy(0, nPer);
+ m_sUrl = m_sUrl.copy(nPer + 1);
+ sal_Int32 nAt = m_sUrl.indexOf("@");
+ OUString sPassword = m_sUrl.copy(0, nAt);
+ m_sUrl = m_sUrl.copy(nAt + 1);
+
+ m_infos = comphelper::InitPropertySequence(
+ { { "user", makeAny(sUsername) }, { "password", makeAny(sPassword) } });
+
+ m_xDriver.set(m_xMysqlcComponent, UNO_QUERY);
+ if (!m_xDriver.is())
+ {
+ CPPUNIT_ASSERT_MESSAGE("cannot connect to mysqlc driver!", m_xDriver.is());
+ }
+}
+
+/**
+ * Test database connection. It is assumed that the given URL is correct and
+ * there is a server running at the location.
+ */
+void MysqlTestDriver::testDBConnection()
+{
+ Reference<XConnection> xConnection = m_xDriver->connect(m_sUrl, m_infos);
+ if (!xConnection.is())
+ {
+ CPPUNIT_ASSERT_MESSAGE("cannot connect to data source!", xConnection.is());
+ }
+
+ uno::Reference<XStatement> xStatement = xConnection->createStatement();
+ CPPUNIT_ASSERT(xStatement.is());
+
+ Reference<XResultSet> xResultSet = xStatement->executeQuery("SELECT 1");
+ CPPUNIT_ASSERT(xResultSet.is());
+ Reference<XRow> xRow(xResultSet, UNO_QUERY);
+ CPPUNIT_ASSERT_MESSAGE("cannot extract row from result set!", xRow.is());
+
+ sal_Bool result = xResultSet->first();
+ CPPUNIT_ASSERT_MESSAGE("fetch first row failed!", result);
+}
+
+/**
+ * Test creation and removal of a table
+ */
+void MysqlTestDriver::testCreateAndDropTable()
+{
+ Reference<XConnection> xConnection = m_xDriver->connect(m_sUrl, m_infos);
+ if (!xConnection.is())
+ {
+ CPPUNIT_ASSERT_MESSAGE("cannot connect to data source!", xConnection.is());
+ }
+
+ uno::Reference<XStatement> xStatement = xConnection->createStatement();
+ CPPUNIT_ASSERT(xStatement.is());
+ xStatement->executeUpdate("DROP TABLE IF EXISTS myTestTable");
+
+ auto nUpdateCount
+ = xStatement->executeUpdate("CREATE TABLE myTestTable (id INTEGER PRIMARY KEY)");
+ CPPUNIT_ASSERT_EQUAL(0, nUpdateCount); // it's a DDL statement
+
+ // we can use the same xStatement instance here
+ nUpdateCount = xStatement->executeUpdate("DROP TABLE myTestTable");
+ CPPUNIT_ASSERT_EQUAL(0, nUpdateCount); // it's a DDL statement
+}
+
+void MysqlTestDriver::testIntegerInsertAndQuery()
+{
+ Reference<XConnection> xConnection = m_xDriver->connect(m_sUrl, m_infos);
+ if (!xConnection.is())
+ {
+ CPPUNIT_ASSERT_MESSAGE("cannot connect to data source!", xConnection.is());
+ }
+
+ Reference<XStatement> xStatement = xConnection->createStatement();
+ CPPUNIT_ASSERT(xStatement.is());
+ xStatement->executeUpdate("DROP TABLE IF EXISTS myTestTable");
+
+ auto nUpdateCount
+ = xStatement->executeUpdate("CREATE TABLE myTestTable (id INTEGER PRIMARY KEY)");
+ CPPUNIT_ASSERT_EQUAL(0, nUpdateCount); // it's a DDL statement
+
+ Reference<XPreparedStatement> xPrepared
+ = xConnection->prepareStatement(OUString{ "INSERT INTO myTestTable VALUES (?)" });
+ Reference<XParameters> xParams(xPrepared, UNO_QUERY);
+ constexpr int ROW_COUNT = 3;
+ for (int i = 0; i < ROW_COUNT; ++i)
+ {
+ xParams->setLong(1, i); // first and only column
+ nUpdateCount = xPrepared->executeUpdate();
+ CPPUNIT_ASSERT_EQUAL(1, nUpdateCount); // one row is inserted at a time
+ }
+
+ // now let's query the existing data
+ Reference<XResultSet> xResultSet = xStatement->executeQuery("SELECT id from myTestTable");
+ CPPUNIT_ASSERT_MESSAGE("result set cannot be instantiated after query", xResultSet.is());
+ Reference<XRow> xRow(xResultSet, UNO_QUERY);
+ Reference<XColumnLocate> xColumnLocate(xResultSet, UNO_QUERY);
+ CPPUNIT_ASSERT_MESSAGE("cannot extract row from result set!", xRow.is());
+
+ for (tools::Long i = 0; i < ROW_COUNT; ++i)
+ {
+ bool hasRow = xResultSet->next();
+ CPPUNIT_ASSERT_MESSAGE("not enough result after query", hasRow);
+ CPPUNIT_ASSERT_EQUAL(i, xRow->getLong(1)); // first and only column
+ CPPUNIT_ASSERT_EQUAL(i, xRow->getLong(xColumnLocate->findColumn("id"))); // test findColumn
+ }
+ CPPUNIT_ASSERT_MESSAGE("Cursor is not on last position.",
+ xResultSet->isLast()); // cursor is on last position
+ CPPUNIT_ASSERT_EQUAL(ROW_COUNT, xResultSet->getRow()); // which is the last position
+
+ bool hasRow = xResultSet->next(); // go to afterlast
+ // no more rows, next should return false
+ CPPUNIT_ASSERT_MESSAGE("next returns true after last row", !hasRow);
+ // cursor should be in afterlast position
+ CPPUNIT_ASSERT_EQUAL(ROW_COUNT + 1, xResultSet->getRow());
+ CPPUNIT_ASSERT_MESSAGE("Cursor is not on after-last position.", xResultSet->isAfterLast());
+
+ nUpdateCount = xStatement->executeUpdate("DROP TABLE myTestTable");
+ CPPUNIT_ASSERT_EQUAL(0, nUpdateCount); // it's a DDL statement
+}
+
+void MysqlTestDriver::testDBPositionChange()
+{
+ Reference<XConnection> xConnection = m_xDriver->connect(m_sUrl, m_infos);
+ if (!xConnection.is())
+ {
+ CPPUNIT_ASSERT_MESSAGE("cannot connect to data source!", xConnection.is());
+ }
+
+ Reference<XStatement> xStatement = xConnection->createStatement();
+ CPPUNIT_ASSERT(xStatement.is());
+ xStatement->executeUpdate("DROP TABLE IF EXISTS myTestTable");
+
+ auto nUpdateCount
+ = xStatement->executeUpdate("CREATE TABLE myTestTable (id INTEGER PRIMARY KEY)");
+ CPPUNIT_ASSERT_EQUAL(0, nUpdateCount); // it's a DDL statement
+ Reference<XPreparedStatement> xPrepared
+ = xConnection->prepareStatement(OUString{ "INSERT INTO myTestTable VALUES (?)" });
+ Reference<XParameters> xParams(xPrepared, UNO_QUERY);
+ constexpr int ROW_COUNT = 3;
+ for (int i = 1; i <= ROW_COUNT; ++i)
+ {
+ xParams->setLong(1, i); // first and only column
+ nUpdateCount = xPrepared->executeUpdate();
+ CPPUNIT_ASSERT_EQUAL(1, nUpdateCount); // one row is inserted at a time
+ }
+ Reference<XResultSet> xResultSet = xStatement->executeQuery("SELECT id from myTestTable");
+ CPPUNIT_ASSERT_MESSAGE("result set cannot be instantiated after query", xResultSet.is());
+ Reference<XRow> xRow(xResultSet, UNO_QUERY);
+ CPPUNIT_ASSERT_MESSAGE("cannot extract row from result set!", xRow.is());
+
+ xResultSet->afterLast();
+ CPPUNIT_ASSERT_EQUAL(ROW_COUNT + 1, xResultSet->getRow());
+ xResultSet->last();
+ CPPUNIT_ASSERT_EQUAL(ROW_COUNT, nUpdateCount);
+ CPPUNIT_ASSERT_EQUAL(ROW_COUNT, xResultSet->getRow());
+ bool successPrevious = xResultSet->previous();
+ CPPUNIT_ASSERT(successPrevious);
+ CPPUNIT_ASSERT_EQUAL(ROW_COUNT - 1, nUpdateCount);
+ xResultSet->beforeFirst();
+ xResultSet->next();
+ CPPUNIT_ASSERT_EQUAL(1, xResultSet->getRow());
+ xResultSet->first();
+ CPPUNIT_ASSERT_EQUAL(1, xResultSet->getRow());
+
+ // Now previous should put the cursor to before-first position, but it
+ // should return with false.
+ successPrevious = xResultSet->previous();
+ CPPUNIT_ASSERT(!successPrevious);
+ CPPUNIT_ASSERT_EQUAL(0, xResultSet->getRow());
+
+ nUpdateCount = xStatement->executeUpdate("DROP TABLE myTestTable");
+ CPPUNIT_ASSERT_EQUAL(0, nUpdateCount); // it's a DDL statement
+}
+
+void MysqlTestDriver::testMultipleResultsets()
+{
+ Reference<XConnection> xConnection = m_xDriver->connect(m_sUrl, m_infos);
+ CPPUNIT_ASSERT(xConnection.is());
+ Reference<XStatement> xStatement = xConnection->createStatement();
+ CPPUNIT_ASSERT(xStatement.is());
+ // create two tables
+ xStatement->executeUpdate("DROP TABLE IF EXISTS myTestTable");
+ xStatement->executeUpdate("DROP TABLE IF EXISTS otherTable");
+ xStatement->executeUpdate("CREATE TABLE myTestTable (id INTEGER PRIMARY KEY)");
+ xStatement->executeUpdate("INSERT INTO myTestTable VALUES (1)");
+ xStatement->executeUpdate("CREATE TABLE otherTable (id INTEGER PRIMARY KEY)");
+ xStatement->executeUpdate("INSERT INTO otherTable VALUES (2)");
+
+ // create first result set
+ Reference<XResultSet> xResultSet = xStatement->executeQuery("SELECT id from myTestTable");
+ CPPUNIT_ASSERT_MESSAGE("result set cannot be instantiated after query", xResultSet.is());
+ // use it
+ xResultSet->next();
+ Reference<XRow> xRowFirst(xResultSet, UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(1l, xRowFirst->getLong(1));
+ // create second result set
+ Reference<XResultSet> xResultSet2 = xStatement->executeQuery("SELECT id from otherTable");
+ // use second result set
+ xResultSet2->next();
+ Reference<XRow> xRowSecond(xResultSet2, UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(2l, xRowSecond->getLong(1));
+ // now use the first result set again
+#if 0
+ // FIXME this was broken by 86c86719782243275b65f1f7f2cfdcc0e56c8cd4 adding closeResultSet() in execute()
+ CPPUNIT_ASSERT_EQUAL(1l, xRowFirst->getLong(1));
+#endif
+
+ xStatement->executeUpdate("DROP TABLE myTestTable");
+ xStatement->executeUpdate("DROP TABLE otherTable");
+}
+
+void MysqlTestDriver::testDBMetaData()
+{
+ Reference<XConnection> xConnection = m_xDriver->connect(m_sUrl, m_infos);
+ if (!xConnection.is())
+ CPPUNIT_ASSERT_MESSAGE("cannot connect to data source!", xConnection.is());
+ uno::Reference<XStatement> xStatement = xConnection->createStatement();
+ CPPUNIT_ASSERT(xStatement.is());
+ xStatement->executeUpdate("DROP TABLE IF EXISTS myTestTable");
+
+ xStatement->executeUpdate(
+ "CREATE TABLE myTestTable (id INTEGER PRIMARY KEY, name VARCHAR(20))");
+ Reference<XPreparedStatement> xPrepared
+ = xConnection->prepareStatement(OUString{ "INSERT INTO myTestTable VALUES (?, ?)" });
+ Reference<XParameters> xParams(xPrepared, UNO_QUERY);
+ constexpr int ROW_COUNT = 3;
+ for (int i = 0; i < ROW_COUNT; ++i)
+ {
+ xParams->setLong(1, i);
+ xParams->setString(2, "lorem");
+ xPrepared->executeUpdate();
+ }
+
+ Reference<XResultSet> xResultSet = xStatement->executeQuery("SELECT * from myTestTable");
+ Reference<XResultSetMetaDataSupplier> xMetaDataSupplier(xResultSet, UNO_QUERY);
+ Reference<XResultSetMetaData> xMetaData = xMetaDataSupplier->getMetaData();
+ CPPUNIT_ASSERT_EQUAL(OUString{ "id" }, xMetaData->getColumnName(1));
+ CPPUNIT_ASSERT_EQUAL(OUString{ "name" }, xMetaData->getColumnName(2));
+ CPPUNIT_ASSERT(!xMetaData->isAutoIncrement(1));
+ CPPUNIT_ASSERT(!xMetaData->isCaseSensitive(2)); // default collation should be case insensitive
+ xResultSet->next(); // use it
+ // test that meta data is usable even after fetching result set
+ CPPUNIT_ASSERT_EQUAL(OUString{ "name" }, xMetaData->getColumnName(2));
+ CPPUNIT_ASSERT_THROW_MESSAGE("exception expected when indexing out of range",
+ xMetaData->getColumnName(3), sdbc::SQLException);
+ xStatement->executeUpdate("DROP TABLE myTestTable");
+}
+
+void MysqlTestDriver::testTimestampField()
+{
+ Reference<XConnection> xConnection = m_xDriver->connect(m_sUrl, m_infos);
+ if (!xConnection.is())
+ CPPUNIT_ASSERT_MESSAGE("cannot connect to data source!", xConnection.is());
+ uno::Reference<XStatement> xStatement = xConnection->createStatement();
+ CPPUNIT_ASSERT(xStatement.is());
+ xStatement->executeUpdate("DROP TABLE IF EXISTS myTestTable");
+
+ xStatement->executeUpdate(
+ "CREATE TABLE myTestTable (id INTEGER PRIMARY KEY, mytimestamp timestamp)");
+ xStatement->executeUpdate("INSERT INTO myTestTable VALUES (1, '2008-02-16 20:15:03')");
+
+ // now let's query
+ Reference<XResultSet> xResultSet
+ = xStatement->executeQuery("SELECT mytimestamp from myTestTable");
+
+ xResultSet->next(); // use it
+ Reference<XRow> xRow(xResultSet, UNO_QUERY);
+ CPPUNIT_ASSERT_MESSAGE("cannot extract row from result set!", xRow.is());
+ util::DateTime dt = xRow->getTimestamp(1);
+ CPPUNIT_ASSERT_EQUAL(static_cast<short>(2008), dt.Year);
+ CPPUNIT_ASSERT_EQUAL(static_cast<unsigned short>(2), dt.Month);
+ CPPUNIT_ASSERT_EQUAL(static_cast<unsigned short>(16), dt.Day);
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<unsigned short>(20), dt.Hours);
+ CPPUNIT_ASSERT_EQUAL(static_cast<unsigned short>(15), dt.Minutes);
+ CPPUNIT_ASSERT_EQUAL(static_cast<unsigned short>(3), dt.Seconds);
+
+ xStatement->executeUpdate("DROP TABLE myTestTable");
+}
+
+/**
+ * Test getting value from a decimal type column from a result set of a
+ * prepared statement, getting as a tinyint, string, short, int, long.
+ */
+void MysqlTestDriver::testNumericConversionPrepared()
+{
+ Reference<XConnection> xConnection = m_xDriver->connect(m_sUrl, m_infos);
+ if (!xConnection.is())
+ CPPUNIT_ASSERT_MESSAGE("cannot connect to data source!", xConnection.is());
+ uno::Reference<XStatement> xStatement = xConnection->createStatement();
+ CPPUNIT_ASSERT(xStatement.is());
+ xStatement->executeUpdate("DROP TABLE IF EXISTS myTestTable");
+
+ xStatement->executeUpdate("CREATE TABLE myTestTable (myDecimal DECIMAL(4,2))");
+ xStatement->executeUpdate("INSERT INTO myTestTable VALUES (11.22)");
+ Reference<XPreparedStatement> xPrepared
+ = xConnection->prepareStatement("SELECT * from myTestTable");
+ Reference<XResultSet> xResultSet = xPrepared->executeQuery();
+ xResultSet->next(); // use it
+ Reference<XRow> xRow(xResultSet, UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("11.22"), xRow->getString(1));
+ // converting to integer types results in rounding down the number
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int8>(11), xRow->getByte(1));
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(11), xRow->getShort(1));
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(11), xRow->getInt(1));
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int64>(11), xRow->getLong(1));
+
+ xStatement->executeUpdate("DROP TABLE myTestTable");
+}
+
+/**
+ * Test cursor positioning method isAfterLast in case of using prepared
+ * statement.
+ */
+void MysqlTestDriver::testPreparedStmtIsAfterLast()
+{
+ Reference<XConnection> xConnection = m_xDriver->connect(m_sUrl, m_infos);
+ if (!xConnection.is())
+ CPPUNIT_ASSERT_MESSAGE("cannot connect to data source!", xConnection.is());
+ uno::Reference<XStatement> xStatement = xConnection->createStatement();
+ CPPUNIT_ASSERT(xStatement.is());
+ xStatement->executeUpdate("DROP TABLE IF EXISTS myTestTable");
+
+ // create test table
+ xStatement->executeUpdate("CREATE TABLE myTestTable (id INTEGER PRIMARY KEY)");
+ Reference<XPreparedStatement> xPrepared
+ = xConnection->prepareStatement(OUString{ "INSERT INTO myTestTable VALUES (?)" });
+ Reference<XParameters> xParams(xPrepared, UNO_QUERY);
+ constexpr int ROW_COUNT = 6;
+ for (int i = 0; i < ROW_COUNT; ++i)
+ {
+ xParams->setShort(1, i);
+ xPrepared->executeUpdate();
+ }
+
+ // query test table
+ xPrepared = xConnection->prepareStatement("SELECT id from myTestTable where id = 3");
+ Reference<XResultSet> xResultSet = xPrepared->executeQuery();
+
+ // There should be exactly one row, therefore IsAfterLast is false at first.
+ xResultSet->next();
+ CPPUNIT_ASSERT(!xResultSet->isAfterLast());
+
+ // attempt to fetch more data
+ bool hasData = xResultSet->next();
+ CPPUNIT_ASSERT(!hasData); // now we are on "AfterLast"
+ CPPUNIT_ASSERT(xResultSet->isAfterLast());
+ xStatement->executeUpdate("DROP TABLE IF EXISTS myTestTable");
+}
+
+void MysqlTestDriver::testGetStringFromBloColumnb()
+{
+ Reference<XConnection> xConnection = m_xDriver->connect(m_sUrl, m_infos);
+ if (!xConnection.is())
+ CPPUNIT_ASSERT_MESSAGE("cannot connect to data source!", xConnection.is());
+ uno::Reference<XStatement> xStatement = xConnection->createStatement();
+ CPPUNIT_ASSERT(xStatement.is());
+ xStatement->executeUpdate("DROP TABLE IF EXISTS myTestTable");
+
+ // create test table
+ xStatement->executeUpdate("CREATE TABLE myTestTable (id INTEGER PRIMARY KEY, tinytexty "
+ "TINYTEXT, texty TEXT, mediumTexty MEDIUMTEXT, longtexty LONGTEXT)");
+ Reference<XPreparedStatement> xPrepared = xConnection->prepareStatement(
+ OUString{ "INSERT INTO myTestTable VALUES (?, ?, ?, ?, ?)" });
+ Reference<XParameters> xParams(xPrepared, UNO_QUERY);
+ constexpr int ROW_COUNT = 6;
+ for (int i = 0; i < ROW_COUNT; ++i)
+ {
+ xParams->setShort(1, i);
+ xParams->setString(2, OUString::number(i));
+ xParams->setString(3, OUString::number(i));
+ xParams->setString(4, OUString::number(i));
+ xParams->setString(5, OUString::number(i));
+ xPrepared->executeUpdate();
+ }
+
+ // query test table
+ xPrepared = xConnection->prepareStatement(
+ "SELECT tinytexty, texty, mediumtexty, longtexty from myTestTable where texty LIKE '3'");
+ Reference<XResultSet> xResultSet = xPrepared->executeQuery();
+ xResultSet->next();
+ Reference<XRow> xRow(xResultSet, UNO_QUERY);
+
+ // all the textual blob types should be able to be queried via getString().
+ CPPUNIT_ASSERT_EQUAL(OUString("3"), xRow->getString(1));
+ CPPUNIT_ASSERT_EQUAL(OUString("3"), xRow->getString(2));
+ CPPUNIT_ASSERT_EQUAL(OUString("3"), xRow->getString(3));
+ CPPUNIT_ASSERT_EQUAL(OUString("3"), xRow->getString(4));
+
+ xStatement->executeUpdate("DROP TABLE IF EXISTS myTestTable");
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(MysqlTestDriver);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/qa/connectivity/resource/sharedresources_test.cxx b/connectivity/qa/connectivity/resource/sharedresources_test.cxx
new file mode 100644
index 000000000..9c8f4e439
--- /dev/null
+++ b/connectivity/qa/connectivity/resource/sharedresources_test.cxx
@@ -0,0 +1,106 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <test/bootstrapfixture.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/types.h>
+
+#include <resource/sharedresources.hxx>
+#include <strings.hrc>
+
+#include <utility>
+#include <vector>
+
+using namespace css;
+
+namespace connectivity_test
+{
+#define TEST_SOURCE_STRING NC_("TEST_SOURCE_STRING", "UnitTest")
+#define TEST_SOURCE_ONE_SUBSTITUTION NC_("TEST_SOURCE_ONE_SUBSTITUTION", "One substitution $sub$")
+#define TEST_SOURCE_TWO_SUBSTITUTION \
+ NC_("TEST_SOURCE_TWO_SUBSTITUTION", "Two substitution $sub0$ $sub1$")
+#define TEST_SOURCE_THREE_SUBSTITUTION \
+ NC_("TEST_SOURCE_THREE_SUBSTITUTION", "Three substitution $sub0$ $sub1$ $sub2$")
+
+class SharedResourcesTest : public test::BootstrapFixture
+{
+public:
+ SharedResourcesTest();
+
+ void testGetSourceString();
+ void testGetSourceStringWithSubstitutionOne();
+ void testGetSourceStringWithSubstitutionTwo();
+ void testGetSourceStringWithSubstitutionThree();
+ void testGetSourceStringWithSubstitutionVector();
+
+ CPPUNIT_TEST_SUITE(SharedResourcesTest);
+
+ CPPUNIT_TEST(testGetSourceString);
+ CPPUNIT_TEST(testGetSourceStringWithSubstitutionOne);
+ CPPUNIT_TEST(testGetSourceStringWithSubstitutionTwo);
+ CPPUNIT_TEST(testGetSourceStringWithSubstitutionThree);
+ CPPUNIT_TEST(testGetSourceStringWithSubstitutionVector);
+
+ CPPUNIT_TEST_SUITE_END();
+
+private:
+ ::connectivity::SharedResources m_aResource;
+};
+
+SharedResourcesTest::SharedResourcesTest()
+ : test::BootstrapFixture(false, false)
+{
+}
+
+void SharedResourcesTest::testGetSourceString()
+{
+ CPPUNIT_ASSERT_EQUAL(OUString("UnitTest"), m_aResource.getResourceString(TEST_SOURCE_STRING));
+}
+
+void SharedResourcesTest::testGetSourceStringWithSubstitutionOne()
+{
+ CPPUNIT_ASSERT_EQUAL(OUString("One substitution UnitTest"),
+ m_aResource.getResourceStringWithSubstitution(TEST_SOURCE_ONE_SUBSTITUTION,
+ "$sub$", "UnitTest"));
+}
+
+void SharedResourcesTest::testGetSourceStringWithSubstitutionTwo()
+{
+ CPPUNIT_ASSERT_EQUAL(OUString("Two substitution UnitTest1 UnitTest2"),
+ m_aResource.getResourceStringWithSubstitution(TEST_SOURCE_TWO_SUBSTITUTION,
+ "$sub0$", "UnitTest1",
+ "$sub1$", "UnitTest2"));
+}
+
+void SharedResourcesTest::testGetSourceStringWithSubstitutionThree()
+{
+ CPPUNIT_ASSERT_EQUAL(OUString("Three substitution UnitTest1 UnitTest2 UnitTest3"),
+ m_aResource.getResourceStringWithSubstitution(
+ TEST_SOURCE_THREE_SUBSTITUTION, "$sub0$", "UnitTest1", "$sub1$",
+ "UnitTest2", "$sub2$", "UnitTest3"));
+}
+
+void SharedResourcesTest::testGetSourceStringWithSubstitutionVector()
+{
+ std::vector<std::pair<const char*, OUString>> aStringToSubstitutes{ { "$sub0$", "vector0" },
+ { "$sub1$", "vector1" },
+ { "$sub2$", "vector2" } };
+
+ CPPUNIT_ASSERT_EQUAL(OUString("Three substitution vector0 vector1 vector2"),
+ m_aResource.getResourceStringWithSubstitution(
+ TEST_SOURCE_THREE_SUBSTITUTION, aStringToSubstitutes));
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SharedResourcesTest);
+
+} // namespace connectivity_test
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/connectivity/qa/connectivity/tools/AbstractDatabase.java b/connectivity/qa/connectivity/tools/AbstractDatabase.java
new file mode 100644
index 000000000..d34b39066
--- /dev/null
+++ b/connectivity/qa/connectivity/tools/AbstractDatabase.java
@@ -0,0 +1,207 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+package connectivity.tools;
+
+import com.sun.star.container.XNameAccess;
+import com.sun.star.frame.XModel;
+import com.sun.star.frame.XStorable;
+import com.sun.star.io.IOException;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.sdb.XDocumentDataSource;
+import com.sun.star.sdb.XOfficeDatabaseDocument;
+import com.sun.star.sdbc.SQLException;
+import com.sun.star.sdbc.XCloseable;
+import com.sun.star.sdbc.XStatement;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.util.CloseVetoException;
+import connectivity.tools.sdb.Connection;
+import static org.junit.Assert.*;
+
+public abstract class AbstractDatabase implements DatabaseAccess
+{
+ public AbstractDatabase(final XMultiServiceFactory orb) throws Exception
+ {
+ m_orb = orb;
+ }
+
+
+ public AbstractDatabase(final XMultiServiceFactory orb, final String _existingDocumentURL ) throws Exception
+ {
+ m_orb = orb;
+ createDBDocument( _existingDocumentURL );
+ }
+
+ /** returns a connection to the database
+ *
+ * Multiple calls to this method return the same connection. The DbaseDatabase object keeps
+ * the ownership of the connection, so you don't need to (and should not) dispose/close it.
+ */
+ public Connection defaultConnection() throws SQLException
+ {
+ if ( m_connection == null )
+ m_connection = new Connection( m_databaseDocument.getDataSource().getConnection("", "") );
+
+ return m_connection;
+ }
+
+ /** executes the given SQL statement via the defaultConnection
+ */
+ public void executeSQL(final String statementString) throws SQLException
+ {
+ final XStatement statement = defaultConnection().createStatement();
+ statement.execute(statementString);
+ }
+
+ /** stores the database document
+ */
+ public void store() throws IOException
+ {
+ if (m_databaseDocument != null)
+ {
+ final XStorable storeDoc = UnoRuntime.queryInterface(XStorable.class, m_databaseDocument);
+ storeDoc.store();
+ }
+ }
+
+ /** closes the database document
+ *
+ * Any CloseVetoExceptions fired by third parties are ignored, and any reference to the
+ * database document is released.
+ */
+ public void close()
+ {
+ // close connection
+ final XCloseable closeConn = UnoRuntime.queryInterface( XCloseable.class,
+ m_connection != null ? m_connection.getXConnection() : null );
+ if (closeConn != null)
+ {
+ try
+ {
+ closeConn.close();
+ }
+ catch (SQLException e)
+ {
+ }
+ }
+ m_connection = null;
+
+ // close document
+ final com.sun.star.util.XCloseable closeDoc = UnoRuntime.queryInterface( com.sun.star.util.XCloseable.class, m_databaseDocument );
+ if (closeDoc != null)
+ {
+ try
+ {
+ closeDoc.close(true);
+ }
+ catch (CloseVetoException e)
+ {
+ }
+ }
+ m_databaseDocument = null;
+ }
+
+ /** closes the document, and deletes the underlying file
+ */
+ public void closeAndDelete()
+ {
+ close();
+ delete();
+ }
+
+ protected void delete() {}
+
+ /** returns the underlying database document
+ */
+ public XOfficeDatabaseDocument getDatabaseDocument()
+ {
+ return m_databaseDocument;
+ }
+
+ /** returns the model interface of the underlying database document
+ */
+ public XModel getModel()
+ {
+ return UnoRuntime.queryInterface( XModel.class, m_databaseDocument );
+ }
+
+ public XMultiServiceFactory getORB()
+ {
+ return m_orb;
+ }
+
+
+ final private void createDBDocument(final String _docURL) throws Exception
+ {
+ m_databaseDocumentFile = _docURL;
+
+ final XNameAccess dbContext = UnoRuntime.queryInterface( XNameAccess.class,
+ m_orb.createInstance( "com.sun.star.sdb.DatabaseContext" ) );
+ final XDocumentDataSource dataSource = UnoRuntime.queryInterface( XDocumentDataSource.class, dbContext.getByName( _docURL ) );
+
+ m_databaseDocument = dataSource.getDatabaseDocument();
+ m_dataSource = new DataSource(m_databaseDocument.getDataSource());
+ }
+
+ /** returns the URL of the ODB document represented by this instance
+ */
+ public String getDocumentURL()
+ {
+ return m_databaseDocumentFile;
+ }
+
+ /** returns the data source belonging to this database
+ */
+ public DataSource getDataSource()
+ {
+ return m_dataSource;
+ }
+
+ /** creates a row set operating the database, with a given command/type
+ */
+ public RowSet createRowSet(final int _commandType, final String _command)
+ {
+ return new RowSet(m_orb, getDocumentURL(), _commandType, _command);
+ }
+
+ @Override
+ protected void finalize() throws Throwable
+ {
+ // Cannot call close() here, as it accesses UNO objects (that may
+ // already have been finalized):
+ assertNull(
+ "missing call to connectivity.tools.AbstractDatabase.close",
+ m_connection);
+ assertNull(
+ "missing call to connectivity.tools.AbstractDatabase.close",
+ m_databaseDocument);
+
+ delete();
+ super.finalize();
+ }
+
+ // the service factory
+ protected final XMultiServiceFactory m_orb;
+ // the URL of the temporary file used for the database document
+ protected String m_databaseDocumentFile;
+ // the database document
+ protected XOfficeDatabaseDocument m_databaseDocument;
+ // the data source belonging to the database document
+ protected DataSource m_dataSource;
+ // the default connection
+ private Connection m_connection;
+}
diff --git a/connectivity/qa/connectivity/tools/CRMDatabase.java b/connectivity/qa/connectivity/tools/CRMDatabase.java
new file mode 100644
index 000000000..3d3392628
--- /dev/null
+++ b/connectivity/qa/connectivity/tools/CRMDatabase.java
@@ -0,0 +1,277 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+package connectivity.tools;
+
+import com.sun.star.beans.PropertyValue;
+import com.sun.star.beans.PropertyState;
+import com.sun.star.container.ElementExistException;
+import com.sun.star.container.NoSuchElementException;
+import com.sun.star.frame.XComponentLoader;
+import com.sun.star.frame.XController;
+import com.sun.star.frame.XModel;
+import com.sun.star.io.IOException;
+import com.sun.star.lang.IllegalArgumentException;
+import com.sun.star.lang.WrappedTargetException;
+import com.sun.star.lang.XComponent;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.sdb.application.XDatabaseDocumentUI;
+import com.sun.star.sdbc.SQLException;
+import com.sun.star.uno.UnoRuntime;
+import connectivity.tools.sdb.Connection;
+
+/** implements a small Customer Relationship Management database
+ *
+ * Not finished, by far. Feel free to add features as you need them.
+ */
+public class CRMDatabase
+{
+ private static final String INTEGER = "INTEGER";
+ private static final String VARCHAR50 = "VARCHAR(50)";
+ private final XMultiServiceFactory m_orb;
+ private final HsqlDatabase m_database;
+ private final Connection m_connection;
+
+ /** constructs the CRM database
+ */
+ public CRMDatabase( XMultiServiceFactory _orb, boolean _withUI ) throws Exception
+ {
+ m_orb = _orb;
+
+ m_database = new HsqlDatabase( m_orb );
+
+ if ( _withUI )
+ {
+ final XComponentLoader loader = UnoRuntime.queryInterface( XComponentLoader.class,
+ m_orb.createInstance( "com.sun.star.frame.Desktop" ) );
+ PropertyValue[] loadArgs = new PropertyValue[] {
+ new PropertyValue( "PickListEntry", 0, false, PropertyState.DIRECT_VALUE )
+ };
+ loader.loadComponentFromURL( m_database.getDocumentURL(), "_blank", 0, loadArgs );
+ getDocumentUI().connect();
+ m_connection = new Connection( getDocumentUI().getActiveConnection() );
+ }
+ else
+ {
+ m_connection = m_database.defaultConnection();
+ }
+
+ createTables();
+ createQueries();
+ }
+
+ /**
+ * creates a CRMDatabase from an existing document, given by URL
+ */
+ public CRMDatabase( XMultiServiceFactory _orb, final String _existingDocumentURL ) throws Exception
+ {
+ m_orb = _orb;
+
+ m_database = new HsqlDatabase( m_orb, _existingDocumentURL );
+ m_connection = m_database.defaultConnection();
+ }
+
+
+ /** returns the database document underlying the CRM database
+ */
+ public final HsqlDatabase getDatabase()
+ {
+ return m_database;
+ }
+
+
+ /** returns the default connection to the database
+ */
+ public final Connection getConnection()
+ {
+ return m_connection;
+ }
+
+
+ public void saveAndClose() throws IOException
+ {
+ XDatabaseDocumentUI ui = getDocumentUI();
+ if ( ui != null )
+ ui.closeSubComponents();
+ m_database.store();
+ m_database.closeAndDelete();
+ }
+
+
+ private XDatabaseDocumentUI getDocumentUI()
+ {
+ XModel docModel = UnoRuntime.queryInterface( XModel.class, m_database.getDatabaseDocument() );
+ return UnoRuntime.queryInterface( XDatabaseDocumentUI.class, docModel.getCurrentController() );
+ }
+
+
+ public XController loadSubComponent( final int _objectType, final String _name ) throws IllegalArgumentException, SQLException, NoSuchElementException
+ {
+ XDatabaseDocumentUI docUI = getDocumentUI();
+ if ( !docUI.isConnected() )
+ docUI.connect();
+
+ XComponent subComponent = docUI.loadComponent( _objectType, _name, false );
+ XController controller = UnoRuntime.queryInterface( XController.class, subComponent );
+ if ( controller != null )
+ return controller;
+ XModel document = UnoRuntime.queryInterface( XModel.class, subComponent );
+ return document.getCurrentController();
+ }
+
+
+ private void createTables() throws SQLException
+ {
+ HsqlTableDescriptor table = new HsqlTableDescriptor( "categories",
+ new HsqlColumnDescriptor[] {
+ new HsqlColumnDescriptor( "ID",INTEGER, HsqlColumnDescriptor.PRIMARY ),
+ new HsqlColumnDescriptor( "Name",VARCHAR50),
+ new HsqlColumnDescriptor( "Description", "VARCHAR(1024)" ),
+ new HsqlColumnDescriptor( "Image", "LONGVARBINARY" ) } );
+ m_database.createTable( table, true );
+
+ m_database.executeSQL( "INSERT INTO \"categories\" ( \"ID\", \"Name\" ) VALUES ( 1, 'Food' )" );
+ m_database.executeSQL( "INSERT INTO \"categories\" ( \"ID\", \"Name\" ) VALUES ( 2, 'Furniture' )" );
+
+ table = new HsqlTableDescriptor( "products",
+ new HsqlColumnDescriptor[] {
+ new HsqlColumnDescriptor( "ID",INTEGER, HsqlColumnDescriptor.PRIMARY ),
+ new HsqlColumnDescriptor( "Name",VARCHAR50),
+ new HsqlColumnDescriptor( "CategoryID",INTEGER, HsqlColumnDescriptor.REQUIRED, "categories", "ID" ) } );
+ m_database.createTable( table, true );
+
+ m_database.executeSQL( "INSERT INTO \"products\" VALUES ( 1, 'Oranges', 1 )" );
+ m_database.executeSQL( "INSERT INTO \"products\" VALUES ( 2, 'Apples', 1 )" );
+ m_database.executeSQL( "INSERT INTO \"products\" VALUES ( 3, 'Pears', 1 )" );
+ m_database.executeSQL( "INSERT INTO \"products\" VALUES ( 4, 'Strawberries', 1 )" );
+
+ table = new HsqlTableDescriptor( "customers",
+ new HsqlColumnDescriptor[] {
+ new HsqlColumnDescriptor( "ID",INTEGER, HsqlColumnDescriptor.PRIMARY ),
+ new HsqlColumnDescriptor( "Name",VARCHAR50),
+ new HsqlColumnDescriptor( "Address",VARCHAR50),
+ new HsqlColumnDescriptor( "City",VARCHAR50),
+ new HsqlColumnDescriptor( "Postal",VARCHAR50),
+ new HsqlColumnDescriptor( "Comment","LONGVARCHAR")} );
+ m_database.createTable( table, true );
+
+ m_database.executeSQL( "INSERT INTO \"customers\" VALUES(1,'Food, Inc.','Down Under','Melbourne','509','Preferred') " );
+ m_database.executeSQL( "INSERT INTO \"customers\" VALUES(2,'Simply Delicious','Down Under','Melbourne','518',null) " );
+ m_database.executeSQL( "INSERT INTO \"customers\" VALUES(3,'Pure Health','10 Fish St.','San Francisco','94107',null) " );
+ m_database.executeSQL( "INSERT INTO \"customers\" VALUES(4,'Milk And More','Arlington Road 21','Dublin','31021','Good one.') " );
+
+ table = new HsqlTableDescriptor( "orders",
+ new HsqlColumnDescriptor[] {
+ new HsqlColumnDescriptor( "ID",INTEGER, HsqlColumnDescriptor.PRIMARY ),
+ new HsqlColumnDescriptor( "CustomerID",INTEGER, HsqlColumnDescriptor.REQUIRED, "customers", "ID" ),
+ new HsqlColumnDescriptor( "OrderDate", "DATE" ),
+ new HsqlColumnDescriptor( "ShipDate", "DATE" ) } );
+ m_database.createTable( table, true );
+
+ m_database.executeSQL( "INSERT INTO \"orders\" (\"ID\", \"CustomerID\", \"OrderDate\") VALUES(1, 1, {D '2009-01-01'})" );
+ m_database.executeSQL( "INSERT INTO \"orders\" VALUES(2, 2, {D '2009-01-01'}, {D '2009-01-23'})" );
+
+ table = new HsqlTableDescriptor( "orders_details",
+ new HsqlColumnDescriptor[] {
+ new HsqlColumnDescriptor( "OrderID",INTEGER, HsqlColumnDescriptor.PRIMARY, "orders", "ID" ),
+ new HsqlColumnDescriptor( "ProductID",INTEGER, HsqlColumnDescriptor.PRIMARY, "products", "ID" ),
+ new HsqlColumnDescriptor( "Quantity",INTEGER) } );
+ m_database.createTable( table, true );
+
+ m_database.executeSQL( "INSERT INTO \"orders_details\" VALUES(1, 1, 100)" );
+ m_database.executeSQL( "INSERT INTO \"orders_details\" VALUES(1, 2, 100)" );
+ m_database.executeSQL( "INSERT INTO \"orders_details\" VALUES(2, 2, 2000)" );
+ m_database.executeSQL( "INSERT INTO \"orders_details\" VALUES(2, 3, 2000)" );
+ m_database.executeSQL( "INSERT INTO \"orders_details\" VALUES(2, 4, 2000)" );
+
+ // since we created the tables by directly executing the SQL statements, we need to refresh
+ // the tables container
+ m_connection.refreshTables();
+ }
+
+
+ private void validateUnparseable()
+ {
+ /*
+ // The "unparseable" query should be indeed be unparseable by OOo (though a valid HSQL query)
+ XSingleSelectQueryComposer composer;
+ QueryDefinition unparseableQuery;
+ try
+ {
+ final XMultiServiceFactory factory = UnoRuntime.queryInterface(
+ XMultiServiceFactory.class, m_database.defaultConnection().getXConnection() );
+ composer = UnoRuntime.queryInterface(
+ XSingleSelectQueryComposer.class, factory.createInstance( "com.sun.star.sdb.SingleSelectQueryComposer" ) );
+ unparseableQuery = m_dataSource.getQueryDefinition( "unparseable" );
+ }
+ catch( Exception e )
+ {
+ throw new RuntimeException( "caught an unexpected exception: " + e.getMessage() );
+ }
+
+ boolean caughtExpected = false;
+ try
+ {
+ composer.setQuery( unparseableQuery.getCommand() );
+ }
+ catch (WrappedTargetException e) { }
+ catch( SQLException e )
+ {
+ caughtExpected = true;
+ }
+
+ if ( !caughtExpected )
+ throw new RuntimeException( "Somebody improved the parser! This is bad :), since we need an unparsable query here!" );
+ */
+ }
+
+
+ private void createQueries() throws ElementExistException, WrappedTargetException, com.sun.star.lang.IllegalArgumentException
+ {
+ m_database.getDataSource().createQuery(
+ "all orders",
+ "SELECT \"orders\".\"ID\" AS \"Order No.\", " +
+ "\"customers\".\"Name\" AS \"Customer Name\", " +
+ "\"orders\".\"OrderDate\" AS \"Order Date\", " +
+ "\"orders\".\"ShipDate\" AS \"Ship Date\", " +
+ "\"orders_details\".\"Quantity\", " +
+ "\"products\".\"Name\" AS \"Product Name\" " +
+ "FROM \"orders_details\" AS \"orders_details\", " +
+ "\"orders\" AS \"orders\", " +
+ "\"products\" AS \"products\", " +
+ "\"customers\" AS \"customers\" " +
+ "WHERE ( \"orders_details\".\"OrderID\" = \"orders\".\"ID\" " +
+ "AND \"orders_details\".\"ProductID\" = \"products\".\"ID\" " +
+ "AND \"orders\".\"CustomerID\" = \"customers\".\"ID\" )"
+ );
+
+ m_database.getDataSource().createQuery(
+ "unshipped orders",
+ "SELECT * " +
+ "FROM \"all orders\"" +
+ "WHERE ( \"ShipDate\" IS NULL )"
+ );
+
+ m_database.getDataSource().createQuery( "parseable", "SELECT * FROM \"customers\"" );
+ m_database.getDataSource().createQuery( "parseable native", "SELECT * FROM INFORMATION_SCHEMA.SYSTEM_VIEWS", false );
+/*
+ m_database.getDataSource().createQuery( "unparseable",
+ "SELECT {fn DAYOFMONTH ('2001-01-01')} AS \"ID_VARCHAR\" FROM \"products\"", false );
+*/
+ validateUnparseable();
+ }
+}
diff --git a/connectivity/qa/connectivity/tools/CsvDatabase.java b/connectivity/qa/connectivity/tools/CsvDatabase.java
new file mode 100644
index 000000000..abb016c90
--- /dev/null
+++ b/connectivity/qa/connectivity/tools/CsvDatabase.java
@@ -0,0 +1,31 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+package connectivity.tools;
+
+import com.sun.star.lang.XMultiServiceFactory;
+
+public class CsvDatabase extends FlatFileDatabase
+{
+
+ public CsvDatabase( final XMultiServiceFactory i_orb ) throws Exception
+ {
+ super( i_orb, "flat" );
+ }
+
+}
diff --git a/connectivity/qa/connectivity/tools/DataSource.java b/connectivity/qa/connectivity/tools/DataSource.java
new file mode 100644
index 000000000..844c4488f
--- /dev/null
+++ b/connectivity/qa/connectivity/tools/DataSource.java
@@ -0,0 +1,150 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+package connectivity.tools;
+
+import com.sun.star.container.ElementExistException;
+import com.sun.star.container.NoSuchElementException;
+import com.sun.star.container.XNameAccess;
+import com.sun.star.container.XNameContainer;
+import com.sun.star.lang.WrappedTargetException;
+import com.sun.star.lang.XSingleServiceFactory;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.sdb.XQueryDefinitionsSupplier;
+import com.sun.star.sdbc.XDataSource;
+import com.sun.star.uno.Exception;
+import com.sun.star.uno.UnoRuntime;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class DataSource
+{
+ // the service factory
+
+ private final XDataSource m_dataSource;
+
+ public DataSource(final XMultiServiceFactory _orb, final String _registeredName) throws Exception
+ {
+ final XNameAccess dbContext = UnoRuntime.queryInterface(
+ XNameAccess.class, _orb.createInstance( "com.sun.star.sdb.DatabaseContext" ) );
+
+ m_dataSource = UnoRuntime.queryInterface( XDataSource.class, dbContext.getByName( _registeredName ) );
+ }
+
+ public DataSource(final XDataSource _dataSource)
+ {
+ m_dataSource = _dataSource;
+ }
+
+ final public XDataSource getXDataSource()
+ {
+ return m_dataSource;
+ }
+
+ /**
+ * retrieves the data source's settings
+ */
+ public XPropertySet geSettings()
+ {
+ return UnoRuntime.queryInterface( XPropertySet.class, impl_getPropertyValue( "Settings" ) );
+ }
+
+ /** creates a query with a given name and SQL command
+ */
+ public void createQuery(final String _name, final String _sqlCommand) throws ElementExistException, WrappedTargetException, com.sun.star.lang.IllegalArgumentException
+ {
+ createQuery(_name, _sqlCommand, true);
+ }
+
+ /** creates a query with a given name, SQL command, and EscapeProcessing flag
+ */
+ public void createQuery(final String _name, final String _sqlCommand, final boolean _escapeProcessing) throws ElementExistException, WrappedTargetException, com.sun.star.lang.IllegalArgumentException
+ {
+ final XSingleServiceFactory queryDefsFac = UnoRuntime.queryInterface( XSingleServiceFactory.class, getQueryDefinitions() );
+ XPropertySet queryDef = null;
+ try
+ {
+ queryDef = UnoRuntime.queryInterface( XPropertySet.class, queryDefsFac.createInstance() );
+ queryDef.setPropertyValue("Command", _sqlCommand);
+ queryDef.setPropertyValue("EscapeProcessing", Boolean.valueOf(_escapeProcessing));
+ }
+ catch (com.sun.star.uno.Exception e)
+ {
+ e.printStackTrace(System.err);
+ }
+
+ final XNameContainer queryDefsContainer = UnoRuntime.queryInterface( XNameContainer.class, getQueryDefinitions() );
+ queryDefsContainer.insertByName(_name, queryDef);
+ }
+
+ /** provides the query definition with the given name
+ */
+ public QueryDefinition getQueryDefinition(final String _name) throws NoSuchElementException
+ {
+ final XNameAccess allDefs = getQueryDefinitions();
+ try
+ {
+ return new QueryDefinition( UnoRuntime.queryInterface( XPropertySet.class, allDefs.getByName( _name) ) );
+ }
+ catch (WrappedTargetException e)
+ {
+ }
+ throw new NoSuchElementException();
+ }
+
+ /** provides the container of query definitions of the data source
+ */
+ private XNameAccess getQueryDefinitions()
+ {
+ final XQueryDefinitionsSupplier suppQueries = UnoRuntime.queryInterface(
+ XQueryDefinitionsSupplier.class, m_dataSource);
+ return suppQueries.getQueryDefinitions();
+ }
+
+ /**
+ * retrieves a property value from the data source
+ * @param i_propertyName
+ * the name of the property whose value is to be returned.
+ */
+ private Object impl_getPropertyValue( final String i_propertyName )
+ {
+ Object propertyValue = null;
+ try
+ {
+ final XPropertySet dataSourceProps = UnoRuntime.queryInterface( XPropertySet.class, m_dataSource );
+ propertyValue = dataSourceProps.getPropertyValue( i_propertyName );
+ }
+ catch (Exception ex)
+ {
+ Logger.getLogger(DataSource.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ return propertyValue;
+ }
+
+ /** returns the name of the data source
+ *
+ * If a data source is registered at the database context, the name is the registration
+ * name. Otherwise, it's the URL which the respective database document is based on.
+ *
+ * Note that the above definition is from the UNO API, not from this wrapper here.
+ */
+ public String getName()
+ {
+ return (String)impl_getPropertyValue( "Name" );
+ }
+}
diff --git a/connectivity/qa/connectivity/tools/DatabaseAccess.java b/connectivity/qa/connectivity/tools/DatabaseAccess.java
new file mode 100644
index 000000000..347faa46e
--- /dev/null
+++ b/connectivity/qa/connectivity/tools/DatabaseAccess.java
@@ -0,0 +1,50 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+package connectivity.tools;
+
+import com.sun.star.frame.XModel;
+import com.sun.star.io.IOException;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.sdb.XOfficeDatabaseDocument;
+import com.sun.star.sdbc.SQLException;
+import connectivity.tools.sdb.Connection;
+
+public interface DatabaseAccess
+{
+ Connection defaultConnection() throws SQLException;
+
+ void executeSQL(final String statementString) throws SQLException;
+
+ void store() throws IOException;
+
+ void close();
+
+ void closeAndDelete();
+
+ XOfficeDatabaseDocument getDatabaseDocument();
+
+ XModel getModel();
+
+ String getDocumentURL();
+
+ DataSource getDataSource();
+
+ RowSet createRowSet(final int _commandType, final String _command);
+
+ XMultiServiceFactory getORB();
+}
diff --git a/connectivity/qa/connectivity/tools/DbaseDatabase.java b/connectivity/qa/connectivity/tools/DbaseDatabase.java
new file mode 100644
index 000000000..9a1dc8448
--- /dev/null
+++ b/connectivity/qa/connectivity/tools/DbaseDatabase.java
@@ -0,0 +1,32 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+package connectivity.tools;
+
+import com.sun.star.lang.XMultiServiceFactory;
+
+public class DbaseDatabase extends FlatFileDatabase
+{
+
+ public DbaseDatabase( final XMultiServiceFactory i_orb ) throws Exception
+ {
+ super( i_orb, "dbase" );
+ }
+
+
+}
diff --git a/connectivity/qa/connectivity/tools/FlatFileDatabase.java b/connectivity/qa/connectivity/tools/FlatFileDatabase.java
new file mode 100644
index 000000000..5351ba953
--- /dev/null
+++ b/connectivity/qa/connectivity/tools/FlatFileDatabase.java
@@ -0,0 +1,74 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+package connectivity.tools;
+
+import com.sun.star.beans.PropertyValue;
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.frame.XStorable;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.sdb.XOfficeDatabaseDocument;
+import com.sun.star.uno.UnoRuntime;
+
+import helper.URLHelper;
+import java.io.File;
+
+class FlatFileDatabase extends AbstractDatabase
+{
+
+ protected FlatFileDatabase( final XMultiServiceFactory i_orb, final String i_urlSubScheme ) throws Exception
+ {
+ super(i_orb);
+ m_urlSubScheme = i_urlSubScheme;
+ createDBDocument();
+ }
+
+
+ /**
+ * returns a {@link File} which represents the folder where the database's table files reside.
+ */
+ public File getTableFileLocation()
+ {
+ return m_tableFileLocation;
+ }
+
+ /** creates an empty database document in a temporary location
+ */
+ private void createDBDocument() throws Exception
+ {
+ final File documentFile = File.createTempFile( m_urlSubScheme, ".odb" );
+ if ( documentFile.exists() )
+ documentFile.delete();
+ m_tableFileLocation = new File(documentFile.getParent() + File.separator + documentFile.getName().replace(".odb", "") + File.separator );
+ m_tableFileLocation.mkdir();
+ m_databaseDocumentFile = URLHelper.getFileURLFromSystemPath(documentFile);
+ final String path = URLHelper.getFileURLFromSystemPath( m_tableFileLocation.getPath() );
+
+ m_databaseDocument = UnoRuntime.queryInterface( XOfficeDatabaseDocument.class,
+ m_orb.createInstance("com.sun.star.sdb.OfficeDatabaseDocument"));
+ m_dataSource = new DataSource(m_databaseDocument.getDataSource());
+
+ final XPropertySet dsProperties = UnoRuntime.queryInterface(XPropertySet.class, m_databaseDocument.getDataSource());
+ dsProperties.setPropertyValue("URL", "sdbc:" + m_urlSubScheme + ":" + path);
+
+ final XStorable storable = UnoRuntime.queryInterface( XStorable.class, m_databaseDocument );
+ storable.storeAsURL( m_databaseDocumentFile, new PropertyValue[] { } );
+ }
+
+ private final String m_urlSubScheme;
+ private File m_tableFileLocation = null;
+}
diff --git a/connectivity/qa/connectivity/tools/HsqlColumnDescriptor.java b/connectivity/qa/connectivity/tools/HsqlColumnDescriptor.java
new file mode 100644
index 000000000..12330ff70
--- /dev/null
+++ b/connectivity/qa/connectivity/tools/HsqlColumnDescriptor.java
@@ -0,0 +1,75 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+package connectivity.tools;
+
+/** is a very simply and rudimentary descriptor of table columns, for creating HSQLDB tables
+ */
+public class HsqlColumnDescriptor
+{
+ private final String Name;
+ private final String TypeName;
+ private final boolean Required;
+ private final boolean PrimaryKey;
+ private final String ForeignTable;
+ private final String ForeignColumn;
+
+ public final String getName() { return Name; }
+ public final String getTypeName() { return TypeName; }
+ public final boolean isRequired() { return Required; }
+ public final boolean isPrimaryKey() { return PrimaryKey; }
+
+ public final boolean isForeignKey() { return ( ForeignTable.length() != 0 ) && ( ForeignColumn.length() != 0 ); }
+ public final String getForeignTable() { return ForeignTable; }
+ public final String getForeignColumn() { return ForeignColumn; }
+
+ /// determines that a column is required, i.e. not nullable
+ public static final int REQUIRED = 1;
+ /// determines that a column is part of the primary key of its table
+ public static final int PRIMARY = 2;
+
+ public HsqlColumnDescriptor( String _Name, String _TypeName )
+ {
+ Name = _Name;
+ TypeName = _TypeName;
+ Required = false;
+ PrimaryKey = false;
+ ForeignTable = "";
+ ForeignColumn = "";
+ }
+
+ public HsqlColumnDescriptor( String _Name, String _TypeName, int _Flags )
+ {
+ Name = _Name;
+ TypeName = _TypeName;
+ Required = ( _Flags & REQUIRED ) != 0;
+ PrimaryKey = ( _Flags & PRIMARY ) != 0;
+ ForeignTable = "";
+ ForeignColumn = "";
+ }
+
+ public HsqlColumnDescriptor( String _Name, String _TypeName, int _Flags, String _ForeignTable, String _ForeignColumn )
+ {
+ Name = _Name;
+ TypeName = _TypeName;
+ Required = ( _Flags & REQUIRED ) != 0;
+ PrimaryKey = ( _Flags & PRIMARY ) != 0;
+ ForeignTable = _ForeignTable;
+ ForeignColumn = _ForeignColumn;
+ }
+}
diff --git a/connectivity/qa/connectivity/tools/HsqlDatabase.java b/connectivity/qa/connectivity/tools/HsqlDatabase.java
new file mode 100644
index 000000000..0d2ab4af9
--- /dev/null
+++ b/connectivity/qa/connectivity/tools/HsqlDatabase.java
@@ -0,0 +1,202 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+package connectivity.tools;
+
+import com.sun.star.beans.PropertyValue;
+import com.sun.star.beans.PropertyState;
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.container.ElementExistException;
+import com.sun.star.frame.XStorable;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.sdb.XOfficeDatabaseDocument;
+import com.sun.star.sdbc.SQLException;
+import com.sun.star.sdbcx.XAppend;
+import com.sun.star.sdbcx.XTablesSupplier;
+import com.sun.star.uno.UnoRuntime;
+
+import helper.URLHelper;
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.Assert;
+
+public class HsqlDatabase extends AbstractDatabase
+{
+
+
+ public HsqlDatabase(final XMultiServiceFactory orb) throws Exception
+ {
+ super(orb);
+ createDBDocument();
+ }
+
+
+ public HsqlDatabase(final XMultiServiceFactory orb, final String _existingDocumentURL) throws Exception
+ {
+ super(orb, _existingDocumentURL);
+ }
+
+ /** creates an empty database document in a temporary location
+ */
+ private void createDBDocument() throws Exception
+ {
+ Assert.assertNull(m_documentFile);
+ m_documentFile = File.createTempFile("testdb", ".odb");
+ if ( m_documentFile.exists() )
+ m_documentFile.delete();
+ m_databaseDocumentFile = URLHelper.getFileURLFromSystemPath(m_documentFile);
+
+ m_databaseDocument = UnoRuntime.queryInterface(
+ XOfficeDatabaseDocument.class, m_orb.createInstance("com.sun.star.sdb.OfficeDatabaseDocument"));
+ m_dataSource = new DataSource(m_databaseDocument.getDataSource());
+
+ final XPropertySet dsProperties = UnoRuntime.queryInterface(XPropertySet.class, m_databaseDocument.getDataSource());
+ dsProperties.setPropertyValue("URL", "sdbc:embedded:hsqldb");
+
+ final XStorable storable = UnoRuntime.queryInterface(XStorable.class, m_databaseDocument);
+ storable.storeAsURL( m_databaseDocumentFile, new PropertyValue[]
+ { new PropertyValue( "PickListEntry", 0, false, PropertyState.DIRECT_VALUE )
+ } );
+ }
+
+ @Override protected final void delete() {
+ if (m_documentFile != null) {
+ boolean ok = m_documentFile.delete();
+ //TODO: fails on Windows: Assert.assertTrue("delete " + m_documentFile.getPath(), ok);
+ }
+ }
+
+ /** drops the table with a given name
+
+ @param _name
+ the name of the table to drop
+ */
+ private void dropTable(final String _name) throws SQLException
+ {
+ final StringBuffer dropStatement = new StringBuffer("DROP TABLE \"");
+ dropStatement.append(_name);
+ dropStatement.append("\" IF EXISTS");
+ executeSQL(dropStatement.toString());
+ }
+
+ public void createTable(final HsqlTableDescriptor _tableDesc, final boolean _dropIfExists) throws SQLException
+ {
+ if (_dropIfExists)
+ {
+ dropTable(_tableDesc.getName());
+ }
+ createTable(_tableDesc);
+ }
+
+ /** creates a table
+ */
+ public void createTable(final HsqlTableDescriptor _tableDesc) throws SQLException
+ {
+ StringBuffer createStatement = new StringBuffer("CREATE CACHED TABLE \"");
+ createStatement.append(_tableDesc.getName());
+ createStatement.append("\" ( ");
+
+ String primaryKeyList = "";
+
+ final HashMap<String, String> foreignKeys = new HashMap<String, String>();
+ final HashMap<String, String> foreignKeyRefs = new HashMap<String, String>();
+
+ final HsqlColumnDescriptor[] columns = _tableDesc.getColumns();
+ for (int i = 0; i < columns.length; ++i)
+ {
+ if (i > 0)
+ {
+ createStatement.append(", ");
+ }
+
+ createStatement.append("\"").append(columns[i].getName());
+ createStatement.append("\" ").append(columns[i].getTypeName());
+
+ if (columns[i].isRequired())
+ {
+ createStatement.append(" NOT NULL");
+ }
+
+ if (columns[i].isPrimaryKey())
+ {
+ if (primaryKeyList.length() > 0)
+ {
+ primaryKeyList += ", ";
+ }
+ primaryKeyList += "\"" + columns[i].getName() + "\"";
+ }
+
+ if (columns[i].isForeignKey())
+ {
+ final String foreignTable = columns[i].getForeignTable();
+
+ String foreignKeysForTable = foreignKeys.containsKey(foreignTable) ? foreignKeys.get(foreignTable) : "";
+ if (foreignKeysForTable.length() > 0)
+ {
+ foreignKeysForTable += ", ";
+ }
+ foreignKeysForTable += "\"" + columns[i].getName() + "\"";
+ foreignKeys.put(foreignTable, foreignKeysForTable);
+
+ final StringBuffer foreignKeyRefsForTable = new StringBuffer(foreignKeyRefs.containsKey(foreignTable) ? foreignKeyRefs.get(foreignTable) : "");
+ if (foreignKeyRefsForTable.length() > 0)
+ {
+ foreignKeyRefsForTable.append(", ");
+ }
+ foreignKeyRefsForTable.append("\"").append(columns[i].getForeignColumn()).append("\"");
+ foreignKeyRefs.put(foreignTable, foreignKeyRefsForTable.toString());
+ }
+ }
+
+ if (primaryKeyList.length() > 0)
+ {
+ createStatement.append(", PRIMARY KEY (");
+ createStatement.append(primaryKeyList);
+ createStatement.append(')');
+ }
+
+ for (Map.Entry<String, String> foreignKey : foreignKeys.entrySet())
+ {
+ final String foreignTable = foreignKey.getKey();
+
+ createStatement.append(", FOREIGN KEY (");
+ createStatement.append(foreignKey.getValue());
+ createStatement.append(") REFERENCES \"");
+ createStatement.append(foreignTable);
+ createStatement.append("\"(");
+ createStatement.append(foreignKeyRefs.get(foreignTable));
+ createStatement.append(')');
+ }
+
+ createStatement.append(')');
+
+ executeSQL(createStatement.toString());
+ }
+
+ /** creates a table in the database. using the SDBCX-API
+ */
+ public void createTableInSDBCX(final HsqlTableDescriptor _tableDesc) throws SQLException, ElementExistException
+ {
+ final XPropertySet sdbcxDescriptor = _tableDesc.createSdbcxDescriptor(defaultConnection());
+ final XTablesSupplier suppTables = UnoRuntime.queryInterface( XTablesSupplier.class, defaultConnection().getXConnection() );
+ final XAppend appendTable = UnoRuntime.queryInterface( XAppend.class, suppTables.getTables() );
+ appendTable.appendByDescriptor(sdbcxDescriptor);
+ }
+
+ private File m_documentFile;
+}
diff --git a/connectivity/qa/connectivity/tools/HsqlTableDescriptor.java b/connectivity/qa/connectivity/tools/HsqlTableDescriptor.java
new file mode 100644
index 000000000..626f62eb8
--- /dev/null
+++ b/connectivity/qa/connectivity/tools/HsqlTableDescriptor.java
@@ -0,0 +1,93 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+package connectivity.tools;
+
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.container.XNameAccess;
+import com.sun.star.sdbc.ColumnValue;
+import com.sun.star.sdbcx.XColumnsSupplier;
+import com.sun.star.sdbcx.XDataDescriptorFactory;
+import com.sun.star.sdbcx.XTablesSupplier;
+import com.sun.star.uno.UnoRuntime;
+import connectivity.tools.sdb.Connection;
+
+/** is a very simply descriptor of a HSQL table, to be used with a HsqlDatabase.createTable method
+ */
+public class HsqlTableDescriptor
+{
+ private final String m_name;
+ private final HsqlColumnDescriptor[] m_columns;
+
+ /** Creates a new instance of HsqlTableDescriptor */
+ public HsqlTableDescriptor( String _name, HsqlColumnDescriptor[] _columns )
+ {
+ m_name = _name;
+ m_columns = _columns;
+ }
+
+ /** returns the name of the table
+ */
+ public String getName()
+ {
+ return m_name;
+ }
+
+ /** returns the set of column descriptors for the table
+ */
+ public HsqlColumnDescriptor[] getColumns()
+ {
+ return m_columns;
+ }
+
+ public XPropertySet createSdbcxDescriptor( Connection _forConnection )
+ {
+ XTablesSupplier suppTables = UnoRuntime.queryInterface( XTablesSupplier.class, _forConnection.getXConnection() );
+ XDataDescriptorFactory tableDescFac = UnoRuntime.queryInterface( XDataDescriptorFactory.class, suppTables.getTables() );
+ XPropertySet tableDesc = tableDescFac.createDataDescriptor();
+
+ try
+ {
+ tableDesc.setPropertyValue( "Name", getName() );
+ }
+ catch ( Exception e ) { e.printStackTrace( System.err ); }
+
+ XColumnsSupplier suppDescCols = UnoRuntime.queryInterface( XColumnsSupplier.class, tableDesc );
+
+ XNameAccess descColumns = suppDescCols.getColumns();
+ XDataDescriptorFactory columnDescFac = UnoRuntime.queryInterface( XDataDescriptorFactory.class, descColumns );
+
+ HsqlColumnDescriptor[] myColumns = getColumns();
+ for ( int i = 0; i < myColumns.length; ++i )
+ {
+ XPropertySet columnDesc = columnDescFac.createDataDescriptor();
+ try
+ {
+ columnDesc.setPropertyValue( "Name", myColumns[i].getName() );
+ columnDesc.setPropertyValue( "IsNullable", Integer.valueOf( myColumns[i].isRequired() ? ColumnValue.NO_NULLS : ColumnValue.NULLABLE) );
+ columnDesc.setPropertyValue( "TypeName", myColumns[i].getTypeName() );
+ if ( myColumns[i].isPrimaryKey() || myColumns[i].isForeignKey() )
+ // not yet implemented
+ throw new java.lang.UnsupportedOperationException("creating a primary or foreign key via SDBCX not yet implemented" );
+ }
+ catch( com.sun.star.uno.Exception e ) { e.printStackTrace( System.err ); }
+ }
+
+ return tableDesc;
+ }
+}
diff --git a/connectivity/qa/connectivity/tools/QueryDefinition.java b/connectivity/qa/connectivity/tools/QueryDefinition.java
new file mode 100644
index 000000000..fc3cba382
--- /dev/null
+++ b/connectivity/qa/connectivity/tools/QueryDefinition.java
@@ -0,0 +1,49 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+package connectivity.tools;
+
+import com.sun.star.beans.UnknownPropertyException;
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.lang.WrappedTargetException;
+
+public class QueryDefinition
+{
+ private final XPropertySet m_queryDef;
+
+ public QueryDefinition( XPropertySet _queryDef )
+ {
+ m_queryDef = _queryDef;
+ }
+
+ /** retrieves the command underlying the query definition
+ *
+ * This method is a mere wrapped around the <code>getPropertyValue( "Command" )</code> call
+ */
+ public final String getCommand() throws WrappedTargetException
+ {
+ String command = null;
+ try {
+ command = (String)m_queryDef.getPropertyValue( "Command" );
+ }
+ catch (UnknownPropertyException e) { }
+
+ return command;
+ }
+
+}
diff --git a/connectivity/qa/connectivity/tools/RowSet.java b/connectivity/qa/connectivity/tools/RowSet.java
new file mode 100644
index 000000000..22b52156f
--- /dev/null
+++ b/connectivity/qa/connectivity/tools/RowSet.java
@@ -0,0 +1,288 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+package connectivity.tools;
+
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.container.XIndexAccess;
+import com.sun.star.container.XNameAccess;
+import com.sun.star.io.XInputStream;
+import com.sun.star.lang.XComponent;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.sdbc.SQLException;
+import com.sun.star.sdbc.XArray;
+import com.sun.star.sdbc.XBlob;
+import com.sun.star.sdbc.XClob;
+import com.sun.star.sdbc.XRef;
+import com.sun.star.sdbc.XRow;
+import com.sun.star.sdbc.XRowSet;
+import com.sun.star.sdbc.XRowSetListener;
+import com.sun.star.sdbcx.XColumnsSupplier;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.util.Date;
+import com.sun.star.util.DateTime;
+import com.sun.star.util.Time;
+
+public class RowSet implements XRowSet, XRow
+{
+ private XRowSet m_rowSet;
+ private XRow m_row;
+
+ public RowSet( XMultiServiceFactory _orb, String _dataSource, int _commandType, String _command )
+ {
+ try
+ {
+ XPropertySet rowSetProps = UnoRuntime.queryInterface( XPropertySet.class, _orb.createInstance( "com.sun.star.sdb.RowSet" ) );
+ rowSetProps.setPropertyValue( "DataSourceName", _dataSource );
+ rowSetProps.setPropertyValue( "CommandType", Integer.valueOf( _commandType ) );
+ rowSetProps.setPropertyValue( "Command", _command );
+
+ m_rowSet = UnoRuntime.queryInterface( XRowSet.class, rowSetProps );
+ m_row = UnoRuntime.queryInterface( XRow.class, rowSetProps );
+ }
+ catch ( Exception e )
+ {
+ throw new java.lang.RuntimeException(e);
+ }
+ }
+
+ // misc
+ public int getColumnCount()
+ {
+ XColumnsSupplier suppCols = UnoRuntime.queryInterface(
+ XColumnsSupplier.class, m_rowSet );
+ XIndexAccess columns = UnoRuntime.queryInterface(
+ XIndexAccess.class, suppCols.getColumns() );
+ return columns.getCount();
+ }
+
+ // XRowSet
+ public void execute() throws SQLException
+ {
+ m_rowSet.execute();
+ }
+
+ public void addRowSetListener( XRowSetListener _listener )
+ {
+ m_rowSet.addRowSetListener( _listener );
+ }
+
+ public void removeRowSetListener( XRowSetListener _listener )
+ {
+ m_rowSet.removeRowSetListener( _listener );
+ }
+
+ public boolean next() throws SQLException
+ {
+ return m_rowSet.next();
+ }
+
+ public boolean isBeforeFirst() throws SQLException
+ {
+ return m_rowSet.isBeforeFirst();
+ }
+
+ public boolean isAfterLast() throws SQLException
+ {
+ return m_rowSet.isAfterLast();
+ }
+
+ public boolean isFirst() throws SQLException
+ {
+ return m_rowSet.isFirst();
+ }
+
+ public boolean isLast() throws SQLException
+ {
+ return m_rowSet.isLast();
+ }
+
+ public void beforeFirst() throws SQLException
+ {
+ m_rowSet.beforeFirst();
+ }
+
+ public void afterLast() throws SQLException
+ {
+ m_rowSet.afterLast();
+ }
+
+ public boolean first() throws SQLException
+ {
+ return m_rowSet.first();
+ }
+
+ public boolean last() throws SQLException
+ {
+ return m_rowSet.last();
+ }
+
+ public int getRow() throws SQLException
+ {
+ return m_rowSet.getRow();
+ }
+
+ public boolean absolute(int i) throws SQLException
+ {
+ return m_rowSet.absolute(i);
+ }
+
+ public boolean relative(int i) throws SQLException
+ {
+ return m_rowSet.relative(i);
+ }
+
+ public boolean previous() throws SQLException
+ {
+ return m_rowSet.previous();
+ }
+
+ public void refreshRow() throws SQLException
+ {
+ m_rowSet.refreshRow();
+ }
+
+ public boolean rowUpdated() throws SQLException
+ {
+ return m_rowSet.rowUpdated();
+ }
+
+ public boolean rowInserted() throws SQLException
+ {
+ return m_rowSet.rowInserted();
+ }
+
+ public boolean rowDeleted() throws SQLException
+ {
+ return m_rowSet.rowDeleted();
+ }
+
+ // XRow
+ public Object getStatement() throws SQLException
+ {
+ return m_rowSet.getStatement();
+ }
+
+ public boolean wasNull() throws SQLException
+ {
+ return m_row.wasNull();
+ }
+
+ public String getString(int i) throws SQLException
+ {
+ return m_row.getString(i);
+ }
+
+ public boolean getBoolean(int i) throws SQLException
+ {
+ return m_row.getBoolean(i);
+ }
+
+ public byte getByte(int i) throws SQLException
+ {
+ return m_row.getByte(i);
+ }
+
+ public short getShort(int i) throws SQLException
+ {
+ return m_row.getShort(i);
+ }
+
+ public int getInt(int i) throws SQLException
+ {
+ return m_row.getInt(i);
+ }
+
+ public long getLong(int i) throws SQLException
+ {
+ return m_row.getLong(i);
+ }
+
+ public float getFloat(int i) throws SQLException
+ {
+ return m_row.getFloat(i);
+ }
+
+ public double getDouble(int i) throws SQLException
+ {
+ return m_row.getDouble(i);
+ }
+
+ public byte[] getBytes(int i) throws SQLException
+ {
+ return m_row.getBytes(i);
+ }
+
+ public Date getDate(int i) throws SQLException
+ {
+ return m_row.getDate(i);
+ }
+
+ public Time getTime(int i) throws SQLException
+ {
+ return m_row.getTime(i);
+ }
+
+ public DateTime getTimestamp(int i) throws SQLException
+ {
+ return m_row.getTimestamp(i);
+ }
+
+ public XInputStream getBinaryStream(int i) throws SQLException
+ {
+ return m_row.getBinaryStream(i);
+ }
+
+ public XInputStream getCharacterStream(int i) throws SQLException
+ {
+ return m_row.getCharacterStream(i);
+ }
+
+ public Object getObject(int i, XNameAccess xNameAccess) throws SQLException
+ {
+ return m_row.getObject(i, xNameAccess);
+ }
+
+ public XRef getRef(int i) throws SQLException
+ {
+ return m_row.getRef(i);
+ }
+
+ public XBlob getBlob(int i) throws SQLException
+ {
+ return m_row.getBlob(i);
+ }
+
+ public XClob getClob(int i) throws SQLException
+ {
+ return m_row.getClob(i);
+ }
+
+ public XArray getArray(int i) throws SQLException
+ {
+ return m_row.getArray(i);
+ }
+
+ public void dispose()
+ {
+ if ( m_rowSet == null )
+ return;
+ XComponent rowSetComp = UnoRuntime.queryInterface( XComponent.class, m_rowSet );
+ rowSetComp.dispose();
+ }
+}
diff --git a/connectivity/qa/connectivity/tools/sdb/Connection.java b/connectivity/qa/connectivity/tools/sdb/Connection.java
new file mode 100644
index 000000000..d713de379
--- /dev/null
+++ b/connectivity/qa/connectivity/tools/sdb/Connection.java
@@ -0,0 +1,80 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+package connectivity.tools.sdb;
+
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.sdb.XSingleSelectQueryComposer;
+import com.sun.star.sdbc.SQLException;
+import com.sun.star.sdbc.XConnection;
+import com.sun.star.sdbc.XPreparedStatement;
+import com.sun.star.sdbc.XStatement;
+import com.sun.star.sdbcx.XTablesSupplier;
+import com.sun.star.uno.Exception;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.util.XRefreshable;
+
+/**
+ * is a convenience wrapper around a SDB-level connection object
+ */
+public class Connection
+{
+ private final XConnection m_connection;
+
+ public Connection( final XConnection _connection )
+ {
+ m_connection = _connection;
+ }
+
+ public XConnection getXConnection()
+ {
+ return m_connection;
+ }
+
+ public void refreshTables()
+ {
+ final XTablesSupplier suppTables = UnoRuntime.queryInterface(XTablesSupplier.class, m_connection);
+ final XRefreshable refresh = UnoRuntime.queryInterface( XRefreshable.class, suppTables.getTables() );
+ refresh.refresh();
+ }
+
+ public XSingleSelectQueryComposer createSingleSelectQueryComposer() throws Exception
+ {
+ final XMultiServiceFactory connectionFactory = UnoRuntime.queryInterface( XMultiServiceFactory.class, m_connection );
+ return UnoRuntime.queryInterface(
+ XSingleSelectQueryComposer.class, connectionFactory.createInstance( "com.sun.star.sdb.SingleSelectQueryComposer" ) );
+ }
+
+ public
+ XStatement createStatement() throws SQLException
+ {
+ return m_connection.createStatement();
+ }
+
+ public
+ XPreparedStatement prepareStatement( String _sql ) throws SQLException
+ {
+ return m_connection.prepareStatement( _sql );
+ }
+
+ public
+ void close() throws SQLException
+ {
+ m_connection.close();
+ }
+}