Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
simontaurus opened this issue Apr 10, 2024 · 10 comments · May be fixed by #861
Open
Labels

Comments

@simontaurus
Copy link

simontaurus commented Apr 10, 2024

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}
@thomas-topway-it
Copy link
Contributor

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.

@simontaurus
Copy link
Author

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.

@krabina krabina added the bug label Apr 17, 2024
@thomas-topway-it
Copy link
Contributor

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 ?

@simontaurus
Copy link
Author

One option would be our docker image / compose-stack

@simontaurus
Copy link
Author

simontaurus commented Jun 11, 2024

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)
Edit: unrelated, see #SemanticMediaWiki/SemanticMediaWiki#5714

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}

@simontaurus
Copy link
Author

simontaurus commented Nov 12, 2024

@thomas-topway-it, @JeroenDeDauw
Since the error above was unrelated, this is actually a solution:

public function getSearchPanes( $printRequests, $searchPanesOptions ) {
        if ( this->datatables->store instanceof \SMW\SPARQLStore\SPARQLStore ) ) { // we got a SPARQLStore
                $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); // works
        }
}

We can get rid of the closure if we make SPARQLStore->baseStore public
see SemanticMediaWiki/SemanticMediaWiki#5748

simontaurus added a commit to simontaurus/SemanticMediaWiki that referenced this issue Nov 12, 2024
in order to allow result format to access the SQLStore since SPARQLStore is not a subclass of SQLStore (different from ElasticStore).

See: SemanticMediaWiki#5748 
SemanticMediaWiki/SemanticResultFormats#827
simontaurus added a commit to simontaurus/SemanticResultFormats that referenced this issue Nov 12, 2024
@simontaurus simontaurus linked a pull request Nov 12, 2024 that will close this issue
JeroenDeDauw added a commit to SemanticMediaWiki/SemanticMediaWiki that referenced this issue Nov 12, 2024
* make $baseStore public

in order to allow result format to access the SQLStore since SPARQLStore is not a subclass of SQLStore (different from ElasticStore).

See: #5748 
SemanticMediaWiki/SemanticResultFormats#827

* Update SPARQLStore.php

---------

Co-authored-by: Jeroen De Dauw <[email protected]>
@thomas-topway-it
Copy link
Contributor

@simontaurus It seems a great solution, so the standard SQLStore is reassigned if this->datatables->store is found an instanceof \SMW\SPARQLStore\SPARQLStore ?

Regarding the unrelated error

Error 1050: Table 't3' already exists

it could be fixed setting \SMW\SQLStore\QueryEngine\QuerySegment::$qnum = 0;
(SRF\DataTables\SearchPanes)

to an higher value than 0. However in a similar case the error showed up anyway, I need to reproduce it to figure out the root cause

@simontaurus
Copy link
Author

simontaurus commented Nov 16, 2024

@thomas-topway-it

It seems a great solution, so the standard SQLStore is reassigned if this->datatables->store is found an instanceof \SMW\SPARQLStore\SPARQLStore ?

Correct. After doing so, panels work as expected with a SPARQLStore

Error 1050: Table 't3' already exists will be fixed in SMW 5.0.0, see SemanticMediaWiki/SemanticMediaWiki#5747

Currently I patch with

fix: create temp table only of not existing yet, see https://github.com/SemanticMediaWiki/SemanticMediaWiki/issues/5714
sed -i -e 's/"CREATE TEMPORARY TABLE "/"CREATE TEMPORARY TABLE IF NOT EXISTS "/g' $MW_HOME/extensions/SemanticMediaWiki/src/SQLStore/TableBuilder/TemporaryTableBuilder.php

Great! This solved the issue

Fixes merged here OpenSemanticLab:SemanticResultFormats:dev resolved all my issues =).

@thomas-topway-it
Copy link
Contributor

@simontaurus I'm not sure to what the statement "Great! This solved the issue" is addressed here ? the IF NOT EXISTS clause or something else ? Is it related to this ? #860

@simontaurus
Copy link
Author

simontaurus commented Nov 21, 2024

sorry, this was indeed a copy past error from my answer to #860

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants