Solved the problem.

For reference, field instanceid in the instance_fields needs to be declared as an integer, thus:
CREATE TABLE instance_fields (
  instanceid integer references instances(instanceid),
  field,
  subscript default NULL,
  value,
  primary key (instanceid, field, subscript) );

DRH,
Is this expected behaviour? I'd have thought the manifest typing would have seen to that, but it appears that join fields need to be the same type.

Christian


Christian Smith uttered:

Hello JOIN expoerts:)

I have the following schema:

CREATE TABLE instances (
 instanceid integer primary key,
 type,
 instance);
CREATE INDEX instances_type_instance ON instances(type,instance);
CREATE TABLE instance_fields (
 instanceid references instances(instanceid),
 field,
 subscript default NULL,
 value,
 primary key (instanceid, field, subscript) );

The idea is that instances catalogs instances of an arbitrary type, and instance_fields records the data of each instance as name value pairs. instance_fields.subscript is for arrays as field values (unused ATM).

Now, suppose I have an instance type of 'event', which contains the following fields:
 count
 first
 last
 severity
 summary
 node
 source

Then the following view will select all the 'event' instances, formtted into a nice table view:

create view events_instance as
 select
   i.instance as event,
   count.value AS count,
   first.value AS first,
   last.value AS last,
   severity.value AS severity,
   summary.value AS summary,
   node.value AS node,
   source.value AS source
 FROM instances as i
   inner join instance_fields as count using(instanceid)
   inner join instance_fields as first using (instanceid)
   inner join instance_fields as last using (instanceid)
   inner join instance_fields as severity using (instanceid)
   inner join instance_fields as summary using (instanceid)
   inner join instance_fields as node using (instanceid)
   inner join instance_fields as source using (instanceid)
 WHERE
   i.type = 'event' AND
   first.field = 'first' AND
   count.field = 'count' AND
   last.field = 'last' AND
   severity.field = 'severity' AND
   summary.field = 'summary' AND
   node.field = 'node' AND
   source.field = 'source';


The problem is that the first join is not being done using the primary key index (on count in this case). The query plan is below:

0|0|TABLE instances AS i WITH INDEX instances_type_instance
1|1|TABLE instance_fields AS count
2|2|TABLE instance_fields AS first WITH INDEX sqlite_autoindex_instance_fields_1 3|3|TABLE instance_fields AS last WITH INDEX sqlite_autoindex_instance_fields_1 4|4|TABLE instance_fields AS severity WITH INDEX sqlite_autoindex_instance_fields_1 5|5|TABLE instance_fields AS summary WITH INDEX sqlite_autoindex_instance_fields_1 6|6|TABLE instance_fields AS node WITH INDEX sqlite_autoindex_instance_fields_1 7|7|TABLE instance_fields AS source WITH INDEX sqlite_autoindex_instance_fields_1

I'd expect count to be opened using sqlite_autoindex_instance_fields_1, which refers to the (instanceid, field, subscript) primary key index, as the instanceid is available from 'instances AS i'

Changing the order of the joins doesn't help. It's always the first join which goes wrong. I've tried it with and without data in the tables, before and after 'VACUUM ANALYZE'.

Anyone know what's wrong?

Cheers,
Christian

PS. This is using less than week old CVS HEAD version.

--
   /"\
   \ /    ASCII RIBBON CAMPAIGN - AGAINST HTML MAIL
    X                           - AGAINST MS ATTACHMENTS
   / \


--
    /"\
    \ /    ASCII RIBBON CAMPAIGN - AGAINST HTML MAIL
     X                           - AGAINST MS ATTACHMENTS
    / \

Reply via email to