semantic-db: I like the new stuff better than the old stuff

db4
Alex Chapman 2008-03-06 23:54:16 +11:00
parent 0c2ceed71b
commit 6bb2a46acb
6 changed files with 136 additions and 107 deletions

View File

@ -1,19 +1,16 @@
! Copyright (C) 2008 Alex Chapman ! Copyright (C) 2008 Alex Chapman
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: kernel semantic-db semantic-db.type ; USING: kernel namespaces semantic-db ;
IN: semantic-db.context IN: semantic-db.context
! contexts: : create-context* ( context-name -- context-id ) create-node* ;
! - have type 'context' in context 'semantic-db' : create-context ( context-name -- ) create-context* drop ;
: current-context ( -- context-id ) : context ( -- context-id )
\ current-context get ; \ context get ;
: set-current-context ( context-id -- ) : set-context ( context-id -- )
\ current-context set ; \ context set ;
: context-id ( name -- context-id ) : with-context ( context-id quot -- )
context-type swap ensure-node-of-type ; >r \ context r> with-variable ;
: with-context ( name quot -- )
swap context-id [ set-current-context ] curry swap compose with-scope ;

View File

@ -1,38 +1,44 @@
! Copyright (C) 2008 Alex Chapman ! Copyright (C) 2008 Alex Chapman
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: accessors kernel new-slots semantic-db semantic-db.relations sequences ; USING: accessors db.tuples kernel new-slots semantic-db semantic-db.relations sequences sequences.deep ;
IN: semantic-db.hierarchy IN: semantic-db.hierarchy
TUPLE: tree id children ; TUPLE: tree id children ;
C: <tree> tree C: <tree> tree
! TODO: don't use context here. Hierarchies should be created within
! arbitrary contexts.
: hierarchy-context ( -- context-id )
"hierarchy" context-id ;
: has-parent-relation ( -- relation-id ) : has-parent-relation ( -- relation-id )
hierarchy-context "has parent" relation-id ; "has parent" relation-id ;
: parent-of ( parent child -- arc-id ) : parent-child* ( parent child -- arc-id )
has-parent-relation spin create-arc ; has-parent-relation spin create-arc* ;
: select-parents ( child -- parents ) : parent-child ( parent child -- )
parent-child* drop ;
: un-parent-child ( parent child -- )
has-parent-relation -rot <arc> select-tuples [ id>> delete-arc ] each ;
: ensure-parent ( child parent -- ) : child-arcs ( node-id -- child-arcs )
! TODO has-parent-relation f rot <arc> select-tuples ;
;
: find-children ( node-id -- children ) : children ( node-id -- children )
! find arcs with: child-arcs [ subject>> ] map ;
! relation = has-parent-relation
! object = node-id : parent-arcs ( node-id -- parent-arcs )
! then load the subjects either as nodes or subtrees has-parent-relation swap f <arc> select-tuples ;
":node_id" INTEGER param
has-parent-relation ":has_parent" INTEGER param 2array : parents ( node-id -- parents )
"select a.subject from arc a where relation = :has_parent and object = :node_id" parent-arcs [ object>> ] map ;
single-int-results ;
: get-node-hierarchy ( node-id -- tree ) : get-node-hierarchy ( node-id -- tree )
dup find-children <tree> ; dup children [ get-node-hierarchy ] map <tree> ;
: (get-root-nodes) ( node-id -- root-nodes/node-id )
dup parents dup empty? [
drop
] [
nip [ (get-root-nodes) ] map
] if ;
: get-root-nodes ( node-id -- root-nodes )
(get-root-nodes) flatten ;

View File

