SemanticMediaWiki/SemanticResultFormats

[datatables] ($store) must be of type SMW\SQLStore\SQLStore, SMW\SPARQLStore\SPARQLStore given

simontaurus opened this issue · 5 comments

Setup

  • MW version: 1.39.5
  • DB (MySQL etc.): MySQL 8.0.17, blazegraph
  • PHP version: 8.1.27 (apache2handler)
  • SMW version: 4.1.3
  • SRF version: 4.2.1
  • Browsers and versions (if applicable): Firefox

Issue

(@thomas-topway-it)
Sporadically pages with a datatables query throw the mentioned error, probably when a purge is executed but it's hard to reproduce

Exception caught: SMW\SQLStore\QueryEngineFactory::__construct(): Argument #1 ($store) must be of type SMW\SQLStore\SQLStore, SMW\SPARQLStore\SPARQLStore given, called in /var/www/html/w/extensions/SemanticResultFormats/formats/datatables/DataTables.php on line 727

The corresponding line is now in:

$this->queryEngineFactory = new QueryEngineFactory( $this->datatables->store );

Not sure in which cases QueryResult->getStore() returns SMW\SPARQLStore\SPARQLStore in a SPARQLStore setup.

$this->store = $res->getStore();

Workaround is to catch cases where SMW\SPARQLStore\SPARQLStore is given

if ( !( $this->store instanceof \SMW\SQLStore\SQLStore ) ) return [];

Steps to reproduce

  1. Setup with SPARQLStore
  2. Page with datatable ask query
{{#ask: [[Category:A...]]
|?Modification date
|format=datatable
|datatables-searchPanes=true
|datatables-searchPanes.initCollapsed=true
|sort=Modification date
|order=desc
}}
  1. Refresh / purge the page

Expected result: No exception

Observed result: exception occurs:

[e288ba64ad67a5461d8397e1] /wiki/Item:OSW1403aaa3e5ab4... TypeError: SMW\SQLStore\QueryEngineFactory::__construct(): Argument #1 ($store) must be of type SMW\SQLStore\SQLStore, SMW\SPARQLStore\SPARQLStore given, called in /var/www/html/w/extensions/SemanticResultFormats/formats/datatables/DataTables.php on line 725

Backtrace:

