Page MenuHomePhabricator

Fatal error for multiple instances of records in subobjects
Closed, ResolvedPublic

Description

Author: my.think

Description:
I'm running MediaWiki 1.20 and SMW 1.8.4, newly setup testing wiki.

TextProperty is a normal Property (type String), RecordProperty is a Record, properly set-up with their own properties, and types, in this case: Page;Number.

This:

{{#subobject: Test

TextProperty = Test
RecordProperty = Testing;123

}}

{{#subobject: Test

TextProperty = Test2

}}

works without flaws, and adds everything to the same subobject, just as #set still works when used multiple times with the same properties.

Now, if I move the RecordProperty declaration to the 2nd #subobject, the wiki will error out with an exception:

{{#subobject: Test

TextProperty = Test

}}

{{#subobject: Test

TextProperty = Test2
RecordProperty = Testing;123

}}

Cannot add subdata. Are you trying to add data to an SMWSemanticData object that is already used as a subdata object?
Backtrace:
#0 .../extensions/SemanticMediaWiki/includes/SMW_SemanticData.php(442)<...>: SMWSemanticData->addSubSemanticData(Object(SMWContainerSemanticData))

I don't exactly know what SMWSemanticData objects are supposed to be (are subobjects?), and what the notion of subdata objects is in this context, and the documentation was a little unhelpful regarding that, too, so I can't say if what the error message really says is what I am doing there.

In 1.7, this worked fine, and would add the record data to the Trash subobject just fine. Am I doing anything that just worked because I was lucky (I supposed the behavior for #set and #subobject was intended to be the same) or is there a deeper bug to this? If at all, this error case should be handled more gracefully than throwing an exception.

I'm using templates on the wiki to hide all the SMW magic, and being able to declare the SMW subobject data in multiple calls to #subobject helps to keep their source code tidier.


Version: unspecified
Severity: normal

Details

Reference
bz47472

Event Timeline

bzimport raised the priority of this task from to Needs Triage.Nov 22 2014, 1:24 AM
bzimport set Reference to bz47472.
bzimport added a subscriber: Unknown Object (MLST).
Unknown Object (User) added a comment.Apr 21 2013, 3:00 PM

Between 1.7 and 1.8 some changes happen in how a container is being handled and while a fatal should not happen try not to use a named identifier and instead use (omitting the named "Test" identifier):

{{#subobject:

TextProperty = Test
RecordProperty = Testing;123

}}

{{#subobject:

TextProperty = Test2

}}

my.think wrote:

That way I will get two different subobjects - what if I want to store these values in the same subobject? It makes the template structure easier, and there's not exactly a good way to fill optional values in #subobjects. The other way is conditionally leaving the value out:

Property = {{#if: {{{param}}}{{{param}}} }}

and using one giant call to #subobject, which makes the template logic so much more complex.

This is all working as intended in the way that multiple calls to #subobject with the same identifier will add data to the subobject, just like multiple calls to #set will add to the properties of the page, except for when a record is called anywhere but in the first call to #subobject, which causes a fatal error.

Shouldn't changing the order of SMW calls in the page cause identical results?

From my example above, I want to create a subobject PAGENAME#Test with the following data, and the records should be added in subsequent #subobject calls from a template:

  • TextProperty: Test & Test2
  • RecordProperty: Testing;123 & TestingAgain;234 or more, up to 4 times.

For context: I'm storing recipes, and every record contains an ingredient name + its amount. There can be multiple recipes for a single page, so I'm storing a subobject for each recipe instead of using the page directly.

Unknown Object (User) added a comment.Apr 21 2013, 10:59 PM

I do understand your scenario but as of now I don't have a fix for this problem.

The problem is that the record type is being handled has a subobject itself (this was the change in 1.8 I think) which means that you are storing a subobject within a subobject and when using the same identifier creates the described unfortunate situation.

The "record type" subobject uses the "real" subobject as a SMWDIWikiPage reference (see below) and this is where the subSemanticData issue occurs.

{{#subobject: Test

TextProperty = Test

}}

protected 'mSubject' =>
object(SMWDIWikiPage)[243]

protected 'm_dbkey' => string 'Subobject_record_type' (length=21)
protected 'm_namespace' => int 0
protected 'm_interwiki' => string '' (length=0)
protected 'm_subobjectname' => string 'Test' (length=4)

protected 'subSemanticData' =>
array (size=0)

empty

{{#subobject: Test

TextProperty = Test
RecordProperty = Testing;123

}}

protected 'mSubject' =>

object(SMWDIWikiPage)[290]
  protected 'm_dbkey' => string 'Subobject_record_type' (length=21)
  protected 'm_namespace' => int 0
  protected 'm_interwiki' => string '' (length=0)
  protected 'm_subobjectname' => string 'Test' (length=4)

protected 'subSemanticData' =>

array (size=1)
  '_d2f07a28343b60fc1a29f127e1820034' =>
    object(SMWContainerSemanticData)[300]
Unknown Object (User) added a comment.Apr 22 2013, 12:08 AM

(In reply to comment #3)

The "record type" subobject uses the "real" subobject as a SMWDIWikiPage
reference (see below) and this is where the subSemanticData issue occurs.

After further investigation, the exception is raised because addSubSemanticData() checks for the "subDataAllowed" property if it set true or false.

addSubSemanticData() is called recursively during the process of adding container data and during that process $semanticData->subDataAllowed = false; is set which inevitably causes the exception during the recursive call.

I can't say for sure why $semanticData->subDataAllowed = false is set at this point, maybe it is to avoid circular reference within subobject.

The documentation points to subDataAllowed being an "Internal flag that indicates if this semantic data will accept subdata. Semantic data objects that are subdata already do not allow (second level) subdata to be added."

It could be that because the record type is a subobject itself and by trying to add the same record (which is what happen when you assign RecordProperty = Testing;123 to the second caller which in fact is the same subobject) by trying to resolve the container data subDataAllowed property is set false which is causing the exception.

(In reply to comment #4)

The documentation points to subDataAllowed being an "Internal flag that
indicates if this semantic data will accept subdata. Semantic data objects
that
are subdata already do not allow (second level) subdata to be added."

It could be that because the record type is a subobject itself and by trying
to
add the same record (which is what happen when you assign RecordProperty =
Testing;123 to the second caller which in fact is the same subobject) by
trying
to resolve the container data subDataAllowed property is set false which is
causing the exception.

Yes, this is right. Though I don't remember why adding subobjects to subobjects was disabled like this. Markus would know :)

my.think wrote:

This is when the change was added:
https://gerrit.wikimedia.org/r/gitweb?p=mediawiki/extensions/SemanticMediaWiki.git;a=commitdiff;h=abbd2693ee3dcafabb5102b3c3c4f3a198bd9885

Now, I have no idea about the internal operations of SMW, but from an outside perspective, in 1.7, I never had a problem with records in subobjects, and found it only natural to use them just like any other type in subobjects.

Also: why can I add a record in the first call to #subobject, but not in later calls, even if there was no record added on the first call? It seems to me that adding a record to a "top-level" subobject should be allowed anyways.

In any case, can we make this fail more gracefully than with an exception? It's rather disturbing for the edit process, because it even triggers on preview. Also, most wikis will not show exception error texts/backtraces to the user, but rather a generic "Internal wiki error" message.

Unknown Object (User) added a comment.Apr 22 2013, 10:58 AM

(In reply to comment #6)

This is when the change was added:
https://gerrit.wikimedia.org/r/gitweb?p=mediawiki/extensions/
SemanticMediaWiki.git;a=commitdiff;h=abbd2693ee3dcafabb5102b3c3c4f3a198bd9885

Nice job finding this commit but the commit message also states that "This fixes some problems with nested subdata (mainly created by using Record properties within #subobject).".

Unless it is clear what those problems were, the current exception was placed their on purpose and I'm inclined not to change this behaviour without further knowledge as to why it was designed this way.

my.think wrote:

I didn't intend that it's changed without reasoning, I'm pretty sure there is a reason. I looked around for any bug reports mentioning problems but couldn't find any.

In case this isn't fixed/working as intended, I can surely find another workaround.

Unknown Object (User) added a comment.Sep 18 2014, 6:15 PM

As described in comment 4/5, it is the intended design. The record type itself is represented internally as subobject and therefore and not be added recursively to another subobject.

Kghbln changed the task status from Invalid to Resolved.Dec 9 2015, 12:07 PM
Kghbln set Security to None.