@ -1,27 +1,26 @@
! Copyright (C) 2008 Alex Chapman ! Copyright (C) 2008 Alex Chapman
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: kernel semantic-db semantic-db.context semantic-db.type ; USING: db.types kernel namespaces semantic-db semantic-db.context
sequences.lib ;
IN: semantic-db.relations IN: semantic-db.relations
! relations: ! relations:
! - have type 'relation' in context 'semantic-db'
! - have a context in context 'semantic-db' ! - have a context in context 'semantic-db'
: create-relation ( context-id relation-name -- relation-id ) : create-relation* ( context-id relation-name -- relation-id )
relation-type swap ensure-node-of-type create-node* tuck has-context-relation spin create-arc ;
tuck has-context-relation spin create-arc ;
: select-relation ( context-id relation-name -- relation-id/f ) : create-relation ( context-id relation-name -- )
create-relation* drop ;
: get-relation ( context-id relation-name -- relation-id/f )
[ [
":name" TEXT param , ":name" TEXT param ,
has-type-relation ":has_type" INTEGER param ,
relation-type ":relation_type" INTEGER param ,
":context" INTEGER param , ":context" INTEGER param ,
has-context-relation ":has_context" INTEGER param , has-context-relation ":has_context" INTEGER param ,
] { } make ] { } make
"select n.id from node n, arc a, arc b where n.content = :name and n.id = a.subject and a.relation = :has_type and a.object = :relation_type and n.id = b.subject and b.relation = :has_context and b.object = :context" "select n.id from node n, arc a where n.content = :name and n.id = a.subject and a.relation = :has_context and a.object = :context"
single-int-results ; single-int-results ?first ;
: relation-id ( context-id relation-name -- relation-id ) : relation-id ( relation-name -- relation-id )
[ select-relation ] [ create-relation ] ensure2 ; context swap [ get-relation ] [ create-relation* ] ensure2 ;
! 2dup select-relation [ 2nip ] [ create-relation ] if* ;

View File