from /var/www/html/w/extensions/SemanticMediaWiki/src/SQLStore/QueryEngineFactory.php(36)
#0 /var/www/html/w/extensions/SemanticResultFormats/formats/datatables/DataTables.php(725): SMW\SQLStore\QueryEngineFactory->__construct()
#1 /var/www/html/w/extensions/SemanticResultFormats/formats/datatables/DataTables.php(522): SRF\DataTables->getSearchPanes()
#2 /var/www/html/w/extensions/SemanticResultFormats/formats/datatables/DataTables.php(395): SRF\DataTables->getResultText()
#3 /var/www/html/w/extensions/SemanticMediaWiki/src/Query/ResultPrinters/ResultPrinter.php(304): SRF\DataTables->buildResult()
#4 /var/www/html/w/extensions/SemanticMediaWiki/includes/query/SMW_QueryProcessor.php(348): SMW\Query\ResultPrinters\ResultPrinter->getResult()
#5 /var/www/html/w/extensions/SemanticMediaWiki/src/ParserFunctions/AskParserFunction.php(370): SMWQueryProcessor::getResultFromQuery()
#6 /var/www/html/w/extensions/SemanticMediaWiki/src/ParserFunctions/AskParserFunction.php(202): SMW\ParserFunctions\AskParserFunction->doFetchResultsFromFunctionParameters()
#7 /var/www/html/w/extensions/SemanticMediaWiki/src/ParserFunctionFactory.php(402): SMW\ParserFunctions\AskParserFunction->parse()
#8 /var/www/html/w/includes/parser/Parser.php(3437): SMW\ParserFunctionFactory->SMW\{closure}()
#9 /var/www/html/w/includes/parser/Parser.php(3122): Parser->callParserFunction()
#10 /var/www/html/w/includes/parser/PPFrame_Hash.php(275): Parser->braceSubstitution()
#11 /var/www/html/w/extensions/Scribunto/includes/engines/LuaCommon/LuaEngine.php(928): PPFrame_Hash->expand()
#12 /var/www/html/w/extensions/Scribunto/includes/engines/LuaCommon/LuaEngine.php(862): Scribunto_LuaEngine->doCachedExpansion()
#13 /var/www/html/w/extensions/Scribunto/includes/engines/LuaStandalone/LuaStandaloneInterpreter.php(399): Scribunto_LuaEngine->preprocess()
#14 /var/www/html/w/extensions/Scribunto/includes/engines/LuaStandalone/LuaStandaloneInterpreter.php(370): MediaWiki\Extension\Scribunto\Engines\LuaStandalone\LuaStandaloneInterpreter->callback()
#15 /var/www/html/w/extensions/Scribunto/includes/engines/LuaStandalone/LuaStandaloneInterpreter.php(446): MediaWiki\Extension\Scribunto\Engines\LuaStandalone\LuaStandaloneInterpreter->handleCall()
#16 /var/www/html/w/extensions/Scribunto/includes/engines/LuaStandalone/LuaStandaloneInterpreter.php(277): MediaWiki\Extension\Scribunto\Engines\LuaStandalone\LuaStandaloneInterpreter->dispatch()
#17 /var/www/html/w/extensions/Scribunto/includes/engines/LuaCommon/LuaEngine.php(302): MediaWiki\Extension\Scribunto\Engines\LuaStandalone\LuaStandaloneInterpreter->callFunction()
#18 /var/www/html/w/extensions/Scribunto/includes/engines/LuaCommon/LuaModule.php(71): Scribunto_LuaEngine->executeFunctionChunk()
#19 /var/www/html/w/extensions/Scribunto/includes/Hooks.php(158): Scribunto_LuaModule->invoke()
#20 /var/www/html/w/includes/parser/Parser.php(3437): MediaWiki\Extension\Scribunto\Hooks::invokeHook()
#21 /var/www/html/w/includes/parser/Parser.php(3122): Parser->callParserFunction()
#22 /var/www/html/w/includes/parser/PPFrame_Hash.php(275): Parser->braceSubstitution()
#23 /var/www/html/w/includes/parser/Parser.php(2951): PPFrame_Hash->expand()
#24 /var/www/html/w/includes/parser/Parser.php(1609): Parser->replaceVariables()
#25 /var/www/html/w/includes/parser/Parser.php(723): Parser->internalParse()
#26 /var/www/html/w/includes/content/WikitextContentHandler.php(301): Parser->parse()
#27 /var/www/html/w/includes/content/ContentHandler.php(1721): WikitextContentHandler->fillParserOutput()
#28 /var/www/html/w/includes/content/Renderer/ContentRenderer.php(47): ContentHandler->getParserOutput()
#29 /var/www/html/w/includes/Revision/RenderedRevision.php(266): MediaWiki\Content\Renderer\ContentRenderer->getParserOutput()
#30 /var/www/html/w/includes/Revision/RenderedRevision.php(237): MediaWiki\Revision\RenderedRevision->getSlotParserOutputUncached()
#31 /var/www/html/w/includes/Revision/RevisionRenderer.php(236): MediaWiki\Revision\RenderedRevision->getSlotParserOutput()
#32 /var/www/html/w/includes/Revision/RevisionRenderer.php(158): MediaWiki\Revision\RevisionRenderer->combineSlotOutput()
#33 [internal function]: MediaWiki\Revision\RevisionRenderer->MediaWiki\Revision\{closure}()
#34 /var/www/html/w/includes/Revision/RenderedRevision.php(199): call_user_func()
#35 /var/www/html/w/includes/poolcounter/PoolWorkArticleView.php(91): MediaWiki\Revision\RenderedRevision->getRevisionParserOutput()
#36 /var/www/html/w/includes/poolcounter/PoolWorkArticleViewCurrent.php(97): PoolWorkArticleView->renderRevision()
#37 /var/www/html/w/includes/poolcounter/PoolCounterWork.php(162): PoolWorkArticleViewCurrent->doWork()
#38 /var/www/html/w/includes/page/ParserOutputAccess.php(299): PoolCounterWork->execute()
#39 /var/www/html/w/includes/page/Article.php(714): MediaWiki\Page\ParserOutputAccess->getParserOutput()
#40 /var/www/html/w/includes/page/Article.php(528): Article->generateContentOutput()
#41 /var/www/html/w/includes/actions/ViewAction.php(78): Article->view()
#42 /var/www/html/w/includes/MediaWiki.php(542): ViewAction->show()
#43 /var/www/html/w/includes/MediaWiki.php(322): MediaWiki->performAction()
#44 /var/www/html/w/includes/MediaWiki.php(904): MediaWiki->performRequest()
#45 /var/www/html/w/includes/MediaWiki.php(562): MediaWiki->main()
#46 /var/www/html/w/index.php(50): MediaWiki->run()
#47 /var/www/html/w/index.php(46): wfIndexMain()
#48 {main}

