https://bugs.documentfoundation.org/show_bug.cgi?id=130564

Julien Nabet <serval2...@yahoo.fr> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |lio...@mamane.lu

--- Comment #9 from Julien Nabet <serval2...@yahoo.fr> ---
After some debugging, here's a code pointer which explains why the creating a
view option only shows when a view exists:
    306         // check if we support types
    307         if ( xMeta.is() )
    308         {
    309             Reference<XResultSet> xRes = xMeta->getTableTypes();
    310             if(xRes.is())
    311             {
    312                 Reference<XRow> xRow(xRes,UNO_QUERY);
    313                 while(xRes->next())
    314                 {
    315                     OUString sValue = xRow->getString(1);
    316                     if( !xRow->wasNull() && sValue == "VIEW")
    317                     {
    318                         m_bSupportsViews = true;
    319                         break;
    320                     }
    321                 }
    322             }
    323             // some dbs don't support this type so we should ask if a
XViewsSupplier is supported
    324             if(!m_bSupportsViews)
    325             {
    326                 Reference< XViewsSupplier >
xMaster(getMasterTables(),UNO_QUERY);
    327 
    328                 if (xMaster.is() && xMaster->getViews().is())
    329                     m_bSupportsViews = true;
    330             }
    331             if(m_bSupportsViews)
    332             {
    333                 m_pViews.reset( new OViewContainer(*this, m_aMutex,
this, bCase, this, m_nInAppend) );
    334                 m_pViews->addContainerListener(m_pTables.get());
    335                 m_pTables->addContainerListener(m_pViews.get());
    336             }
see
https://opengrok.libreoffice.org/xref/core/dbaccess/source/core/dataaccess/connection.cxx?r=bc3a0205#307

getTableTypes is implemented for each database connector so also for ODBC.
Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTableTypes(  )
{
    Reference< XResultSet > xRef;
    try
    {
        rtl::Reference<ODatabaseMetaDataResultSet> pResult = new
ODatabaseMetaDataResultSet(m_pConnection);
        xRef = pResult;
        pResult->openTablesTypes();
    }
    catch(SQLException&)
    {
        xRef = new
::connectivity::ODatabaseMetaDataResultSet(::connectivity::ODatabaseMetaDataResultSet::eTableTypes);
    }
    return xRef;
}
See
https://opengrok.libreoffice.org/xref/core/connectivity/source/drivers/odbc/ODatabaseMetaData.cxx?r=dffe9495#715

It uses "openTablesTypes"
void ODatabaseMetaDataResultSet::openTablesTypes( )
{
    SQLRETURN nRetcode = N3SQLTables(m_aStatementHandle,
                            nullptr,0,
                            nullptr,0,
                            nullptr,0,
                            reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char
*>(SQL_ALL_TABLE_TYPES)),SQL_NTS);
   
OTools::ThrowException(m_pConnection.get(),nRetcode,m_aStatementHandle,SQL_HANDLE_STMT,*this);

    m_aColMapping.clear();
    m_aColMapping.push_back(-1);
    m_aColMapping.push_back(4);
    m_xMetaData = new
OResultSetMetaData(m_pConnection.get(),m_aStatementHandle,std::vector(m_aColMapping));
    checkColumnCount();
}
See
https://opengrok.libreoffice.org/xref/core/connectivity/source/drivers/odbc/ODatabaseMetaDataResultSet.cxx?r=7c3990c3#872

The pb is the ODBC function used
(https://docs.microsoft.com/en-us/sql/odbc/reference/syntax/sqltables-function?view=sql-server-ver15)
retrieves types from existing elements not types from every elements possible
in a database like original "getTableTypes" from JDBC (see
https://docs.oracle.com/javase/7/docs/api/java/sql/DatabaseMetaData.html#getTableTypes()).
So if there's no existing VIEW in the database (Mysql, Postgresql, whatever),
the first method never goes in line 318 ( m_bSupportsViews = true;)

So LO tries another way by calling getMasterTables() and when digging a bit, it
tries to call getDataDefinitionByURLAndConnection()
(See
https://opengrok.libreoffice.org/xref/core/connectivity/source/commontools/dbtools2.cxx?r=d8538d7f#660)
    660 Reference< XTablesSupplier> getDataDefinitionByURLAndConnection(
    661             const OUString& _rsUrl,
    662             const Reference< XConnection>& _xConnection,
    663             const Reference< XComponentContext >& _rxContext)
    664 {
    665     Reference< XTablesSupplier> xTablesSup;
    666     try
    667     {
    668         Reference< XDriverManager2 > xManager = DriverManager::create(
_rxContext );
    669         Reference< XDataDefinitionSupplier > xSupp(
xManager->getDriverByURL( _rsUrl ), UNO_QUERY );
    670 
    671         if ( xSupp.is() )
    672         {
    673             xTablesSup = xSupp->getDataDefinitionByConnection(
_xConnection );
    674             OSL_ENSURE(xTablesSup.is(),"No table supplier!");
    675         }
    676     }
    677     catch( const Exception& )
    678     {
    679         DBG_UNHANDLED_EXCEPTION("connectivity.commontools");
    680     }
    681     return xTablesSup;
    682 }


and finally since ODBC connector in LO doesn't implement
XDataDefinitionSupplier, it doesn't go into the "if" and returns empty ref
"xTablesSup".

So now, what to do?
Taking a look how to implement "XDataDefinitionSupplier", it seems we need
catalog part, which needs tables part and perhaps views part.

I tried this with Mysql direct connector, it takes some time and perhaps there
are regressions in what I did. Moreover, calling ODBC functions is less easy
than looking into INFORMATION_SCHEMA.

A radical (and I suppose wrong) workaround would be in
ODatabaseMetaData::getTableTypes from odbc part to just return "VIEW" (in a
Reference< XResultSet >) since getTableTypes is only used to know if "VIEW"
concept is known.
It would mean we'd consider every database which can be accessed from ODBC
driver would support VIEWS (!!).

Lionel: if you've got some idea here, don't hesitate! :-)

-- 
You are receiving this mail because:
You are the assignee for the bug.

Reply via email to