@ -1,26 +1,58 @@
USING: accessors arrays db db.sqlite db.tuples kernel math semantic-db semantic-db.type sequences tools.test tools.walker ; USING: accessors arrays db db.sqlite db.tuples kernel math namespaces
IN: temporary semantic-db semantic-db.context semantic-db.hierarchy semantic-db.relations
sequences tools.test tools.walker ;
IN: vocab.tests
[ [
create-node-table create-arc-table create-node-table create-arc-table
[ 1 ] [ "first node" create-node ] unit-test [ 1 ] [ "first node" create-node* ] unit-test
[ 2 ] [ "second node" create-node ] unit-test [ 2 ] [ "second node" create-node* ] unit-test
[ 3 ] [ "third node" create-node ] unit-test [ 3 ] [ "third node" create-node* ] unit-test
[ 4 ] [ f create-node ] unit-test [ 4 ] [ f create-node* ] unit-test
[ 5 ] [ 1 2 3 create-arc ] unit-test [ 5 ] [ 1 2 3 create-arc* ] unit-test
] with-tmp-sqlite ] with-tmp-sqlite
[ [
init-semantic-db init-semantic-db
type-type 1array [ "type" ensure-type ] unit-test "test content" create-context* [
[ { 1 2 3 } ] [ type-type select-nodes-of-type ] unit-test [ 4 ] [ context ] unit-test
[ 1 ] [ type-type select-node-of-type ] unit-test [ 5 ] [ context "is test content" create-relation* ] unit-test
[ t ] [ "content" ensure-type integer? ] unit-test [ 5 ] [ context "is test content" get-relation ] unit-test
[ t ] [ "content" ensure-type "content" ensure-type = ] unit-test [ 5 ] [ "is test content" relation-id ] unit-test
[ t ] [ "content" ensure-type "first content" create-node-of-type integer? ] unit-test [ 7 ] [ "has parent" relation-id ] unit-test
[ t ] [ "content" ensure-type select-node-of-type integer? ] unit-test [ 7 ] [ "has parent" relation-id ] unit-test
[ t ] [ "content" ensure-type "first content" select-node-of-type-with-content integer? ] unit-test [ "has parent" ] [ "has parent" relation-id node-content ] unit-test
[ t ] [ "content" ensure-type "first content" ensure-node-of-type integer? ] unit-test [ "test content" ] [ context node-content ] unit-test
[ t ] [ "content" ensure-type "second content" ensure-node-of-type integer? ] unit-test ] with-context
[ 2 ] [ "content" ensure-type select-nodes-of-type length ] unit-test ! type-type 1array [ "type" ensure-type ] unit-test
! [ { 1 2 3 } ] [ type-type select-nodes-of-type ] unit-test
! [ 1 ] [ type-type select-node-of-type ] unit-test
! [ t ] [ "content" ensure-type integer? ] unit-test
! [ t ] [ "content" ensure-type "content" ensure-type = ] unit-test
! [ t ] [ "content" ensure-type "first content" create-node-of-type integer? ] unit-test
! [ t ] [ "content" ensure-type select-node-of-type integer? ] unit-test
! [ t ] [ "content" ensure-type "first content" select-node-of-type-with-content integer? ] unit-test
! [ t ] [ "content" ensure-type "first content" ensure-node-of-type integer? ] unit-test
! [ t ] [ "content" ensure-type "second content" ensure-node-of-type integer? ] unit-test
! [ 2 ] [ "content" ensure-type select-nodes-of-type length ] unit-test
] with-tmp-sqlite
! test hierarchy
[
init-semantic-db
"family tree" create-context* [
"adam" create-node* "adam" set
"eve" create-node* "eve" set
"bob" create-node* "bob" set
"fran" create-node* "fran" set
"charlie" create-node* "charlie" set
"gertrude" create-node* "gertrude" set
[ t ] [ "adam" get "bob" get parent-child* integer? ] unit-test
{ { "eve" "bob" } { "eve" "fran" } { "bob" "gertrude" } { "fran" "charlie" } } [ first2 [ get ] 2apply parent-child ] each
[ { "bob" "fran" } ] [ "eve" get children [ node-content ] map ] unit-test
[ { "adam" "eve" } ] [ "bob" get parents [ node-content ] map ] unit-test
[ "fran" { "charlie" } ] [ "fran" get get-node-hierarchy dup tree-id node-content swap tree-children [ tree-id node-content ] map ] unit-test
[ { "adam" "eve" } ] [ "charlie" get get-root-nodes ] unit-test
[ { } ] [ "fran" get "charlie" get tuck un-parent-child parents ] unit-test
] with-context
] with-tmp-sqlite ] with-tmp-sqlite

View File