Hello @simontaurus as far as I understand you are using as SPARQLStore, is that correct ? I haven't tested it directly, however I think that QueryEngineFactory (for it to work) should be a subclass of SMW\SPARQLStore, not SMW\SQLStore. On the other side, a class SMW\SPARQLStore\QueryEngineFactory does not exist.
So first I would need to know whether search panes queries are applicable to the SPARQLStore and they should be implemented for it. If so, we have to look at the class SMW\SPARQLStore\SPARQLStoreFactory (function newMasterQueryEngine), where there is some hint. Otherwise we could just use your workaround to provide an empty result.

Thank you for your response. Correct, I'm using a SPARQLStore.
The missing SMW\SPARQLStore\QueryEngineFactory was also comming up while I was browsing the SMW sources.
Apparently the issue only occurs with |sort=SomePropertyOfTypeDateTime while saving the page edits or purging the page, in all other cases (also normal reloads) everything including the search panels looks fine.
Since |sort=SomePropertyOfTypeDateTime works in principle with other result formats I hope there's a solution.

hello @simontaurus I've checked but I need to test with a SPARQLStore and I don't have it installed right now. Is there any docker container that I can use for this purpose ?

One option would be our docker image / compose-stack

After doing some research on that I still do not understand in which cases SMW passes an SPARQLStore as store and in which cases a SQLStore - it seems random. Maybe @JeroenDeDauw / @kghbln can elaborate on that.

While ElasticStore subclasses SQLStore
https://github.com/SemanticMediaWiki/SemanticMediaWiki/blob/c8f778a85aca38d4d78173c4014f9dc40d067473/src/Elastic/ElasticStore.php#L39

SPARQLStore has a private member that is a SQLStore
https://github.com/SemanticMediaWiki/SemanticMediaWiki/blob/c8f778a85aca38d4d78173c4014f9dc40d067473/src/SPARQLStore/SPARQLStore.php#L49-L66

So theoretically using this basestore should work, but any try to provide a SQLStore as fallback fails, see below.

public function getSearchPanes( $printRequests, $searchPanesOptions ) {
        if ( !( $this->datatables->store instanceof \SMW\SQLStore\SQLStore ) ) { // we got a SPARQLStore
                // $this->datatables->store = new SQLStore(); // fails, see exception
                // $this->datatables->store = \SMW\Services\ServicesFactory::getInstance()->getStore(); // fails, see exception
                // $this->datatables->store = \SMW\StoreFactory::getStore( "\SMW\SQLStore\SQLStore" ); // fails, see exception
                // $this->datatables->store = $this->datatables->store->baseStore; // fails, private property 'baseStore'
                $closure = \Closure::bind(function &(\SMW\SPARQLStore\SPARQLStore $class) { // dirty hack to access private member
                        return $class->baseStore;
                }, null, \SMW\SPARQLStore\SPARQLStore::class);
                $this->datatables->store = &$closure($this->datatables->store); // fails, see exception
        }
}

Exception (may indicate a dirty state on the DB due to a previous exception while playing around with some dirty hacks)

Error 1050: Table 't3' already exists
Function: SMW\SQLStore\TableBuilder\TemporaryTableBuilder::create
Query: CREATE TEMPORARY TABLE `t3`( id INT UNSIGNED KEY ) ENGINE=MEMORY

Backtrace:

