diff --git a/maintenance/setupStore.php b/maintenance/setupStore.php index c80398805c..30d4eccaf1 100644 --- a/maintenance/setupStore.php +++ b/maintenance/setupStore.php @@ -4,6 +4,8 @@ use SMW\Store; use SMW\StoreFactory; +use Onoi\MessageReporter\MessageReporterFactory; +use SMW\SQLStore\Installer; $basePath = getenv( 'MW_INSTALL_PATH' ) !== false ? getenv( 'MW_INSTALL_PATH' ) : __DIR__ . '/../../..'; @@ -74,6 +76,7 @@ public function __construct() { * @since 2.0 */ public function execute() { + // TODO It would be good if this script would work with SMW not being enable (yet). // Then one could setup the store without first enabling SMW (which will break the wiki until the store is setup). if ( !defined( 'SMW_VERSION' ) || !$GLOBALS['smwgSemanticsEnabled'] ) { @@ -84,11 +87,28 @@ public function execute() { $this->loadGlobalFunctions(); $store = $this->getStore(); + $store->clear(); + + if ( $this->getOption( 'quiet' ) ) { + $messageReporter = MessageReporterFactory::getInstance()->newNullMessageReporter(); + } else { + $messageReporter = MessageReporterFactory::getInstance()->newObservableMessageReporter(); + $messageReporter->registerReporterCallback( array( $this, 'reportMessage' ) ); + } + + $store->getOptions()->set( + Installer::OPT_MESSAGEREPORTER, + $messageReporter + ); + + if ( method_exists( $store, 'getPropertyTableInfoFetcher' ) ) { + $store->getPropertyTableInfoFetcher()->clearCache(); + } if ( $this->hasOption( 'delete' ) ) { $this->dropStore( $store ); } else { - Store::setupStore( !$this->isQuiet() ); + $store->setup(); } } @@ -114,7 +134,7 @@ protected function getStore() { $this->error( "\nError: There is no backend class \"$storeClass\". Aborting.", 1 ); } - return StoreFactory::getStore(); + return StoreFactory::getStore( $storeClass ); } protected function dropStore( Store $store ) { @@ -163,6 +183,15 @@ protected function promptDeletionVerification( $storeName ) { return true; } + /** + * @since 3.0 + * + * @param string $message + */ + public function reportMessage( $message ) { + $this->output( $message ); + } + } $maintClass = 'SMW\Maintenance\SetupStore'; diff --git a/src/Maintenance/DistinctEntityDataRebuilder.php b/src/Maintenance/DistinctEntityDataRebuilder.php index a89a12bc35..5a1e0db2ac 100644 --- a/src/Maintenance/DistinctEntityDataRebuilder.php +++ b/src/Maintenance/DistinctEntityDataRebuilder.php @@ -155,6 +155,7 @@ public function doRebuild() { private function doExecuteUpdateJobFor( $page ) { $updatejob = new UpdateJob( $page, array( + UpdateJob::FORCED_UPDATE => true, 'pm' => $this->options->has( 'shallow-update' ) ? SMW_UJ_PM_CLASTMDATE : false ) ); diff --git a/src/SQLStore/ChangeOp/TableChangeOp.php b/src/SQLStore/ChangeOp/TableChangeOp.php index 185ff6e79e..7dc9227f1f 100644 --- a/src/SQLStore/ChangeOp/TableChangeOp.php +++ b/src/SQLStore/ChangeOp/TableChangeOp.php @@ -94,6 +94,8 @@ public function getFieldChangeOps( $opType = null ) { $changeOps = $this->changeOps[$opType]; } + unset( $changeOps['property'] ); + foreach ( $changeOps as $op ) { $fieldOps[] = new FieldChangeOp( $op ); } diff --git a/src/SQLStore/CompositePropertyTableDiffIterator.php b/src/SQLStore/CompositePropertyTableDiffIterator.php index bf0f35ca81..cead504720 100644 --- a/src/SQLStore/CompositePropertyTableDiffIterator.php +++ b/src/SQLStore/CompositePropertyTableDiffIterator.php @@ -116,6 +116,11 @@ public function getDataChangeOps() { foreach ( $this->data as $hash => $data ) { foreach ( $data as $tableName => $d ) { + + if ( isset( $this->fixedPropertyRecords[$tableName] ) ) { + $d['property'] = $this->fixedPropertyRecords[$tableName]; + } + $dataChangeOps[] = new TableChangeOp( $tableName, $d ); } } diff --git a/src/SQLStore/PropertyTableRowDiffer.php b/src/SQLStore/PropertyTableRowDiffer.php index 019314e8ce..935ff4113a 100644 --- a/src/SQLStore/PropertyTableRowDiffer.php +++ b/src/SQLStore/PropertyTableRowDiffer.php @@ -109,6 +109,10 @@ public function computeTableRowDiffFor( $sid, SemanticData $semanticData ) { } } + if ( $fixedProperty ) { + $this->getCompositePropertyTableDiff()->addFixedPropertyRecord( $tableName, $fixedProperty ); + } + if ( array_key_exists( $tableName, $newData ) ) { // Note: the order within arrays should remain the same while page is not updated. // Hence we do not sort before serializing. It is hoped that this assumption is valid. @@ -139,10 +143,6 @@ public function computeTableRowDiffFor( $sid, SemanticData $semanticData ) { $sid, $propertyTable ); - - if ( $fixedProperty ) { - $this->getCompositePropertyTableDiff()->addFixedPropertyRecord( $tableName, $fixedProperty ); - } } } diff --git a/src/SQLStore/QueryEngine/Fulltext/TextByChangeUpdater.php b/src/SQLStore/QueryEngine/Fulltext/TextByChangeUpdater.php index e08fb8db5f..e296c9279e 100644 --- a/src/SQLStore/QueryEngine/Fulltext/TextByChangeUpdater.php +++ b/src/SQLStore/QueryEngine/Fulltext/TextByChangeUpdater.php @@ -239,6 +239,10 @@ private function doCreateCompositeUpdate( TableChangeOp $dataChangeOp, &$updates foreach ( $dataChangeOp->getFieldChangeOps() as $fieldChangeOp ) { + if ( $dataChangeOp->isFixedPropertyOp() ) { + $fieldChangeOp->set( 'p_id', $dataChangeOp->getFixedPropertyValueBy( 'p_id' ) ); + } + // Exempted property -> out if ( !$fieldChangeOp->has( 'p_id' ) || $searchTable->isExemptedPropertyById( $fieldChangeOp->get( 'p_id' ) ) ) { continue; diff --git a/src/SQLStore/SQLStoreFactory.php b/src/SQLStore/SQLStoreFactory.php index e0a05734bb..179b7ede07 100644 --- a/src/SQLStore/SQLStoreFactory.php +++ b/src/SQLStore/SQLStoreFactory.php @@ -324,7 +324,7 @@ public function newRequestOptionsProcessor() { */ public function newPropertyTableInfoFetcher() { - $settings = $this->applicationFactory->getSettings(); + $settings = ApplicationFactory::getInstance()->getSettings(); $propertyTableInfoFetcher = new PropertyTableInfoFetcher( new PropertyTypeFinder( $this->store->getConnection( 'mw.db' ) ) diff --git a/tests/phpunit/Integration/JSONScript/JsonTestCaseScriptRunnerTest.php b/tests/phpunit/Integration/JSONScript/JsonTestCaseScriptRunnerTest.php index aa57fbe96e..e028b14c67 100644 --- a/tests/phpunit/Integration/JSONScript/JsonTestCaseScriptRunnerTest.php +++ b/tests/phpunit/Integration/JSONScript/JsonTestCaseScriptRunnerTest.php @@ -177,6 +177,7 @@ private function prepareTest( $jsonTestCaseFileHandler ) { 'smwgEnabledFulltextSearch', 'smwgFulltextDeferredUpdate', 'smwgFulltextSearchIndexableDataTypes', + 'smwgFixedProperties', 'smwgPropertyZeroCountDisplay', 'smwgQueryResultCacheType', 'smwgLinksInValues', @@ -206,28 +207,58 @@ private function prepareTest( $jsonTestCaseFileHandler ) { ); } + $pageList = $jsonTestCaseFileHandler->getPageCreationSetupList(); + + // Special handling for fixed properties to fetch the correct type + // before being used as annotation + if ( $jsonTestCaseFileHandler->getSettingsFor( 'smwgFixedProperties' ) !== array() ) { + foreach ( $pageList as $page ) { + if ( isset( $page['namespace'] ) && $page['namespace'] === 'SMW_NS_PROPERTY' ) { + $this->doRunFixedPropertyTableCreation( $page ); + } + } + } + $this->createPagesFrom( - $jsonTestCaseFileHandler->getPageCreationSetupList(), + $pageList, NS_MAIN ); } + private function doRunFixedPropertyTableCreation( $page ) { + // Create property to ... + $this->createPagesFrom( array( $page ) ); + + // Create table + $maintenanceRunner = $this->runnerFactory->newMaintenanceRunner( 'setupStore' ); + $maintenanceRunner->setQuiet(); + $maintenanceRunner->run(); + } + private function doRunBeforeTest( $jsonTestCaseFileHandler ) { foreach ( $jsonTestCaseFileHandler->findTaskBeforeTestExecutionByType( 'maintenance-run' ) as $runner => $options ) { + $maintenanceRunner = $this->runnerFactory->newMaintenanceRunner( $runner ); + $maintenanceRunner->setQuiet(); $maintenanceRunner->setOptions( (array)$options ); - $maintenanceRunner->setQuiet()->run(); + $maintenanceRunner->run(); + + if ( isset( $options['quiet'] ) && $options['quiet'] === false ) { + print_r( $maintenanceRunner->getOutput() ); + } } foreach ( $jsonTestCaseFileHandler->findTaskBeforeTestExecutionByType( 'job-run' ) as $jobType ) { $jobQueueRunner = $this->runnerFactory->newJobQueueRunner( $jobType ); $jobQueueRunner->run(); } + + $this->testEnvironment->executePendingDeferredUpdates(); } private function doRunParserTests( $jsonTestCaseFileHandler ) { diff --git a/tests/phpunit/Integration/JSONScript/TestCases/q-0106.json b/tests/phpunit/Integration/JSONScript/TestCases/q-0106.json new file mode 100644 index 0000000000..8b46a4df20 --- /dev/null +++ b/tests/phpunit/Integration/JSONScript/TestCases/q-0106.json @@ -0,0 +1,94 @@ +{ + "description": "Test `_txt`/`~` with enabled full-text search support on fixed user property (only enabled for MySQL, SQLite, `smwgFixedProperties`)", + "setup": [ + { + "namespace": "SMW_NS_PROPERTY", + "page": "Has fixed text", + "contents": "[[Has type::Text]]" + }, + { + "namespace": "SMW_NS_PROPERTY", + "page": "Has fixed page", + "contents": "[[Has type::Page]]" + }, + { + "page": "Example/Q0106/1", + "contents": "{{#subobject: |Has fixed text=MySQL vs MariaDB database}} {{#subobject: |Has fixed text=Oracle vs MariaDB database}} {{#subobject: |Has fixed text=PostgreSQL vs MariaDB database and more of}} {{#subobject: |Has fixed text=MariaDB overview}}" + }, + { + "page": "Example/Q0106/2", + "contents": "{{#subobject: |Has fixed page=Elastic search}} {{#subobject: |Has fixed page=Sphinx search}}" + } + ], + "beforeTest": { + "maintenance-run": { + "rebuildData": { + "page": "Property:Has fixed text|Property:Has fixed page|Example/Q0106/1|Example/Q0106/2" + } + } + }, + "tests": [ + { + "type": "query", + "store": { + "clear-cache": true + }, + "about": "#0 on fixed blob user property", + "condition": "[[Has fixed text::~+MariaDB -database]]", + "printouts": [], + "parameters": { + "limit": "10" + }, + "assert-queryresult": { + "count": 1, + "results": [ + "Example/Q0106/1#0##_29f6aa337d1dc1e2f79376c7940aeab3" + ] + } + }, + { + "type": "query", + "store": { + "clear-cache": true + }, + "about": "#1 on fixed page user property", + "condition": "[[Has fixed page::~*search*]]", + "printouts": [], + "parameters": { + "limit": "10" + }, + "assert-queryresult": { + "count": 2, + "results": [ + "Example/Q0106/2#0##_39c07b506d692088c97dc0d1cbfd67e6", + "Example/Q0106/2#0##_89e5e037d244e08b050101bb8ddb7768" + ] + } + } + ], + "settings": { + "smwgEnabledFulltextSearch": true, + "smwgFulltextDeferredUpdate": false, + "smwgFulltextSearchIndexableDataTypes": [ + "SMW_FT_BLOB", + "SMW_FT_URI", + "SMW_FT_WIKIPAGE" + ], + "smwgFixedProperties": [ + "Has_fixed_text", + "Has fixed page" + ] + }, + "meta": { + "skip-on": { + "postgres": "Not supported by PostgreSQL.", + "sesame": "Not supported by SPARQLStore (Sesame).", + "virtuoso": "Not supported by SPARQLStore (Virtuoso).", + "fuseki": "Not supported by SPARQLStore (Fuskei).", + "blazegraph": "Not supported by SPARQLStore (Blazegraph)." + }, + "version": "2", + "is-incomplete": false, + "debug": false + } +} \ No newline at end of file diff --git a/tests/phpunit/Integration/MediaWiki/Hooks/FileUploadIntegrationTest.php b/tests/phpunit/Integration/MediaWiki/Hooks/FileUploadIntegrationTest.php index 1b96654f87..e232010437 100644 --- a/tests/phpunit/Integration/MediaWiki/Hooks/FileUploadIntegrationTest.php +++ b/tests/phpunit/Integration/MediaWiki/Hooks/FileUploadIntegrationTest.php @@ -68,6 +68,8 @@ protected function setUp() { 'LinksUpdateConstructed', $this->mwHooksHandler->getHookRegistry()->getHandlerFor( 'LinksUpdateConstructed' ) ); + + $this->getStore()->setup( false ); } protected function tearDown() { diff --git a/tests/phpunit/Unit/SQLStore/ChangeOp/TableChangeOpTest.php b/tests/phpunit/Unit/SQLStore/ChangeOp/TableChangeOpTest.php index df9e08ad9b..22c0223850 100644 --- a/tests/phpunit/Unit/SQLStore/ChangeOp/TableChangeOpTest.php +++ b/tests/phpunit/Unit/SQLStore/ChangeOp/TableChangeOpTest.php @@ -146,7 +146,7 @@ public function testGetFieldChangeOpsNoType() { ); $this->assertCount( - 3, + 2, $instance->getFieldChangeOps() ); } diff --git a/tests/phpunit/Utils/Runners/MaintenanceRunner.php b/tests/phpunit/Utils/Runners/MaintenanceRunner.php index f0e6b105ce..9126b27ba4 100644 --- a/tests/phpunit/Utils/Runners/MaintenanceRunner.php +++ b/tests/phpunit/Utils/Runners/MaintenanceRunner.php @@ -55,7 +55,7 @@ public function setOptions( array $options ) { * @return MaintenanceRunner */ public function setQuiet() { - $this->quiet = true; + $this->options['quiet'] = true; return $this; } @@ -80,9 +80,14 @@ public function run() { throw new DomainException( "Expected a Maintenance instance" ); } + // isset/ null + if ( isset( $this->options['quiet'] ) && $this->options['quiet'] === false ) { + unset( $this->options['quiet'] ); + } + $maintenance->loadParamsAndArgs( $this->maintenanceClass, - array_merge( $this->options, array( 'quiet' => $this->quiet ) ) + $this->options ); ob_start(); diff --git a/tests/phpunit/Utils/Runners/RunnerFactory.php b/tests/phpunit/Utils/Runners/RunnerFactory.php index 97dfafb3ce..efa8d8ce5a 100644 --- a/tests/phpunit/Utils/Runners/RunnerFactory.php +++ b/tests/phpunit/Utils/Runners/RunnerFactory.php @@ -48,6 +48,9 @@ public function newMaintenanceRunner( $maintenanceClass ) { case 'rebuildConceptCache'; $maintenanceClass = 'SMW\Maintenance\RebuildConceptCache'; break; + case 'setupStore'; + $maintenanceClass = 'SMW\Maintenance\SetupStore'; + break; } return new MaintenanceRunner( $maintenanceClass );