Commit a3c63db9 authored by Dave Griffiths's avatar Dave Griffiths
Browse files

big syncing changes, partially complete

parent 37bd7a16
...@@ -75,13 +75,23 @@ ...@@ -75,13 +75,23 @@
(get-current 'entity-values '()) (get-current 'entity-values '())
(ktv key type value)))) (ktv key type value))))
;; internal version for checking version numbers are propagating properly
;; this is for automatically added ktv data (and adds 0 version)
;; rather than from the ui (which adds -999 by default)
(define (entity-add-value-create! key type value)
(set-current!
'entity-values
(ktv-set
(get-current 'entity-values '())
(ktv-create key type value))))
(define (entity-set! ktv-list) (define (entity-set! ktv-list)
(set-current! 'entity-values ktv-list)) (set-current! 'entity-values ktv-list))
(define (entity-get-value key) (define (entity-get-value key)
(ktv-get (get-current 'entity-values '()) key)) (ktv-get (get-current 'entity-values '()) key))
;; version to check the entity has the key ;; version to check the entity has the key
(define (entity-set-value! key type value) (define (entity-set-value! key type value)
(msg "entity-set-value!") (msg "entity-set-value!")
...@@ -110,11 +120,11 @@ ...@@ -110,11 +120,11 @@
(table (get-current 'table #f)) (table (get-current 'table #f))
(type (get-current 'entity-type #f))) (type (get-current 'entity-type #f)))
;; standard bits ;; standard bits
(entity-add-value! "user" "varchar" (get-current 'user-id "none")) (entity-add-value-create! "user" "varchar" (get-current 'user-id "none"))
(entity-add-value! "time" "varchar" (date-time->string (date-time))) (entity-add-value-create! "time" "varchar" (date-time->string (date-time)))
(entity-add-value! "lat" "real" (car (get-current 'location '(0 0)))) (entity-add-value-create! "lat" "real" (car (get-current 'location '(0 0))))
(entity-add-value! "lon" "real" (cadr (get-current 'location '(0 0)))) (entity-add-value-create! "lon" "real" (cadr (get-current 'location '(0 0))))
(entity-add-value! "deleted" "int" 0) (entity-add-value-create! "deleted" "int" 0)
(let ((values (get-current 'entity-values '()))) (let ((values (get-current 'entity-values '())))
(cond (cond
((not (null? values)) ((not (null? values))
...@@ -165,7 +175,7 @@ ...@@ -165,7 +175,7 @@
(msg "url") (msg "url")
(define (build-url-from-ktv ktv) (define (build-url-from-ktv ktv)
(string-append "&" (ktv-key ktv) ":" (ktv-type ktv) "=" (stringify-value-url ktv))) (string-append "&" (ktv-key ktv) ":" (ktv-type ktv) ":" (number->string (ktv-version ktv)) "=" (stringify-value-url ktv)))
(define (build-url-from-ktvlist ktvlist) (define (build-url-from-ktvlist ktvlist)
(foldl (foldl
...@@ -201,13 +211,12 @@ ...@@ -201,13 +211,12 @@
r)) r))
'() ktvlist)) '() ktvlist))
(msg "spit")
;; spit all dirty entities to server ;; spit all dirty entities to server
(define (spit db table entities) (define (spit db table entities)
(msg "running spit")
(foldl (foldl
(lambda (e r) (lambda (e r)
(msg (car (car e)))
(debug! (string-append "Sending a " (car (car e)) " to Raspberry Pi")) (debug! (string-append "Sending a " (car (car e)) " to Raspberry Pi"))
(append (append
(list (list
...@@ -272,6 +281,8 @@ ...@@ -272,6 +281,8 @@
(ktvlist (list-ref data 1)) (ktvlist (list-ref data 1))
(unique-id (list-ref entity 1)) (unique-id (list-ref entity 1))
(exists (entity-exists? db table unique-id))) (exists (entity-exists? db table unique-id)))
(msg "from server...:")
(msg ktvlist)
;; need to check exists again here, due to delays back and forth ;; need to check exists again here, due to delays back and forth
(if (not exists) (if (not exists)
(insert-entity-wholesale (insert-entity-wholesale
...@@ -537,7 +548,7 @@ ...@@ -537,7 +548,7 @@
((eq? widget-type 'image-view) ((eq? widget-type 'image-view)
(let ((image-name (entity-get-value key))) (let ((image-name (entity-get-value key)))
(msg "updating image widget to: " image-name) (msg "updating image widget to: " image-name)
(if (or (not image-name) (equal? image-name "none")) (if (image-invalid? image-name)
(update-widget widget-type (get-symbol-id id-symbol) 'image "face") (update-widget widget-type (get-symbol-id id-symbol) 'image "face")
(update-widget widget-type (get-symbol-id id-symbol) 'external-image (update-widget widget-type (get-symbol-id id-symbol) 'external-image
(string-append dirname "files/" image-name))))) (string-append dirname "files/" image-name)))))
...@@ -584,8 +595,8 @@ ...@@ -584,8 +595,8 @@
(define (do-gps display-id key-prepend) (define (do-gps display-id key-prepend)
(let ((loc (get-current 'location '(0 0)))) (let ((loc (get-current 'location '(0 0))))
(entity-add-value! (string-append key-prepend "-lat") "real" (car loc)) (entity-add-value-create! (string-append key-prepend "-lat") "real" (car loc))
(entity-add-value! (string-append key-prepend "-lon") "real" (cadr loc)) (entity-add-value-create! (string-append key-prepend "-lon") "real" (cadr loc))
(list (list
(update-widget (update-widget
'text-view 'text-view
...@@ -623,7 +634,7 @@ ...@@ -623,7 +634,7 @@
40 (layout 100 'wrap-content 1 'centre 5) 40 (layout 100 'wrap-content 1 'centre 5)
(lambda () (lambda ()
(entity-init! db table entity-type ktv-default) (entity-init! db table entity-type ktv-default)
(entity-add-value! "parent" "varchar" (parent-fn)) (entity-add-value-create! "parent" "varchar" (parent-fn))
(entity-record-values!) (entity-record-values!)
(list (update-list-widget db table entity-type edit-activity (parent-fn)))))) (list (update-list-widget db table entity-type edit-activity (parent-fn))))))
(linear-layout (linear-layout
......
...@@ -31,18 +31,40 @@ ...@@ -31,18 +31,40 @@
(define (setup db table) (define (setup db table)
(db-exec db (string-append "create table " table "_entity ( entity_id integer primary key autoincrement, entity_type varchar(256), unique_id varchar(256), dirty integer, version integer)")) (db-exec db (string-append "create table " table "_entity ( entity_id integer primary key autoincrement, entity_type varchar(256), unique_id varchar(256), dirty integer, version integer)"))
(db-exec db (string-append "create table " table "_attribute ( id integer primary key autoincrement, attribute_id varchar(256), entity_type varchar(256), attribute_type varchar(256))")) (db-exec db (string-append "create table " table "_attribute ( id integer primary key autoincrement, attribute_id varchar(256), entity_type varchar(256), attribute_type varchar(256))"))
(db-exec db (string-append "create table " table "_value_varchar ( id integer primary key autoincrement, entity_id integer, attribute_id varchar(255), value varchar(4096), dirty integer)")) (db-exec db (string-append "create table " table "_value_varchar ( id integer primary key autoincrement, entity_id integer, attribute_id varchar(255), value varchar(4096), dirty integer, version integer)"))
(db-exec db (string-append "create table " table "_value_int ( id integer primary key autoincrement, entity_id integer, attribute_id varchar(255), value integer, dirty integer)")) (db-exec db (string-append "create table " table "_value_int ( id integer primary key autoincrement, entity_id integer, attribute_id varchar(255), value integer, dirty integer, version integer)"))
(db-exec db (string-append "create table " table "_value_real ( id integer primary key autoincrement, entity_id integer, attribute_id varchar(255), value real, dirty integer)")) (db-exec db (string-append "create table " table "_value_real ( id integer primary key autoincrement, entity_id integer, attribute_id varchar(255), value real, dirty integer, version integer)"))
(db-exec db (string-append "create table " table "_value_file ( id integer primary key autoincrement, entity_id integer, attribute_id varchar(255), value varchar(4096), dirty integer)"))) (db-exec db (string-append "create table " table "_value_file ( id integer primary key autoincrement, entity_id integer, attribute_id varchar(255), value varchar(4096), dirty integer, version integer)")))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; basic key/type/value structure ;; basic key/type/value structure
(define (ktv key type value) (list key type value)) ;; used for all data internally, and maps to the eavdb types
(define (ktv key type value) (list key type value -999))
(define (ktv-with-version key type value version) (list key type value version))
(define (ktv-create key type value) (list key type value 0))
(define ktv-key car) (define ktv-key car)
(define ktv-type cadr) (define ktv-type cadr)
(define ktv-value caddr) (define ktv-value caddr)
(define (ktv-version ktv) (list-ref ktv 3))
(define (ktv-eq? a b)
(and
(equal? (ktv-key a) (ktv-key b))
(equal? (ktv-type a) (ktv-type b))
(cond
((or
(equal? (ktv-type a) "int")
(equal? (ktv-type a) "real"))
(eqv? (ktv-value a) (ktv-value b)))
((or
(equal? (ktv-type a) "varchar")
(equal? (ktv-type a) "file"))
(equal? (ktv-value a) (ktv-value b)))
(else
(msg "unsupported ktv type in ktv-eq?: " (ktv-type a))
#f))))
;; stringify based on type (for url) ;; stringify based on type (for url)
(define (stringify-value ktv) (define (stringify-value ktv)
...@@ -64,6 +86,7 @@ ...@@ -64,6 +86,7 @@
(number->string (ktv-value ktv)) (number->string (ktv-value ktv))
(ktv-value ktv))))) (ktv-value ktv)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; helper to return first instance from a select ;; helper to return first instance from a select
(define (select-first db str . args) (define (select-first db str . args)
...@@ -104,11 +127,11 @@ ...@@ -104,11 +127,11 @@
type)))))) type))))))
;; low level insert of a ktv ;; low level insert of a ktv
(define (insert-value db table entity-id ktv) (define (insert-value db table entity-id ktv dirty)
;; use type to dispatch insert to correct value table ;; use type to dispatch insert to correct value table
(db-insert db (string-append "insert into " table "_value_" (ktv-type ktv) (db-insert db (string-append "insert into " table "_value_" (ktv-type ktv)
" values (null, ?, ?, ?, 0)") " values (null, ?, ?, ?, ?, ?)")
entity-id (ktv-key ktv) (ktv-value ktv))) entity-id (ktv-key ktv) (ktv-value ktv) dirty (ktv-version ktv)))
(define (get-unique user) (define (get-unique user)
(let ((t (time-of-day))) (let ((t (time-of-day)))
...@@ -139,23 +162,46 @@ ...@@ -139,23 +162,46 @@
;; add all the keys ;; add all the keys
(for-each (for-each
(lambda (ktv) (lambda (ktv)
(insert-value db table id ktv)) (insert-value db table id ktv dirty))
ktvlist) ktvlist)
id)) id))
;; update the value given an entity type, a attribute type and it's key (= attriute_id) ;; update the value given an entity type, a attribute type and it's key (= attriute_id)
;; creates the value if it doesn't already exist, updates it otherwise ;; creates the value if it doesn't already exist, updates it otherwise if it's different
(define (update-value db table entity-id ktv) (define (update-value db table entity-id ktv)
(if (null? (select-first (msg "update-value")
db (string-append (let ((s (select-first
"select * from " table "_value_" (ktv-type ktv) " where entity_id = ? and attribute_id = ?") db (string-append
entity-id (ktv-key ktv))) "select value from " table "_value_" (ktv-type ktv) " where entity_id = ? and attribute_id = ?")
(insert-value db table entity-id ktv) entity-id (ktv-key ktv))))
(db-exec (if (null? s)
db (string-append "update " table "_value_" (ktv-type ktv) (insert-value db table entity-id ktv #t)
" set value=? where entity_id = ? and attribute_id = ?") ;; only update if they are different
(ktv-value ktv) entity-id (ktv-key ktv)))) (if (not (ktv-eq? ktv (list (ktv-key ktv) (ktv-type ktv) s)))
(begin
(msg "incrementing value version in update-value")
(db-exec
db (string-append "update " table "_value_" (ktv-type ktv)
" set value=?, dirty=1, version=version+1 where entity_id = ? and attribute_id = ?")
(ktv-value ktv) entity-id (ktv-key ktv)))
'())))) ;;(msg "values for" (ktv-key ktv) "are the same (" (ktv-value ktv) "==" s ")")))))
;; don't make dirty or update version here
(define (update-value-from-sync db table entity-id ktv version)
(let ((s (select-first
db (string-append
"select value from " table "_value_" (ktv-type ktv) " where entity_id = ? and attribute_id = ?")
entity-id (ktv-key ktv))))
(msg "uvfs")
(msg (ktv-value ktv))
(msg s)
(if (null? s)
(insert-value db table entity-id ktv #t)
(db-exec
db (string-append "update " table "_value_" (ktv-type ktv)
" set value=?, dirty=0, version=? where entity_id = ? and attribute_id = ?")
(ktv-value ktv) entity-id (ktv-key ktv) (ktv-version ktv)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; getting data out ;; getting data out
...@@ -188,22 +234,56 @@ ...@@ -188,22 +234,56 @@
(vector-ref row 3))) ;; type (vector-ref row 3))) ;; type
(cdr s))))) (cdr s)))))
;; get the value given an entity type, a attribute type and it's key (= attriute_id) ;; get the value, dirty and version given an entity type, a attribute type and it's key (= attriute_id)
(define (get-value db table entity-id kt) (define (get-value db table entity-id kt)
(select-first (let ((s (db-select
db (string-append "select value from " table "_value_" (ktv-type kt) db (string-append "select value, dirty, version from " table "_value_" (ktv-type kt)
" where entity_id = ? and attribute_id = ?") " where entity_id = ? and attribute_id = ?")
entity-id (ktv-key kt))) entity-id (ktv-key kt))))
(if (null? s) '()
(list (vector-ref (cadr s) 0)
(vector-ref (cadr s) 1)
(vector-ref (cadr s) 2)))))
;; get an entire entity, as a list of key/value pairs ;; get an entire entity, as a list of key/value pairs
(define (get-entity-plain db table entity-id) (define (get-entity-plain db table entity-id)
(msg "get-entity-plain")
(let* ((entity-type (get-entity-type db table entity-id))) (let* ((entity-type (get-entity-type db table entity-id)))
(cond (cond
((null? entity-type) (msg "entity" entity-id "not found!") '()) ((null? entity-type) (msg "entity" entity-id "not found!") '())
(else (else
(map (map
(lambda (kt) (lambda (kt)
(list (ktv-key kt) (ktv-type kt) (get-value db table entity-id kt))) (let ((vdv (get-value db table entity-id kt)))
(msg vdv)
(if (null? vdv)
(msg "ERROR: get-entity-plain: no value found for " entity-id " " (ktv-key kt))
(list (ktv-key kt) (ktv-type kt)
(list-ref vdv 0) (list-ref vdv 2)))))
(get-attribute-ids/types db table entity-type))))))
;; get an entire entity, as a list of key/value pairs, only dirty values
(define (get-entity-plain-for-sync db table entity-id)
(let* ((entity-type (get-entity-type db table entity-id)))
(cond
((null? entity-type) (msg "entity" entity-id "not found!") '())
(else
(foldl
(lambda (kt r)
(msg "kt is" kt)
(let ((vdv (get-value db table entity-id kt)))
(cond
((null? vdv)
(msg "ERROR: get-entity-plain-for-sync: no value found for " entity-id " " (ktv-key kt))
r)
;; only return if dirty
((not (zero? (cadr vdv)))
(msg "value-dirty-version found" vdv)
(cons
(list (ktv-key kt) (ktv-type kt) (list-ref vdv 0) (list-ref vdv 2))
r))
(else r))))
'()
(get-attribute-ids/types db table entity-type)))))) (get-attribute-ids/types db table entity-type))))))
;; get an entire entity, as a list of key/value pairs (includes entity id) ;; get an entire entity, as a list of key/value pairs (includes entity id)
...@@ -376,16 +456,39 @@ ...@@ -376,16 +456,39 @@
;; update an entire entity (version incl), via a (possibly partial) list of key/value pairs ;; update an entire entity (version incl), via a (possibly partial) list of key/value pairs
(define (update-to-version db table entity-id version ktvlist) (define (update-to-version db table entity-id version ktvlist)
(update-entity-values db table entity-id ktvlist) ;; not dirty
(update-entity-values db table entity-id ktvlist #f)
(update-entity-version db table entity-id version)) (update-entity-version db table entity-id version))
;; auto update version ;; auto update version
(define (update-entity db table entity-id ktvlist) (define (update-entity db table entity-id ktvlist)
(msg "update-entity")
;; dirty
(update-entity-changed db table entity-id) (update-entity-changed db table entity-id)
(update-entity-values db table entity-id ktvlist)) (update-entity-values db table entity-id ktvlist #t))
(define (clean-value db table entity-id kt)
(db-exec db (string-append "update " table "_value_" (ktv-type kt)
" set dirty=0 where entity_id = ? and attribute_id = ?")
entity-id (ktv-key kt)))
(define (clean-entity-values db table entity-id)
(msg "clean-entity-values")
(let* ((entity-type (get-entity-type db table entity-id)))
(cond
((null? entity-type)
(msg "clean-entity-values: entity" entity-id "not found!") '())
(else
(for-each
(lambda (kt)
(msg "cleaning" kt)
(clean-value db table entity-id (list (ktv-key kt) (ktv-type kt))))
(get-attribute-ids/types db table entity-type))))))
;; update an entity, via a (possibly partial) list of key/value pairs ;; update an entity, via a (possibly partial) list of key/value pairs
(define (update-entity-values db table entity-id ktvlist) ;; if dirty is not true, this is coming from a sync
(define (update-entity-values db table entity-id ktvlist dirty)
(msg "update-entity-values")
(let* ((entity-type (get-entity-type db table entity-id))) (let* ((entity-type (get-entity-type db table entity-id)))
(cond (cond
((null? entity-type) (msg "entity" entity-id "not found!") '()) ((null? entity-type) (msg "entity" entity-id "not found!") '())
...@@ -398,7 +501,10 @@ ...@@ -398,7 +501,10 @@
ktvlist) ktvlist)
(for-each (for-each
(lambda (ktv) (lambda (ktv)
(update-value db table entity-id ktv)) (when (not (equal? (ktv-key ktv) "unique_id"))
(if dirty
(update-value db table entity-id ktv)
(update-value-from-sync db table entity-id ktv))))
ktvlist))))) ktvlist)))))
;; update or create an entire entity if it doesn't exist ;; update or create an entire entity if it doesn't exist
...@@ -434,8 +540,8 @@ ...@@ -434,8 +540,8 @@
(define (update-entity-changed db table entity-id) (define (update-entity-changed db table entity-id)
(db-exec (db-exec
db (string-append db (string-append
"update " table "_entity set dirty=?, version=? where entity_id = ?") "update " table "_entity set dirty=?, version=version+1 where entity_id = ?")
1 (+ 1 (get-entity-version db table entity-id)) entity-id)) 1 entity-id))
(define (update-entity-version db table entity-id version) (define (update-entity-version db table entity-id version)
(db-exec (db-exec
...@@ -444,9 +550,14 @@ ...@@ -444,9 +550,14 @@
1 version entity-id)) 1 version entity-id))
(define (update-entity-clean db table unique-id) (define (update-entity-clean db table unique-id)
(msg "cleaning")
;; clean entity table
(db-exec (db-exec
db (string-append "update " table "_entity set dirty=? where unique_id = ?") db (string-append "update " table "_entity set dirty=? where unique_id = ?")
0 unique-id)) 0 unique-id)
;; clean value tables for this entity
(msg "cleaning values")
(clean-entity-values db table (entity-id-from-unique db table unique-id)) )
(define (get-dirty-stats db table) (define (get-dirty-stats db table)
(list (list
...@@ -455,6 +566,8 @@ ...@@ -455,6 +566,8 @@
(select-first (select-first
db (string-append "select count(entity_id) from " table "_entity;")))) db (string-append "select count(entity_id) from " table "_entity;"))))
(define (dirty-entities db table) (define (dirty-entities db table)
(let ((de (db-select (let ((de (db-select
db (string-append db (string-append
...@@ -463,13 +576,16 @@ ...@@ -463,13 +576,16 @@
'() '()
(map (map
(lambda (i) (lambda (i)
(msg "dirty-entities")
(list (list
;; build according to url ([table] entity-type unique-id dirty version) ;; build according to url ([table] entity-type unique-id dirty version)
(cdr (vector->list i)) (cdr (vector->list i))
;; data entries (todo - only dirty values!) ;; data entries (todo - only dirty values!)
(get-entity-plain db table (vector-ref i 0)))) (dbg (get-entity-plain-for-sync db table (vector-ref i 0)))))
(cdr de))))) (cdr de)))))
;; todo: BROKEN...
;; used for sync-all
(define (dirty-and-all-entities db table) (define (dirty-and-all-entities db table)
(let ((de (db-select (let ((de (db-select
db (string-append db (string-append
...@@ -481,7 +597,7 @@ ...@@ -481,7 +597,7 @@
(list (list
;; build according to url ([table] entity-type unique-id dirty version) ;; build according to url ([table] entity-type unique-id dirty version)
(cdr (vector->list i)) (cdr (vector->list i))
;; data entries (todo - only dirty values!) ;; data entries (todo - only dirty values!)???????????
(get-entity-plain db table (vector-ref i 0)))) (get-entity-plain db table (vector-ref i 0))))
(cdr de))))) (cdr de)))))
......
...@@ -529,10 +529,10 @@ ...@@ -529,10 +529,10 @@
(build-list-widget (build-list-widget
db "sync" 'villages "village" "village" (lambda () #f) db "sync" 'villages "village" "village" (lambda () #f)
(list (list
(ktv "name" "varchar" (mtext-lookup 'default-village-name)) (ktv-create "name" "varchar" (mtext-lookup 'default-village-name))
(ktv "block" "varchar" "") (ktv-create "block" "varchar" "")
(ktv "district" "varchar" "test") (ktv-create "district" "varchar" "test")
(ktv "car" "int" 0)))) (ktv-create "car" "int" 0))))
(lambda (activity arg) (lambda (activity arg)
(set-current! 'activity-title "Main screen") (set-current! 'activity-title "Main screen")
...@@ -622,12 +622,12 @@ ...@@ -622,12 +622,12 @@
(build-list-widget (build-list-widget
db "sync" 'households "household" "household" (lambda () (get-current 'village #f)) db "sync" 'households "household" "household" (lambda () (get-current 'village #f))
(list (list
(ktv "name" "varchar" (mtext-lookup 'default-household-name)) (ktv-create "name" "varchar" (mtext-lookup 'default-household-name))
(ktv "num-pots" "int" 0) (ktv-create "num-pots" "int" 0)
(ktv "house-lat" "real" 0) ;; get from current location? (ktv-create "house-lat" "real" 0) ;; get from current location?
(ktv "house-lon" "real" 0) (ktv-create "house-lon" "real" 0)
(ktv "toilet-lat" "real" 0) (ktv-create "toilet-lat" "real" 0)
(ktv "toilet-lon" "real" 0)))) (ktv-create "toilet-lon" "real" 0))))
(lambda (activity arg) (lambda (activity arg)
(set-current! 'activity-title "Household List") (set-current! 'activity-title "Household List")
(activity-layout activity)) (activity-layout activity))
...@@ -664,44 +664,44 @@ ...@@ -664,44 +664,44 @@
db "sync" 'individuals "individual" "individual" db "sync" 'individuals "individual" "individual"
(lambda () (get-current 'household #f)) (lambda () (get-current 'household #f))
(list (list
(ktv "name" "varchar" (mtext-lookup 'default-individual-name)) (ktv-create "name" "varchar" (mtext-lookup 'default-individual-name))
(ktv "family" "varchar" (mtext-lookup 'default-family-name)) (ktv-create "family" "varchar" (mtext-lookup 'default-family-name))
(ktv "photo-id" "varchar" (mtext-lookup 'default-photo-id)) (ktv-create "photo-id" "varchar" (mtext-lookup 'default-photo-id))
(ktv "photo" "file" "none") (ktv-create "photo" "file" "none")
(ktv "tribe" "varchar" "none") (ktv-create "tribe" "varchar" "none")
(ktv "subtribe" "varchar" "none") (ktv-create "subtribe" "varchar" "none")
(ktv "age" "int" 0) (ktv-create "age" "int" 0)
(ktv "gender" "varchar" "Female") (ktv-create "gender" "varchar" "Female")
(ktv "education" "varchar" "none") (ktv-create "education" "varchar" "none")
(ktv "head-of-house" "varchar" "none") (ktv-create "head-of-house" "varchar" "none")
(ktv "marital-status" "varchar" "none")