So... I guess something like this works; other than the triplication
of the initial path string. works for read-only access... doesn't
return where it failed (although can with leaf == 0 )
option4_map ( option_id,parent_option_id,name_id )
option4_names ( name_id, name )
option4_values ( option_id, string_segment, segment_number )
-- rpath is remaining path
with option (option_id,path,rpath, leaf) as ( \
select option_id \
,'./DEFAULT/jackpot_sign/sack/PSI/Frame border/Height' as path \
, substr( './DEFAULT/jackpot_sign/sack/PSI/Frame border/Height' \
, instr( './DEFAULT/jackpot_sign/sack/PSI/Frame
border/Height', '/' ) + 1 ) as rpath \
, 0 as leaf \
from option4_map \
join option4_name on option4_map.name_id=option4_name.name_id \
where option_id='00000000-0000-0000-0000-000000000000' \
and name=substr(path,0,instr(path,'/')) \
union all select option4_map.option_id, name, ''as path, substr(
rpath, instr( rpath, '/' ) + 1 ) \
, instr(rpath,'/') == 0 as leaf \
from option4_map \
join option4_name on option4_map.name_id=option4_name.name_id \
join option on option.option_id=option4_map.parent_option_id \
where option4_map.parent_option_id != option4_map.option_id \
and ( name= substr( rpath, 0, instr( rpath, '/' )
) or name = rpath ) \
) \
select * from option
join option4_values on option.option_id=option4_values.option_id
where leaf=1 -- added leaf indicator to just select final value.
order by segment_number
-- Yes; given such a large name_id, it would less data to just store
the name usually in the option4_map entry... used to just be an int
but it evolved... guess I should revise a version 5...
CREATE TABLE `option4_name` (
`name_id` char(36) NOT NULL
,`name` varchar(255) NOT NULL default ''
CONSTRAINT `name` UNIQUE)
index,sqlite_autoindex_option4_name_1,option4_name,3,NULL
(index on name_id)
CREATE TABLE `option4_map` (
`option_id` char(36) NOT NULL
,`parent_option_id` char(36) NOT NULL default '0'
,`name_id` char(36) NOT NULL default '0'
,`description` tinytext
,CONSTRAINT `parent_key2` UNIQUE
(`parent_option_id`,`name_id`) ON CONFLICT REPLACE
,CONSTRAINT `FK_map_map` FOREIGN KEY (`parent_option_id`)
REFERENCES `option4_map`(`option_id`)ON UPDATE
CASCADE ON DELETE CASCADE
,CONSTRAINT `FK_name_map` FOREIGN KEY (`name_id`)
REFERENCES `option4_name`(`name_id`)ON UPDATE
CASCADE ON DELETE CASCADE)
index,sqlite_autoindex_option4_map_1,option4_map,5,NULL
(index on option_id)
CREATE TABLE `option4_values` (
`option_id` char(36) default '0'
,`string` varchar(100) default NULL
,`segment` int(11) default 0
,CONSTRAINT `value_id` UNIQUE (`option_id`,`segment`) ON
CONFLICT REPLACE
,CONSTRAINT `FK_map_values` FOREIGN KEY (`option_id`)
REFERENCES `option4_map`(`option_id`)ON UPDATE
CASCADE ON DELETE CASCADE)
index,sqlite_autoindex_option4_values_1,option4_values,11,NULL
(index on option_id)
On Thu, Nov 12, 2015 at 8:35 AM, J Decker <d3ck0r at gmail.com> wrote:
> On Thu, Nov 12, 2015 at 7:16 AM, E.Pasma <pasma10 at concepts.nl> wrote:
>> 12 nov 2015, om 07:02, J Decker:
>>
>>
>>> So I've used CTE to solve a simple problem... I'm tempted to use it to
>>> fix more problems... but I'm wondering how to select different values
>>> at different levels. I know there's like 'select * from table where
>>> column in ( set,of,things) ' but can I index into the set? is there
>>> some sort of way I can specify an array of values?
>>>
>>> would like to do something like ' select value from option_map where
>>> name is ["system","device","com port", "1" ] ' where the program
>>> statement would look more like
>>>
>>> GetOptionValue ( "/system/device/com port/1" ) where the name is
>>> really sort of registry like and variable in length...
>>>
>>> I could probably do some sort of indexing passing that exact string
>>> through and parsing in SQL the substrings of interest based on the
>>> level of the query... but would rather preparse the string.
>>
>>
>>
>> Below is another possible answer. This uses a recursive cte to split an
>> input full path name into seperate names.
>> create table map (id, name, parent);
>> insert into map values
>> (0, '',''), -- level 0
>> (1, 'system', 0), -- level 1
>> (2, 'device', 1), -- level 2
>> (3, 'com port', 2), -- level 3
>> (4, '1', 3), -- level 4
>> (5, '2', 3) -- level 4
>> ;
>> with walk as (
>> select 0 as parent, --root
>> '/system/device/com port/1' as path ,
> 0 as level
>> union
>> select id,
>> substr(path,length(name)+2) ,
> level+1 as level
>> from walk
>> join map using(parent)
>> where name = substr(path,2,instr(substr(path,2)||'/','/')-1) --oef
>> )
>> select parent as id from walk
>> where path='' -- nothing left
>> ;
>
> (something like that....)
>
> was hoping to not have to do the substr part in the query....
> and would like the path to be more on the external usage of 'walk' in
> this case than inside the expression
>
> would be better than building up the address to get a comparison at
> the end since the whole map would have to be walked.
>
> TO answer other's questions; 'level' refers to the dept of the tree
> searched... level indiciators added as comments to the insert above...