xref: /sqlite-3.40.0/test/attach.test (revision cd7274ce)
1# 2003 April 4
2#
3# The author disclaims copyright to this source code.  In place of
4# a legal notice, here is a blessing:
5#
6#    May you do good and not evil.
7#    May you find forgiveness for yourself and forgive others.
8#    May you share freely, never taking more than you give.
9#
10#***********************************************************************
11# This file implements regression tests for SQLite library.  The
12# focus of this script is testing the ATTACH and DETACH commands
13# and related functionality.
14#
15# $Id: attach.test,v 1.47 2007/10/09 08:29:32 danielk1977 Exp $
16#
17
18set testdir [file dirname $argv0]
19source $testdir/tester.tcl
20
21ifcapable !attach {
22  finish_test
23  return
24}
25
26for {set i 2} {$i<=15} {incr i} {
27  file delete -force test$i.db
28  file delete -force test$i.db-journal
29}
30
31set btree_trace 0
32do_test attach-1.1 {
33  execsql {
34    CREATE TABLE t1(a,b);
35    INSERT INTO t1 VALUES(1,2);
36    INSERT INTO t1 VALUES(3,4);
37    SELECT * FROM t1;
38  }
39} {1 2 3 4}
40do_test attach-1.2 {
41  sqlite3 db2 test2.db
42  execsql {
43    CREATE TABLE t2(x,y);
44    INSERT INTO t2 VALUES(1,'x');
45    INSERT INTO t2 VALUES(2,'y');
46    SELECT * FROM t2;
47  } db2
48} {1 x 2 y}
49do_test attach-1.3 {
50  execsql {
51    ATTACH DATABASE 'test2.db' AS two;
52    SELECT * FROM two.t2;
53  }
54} {1 x 2 y}
55do_test attach-1.4 {
56  execsql {
57    SELECT * FROM t2;
58  }
59} {1 x 2 y}
60do_test attach-1.5 {
61btree_breakpoint
62  execsql {
63    DETACH DATABASE two;
64    SELECT * FROM t1;
65  }
66} {1 2 3 4}
67do_test attach-1.6 {
68  catchsql {
69    SELECT * FROM t2;
70  }
71} {1 {no such table: t2}}
72do_test attach-1.7 {
73  catchsql {
74    SELECT * FROM two.t2;
75  }
76} {1 {no such table: two.t2}}
77do_test attach-1.8 {
78  catchsql {
79    ATTACH DATABASE 'test3.db' AS three;
80  }
81} {0 {}}
82do_test attach-1.9 {
83  catchsql {
84    SELECT * FROM three.sqlite_master;
85  }
86} {0 {}}
87do_test attach-1.10 {
88  catchsql {
89    DETACH DATABASE [three];
90  }
91} {0 {}}
92do_test attach-1.11 {
93  execsql {
94    ATTACH 'test.db' AS db2;
95    ATTACH 'test.db' AS db3;
96    ATTACH 'test.db' AS db4;
97    ATTACH 'test.db' AS db5;
98    ATTACH 'test.db' AS db6;
99    ATTACH 'test.db' AS db7;
100    ATTACH 'test.db' AS db8;
101    ATTACH 'test.db' AS db9;
102  }
103} {}
104proc db_list {db} {
105  set list {}
106  foreach {idx name file} [execsql {PRAGMA database_list} $db] {
107    lappend list $idx $name
108  }
109  return $list
110}
111ifcapable schema_pragmas {
112do_test attach-1.11b {
113  db_list db
114} {0 main 2 db2 3 db3 4 db4 5 db5 6 db6 7 db7 8 db8 9 db9}
115} ;# ifcapable schema_pragmas
116do_test attach-1.12 {
117  catchsql {
118    ATTACH 'test.db' as db2;
119  }
120} {1 {database db2 is already in use}}
121do_test attach-1.13 {
122  catchsql {
123    ATTACH 'test.db' as db5;
124  }
125} {1 {database db5 is already in use}}
126do_test attach-1.14 {
127  catchsql {
128    ATTACH 'test.db' as db9;
129  }
130} {1 {database db9 is already in use}}
131do_test attach-1.15 {
132  catchsql {
133    ATTACH 'test.db' as main;
134  }
135} {1 {database main is already in use}}
136ifcapable tempdb {
137  do_test attach-1.16 {
138    catchsql {
139      ATTACH 'test.db' as temp;
140    }
141  } {1 {database temp is already in use}}
142}
143do_test attach-1.17 {
144  catchsql {
145    ATTACH 'test.db' as MAIN;
146  }
147} {1 {database MAIN is already in use}}
148do_test attach-1.18 {
149  catchsql {
150    ATTACH 'test.db' as db10;
151    ATTACH 'test.db' as db11;
152  }
153} {0 {}}
154do_test attach-1.19 {
155  catchsql {
156    ATTACH 'test.db' as db12;
157  }
158} {1 {too many attached databases - max 10}}
159do_test attach-1.20.1 {
160  execsql {
161    DETACH db5;
162  }
163} {}
164ifcapable schema_pragmas {
165do_test attach-1.20.2 {
166  db_list db
167} {0 main 2 db2 3 db3 4 db4 5 db6 6 db7 7 db8 8 db9 9 db10 10 db11}
168} ;# ifcapable schema_pragmas
169integrity_check attach-1.20.3
170ifcapable tempdb {
171  execsql {select * from sqlite_temp_master}
172}
173do_test attach-1.21 {
174  catchsql {
175    ATTACH 'test.db' as db12;
176  }
177} {0 {}}
178do_test attach-1.22 {
179  catchsql {
180    ATTACH 'test.db' as db13;
181  }
182} {1 {too many attached databases - max 10}}
183do_test attach-1.23 {
184  catchsql {
185    DETACH "db14";
186  }
187} {1 {no such database: db14}}
188do_test attach-1.24 {
189  catchsql {
190    DETACH db12;
191  }
192} {0 {}}
193do_test attach-1.25 {
194  catchsql {
195    DETACH db12;
196  }
197} {1 {no such database: db12}}
198do_test attach-1.26 {
199  catchsql {
200    DETACH main;
201  }
202} {1 {cannot detach database main}}
203
204ifcapable tempdb {
205  do_test attach-1.27 {
206    catchsql {
207      DETACH Temp;
208    }
209  } {1 {cannot detach database Temp}}
210} else {
211  do_test attach-1.27 {
212    catchsql {
213      DETACH Temp;
214    }
215  } {1 {no such database: Temp}}
216}
217
218do_test attach-1.28 {
219  catchsql {
220    DETACH db11;
221    DETACH db10;
222    DETACH db9;
223    DETACH db8;
224    DETACH db7;
225    DETACH db6;
226    DETACH db4;
227    DETACH db3;
228    DETACH db2;
229  }
230} {0 {}}
231ifcapable schema_pragmas {
232  ifcapable tempdb {
233    do_test attach-1.29 {
234      db_list db
235    } {0 main 1 temp}
236  } else {
237    do_test attach-1.29 {
238      db_list db
239    } {0 main}
240  }
241} ;# ifcapable schema_pragmas
242
243ifcapable {trigger} {  # Only do the following tests if triggers are enabled
244do_test attach-2.1 {
245  execsql {
246    CREATE TABLE tx(x1,x2,y1,y2);
247    CREATE TRIGGER r1 AFTER UPDATE ON t2 FOR EACH ROW BEGIN
248      INSERT INTO tx(x1,x2,y1,y2) VALUES(OLD.x,NEW.x,OLD.y,NEW.y);
249    END;
250    SELECT * FROM tx;
251  } db2;
252} {}
253do_test attach-2.2 {
254  execsql {
255    UPDATE t2 SET x=x+10;
256    SELECT * FROM tx;
257  } db2;
258} {1 11 x x 2 12 y y}
259do_test attach-2.3 {
260  execsql {
261    CREATE TABLE tx(x1,x2,y1,y2);
262    SELECT * FROM tx;
263  }
264} {}
265do_test attach-2.4 {
266  execsql {
267    ATTACH 'test2.db' AS db2;
268  }
269} {}
270do_test attach-2.5 {
271  execsql {
272    UPDATE db2.t2 SET x=x+10;
273    SELECT * FROM db2.tx;
274  }
275} {1 11 x x 2 12 y y 11 21 x x 12 22 y y}
276do_test attach-2.6 {
277  execsql {
278    SELECT * FROM main.tx;
279  }
280} {}
281do_test attach-2.7 {
282  execsql {
283    SELECT type, name, tbl_name FROM db2.sqlite_master;
284  }
285} {table t2 t2 table tx tx trigger r1 t2}
286
287ifcapable schema_pragmas&&tempdb {
288  do_test attach-2.8 {
289    db_list db
290  } {0 main 1 temp 2 db2}
291} ;# ifcapable schema_pragmas&&tempdb
292ifcapable schema_pragmas&&!tempdb {
293  do_test attach-2.8 {
294    db_list db
295  } {0 main 2 db2}
296} ;# ifcapable schema_pragmas&&!tempdb
297
298do_test attach-2.9 {
299  execsql {
300    CREATE INDEX i2 ON t2(x);
301    SELECT * FROM t2 WHERE x>5;
302  } db2
303} {21 x 22 y}
304do_test attach-2.10 {
305  execsql {
306    SELECT type, name, tbl_name FROM sqlite_master;
307  } db2
308} {table t2 t2 table tx tx trigger r1 t2 index i2 t2}
309#do_test attach-2.11 {
310#  catchsql {
311#    SELECT * FROM t2 WHERE x>5;
312#  }
313#} {1 {database schema has changed}}
314ifcapable schema_pragmas {
315  ifcapable tempdb {
316    do_test attach-2.12 {
317      db_list db
318    } {0 main 1 temp 2 db2}
319  } else {
320    do_test attach-2.12 {
321      db_list db
322    } {0 main 2 db2}
323  }
324} ;# ifcapable schema_pragmas
325do_test attach-2.13 {
326  catchsql {
327    SELECT * FROM t2 WHERE x>5;
328  }
329} {0 {21 x 22 y}}
330do_test attach-2.14 {
331  execsql {
332    SELECT type, name, tbl_name FROM sqlite_master;
333  }
334} {table t1 t1 table tx tx}
335do_test attach-2.15 {
336  execsql {
337    SELECT type, name, tbl_name FROM db2.sqlite_master;
338  }
339} {table t2 t2 table tx tx trigger r1 t2 index i2 t2}
340do_test attach-2.16 {
341  db close
342  sqlite3 db test.db
343  execsql {
344    ATTACH 'test2.db' AS db2;
345    SELECT type, name, tbl_name FROM db2.sqlite_master;
346  }
347} {table t2 t2 table tx tx trigger r1 t2 index i2 t2}
348} ;# End of ifcapable {trigger}
349
350do_test attach-3.1 {
351  db close
352  db2 close
353  sqlite3 db test.db
354  sqlite3 db2 test2.db
355  execsql {
356    SELECT * FROM t1
357  }
358} {1 2 3 4}
359
360# If we are testing a version of the code that lacks trigger support,
361# adjust the database contents so that they are the same if triggers
362# had been enabled.
363ifcapable {!trigger} {
364  db2 eval {
365    DELETE FROM t2;
366    INSERT INTO t2 VALUES(21, 'x');
367    INSERT INTO t2 VALUES(22, 'y');
368    CREATE TABLE tx(x1,x2,y1,y2);
369    INSERT INTO tx VALUES(1, 11, 'x', 'x');
370    INSERT INTO tx VALUES(2, 12, 'y', 'y');
371    INSERT INTO tx VALUES(11, 21, 'x', 'x');
372    INSERT INTO tx VALUES(12, 22, 'y', 'y');
373    CREATE INDEX i2 ON t2(x);
374  }
375}
376
377do_test attach-3.2 {
378  catchsql {
379    SELECT * FROM t2
380  }
381} {1 {no such table: t2}}
382do_test attach-3.3 {
383  catchsql {
384    ATTACH DATABASE 'test2.db' AS db2;
385    SELECT * FROM t2
386  }
387} {0 {21 x 22 y}}
388
389# Even though 'db' has started a transaction, it should not yet have
390# a lock on test2.db so 'db2' should be readable.
391do_test attach-3.4 {
392  execsql BEGIN
393  catchsql {
394    SELECT * FROM t2;
395  } db2;
396} {0 {21 x 22 y}}
397
398# Reading from test2.db from db within a transaction should not
399# prevent test2.db from being read by db2.
400do_test attach-3.5 {
401  execsql {SELECT * FROM t2}
402btree_breakpoint
403  catchsql {
404    SELECT * FROM t2;
405  } db2;
406} {0 {21 x 22 y}}
407
408# Making a change to test2.db through db  causes test2.db to get
409# a reserved lock.  It should still be accessible through db2.
410do_test attach-3.6 {
411  execsql {
412    UPDATE t2 SET x=x+1 WHERE x=50;
413  }
414  catchsql {
415    SELECT * FROM t2;
416  } db2;
417} {0 {21 x 22 y}}
418
419do_test attach-3.7 {
420  execsql ROLLBACK
421  execsql {SELECT * FROM t2} db2
422} {21 x 22 y}
423
424# Start transactions on both db and db2.  Once again, just because
425# we make a change to test2.db using db2, only a RESERVED lock is
426# obtained, so test2.db should still be readable using db.
427#
428do_test attach-3.8 {
429  execsql BEGIN
430  execsql BEGIN db2
431  execsql {UPDATE t2 SET x=0 WHERE 0} db2
432  catchsql {SELECT * FROM t2}
433} {0 {21 x 22 y}}
434
435# It is also still accessible from db2.
436do_test attach-3.9 {
437  catchsql {SELECT * FROM t2} db2
438} {0 {21 x 22 y}}
439
440do_test attach-3.10 {
441  execsql {SELECT * FROM t1}
442} {1 2 3 4}
443
444do_test attach-3.11 {
445  catchsql {UPDATE t1 SET a=a+1}
446} {0 {}}
447do_test attach-3.12 {
448  execsql {SELECT * FROM t1}
449} {2 2 4 4}
450
451# db2 has a RESERVED lock on test2.db, so db cannot write to any tables
452# in test2.db.
453do_test attach-3.13 {
454  catchsql {UPDATE t2 SET x=x+1 WHERE x=50}
455} {1 {database is locked}}
456
457# Change for version 3. Transaction is no longer rolled back
458# for a locked database.
459execsql {ROLLBACK}
460
461# db is able to reread its schema because db2 still only holds a
462# reserved lock.
463do_test attach-3.14 {
464  catchsql {SELECT * FROM t1}
465} {0 {1 2 3 4}}
466do_test attach-3.15 {
467  execsql COMMIT db2
468  execsql {SELECT * FROM t1}
469} {1 2 3 4}
470
471#set btree_trace 1
472
473# Ticket #323
474do_test attach-4.1 {
475  execsql {DETACH db2}
476  db2 close
477  sqlite3 db2 test2.db
478  execsql {
479    CREATE TABLE t3(x,y);
480    CREATE UNIQUE INDEX t3i1 ON t3(x);
481    INSERT INTO t3 VALUES(1,2);
482    SELECT * FROM t3;
483  } db2;
484} {1 2}
485do_test attach-4.2 {
486  execsql {
487    CREATE TABLE t3(a,b);
488    CREATE UNIQUE INDEX t3i1b ON t3(a);
489    INSERT INTO t3 VALUES(9,10);
490    SELECT * FROM t3;
491  }
492} {9 10}
493do_test attach-4.3 {
494  execsql {
495    ATTACH DATABASE 'test2.db' AS db2;
496    SELECT * FROM db2.t3;
497  }
498} {1 2}
499do_test attach-4.4 {
500  execsql {
501    SELECT * FROM main.t3;
502  }
503} {9 10}
504do_test attach-4.5 {
505  execsql {
506    INSERT INTO db2.t3 VALUES(9,10);
507    SELECT * FROM db2.t3;
508  }
509} {1 2 9 10}
510execsql {
511  DETACH db2;
512}
513ifcapable {trigger} {
514  do_test attach-4.6 {
515    execsql {
516      CREATE TABLE t4(x);
517      CREATE TRIGGER t3r3 AFTER INSERT ON t3 BEGIN
518        INSERT INTO t4 VALUES('db2.' || NEW.x);
519      END;
520      INSERT INTO t3 VALUES(6,7);
521      SELECT * FROM t4;
522    } db2
523  } {db2.6}
524  do_test attach-4.7 {
525    execsql {
526      CREATE TABLE t4(y);
527      CREATE TRIGGER t3r3 AFTER INSERT ON t3 BEGIN
528        INSERT INTO t4 VALUES('main.' || NEW.a);
529      END;
530      INSERT INTO main.t3 VALUES(11,12);
531      SELECT * FROM main.t4;
532    }
533  } {main.11}
534}
535ifcapable {!trigger} {
536  # When we do not have trigger support, set up the table like they
537  # would have been had triggers been there.  The tests that follow need
538  # this setup.
539  execsql {
540    CREATE TABLE t4(x);
541    INSERT INTO t3 VALUES(6,7);
542    INSERT INTO t4 VALUES('db2.6');
543    INSERT INTO t4 VALUES('db2.13');
544  } db2
545  execsql {
546    CREATE TABLE t4(y);
547    INSERT INTO main.t3 VALUES(11,12);
548    INSERT INTO t4 VALUES('main.11');
549  }
550}
551
552
553# This one is tricky.  On the UNION ALL select, we have to make sure
554# the schema for both main and db2 is valid before starting to execute
555# the first query of the UNION ALL.  If we wait to test the validity of
556# the schema for main until after the first query has run, that test will
557# fail and the query will abort but we will have already output some
558# results.  When the query is retried, the results will be repeated.
559#
560ifcapable compound {
561do_test attach-4.8 {
562  execsql {
563    ATTACH DATABASE 'test2.db' AS db2;
564    INSERT INTO db2.t3 VALUES(13,14);
565    SELECT * FROM db2.t4 UNION ALL SELECT * FROM main.t4;
566  }
567} {db2.6 db2.13 main.11}
568
569do_test attach-4.9 {
570  ifcapable {!trigger} {execsql {INSERT INTO main.t4 VALUES('main.15')}}
571  execsql {
572    INSERT INTO main.t3 VALUES(15,16);
573    SELECT * FROM db2.t4 UNION ALL SELECT * FROM main.t4;
574  }
575} {db2.6 db2.13 main.11 main.15}
576} ;# ifcapable compound
577
578ifcapable !compound {
579  ifcapable {!trigger} {execsql {INSERT INTO main.t4 VALUES('main.15')}}
580  execsql {
581    ATTACH DATABASE 'test2.db' AS db2;
582    INSERT INTO db2.t3 VALUES(13,14);
583    INSERT INTO main.t3 VALUES(15,16);
584  }
585} ;# ifcapable !compound
586
587ifcapable view {
588do_test attach-4.10 {
589  execsql {
590    DETACH DATABASE db2;
591  }
592  execsql {
593    CREATE VIEW v3 AS SELECT x*100+y FROM t3;
594    SELECT * FROM v3;
595  } db2
596} {102 910 607 1314}
597do_test attach-4.11 {
598  execsql {
599    CREATE VIEW v3 AS SELECT a*100+b FROM t3;
600    SELECT * FROM v3;
601  }
602} {910 1112 1516}
603do_test attach-4.12 {
604  execsql {
605    ATTACH DATABASE 'test2.db' AS db2;
606    SELECT * FROM db2.v3;
607  }
608} {102 910 607 1314}
609do_test attach-4.13 {
610  execsql {
611    SELECT * FROM main.v3;
612  }
613} {910 1112 1516}
614} ;# ifcapable view
615
616# Tests for the sqliteFix...() routines in attach.c
617#
618ifcapable {trigger} {
619do_test attach-5.1 {
620  db close
621  sqlite3 db test.db
622  db2 close
623  file delete -force test2.db
624  sqlite3 db2 test2.db
625  catchsql {
626    ATTACH DATABASE 'test.db' AS orig;
627    CREATE TRIGGER r1 AFTER INSERT ON orig.t1 BEGIN
628      SELECT 'no-op';
629    END;
630  } db2
631} {1 {trigger r1 cannot reference objects in database orig}}
632do_test attach-5.2 {
633  catchsql {
634    CREATE TABLE t5(x,y);
635    CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
636      SELECT 'no-op';
637    END;
638  } db2
639} {0 {}}
640do_test attach-5.3 {
641  catchsql {
642    DROP TRIGGER r5;
643    CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
644      SELECT 'no-op' FROM orig.t1;
645    END;
646  } db2
647} {1 {trigger r5 cannot reference objects in database orig}}
648ifcapable tempdb {
649  do_test attach-5.4 {
650    catchsql {
651      CREATE TEMP TABLE t6(p,q,r);
652      CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
653        SELECT 'no-op' FROM temp.t6;
654      END;
655    } db2
656  } {1 {trigger r5 cannot reference objects in database temp}}
657}
658ifcapable subquery {
659  do_test attach-5.5 {
660    catchsql {
661      CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
662        SELECT 'no-op' || (SELECT * FROM temp.t6);
663      END;
664    } db2
665  } {1 {trigger r5 cannot reference objects in database temp}}
666  do_test attach-5.6 {
667    catchsql {
668      CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
669        SELECT 'no-op' FROM t1 WHERE x<(SELECT min(x) FROM temp.t6);
670      END;
671    } db2
672  } {1 {trigger r5 cannot reference objects in database temp}}
673  do_test attach-5.7 {
674    catchsql {
675      CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
676        SELECT 'no-op' FROM t1 GROUP BY 1 HAVING x<(SELECT min(x) FROM temp.t6);
677      END;
678    } db2
679  } {1 {trigger r5 cannot reference objects in database temp}}
680  do_test attach-5.7 {
681    catchsql {
682      CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
683        SELECT max(1,x,(SELECT min(x) FROM temp.t6)) FROM t1;
684      END;
685    } db2
686  } {1 {trigger r5 cannot reference objects in database temp}}
687  do_test attach-5.8 {
688    catchsql {
689      CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
690        INSERT INTO t1 VALUES((SELECT min(x) FROM temp.t6),5);
691      END;
692    } db2
693  } {1 {trigger r5 cannot reference objects in database temp}}
694  do_test attach-5.9 {
695    catchsql {
696      CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
697        DELETE FROM t1 WHERE x<(SELECT min(x) FROM temp.t6);
698      END;
699    } db2
700  } {1 {trigger r5 cannot reference objects in database temp}}
701} ;# endif subquery
702} ;# endif trigger
703
704# Check to make sure we get a sensible error if unable to open
705# the file that we are trying to attach.
706#
707do_test attach-6.1 {
708  catchsql {
709    ATTACH DATABASE 'no-such-file' AS nosuch;
710  }
711} {0 {}}
712if {$tcl_platform(platform)=="unix"} {
713  do_test attach-6.2 {
714    sqlite3 dbx cannot-read
715    dbx eval {CREATE TABLE t1(a,b,c)}
716    dbx close
717    file attributes cannot-read -permission 0000
718    if {[file writable cannot-read]} {
719      puts "\n**** Tests do not work when run as root ****"
720      file delete -force cannot-read
721      exit 1
722    }
723    catchsql {
724      ATTACH DATABASE 'cannot-read' AS noread;
725    }
726  } {1 {unable to open database: cannot-read}}
727  file delete -force cannot-read
728}
729
730# Check the error message if we try to access a database that has
731# not been attached.
732do_test attach-6.3 {
733  catchsql {
734    CREATE TABLE no_such_db.t1(a, b, c);
735  }
736} {1 {unknown database no_such_db}}
737for {set i 2} {$i<=15} {incr i} {
738  catch {db$i close}
739}
740db close
741file delete -force test2.db
742file delete -force no-such-file
743
744ifcapable subquery {
745  do_test attach-7.1 {
746    file delete -force test.db test.db-journal
747    sqlite3 db test.db
748    catchsql {
749      DETACH RAISE ( IGNORE ) IN ( SELECT "AAAAAA" . * ORDER BY
750      REGISTER LIMIT "AAAAAA" . "AAAAAA" OFFSET RAISE ( IGNORE ) NOT NULL )
751    }
752  } {1 {invalid name: "RAISE ( IGNORE ) IN ( SELECT "AAAAAA" . * ORDER BY
753      REGISTER LIMIT "AAAAAA" . "AAAAAA" OFFSET RAISE ( IGNORE ) NOT NULL )"}}
754}
755finish_test
756