@ -7,6 +7,9 @@ TUPLE: node id content ;
: <node> ( content -- node ) : <node> ( content -- node )
node construct-empty swap >>content ; node construct-empty swap >>content ;
: <id-node> ( id -- node )
node construct-empty swap >>id ;
node "node" node "node"
{ {
{ "id" "id" +native-id+ +autoincrement+ } { "id" "id" +native-id+ +autoincrement+ }
@ -16,14 +19,38 @@ node "node"
: create-node-table ( -- ) : create-node-table ( -- )
node create-table ; node create-table ;
: create-node ( content -- id ) : delete-node ( node-id -- )
<id-node> delete-tuple ;
: create-node* ( str -- node-id )
<node> dup insert-tuple id>> ; <node> dup insert-tuple id>> ;
: create-node ( str -- )
create-node* drop ;
: node-content ( id -- str )
f <node> swap >>id select-tuple content>> ;
TUPLE: arc id relation subject object ; TUPLE: arc id relation subject object ;
: <arc> ( relation subject object -- arc ) : <arc> ( relation subject object -- arc )
arc construct-empty swap >>object swap >>subject swap >>relation ; arc construct-empty swap >>object swap >>subject swap >>relation ;
: <id-arc> ( id -- arc )
arc construct-empty swap >>id ;
: insert-arc ( arc -- )
f <node> dup insert-tuple id>> >>id insert-tuple ;
: delete-arc ( arc-id -- )
dup delete-node <id-arc> delete-tuple ;
: create-arc* ( relation subject object -- arc-id )
<arc> dup insert-arc id>> ;
: create-arc ( relation subject object -- )
create-arc* drop ;
arc "arc" arc "arc"
{ {
{ "id" "id" INTEGER +assigned-id+ } ! foreign key to node table? { "id" "id" INTEGER +assigned-id+ } ! foreign key to node table?
@ -35,47 +62,15 @@ arc "arc"
: create-arc-table ( -- ) : create-arc-table ( -- )
arc create-table ; arc create-table ;
: insert-arc ( arc -- )
f <node> dup insert-tuple id>> >>id insert-tuple ;
: delete-arc ( arc -- )
dup delete-tuple delegate delete-tuple ;
: create-arc ( relation subject object -- id )
<arc> dup insert-arc id>> ;
: create-bootstrap-nodes ( -- ) : create-bootstrap-nodes ( -- )
{ "context" "type" "relation" "has type" "semantic-db" "has context" } "semantic-db" create-node
[ create-node drop ] each ; "has context" create-node ;
! TODO: maybe put these in a 'special nodes' table : semantic-db-context 1 ;
: context-type 1 ; inline : has-context-relation 2 ;
: type-type 2 ; inline
: relation-type 3 ; inline
: has-type-relation 4 ; inline
: semantic-db-context 5 ; inline
: has-context-relation 6 ; inline
: has-semantic-db-context ( id -- )
has-context-relation swap semantic-db-context create-arc drop ;
: has-type-in-semantic-db ( subject type -- )
has-type-relation -rot create-arc drop ;
: create-bootstrap-arcs ( -- ) : create-bootstrap-arcs ( -- )
! give everything a type has-context-relation has-context-relation semantic-db-context create-arc ;
context-type type-type has-type-in-semantic-db
type-type type-type has-type-in-semantic-db
relation-type type-type has-type-in-semantic-db
has-type-relation relation-type has-type-in-semantic-db
semantic-db-context context-type has-type-in-semantic-db
has-context-relation relation-type has-type-in-semantic-db
! give relations and types the semantic-db context
context-type has-semantic-db-context
type-type has-semantic-db-context
relation-type has-semantic-db-context
has-type-relation has-semantic-db-context
has-context-relation has-semantic-db-context ;
: init-semantic-db ( -- ) : init-semantic-db ( -- )
create-node-table create-arc-table create-bootstrap-nodes create-bootstrap-arcs ; create-node-table create-arc-table create-bootstrap-nodes create-bootstrap-arcs ;

View File

@ -8,10 +8,10 @@ IN: semantic-db.type
! - have a context in context 'semantic-db' ! - have a context in context 'semantic-db'
: assign-type ( type nid -- arc-id ) : assign-type ( type nid -- arc-id )
has-type-relation spin create-arc ; has-type-relation spin arc-id ;
: create-node-of-type ( type content -- node-id ) : create-node-of-type ( type content -- node-id )
create-node [ assign-type drop ] keep ; node-id [ assign-type drop ] keep ;
: select-nodes-of-type ( type -- node-ids ) : select-nodes-of-type ( type -- node-ids )
":type" INTEGER param ":type" INTEGER param
@ -33,7 +33,7 @@ IN: semantic-db.type
single-int-results ; single-int-results ;
: select-node-of-type-with-content ( type content -- node-id/f ) : select-node-of-type-with-content ( type content -- node-id/f )
select-nodes-of-type-with-content 1result ; select-nodes-of-type-with-content ?first ;
: ensure-node-of-type ( type content -- node-id ) : ensure-node-of-type ( type content -- node-id )
[ select-node-of-type-with-content ] [ create-node-of-type ] ensure2 ; [ select-node-of-type-with-content ] [ create-node-of-type ] ensure2 ;