1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_dbaccess.hxx"
26 
27 #include "viewcontainer.hxx"
28 #include "dbastrings.hrc"
29 #include "core_resource.hxx"
30 #include "core_resource.hrc"
31 #include "View.hxx"
32 
33 #include <tools/debug.hxx>
34 #include <tools/wldcrd.hxx>
35 #include <comphelper/enumhelper.hxx>
36 #include <comphelper/types.hxx>
37 #include <connectivity/dbtools.hxx>
38 #include <comphelper/extract.hxx>
39 #include <connectivity/dbexception.hxx>
40 #include <rtl/ustrbuf.hxx>
41 
42 #include <com/sun/star/beans/XPropertySet.hpp>
43 #include <com/sun/star/sdbc/XConnection.hpp>
44 #include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
45 #include <com/sun/star/sdbc/KeyRule.hpp>
46 #include <com/sun/star/sdbc/ColumnValue.hpp>
47 #include <com/sun/star/sdbc/XRow.hpp>
48 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
49 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
50 #include <com/sun/star/sdbcx/KeyType.hpp>
51 
52 using namespace dbaccess;
53 using namespace dbtools;
54 using namespace ::com::sun::star::uno;
55 using namespace ::com::sun::star::lang;
56 using namespace ::com::sun::star::beans;
57 using namespace ::com::sun::star::sdbc;
58 using namespace ::com::sun::star::sdb;
59 using namespace ::com::sun::star::sdbcx;
60 using namespace ::com::sun::star::util;
61 using namespace ::com::sun::star::container;
62 using namespace ::osl;
63 using namespace ::comphelper;
64 using namespace ::cppu;
65 using namespace ::connectivity::sdbcx;
66 
67 //==========================================================================
68 //= OViewContainer
69 //==========================================================================
DBG_NAME(OViewContainer)70 DBG_NAME(OViewContainer)
71 //------------------------------------------------------------------------------
72 OViewContainer::OViewContainer(::cppu::OWeakObject& _rParent
73 								 ,::osl::Mutex& _rMutex
74 								 ,const Reference< XConnection >& _xCon
75 								 ,sal_Bool _bCase
76 								 ,IRefreshListener*	_pRefreshListener
77 								 ,::dbtools::IWarningsContainer* _pWarningsContainer
78                                  ,oslInterlockedCount& _nInAppend)
79 	:OFilteredContainer(_rParent,_rMutex,_xCon,_bCase,_pRefreshListener,_pWarningsContainer,_nInAppend)
80     ,m_bInElementRemoved(false)
81 {
82     DBG_CTOR(OViewContainer, NULL);
83 }
84 
85 //------------------------------------------------------------------------------
~OViewContainer()86 OViewContainer::~OViewContainer()
87 {
88 	//	dispose();
89 	DBG_DTOR(OViewContainer, NULL);
90 }
91 //------------------------------------------------------------------------------
92 // XServiceInfo
93 //------------------------------------------------------------------------------
94 IMPLEMENT_SERVICE_INFO2(OViewContainer, "com.sun.star.sdb.dbaccess.OViewContainer", SERVICE_SDBCX_CONTAINER, SERVICE_SDBCX_TABLES)
95 // -----------------------------------------------------------------------------
createObject(const::rtl::OUString & _rName)96 ObjectType OViewContainer::createObject(const ::rtl::OUString& _rName)
97 {
98 	ObjectType xProp;
99 	if ( m_xMasterContainer.is() && m_xMasterContainer->hasByName(_rName) )
100 		xProp.set(m_xMasterContainer->getByName(_rName),UNO_QUERY);
101 
102 	if ( !xProp.is() )
103 	{
104 		::rtl::OUString sCatalog,sSchema,sTable;
105 		::dbtools::qualifiedNameComponents(m_xMetaData,
106 											_rName,
107 											sCatalog,
108 											sSchema,
109 											sTable,
110 											::dbtools::eInDataManipulation);
111 		return new View(m_xConnection,
112                         isCaseSensitive(),
113                         sCatalog,
114 						sSchema,
115 						sTable
116 						);
117 	}
118 
119 	return xProp;
120 }
121 // -----------------------------------------------------------------------------
createDescriptor()122 Reference< XPropertySet > OViewContainer::createDescriptor()
123 {
124 	Reference< XPropertySet > xRet;
125 	// frist we have to look if the master tables does support this
126 	// and if then create a table object as well with the master tables
127 	Reference<XColumnsSupplier > xMasterColumnsSup;
128 	Reference<XDataDescriptorFactory> xDataFactory(m_xMasterContainer,UNO_QUERY);
129 	if(xDataFactory.is())
130 		xRet = xDataFactory->createDataDescriptor();
131 	else
132 		xRet = new ::connectivity::sdbcx::OView(isCaseSensitive(),m_xMetaData);
133 
134 	return xRet;
135 }
136 // -----------------------------------------------------------------------------
137 // XAppend
appendObject(const::rtl::OUString & _rForName,const Reference<XPropertySet> & descriptor)138 ObjectType OViewContainer::appendObject( const ::rtl::OUString& _rForName, const Reference< XPropertySet >& descriptor )
139 {
140 	// append the new table with a create stmt
141 	::rtl::OUString aName = getString(descriptor->getPropertyValue(PROPERTY_NAME));
142 
143 	Reference<XAppend> xAppend(m_xMasterContainer,UNO_QUERY);
144 	Reference< XPropertySet > xProp = descriptor;
145 	if(xAppend.is())
146 	{
147         EnsureReset aReset(m_nInAppend);
148 
149         xAppend->appendByDescriptor(descriptor);
150 		if(m_xMasterContainer->hasByName(aName))
151 			xProp.set(m_xMasterContainer->getByName(aName),UNO_QUERY);
152 	}
153 	else
154 	{
155 		::rtl::OUString sComposedName = ::dbtools::composeTableName( m_xMetaData, descriptor, ::dbtools::eInTableDefinitions, false, false, true );
156 		if(!sComposedName.getLength())
157 			::dbtools::throwFunctionSequenceException(static_cast<XTypeProvider*>(static_cast<OFilteredContainer*>(this)));
158 
159 		::rtl::OUString sCommand;
160 		descriptor->getPropertyValue(PROPERTY_COMMAND) >>= sCommand;
161 
162         ::rtl::OUStringBuffer aSQL;
163         aSQL.appendAscii( "CREATE VIEW " );
164         aSQL.append     ( sComposedName );
165         aSQL.appendAscii( " AS " );
166         aSQL.append     ( sCommand );
167 
168 		Reference<XConnection> xCon = m_xConnection;
169 		OSL_ENSURE(xCon.is(),"Connection is null!");
170 		if ( xCon.is() )
171 		{
172             ::utl::SharedUNOComponent< XStatement > xStmt( xCon->createStatement() );
173 			if ( xStmt.is() )
174 				xStmt->execute( aSQL.makeStringAndClear() );
175 		}
176 	}
177 
178     return createObject( _rForName );
179 }
180 // -------------------------------------------------------------------------
181 // XDrop
dropObject(sal_Int32 _nPos,const::rtl::OUString _sElementName)182 void OViewContainer::dropObject(sal_Int32 _nPos,const ::rtl::OUString _sElementName)
183 {
184     if ( !m_bInElementRemoved )
185     {
186 	    Reference< XDrop > xDrop(m_xMasterContainer,UNO_QUERY);
187 	    if(xDrop.is())
188 		    xDrop->dropByName(_sElementName);
189 	    else
190 	    {
191 		    ::rtl::OUString sCatalog,sSchema,sTable,sComposedName;
192 
193 		    Reference<XPropertySet> xTable(getObject(_nPos),UNO_QUERY);
194 		    if ( xTable.is() )
195 		    {
196 			    xTable->getPropertyValue(PROPERTY_CATALOGNAME)	>>= sCatalog;
197 			    xTable->getPropertyValue(PROPERTY_SCHEMANAME)	>>= sSchema;
198 			    xTable->getPropertyValue(PROPERTY_NAME)			>>= sTable;
199 
200 			    sComposedName = ::dbtools::composeTableName( m_xMetaData, sCatalog, sSchema, sTable, sal_True, ::dbtools::eInTableDefinitions );
201 		    }
202 
203 		    if(!sComposedName.getLength())
204 			    ::dbtools::throwFunctionSequenceException(static_cast<XTypeProvider*>(static_cast<OFilteredContainer*>(this)));
205 
206 		    ::rtl::OUString aSql = ::rtl::OUString::createFromAscii("DROP VIEW ");
207 		    aSql += sComposedName;
208 		    Reference<XConnection> xCon = m_xConnection;
209 		    OSL_ENSURE(xCon.is(),"Connection is null!");
210 		    if ( xCon.is() )
211 		    {
212 			    Reference< XStatement > xStmt = xCon->createStatement(  );
213 			    if(xStmt.is())
214 				    xStmt->execute(aSql);
215 			    ::comphelper::disposeComponent(xStmt);
216 		    }
217 	    }
218     }
219 }
220 // -----------------------------------------------------------------------------
elementInserted(const ContainerEvent & Event)221 void SAL_CALL OViewContainer::elementInserted( const ContainerEvent& Event ) throw (RuntimeException)
222 {
223 	::osl::MutexGuard aGuard(m_rMutex);
224 	::rtl::OUString sName;
225 	if  (   ( Event.Accessor >>= sName )
226         &&  ( !m_nInAppend )
227         &&  ( !hasByName( sName ) )
228         )
229 	{
230 		Reference<XPropertySet> xProp(Event.Element,UNO_QUERY);
231 		::rtl::OUString sType;
232 		xProp->getPropertyValue(PROPERTY_TYPE) >>= sType;
233 		if ( sType == ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("VIEW")) )
234 			insertElement(sName,createObject(sName));
235 	}
236 }
237 // -----------------------------------------------------------------------------
elementRemoved(const ContainerEvent & Event)238 void SAL_CALL OViewContainer::elementRemoved( const ContainerEvent& Event ) throw (RuntimeException)
239 {
240     ::osl::MutexGuard aGuard(m_rMutex);
241 	::rtl::OUString sName;
242 	if ( (Event.Accessor >>= sName) && hasByName(sName) )
243 	{
244         m_bInElementRemoved = true;
245         try
246         {
247             dropByName(sName);
248         }
249 	    catch(Exception&)
250 	    {
251 		    m_bInElementRemoved = sal_False;
252 		    throw;
253 	    }
254         m_bInElementRemoved = false;
255 	}
256 }
257 // -----------------------------------------------------------------------------
disposing(const::com::sun::star::lang::EventObject &)258 void SAL_CALL OViewContainer::disposing( const ::com::sun::star::lang::EventObject& /*Source*/ ) throw (RuntimeException)
259 {
260 }
261 // -----------------------------------------------------------------------------
elementReplaced(const ContainerEvent &)262 void SAL_CALL OViewContainer::elementReplaced( const ContainerEvent& /*Event*/ ) throw (RuntimeException)
263 {
264 }
265 // -----------------------------------------------------------------------------
getTableTypeRestriction() const266 ::rtl::OUString OViewContainer::getTableTypeRestriction() const
267 {
268     // no restriction at all (other than the ones provided externally)
269     return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "VIEW" ) );
270 }
271