from /var/www/html/w/includes/libs/rdbms/database/Database.php(1618)
#0 /var/www/html/w/includes/libs/rdbms/database/Database.php(1602): Wikimedia\Rdbms\Database->getQueryException()
#1 /var/www/html/w/includes/libs/rdbms/database/Database.php(1576): Wikimedia\Rdbms\Database->getQueryExceptionAndLog()
#2 /var/www/html/w/includes/libs/rdbms/database/Database.php(952): Wikimedia\Rdbms\Database->reportQueryError()
#3 /var/www/html/w/includes/libs/rdbms/database/DBConnRef.php(103): Wikimedia\Rdbms\Database->query()
#4 /var/www/html/w/includes/libs/rdbms/database/DBConnRef.php(293): Wikimedia\Rdbms\DBConnRef->__call()
#5 /var/www/html/w/extensions/SemanticMediaWiki/src/MediaWiki/Connection/Database.php(380): Wikimedia\Rdbms\DBConnRef->query()
#6 /var/www/html/w/extensions/SemanticMediaWiki/src/MediaWiki/Connection/Database.php(292): SMW\MediaWiki\Connection\Database->executeQuery()
#7 /var/www/html/w/extensions/SemanticMediaWiki/src/SQLStore/TableBuilder/TemporaryTableBuilder.php(59): SMW\MediaWiki\Connection\Database->query()
#8 /var/www/html/w/extensions/SemanticMediaWiki/src/SQLStore/QueryEngine/HierarchyTempTableBuilder.php(111): SMW\SQLStore\TableBuilder\TemporaryTableBuilder->create()
#9 /var/www/html/w/extensions/SemanticMediaWiki/src/SQLStore/QueryEngine/QuerySegmentListProcessor.php(355): SMW\SQLStore\QueryEngine\HierarchyTempTableBuilder->fillTempTable()
#10 /var/www/html/w/extensions/SemanticMediaWiki/src/SQLStore/QueryEngine/QuerySegmentListProcessor.php(132): SMW\SQLStore\QueryEngine\QuerySegmentListProcessor->hierarchy()
#11 /var/www/html/w/extensions/SemanticMediaWiki/src/SQLStore/QueryEngine/QuerySegmentListProcessor.php(146): SMW\SQLStore\QueryEngine\QuerySegmentListProcessor->segment()
#12 /var/www/html/w/extensions/SemanticMediaWiki/src/SQLStore/QueryEngine/QuerySegmentListProcessor.php(122): SMW\SQLStore\QueryEngine\QuerySegmentListProcessor->table()
#13 /var/www/html/w/extensions/SemanticMediaWiki/src/SQLStore/QueryEngine/QuerySegmentListProcessor.php(220): SMW\SQLStore\QueryEngine\QuerySegmentListProcessor->segment()
#14 /var/www/html/w/extensions/SemanticMediaWiki/src/SQLStore/QueryEngine/QuerySegmentListProcessor.php(125): SMW\SQLStore\QueryEngine\QuerySegmentListProcessor->conjunction()
#15 /var/www/html/w/extensions/SemanticMediaWiki/src/SQLStore/QueryEngine/QuerySegmentListProcessor.php(146): SMW\SQLStore\QueryEngine\QuerySegmentListProcessor->segment()
#16 /var/www/html/w/extensions/SemanticMediaWiki/src/SQLStore/QueryEngine/QuerySegmentListProcessor.php(122): SMW\SQLStore\QueryEngine\QuerySegmentListProcessor->table()
#17 /var/www/html/w/extensions/SemanticMediaWiki/src/SQLStore/QueryEngine/QuerySegmentListProcessor.php(115): SMW\SQLStore\QueryEngine\QuerySegmentListProcessor->segment()
#18 /var/www/html/w/extensions/SemanticResultFormats/formats/datatables/SearchPanes.php(153): SMW\SQLStore\QueryEngine\QuerySegmentListProcessor->process()
#19 /var/www/html/w/extensions/SemanticResultFormats/formats/datatables/SearchPanes.php(85): SRF\DataTables\SearchPanes->getPanesOptions()
#20 /var/www/html/w/extensions/SemanticResultFormats/formats/datatables/DataTables.php(586): SRF\DataTables\SearchPanes->getSearchPanes()
#21 /var/www/html/w/extensions/SemanticResultFormats/formats/datatables/DataTables.php(440): SRF\DataTables->getResultText()
#22 /var/www/html/w/extensions/SemanticMediaWiki/src/Query/ResultPrinters/ResultPrinter.php(304): SRF\DataTables->buildResult()
#23 /var/www/html/w/extensions/SemanticMediaWiki/includes/query/SMW_QueryProcessor.php(348): SMW\Query\ResultPrinters\ResultPrinter->getResult()
#24 /var/www/html/w/extensions/SemanticMediaWiki/src/ParserFunctions/AskParserFunction.php(370): SMWQueryProcessor::getResultFromQuery()
#25 /var/www/html/w/extensions/SemanticMediaWiki/src/ParserFunctions/AskParserFunction.php(202): SMW\ParserFunctions\AskParserFunction->doFetchResultsFromFunctionParameters()
#26 /var/www/html/w/extensions/SemanticMediaWiki/src/ParserFunctionFactory.php(402): SMW\ParserFunctions\AskParserFunction->parse()
#27 /var/www/html/w/includes/parser/Parser.php(3437): SMW\ParserFunctionFactory->SMW\{closure}()
#28 /var/www/html/w/includes/parser/Parser.php(3122): Parser->callParserFunction()
#29 /var/www/html/w/includes/parser/PPFrame_Hash.php(275): Parser->braceSubstitution()
#30 /var/www/html/w/includes/parser/Parser.php(2951): PPFrame_Hash->expand()
#31 /var/www/html/w/includes/parser/Parser.php(1609): Parser->replaceVariables()
#32 /var/www/html/w/includes/parser/Parser.php(723): Parser->internalParse()
#33 /var/www/html/w/includes/content/WikitextContentHandler.php(301): Parser->parse()
#34 /var/www/html/w/includes/content/ContentHandler.php(1721): WikitextContentHandler->fillParserOutput()
#35 /var/www/html/w/includes/content/Renderer/ContentRenderer.php(47): ContentHandler->getParserOutput()
#36 /var/www/html/w/includes/Revision/RenderedRevision.php(266): MediaWiki\Content\Renderer\ContentRenderer->getParserOutput()
#37 /var/www/html/w/includes/Revision/RenderedRevision.php(237): MediaWiki\Revision\RenderedRevision->getSlotParserOutputUncached()
#38 /var/www/html/w/includes/Revision/RevisionRenderer.php(221): MediaWiki\Revision\RenderedRevision->getSlotParserOutput()
#39 /var/www/html/w/includes/Revision/RevisionRenderer.php(158): MediaWiki\Revision\RevisionRenderer->combineSlotOutput()
#40 [internal function]: MediaWiki\Revision\RevisionRenderer->MediaWiki\Revision\{closure}()
#41 /var/www/html/w/includes/Revision/RenderedRevision.php(199): call_user_func()
#42 /var/www/html/w/includes/poolcounter/PoolWorkArticleView.php(91): MediaWiki\Revision\RenderedRevision->getRevisionParserOutput()
#43 /var/www/html/w/includes/poolcounter/PoolWorkArticleViewCurrent.php(97): PoolWorkArticleView->renderRevision()
#44 /var/www/html/w/includes/poolcounter/PoolCounterWork.php(162): PoolWorkArticleViewCurrent->doWork()
#45 /var/www/html/w/includes/page/ParserOutputAccess.php(299): PoolCounterWork->execute()
#46 /var/www/html/w/includes/page/Article.php(714): MediaWiki\Page\ParserOutputAccess->getParserOutput()
#47 /var/www/html/w/includes/page/Article.php(528): Article->generateContentOutput()
#48 /var/www/html/w/includes/actions/ViewAction.php(78): Article->view()
#49 /var/www/html/w/includes/MediaWiki.php(542): ViewAction->show()
#50 /var/www/html/w/includes/MediaWiki.php(322): MediaWiki->performAction()
#51 /var/www/html/w/includes/MediaWiki.php(904): MediaWiki->performRequest()
#52 /var/www/html/w/includes/MediaWiki.php(562): MediaWiki->main()
#53 /var/www/html/w/index.php(50): MediaWiki->run()
#54 /var/www/html/w/index.php(46): wfIndexMain()
#55 {main}