! Copyright (C) 2008 Doug Coleman. ! See http://factorcode.org/license.txt for BSD license. USING: io.files kernel tools.test db db.tuples classes db.types continuations namespaces math math.ranges prettyprint calendar sequences db.sqlite math.intervals db.postgresql accessors random math.bitwise math.ranges strings urls fry ; IN: db.tuples.tests TUPLE: person the-id the-name the-number the-real ts date time blob factor-blob url ; : ( name age real ts date time blob factor-blob url -- person ) person new swap >>url swap >>factor-blob swap >>blob swap >>time swap >>date swap >>ts swap >>the-real swap >>the-number swap >>the-name ; : ( id name age real ts date time blob factor-blob url -- person ) swap >>the-id ; SYMBOL: person1 SYMBOL: person2 SYMBOL: person3 SYMBOL: person4 : test-tuples ( -- ) [ ] [ person recreate-table ] unit-test [ ] [ person ensure-table ] unit-test [ ] [ person drop-table ] unit-test [ ] [ person create-table ] unit-test [ person create-table ] must-fail [ ] [ person ensure-table ] unit-test [ ] [ person1 get insert-tuple ] unit-test [ 1 ] [ person1 get the-id>> ] unit-test [ ] [ person1 get 200 >>the-number drop ] unit-test [ ] [ person1 get update-tuple ] unit-test [ T{ person f 1 "billy" 200 3.14 } ] [ T{ person f 1 } select-tuple ] unit-test [ ] [ person2 get insert-tuple ] unit-test [ { T{ person f 1 "billy" 200 3.14 } T{ person f 2 "johnny" 10 3.14 } } ] [ T{ person f f f f 3.14 } select-tuples ] unit-test [ { T{ person f 1 "billy" 200 3.14 } T{ person f 2 "johnny" 10 3.14 } } ] [ T{ person f } select-tuples ] unit-test [ { T{ person f 2 "johnny" 10 3.14 } } ] [ T{ person f f f 10 3.14 } select-tuples ] unit-test [ ] [ person1 get delete-tuples ] unit-test [ f ] [ T{ person f 1 } select-tuple ] unit-test [ ] [ person3 get insert-tuple ] unit-test [ T{ person f 3 "teddy" 10 3.14 T{ timestamp f 2008 3 5 16 24 11 T{ duration f 0 0 0 0 0 0 } } T{ timestamp f 2008 11 22 0 0 0 T{ duration f 0 0 0 0 0 0 } } T{ timestamp f 0 0 0 12 34 56 T{ duration f 0 0 0 0 0 0 } } B{ 115 116 111 114 101 105 110 97 98 108 111 98 } } ] [ T{ person f 3 } select-tuple ] unit-test [ ] [ person4 get insert-tuple ] unit-test [ T{ person f 4 "eddie" 10 3.14 T{ timestamp f 2008 3 5 16 24 11 T{ duration f 0 0 0 0 0 0 } } T{ timestamp f 2008 11 22 0 0 0 T{ duration f 0 0 0 0 0 0 } } T{ timestamp f 0 0 0 12 34 56 T{ duration f 0 0 0 0 0 0 } } f H{ { 1 2 } { 3 4 } { 5 "lol" } } URL" http://www.google.com/search?hl=en&q=trailer+park+boys&btnG=Google+Search" } ] [ T{ person f 4 } select-tuple ] unit-test [ ] [ person drop-table ] unit-test ; : db-assigned-person-schema ( -- ) person "PERSON" { { "the-id" "ID" +db-assigned-id+ } { "the-name" "NAME" { VARCHAR 256 } +not-null+ } { "the-number" "AGE" INTEGER { +default+ 0 } } { "the-real" "REAL" DOUBLE { +default+ 0.3 } } { "ts" "TS" TIMESTAMP } { "date" "D" DATE } { "time" "T" TIME } { "blob" "B" BLOB } { "factor-blob" "FB" FACTOR-BLOB } { "url" "U" URL } } define-persistent "billy" 10 3.14 f f f f f f person1 set "johnny" 10 3.14 f f f f f f person2 set "teddy" 10 3.14 T{ timestamp f 2008 3 5 16 24 11 T{ duration f 0 0 0 0 0 0 } } T{ timestamp f 2008 11 22 0 0 0 T{ duration f 0 0 0 0 0 0 } } T{ timestamp f 0 0 0 12 34 56 T{ duration f 0 0 0 0 0 0 } } B{ 115 116 111 114 101 105 110 97 98 108 111 98 } f f person3 set "eddie" 10 3.14 T{ timestamp f 2008 3 5 16 24 11 T{ duration f 0 0 0 0 0 0 } } T{ timestamp f 2008 11 22 0 0 0 T{ duration f 0 0 0 0 0 0 } } T{ timestamp f 0 0 0 12 34 56 T{ duration f 0 0 0 0 0 0 } } f H{ { 1 2 } { 3 4 } { 5 "lol" } } URL" http://www.google.com/search?hl=en&q=trailer+park+boys&btnG=Google+Search" person4 set ; : user-assigned-person-schema ( -- ) person "PERSON" { { "the-id" "ID" INTEGER +user-assigned-id+ } { "the-name" "NAME" { VARCHAR 256 } +not-null+ } { "the-number" "AGE" INTEGER { +default+ 0 } } { "the-real" "REAL" DOUBLE { +default+ 0.3 } } { "ts" "TS" TIMESTAMP } { "date" "D" DATE } { "time" "T" TIME } { "blob" "B" BLOB } { "factor-blob" "FB" FACTOR-BLOB } { "url" "U" URL } } define-persistent 1 "billy" 10 3.14 f f f f f f person1 set 2 "johnny" 10 3.14 f f f f f f person2 set 3 "teddy" 10 3.14 T{ timestamp f 2008 3 5 16 24 11 T{ duration f 0 0 0 0 0 0 } } T{ timestamp f 2008 11 22 0 0 0 T{ duration f 0 0 0 0 0 0 } } T{ timestamp f 0 0 0 12 34 56 T{ duration f 0 0 0 0 0 0 } } B{ 115 116 111 114 101 105 110 97 98 108 111 98 } f f person3 set 4 "eddie" 10 3.14 T{ timestamp f 2008 3 5 16 24 11 T{ duration f 0 0 0 0 0 0 } } T{ timestamp f 2008 11 22 0 0 0 T{ duration f 0 0 0 0 0 0 } } T{ timestamp f 0 0 0 12 34 56 T{ duration f 0 0 0 0 0 0 } } f H{ { 1 2 } { 3 4 } { 5 "lol" } } URL" http://www.google.com/search?hl=en&q=trailer+park+boys&btnG=Google+Search" person4 set ; TUPLE: paste n summary author channel mode contents timestamp annotations ; TUPLE: annotation n paste-id summary author mode contents ; : db-assigned-paste-schema ( -- ) paste "PASTE" { { "n" "ID" +db-assigned-id+ } { "summary" "SUMMARY" TEXT } { "author" "AUTHOR" TEXT } { "channel" "CHANNEL" TEXT } { "mode" "MODE" TEXT } { "contents" "CONTENTS" TEXT } { "date" "DATE" TIMESTAMP } { "annotations" { +has-many+ annotation } } } define-persistent annotation "ANNOTATION" { { "n" "ID" +db-assigned-id+ } { "paste-id" "PASTE_ID" INTEGER { +foreign-id+ paste "n" } } { "summary" "SUMMARY" TEXT } { "author" "AUTHOR" TEXT } { "mode" "MODE" TEXT } { "contents" "CONTENTS" TEXT } } define-persistent ; ! { "localhost" "postgres" "" "factor-test" } postgresql-db [ ! [ paste drop-table ] [ drop ] recover ! [ annotation drop-table ] [ drop ] recover ! [ paste drop-table ] [ drop ] recover ! [ annotation drop-table ] [ drop ] recover ! [ ] [ paste create-table ] unit-test ! [ ] [ annotation create-table ] unit-test ! ] with-db : test-sqlite ( quot -- ) [ ] swap '[ "tuples-test.db" temp-file sqlite-db , with-db ] unit-test ; : test-postgresql ( quot -- ) [ ] swap '[ { "localhost" "postgres" "foob" "factor-test" } postgresql-db , with-db ] unit-test ; : test-repeated-insert [ ] [ person ensure-table ] unit-test [ ] [ person1 get insert-tuple ] unit-test [ person1 get insert-tuple ] must-fail ; TUPLE: serialize-me id data ; : test-serialize ( -- ) serialize-me "SERIALIZED" { { "id" "ID" +db-assigned-id+ } { "data" "DATA" FACTOR-BLOB } } define-persistent [ serialize-me drop-table ] [ drop ] recover [ ] [ serialize-me create-table ] unit-test [ ] [ T{ serialize-me f f H{ { 1 2 } } } insert-tuple ] unit-test [ { T{ serialize-me f 1 H{ { 1 2 } } } } ] [ T{ serialize-me f 1 } select-tuples ] unit-test ; TUPLE: exam id name score ; : random-exam ( -- exam ) f 6 [ CHAR: a CHAR: z [a,b] random ] replicate >string 100 random exam boa ; : test-intervals ( -- ) exam "EXAM" { { "id" "ID" +db-assigned-id+ } { "name" "NAME" TEXT } { "score" "SCORE" INTEGER } } define-persistent [ exam drop-table ] [ drop ] recover [ ] [ exam create-table ] unit-test [ ] [ T{ exam f f "Kyle" 100 } insert-tuple ] unit-test [ ] [ T{ exam f f "Stan" 80 } insert-tuple ] unit-test [ ] [ T{ exam f f "Kenny" 60 } insert-tuple ] unit-test [ ] [ T{ exam f f "Cartman" 41 } insert-tuple ] unit-test [ { T{ exam f 3 "Kenny" 60 } T{ exam f 4 "Cartman" 41 } } ] [ T{ exam f f f T{ interval f { 0 t } { 70 t } } } select-tuples ] unit-test [ { } ] [ T{ exam f T{ interval f { 3 f } { 4 f } } f } select-tuples ] unit-test [ { T{ exam f 4 "Cartman" 41 } } ] [ T{ exam f T{ interval f { 3 f } { 4 t } } f } select-tuples ] unit-test [ { T{ exam f 3 "Kenny" 60 } } ] [ T{ exam f T{ interval f { 3 t } { 4 f } } f } select-tuples ] unit-test [ { T{ exam f 3 "Kenny" 60 } T{ exam f 4 "Cartman" 41 } } ] [ T{ exam f T{ interval f { 3 t } { 4 t } } f } select-tuples ] unit-test [ { T{ exam f 1 "Kyle" 100 } T{ exam f 2 "Stan" 80 } } ] [ T{ exam f f { "Stan" "Kyle" } } select-tuples ] unit-test [ { T{ exam f 1 "Kyle" 100 } T{ exam f 2 "Stan" 80 } T{ exam f 3 "Kenny" 60 } } ] [ T{ exam f T{ range f 1 3 1 } } select-tuples ] unit-test [ { T{ exam f 2 "Stan" 80 } T{ exam f 3 "Kenny" 60 } T{ exam f 4 "Cartman" 41 } } ] [ T{ exam f T{ interval f { 2 t } { 1.0/0.0 f } } } select-tuples ] unit-test [ { T{ exam f 1 "Kyle" 100 } } ] [ T{ exam f T{ interval f { -1.0/0.0 t } { 2 f } } } select-tuples ] unit-test [ { T{ exam f 1 "Kyle" 100 } T{ exam f 2 "Stan" 80 } T{ exam f 3 "Kenny" 60 } T{ exam f 4 "Cartman" 41 } } ] [ T{ exam f T{ interval f { -1.0/0.0 t } { 1/0. f } } } select-tuples ] unit-test [ { T{ exam f 1 "Kyle" 100 } T{ exam f 2 "Stan" 80 } T{ exam f 3 "Kenny" 60 } T{ exam f 4 "Cartman" 41 } } ] [ T{ exam } select-tuples ] unit-test [ 4 ] [ T{ exam } f count-tuples ] unit-test ; TUPLE: bignum-test id m n o ; : ( m n o -- obj ) bignum-test new swap >>o swap >>n swap >>m ; : test-bignum bignum-test "BIGNUM_TEST" { { "id" "ID" +db-assigned-id+ } { "m" "M" BIG-INTEGER } { "n" "N" UNSIGNED-BIG-INTEGER } { "o" "O" SIGNED-BIG-INTEGER } } define-persistent [ bignum-test drop-table ] ignore-errors [ ] [ bignum-test ensure-table ] unit-test [ ] [ 63 2^ 1- dup dup insert-tuple ] unit-test ; ! sqlite only ! [ T{ bignum-test f 1 ! -9223372036854775808 9223372036854775808 -9223372036854775808 } ] ! [ T{ bignum-test f 1 } select-tuple ] unit-test ; TUPLE: secret n message ; C: secret : test-random-id secret "SECRET" { { "n" "ID" +random-id+ system-random-generator } { "message" "MESSAGE" TEXT } } define-persistent [ ] [ secret recreate-table ] unit-test [ t ] [ f "kilroy was here" [ insert-tuple ] keep n>> integer? ] unit-test [ ] [ f "kilroy was here2" insert-tuple ] unit-test [ ] [ f "kilroy was here3" insert-tuple ] unit-test [ t ] [ T{ secret } select-tuples first message>> "kilroy was here" head? ] unit-test [ t ] [ T{ secret } select-tuples length 3 = ] unit-test ; [ db-assigned-person-schema test-tuples ] test-sqlite [ user-assigned-person-schema test-tuples ] test-sqlite [ user-assigned-person-schema test-repeated-insert ] test-sqlite [ test-bignum ] test-sqlite [ test-serialize ] test-sqlite [ test-intervals ] test-sqlite [ test-random-id ] test-sqlite [ db-assigned-person-schema test-tuples ] test-postgresql [ user-assigned-person-schema test-tuples ] test-postgresql [ user-assigned-person-schema test-repeated-insert ] test-postgresql [ test-bignum ] test-postgresql [ test-serialize ] test-postgresql [ test-intervals ] test-postgresql [ test-random-id ] test-postgresql TUPLE: does-not-persist ; [ [ does-not-persist create-sql-statement ] [ class \ not-persistent = ] must-fail-with ] test-sqlite [ [ does-not-persist create-sql-statement ] [ class \ not-persistent = ] must-fail-with ] test-postgresql TUPLE: suparclass id a ; suparclass f { { "id" "ID" +db-assigned-id+ } { "a" "A" INTEGER } } define-persistent TUPLE: subbclass < suparclass b ; subbclass "SUBCLASS" { { "b" "B" TEXT } } define-persistent TUPLE: fubbclass < subbclass ; fubbclass "FUBCLASS" { } define-persistent : test-db-inheritance ( -- ) [ ] [ subbclass ensure-table ] unit-test [ ] [ fubbclass ensure-table ] unit-test [ ] [ subbclass new 5 >>a "hi" >>b dup insert-tuple id>> "id" set ] unit-test [ t "hi" 5 ] [ subbclass new "id" get >>id select-tuple [ subbclass? ] [ b>> ] [ a>> ] tri ] unit-test [ ] [ fubbclass new 0 >>a "hi" >>b insert-tuple ] unit-test [ t ] [ fubbclass new select-tuples [ fubbclass? ] all? ] unit-test ; [ test-db-inheritance ] test-sqlite [ test-db-inheritance ] test-postgresql TUPLE: string-encoding-test id string ; string-encoding-test "STRING_ENCODING_TEST" { { "id" "ID" +db-assigned-id+ } { "string" "STRING" TEXT } } define-persistent : test-string-encoding ( -- ) [ ] [ string-encoding-test ensure-table ] unit-test [ ] [ string-encoding-test new "\u{copyright-sign}\u{bengali-letter-cha}" >>string [ insert-tuple ] [ id>> "id" set ] bi ] unit-test [ "\u{copyright-sign}\u{bengali-letter-cha}" ] [ string-encoding-test new "id" get >>id select-tuple string>> ] unit-test ; [ test-string-encoding ] test-sqlite [ test-string-encoding ] test-postgresql ! Don't comment these out. These words must infer \ bind-tuple must-infer \ insert-tuple must-infer \ update-tuple must-infer \ delete-tuples must-infer \ select-tuple must-infer \ define-persistent must-infer \ ensure-table must-infer \ create-table must-infer \ drop-table must-infer