PageRenderTime 40ms CodeModel.GetById 11ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/rdbms/test/src/rdbms_basic_SUITE.erl

https://github.com/gebi/jungerl
Erlang | 754 lines | 641 code | 60 blank | 53 comment | 3 complexity | 886f0966844f0f0a9bdd7ad0e6d8fca6 MD5 | raw file
Possible License(s): LGPL-2.1, BSD-3-Clause, AGPL-1.0
  1. %%%
  2. %%% The contents of this file are subject to the Erlang Public License,
  3. %%% Version 1.0, (the "License"); you may not use this file except in
  4. %%% compliance with the License. You may obtain a copy of the License at
  5. %%% http://www.erlang.org/license/EPL1_0.txt
  6. %%%
  7. %%% Software distributed under the License is distributed on an "AS IS"
  8. %%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  9. %%% the License for the specific language governing rights and limitations
  10. %%% under the License.
  11. %%%
  12. %%% The Original Code is rdbms-1.2.
  13. %%%
  14. %%% The Initial Developer of the Original Code is Ericsson Telecom
  15. %%% AB. Portions created by Ericsson are Copyright (C), 1998, Ericsson
  16. %%% Telecom AB. All Rights Reserved.
  17. %%%
  18. %%% Contributor(s): ______________________________________.
  19. %%%----------------------------------------------------------------------
  20. %%% #0. BASIC INFORMATION
  21. %%%----------------------------------------------------------------------
  22. %%%-------------------------------------------------------------------
  23. %%% File : rdbms_basic_SUITE.erl
  24. %%% Author : Ulf Wiger <ulf.wiger@ericsson.com>
  25. %%% Description : Test suite for rdbms
  26. %%%
  27. %%% Created : 20 Feb 2006 by Ulf Wiger
  28. %%%-------------------------------------------------------------------
  29. -module(rdbms_basic_SUITE).
  30. -define(default_timeout, ?t:minutes(1)).
  31. -define(application, rdbms).
  32. -define(MNESIA_RECOMPILED, "/home/etxuwig/wrk/erlang/mnesia-4.2.3ext/ebin").
  33. -define(MNESIA_PATCH_PATH, "/home/etxuwig/wrk/blogorum/patches").
  34. -define(RDBMS_PATH, "/home/etxuwig/wrk/blogorum/lib/rdbms-1.991/ebin").
  35. -export([
  36. all/1,
  37. init_per_testcase/2,
  38. fin_per_testcase/2,
  39. %%
  40. %% basic create/delete tables tests
  41. %%
  42. install_schema/1,
  43. delete_schema/1,
  44. basic_create_table/1,
  45. rdbms_basic/1,
  46. rdbms_create_table/1,
  47. rdbms_verify_write_basic/1,
  48. rdbms_types_undef/1,
  49. rdbms_types_list/1,
  50. rdbms_types_enum/1,
  51. rdbms_write_filter/1,
  52. rdbms_acl/1,
  53. rdbms_references/1,
  54. rdbms_indexes/1,
  55. rdbms_refs_cascade/1,
  56. rdbms_refs_lookup/1,
  57. rdbms_ix_ix/1,
  58. rdbms_ix_vals/1,
  59. rdbms_ix_list/1,
  60. rdbms_ix/1,
  61. rdbms_ix_load/1,
  62. rdbms_add_ix/1,
  63. rdbms_unique_ix/1
  64. ]).
  65. -export([word_attr_ix/2,
  66. ix_value/2]).
  67. -export([acl2_read/3]).
  68. %%% snipped from test_server.hrl
  69. -ifdef(line_trace).
  70. -line_trace(true).
  71. -define(line,
  72. put(test_server_loc,{?MODULE,?LINE}),
  73. io:format(lists:concat([?MODULE,",",integer_to_list(?LINE),": ~p"]),
  74. [erlang:now()]),).
  75. -else.
  76. -define(line,put(test_server_loc,{?MODULE,?LINE}),).
  77. -endif.
  78. -define(t,test_server).
  79. -define(config,test_server:lookup_config).
  80. %%% end snip
  81. all(doc) ->
  82. "rdbms test suite";
  83. all(suite) ->
  84. [
  85. install_schema,
  86. basic_create_table,
  87. %%% rdbms_create_table,
  88. rdbms_basic,
  89. rdbms_indexes,
  90. rdbms_references,
  91. delete_schema
  92. ].
  93. rdbms_references(doc) ->
  94. [];
  95. rdbms_references(suite) ->
  96. [rdbms_refs_cascade, rdbms_refs_lookup].
  97. rdbms_indexes(doc) ->
  98. [];
  99. rdbms_indexes(suite) ->
  100. [rdbms_ix_ix, rdbms_ix_list, rdbms_ix_vals,
  101. rdbms_ix, rdbms_ix_load, rdbms_add_ix, rdbms_unique_ix].
  102. rdbms_basic(doc) ->
  103. [];
  104. rdbms_basic(suite) ->
  105. [rdbms_create_table,
  106. rdbms_verify_write_basic, rdbms_types_undef, rdbms_types_list,
  107. rdbms_types_enum, rdbms_write_filter, rdbms_acl].
  108. init_per_testcase(_Case, Config) ->
  109. ?line Dog = test_server:timetrap(?default_timeout),
  110. [{watchdog, Dog}|Config].
  111. fin_per_testcase(_Case, Config) ->
  112. Dog = ?config(watchdog, Config),
  113. test_server:timetrap_cancel(Dog),
  114. ok.
  115. install_schema(doc) ->
  116. [];
  117. %%% "delete existing schema (if any), create new schema, and start mnesia.";
  118. install_schema(Config) when is_list(Config) ->
  119. ?line true = code:add_patha(?MNESIA_RECOMPILED),
  120. ?line true = code:add_patha(?MNESIA_PATCH_PATH),
  121. ?line true = code:add_patha(?RDBMS_PATH),
  122. ?line delete_schema(Config),
  123. %% ?line start_trace(),
  124. ?line mnesia:create_schema([node()]),
  125. ?line application:start(sasl),
  126. ?line mnesia:start([{access_module, rdbms},{debug,false}]),
  127. ok.
  128. start_trace() ->
  129. dbg:tracer(),
  130. dbg:tpl(rdbms,ix_vals,[{'_',[],[{message,{return_trace}}]}]),
  131. %% dbg:tpl(mnesia_loader,[{'_',[],[{message,{return_trace}}]}]),
  132. %% dbg:tpl(mnesia_log,[{'_',[],[{message,{return_trace}}]}]),
  133. %% dbg:tpl(ets,insert,[{'_',[],[{message,{return_trace}}]}]),
  134. %% dbg:tpl(?MODULE,[{'_',[],[{message,{return_trace}}]}]),
  135. dbg:p(all,[c]).
  136. %% dbg:p(mnesia_tm,[p]).
  137. delete_schema(doc) ->
  138. [];
  139. %%% "delete schema and stop mnesia.";
  140. delete_schema(Config) when is_list(Config) ->
  141. ?line case application:get_application(mnesia) of
  142. undefined ->
  143. ok;
  144. _Pid ->
  145. ?line mnesia:stop()
  146. end,
  147. ?line mnesia:delete_schema([node()]),
  148. ok.
  149. basic_create_table(doc) ->
  150. [];
  151. basic_create_table(Config) when is_list(Config) ->
  152. ?line {atomic, ok} = mnesia:create_table(basic, []),
  153. ?line chk_codegen(),
  154. ?line {atomic, ok} = mnesia:delete_table(basic),
  155. ?line chk_codegen(),
  156. ok.
  157. rdbms_create_table(doc) ->
  158. "use rdbms:create_table() with a few rdbms attributes.";
  159. rdbms_create_table(Config) when is_list(Config) ->
  160. io:format("rdbms_create_table()~n", []),
  161. ?line {atomic, ok} = rdbms:create_table(
  162. rdbms_basic,
  163. [{attributes, [a1,a2]},
  164. {rdbms,
  165. [{{attr, a1, type}, integer},
  166. {{attr, a2, type}, string}
  167. ]}
  168. ]),
  169. ?line chk_codegen(),
  170. ok.
  171. rdbms_verify_write_basic(doc) ->
  172. [];
  173. rdbms_verify_write_basic(Config) when is_list(Config) ->
  174. io:format("rdbms_verify_write_basic()~n", []),
  175. ?line trans(fun() ->
  176. mnesia:write({rdbms_basic, 17, "foo"})
  177. end),
  178. ?line fail_trans(fun() ->
  179. mnesia:write({rdbms_basic, 17, 17})
  180. end),
  181. ?line fail_trans(fun() ->
  182. mnesia:write({rdbms_basic, foo, "str"})
  183. end).
  184. rdbms_types_undef(doc) ->
  185. "test the 'undefined' type";
  186. rdbms_types_undef(Config) when is_list(Config) ->
  187. ?line {atomic, ok} = rdbms:create_table(
  188. rdbms_t_undef,
  189. [{attributes, [key, value]},
  190. {rdbms,
  191. [{{attr,value,type}, {'or',
  192. [integer,
  193. undefined]}}
  194. ]}
  195. ]),
  196. ?line chk_codegen(),
  197. %%% ?line start_trace(),
  198. ?line trans(fun() ->
  199. ?line mnesia:write({rdbms_t_undef,1,undefined}),
  200. ?line mnesia:write({rdbms_t_undef,1,17})
  201. end),
  202. ?line fail_trans(fun() ->
  203. ?line mnesia:write({rdbms_t_undef,1,foo})
  204. end),
  205. ok.
  206. rdbms_types_list(doc) ->
  207. "test the {list,T} type";
  208. rdbms_types_list(Config) when is_list(Config) ->
  209. ?line {atomic, ok} = rdbms:create_table(
  210. rdbms_t_list,
  211. [{attributes, [key, value]},
  212. {rdbms,
  213. [{{attr,value,type}, {list,integer}}
  214. ]}
  215. ]),
  216. ?line chk_codegen(),
  217. %%% ?line start_trace(),
  218. ?line trans(fun() ->
  219. ?line mnesia:write({rdbms_t_list,1,[]}),
  220. ?line mnesia:write({rdbms_t_list,2,
  221. lists:seq(1,7)})
  222. end),
  223. ?line fail_trans(fun() ->
  224. ?line mnesia:write({rdbms_t_list,1,[1,2,a]})
  225. end),
  226. ok.
  227. rdbms_types_enum(doc) ->
  228. "test the {enum,T} type";
  229. rdbms_types_enum(Config) when is_list(Config) ->
  230. ?line {atomic, ok} = rdbms:create_table(
  231. rdbms_t_enum,
  232. [{attributes, [key, value]},
  233. {rdbms,
  234. [{{attr,value,type}, {enum,[a,b,c]}}
  235. ]}
  236. ]),
  237. ?line chk_codegen(),
  238. %%% ?line start_trace(),
  239. ?line trans(fun() ->
  240. ?line mnesia:write({rdbms_t_enum,1,a}),
  241. ?line mnesia:write({rdbms_t_enum,1,b}),
  242. ?line mnesia:write({rdbms_t_enum,2,c})
  243. end),
  244. ?line fail_trans(fun() ->
  245. ?line mnesia:write({rdbms_t_enum,1,d})
  246. end),
  247. ok.
  248. rdbms_write_filter(doc) ->
  249. [];
  250. rdbms_write_filter(Config) when is_list(Config) ->
  251. ?line {atomic, ok} = rdbms:create_table(
  252. rdbms_w_filter,
  253. [{attributes, [key, value]},
  254. {rdbms,
  255. [{write_filter,
  256. [{{rdbms_w_filter,'$1','$2'},
  257. [], [{{rdbms_w_filter,'$1',{float,'$2'}}}]}]},
  258. {{attr,value,type}, float}
  259. ]}
  260. ]),
  261. ?line {atomic, ok} = rdbms:create_table(
  262. rdbms_no_w_filter,
  263. [{attributes, [key, value]},
  264. {rdbms,
  265. [
  266. {{attr,value,type}, float}
  267. ]}
  268. ]),
  269. ?line trans(fun() ->
  270. mnesia:write({rdbms_w_filter, 17, 1})
  271. end),
  272. ?line trans(fun() ->
  273. mnesia:write({rdbms_w_filter, 17, 1.0})
  274. end),
  275. ?line fail_trans(fun() ->
  276. mnesia:write({rdbms_no_w_filter, 17, 1})
  277. end),
  278. ?line trans(fun() ->
  279. mnesia:write({rdbms_no_w_filter, 17, 1.0})
  280. end).
  281. rdbms_acl(doc) ->
  282. "test access control list";
  283. rdbms_acl(Config) when is_list(Config) ->
  284. %%% ?line start_trace(),
  285. ?line {atomic,ok} = rdbms:create_table(
  286. acl1, [{rdbms,
  287. [
  288. {acl, [{delete,false}]}
  289. ]}]),
  290. ?line {atomic,ok} = rdbms:create_table(
  291. acl2, [{rdbms,
  292. [
  293. {acl, [{read,{?MODULE,acl2_read}}]}
  294. ]}]),
  295. ?line trans(fun() ->
  296. mnesia:write({acl1,1,a}),
  297. mnesia:write({acl2,1,a}),
  298. mnesia:write({acl2,2,b})
  299. end),
  300. ?line fail_trans(fun() ->
  301. mnesia:delete({acl1,1})
  302. end),
  303. ?line trans(fun() ->
  304. [] = mnesia:read({acl2,2})
  305. end),
  306. ?line trans(fun() ->
  307. mnesia:read({acl2,1})
  308. end).
  309. acl2_read(Tab, Mode, {acl2,1}) ->
  310. true;
  311. acl2_read(Tab, Mode, Other) ->
  312. false.
  313. rdbms_refs_cascade(doc) ->
  314. [];
  315. rdbms_refs_cascade(Config) when is_list(Config) ->
  316. ?line dbg:stop(),
  317. ?line {atomic,ok} = rdbms:create_table(
  318. refs1_base,
  319. [{attributes, [key, value]},
  320. {rdbms, [{references,
  321. [{attr, value,
  322. [{refs1_child, parent,
  323. [{match, full},
  324. {update, set_null},
  325. {delete, cascade}]}]}
  326. ]}
  327. ]}
  328. ]),
  329. ?line rdbms_codegen:output_src_file(),
  330. ?line {atomic,ok} = rdbms:create_table(
  331. refs1_child,
  332. [{attributes, [key, parent, value]}
  333. ]),
  334. %%% ?line start_trace(),
  335. ?line trans(fun() ->
  336. mnesia:write({refs1_base, 1, a}),
  337. mnesia:write({refs1_child, 1, a, v1}),
  338. mnesia:write({refs1_child, 2, a, v2})
  339. end),
  340. ?line trans(fun() ->
  341. mnesia:delete({refs1_base, 1}),
  342. [] = mnesia:match_object({refs1_child,'_','_','_'})
  343. end),
  344. ok.
  345. rdbms_refs_lookup(doc) ->
  346. ["Check referential integrity: deletes in the parent "
  347. "table are only allowed when there are no child objects, "
  348. "and inserts in the child table are only allowed if there is "
  349. "a parent object."];
  350. rdbms_refs_lookup(Config) when is_list(Config) ->
  351. ?line {atomic,ok} = rdbms:create_table(
  352. refs2_base,
  353. [{attributes, [key, value]},
  354. {rdbms, [{references,
  355. [{attr, value,
  356. [{refs2_child, parent,
  357. [{match, full},
  358. {update, set_default},
  359. {delete, no_action}]}]}
  360. ]}
  361. ]}
  362. ]),
  363. ?line rdbms_codegen:output_src_file(),
  364. ?line {atomic,ok} = rdbms:create_table(
  365. refs2_child,
  366. [{attributes, [key, parent, value]},
  367. {rdbms,
  368. [{references,
  369. [{attr, parent,
  370. [{refs2_base, value,
  371. [{match, full},
  372. {update, no_action},
  373. {delete, ignore}]}]}
  374. ]}
  375. ]}
  376. ]),
  377. ?line trans(fun() ->
  378. mnesia:write({refs2_base, 1, a}),
  379. mnesia:write({refs2_child, 1, a, v1}),
  380. mnesia:write({refs2_child, 2, a, v2})
  381. end),
  382. ?line fail_trans(fun() ->
  383. mnesia:write({refs2_child, 3, b, v3})
  384. end),
  385. %%% ?line start_trace(),
  386. ?line fail_trans(fun() ->
  387. mnesia:delete({refs2_base, 1})
  388. end),
  389. ?line trans(fun() ->
  390. mnesia:delete({refs2_child, 1}),
  391. mnesia:delete({refs2_child, 2}),
  392. mnesia:delete({refs2_base, 1})
  393. end),
  394. ok.
  395. rdbms_ix_ix(doc) ->
  396. [];
  397. rdbms_ix_ix(Config) when is_list(Config) ->
  398. %%% ?line start_trace(),
  399. ?line {atomic,ok} = rdbms:create_table(
  400. ix_ix,
  401. [{disc_copies, [node()]},
  402. {attributes, [key, value]},
  403. {rdbms,
  404. [
  405. {indexes,
  406. [{{value,ix},rdbms,ix,[],[{type,ordered}]}]}
  407. ]}
  408. ]),
  409. ?line mnesia:wait_for_tables([ix_ix], 30000),
  410. OldLevel = mnesia:set_debug_level(trace),
  411. ?line trans(fun() ->
  412. mnesia:write({ix_ix, 1, a}),
  413. mnesia:write({ix_ix, 2, b}),
  414. mnesia:write({ix_ix, 3, b})
  415. end),
  416. ?line trans(fun() ->
  417. [{ix_ix,1,a}] =
  418. mnesia:index_read(ix_ix,a,{value,ix}),
  419. [{ix_ix,2,b},{ix_ix,3,b}] =
  420. mnesia:index_read(ix_ix,b,{value,ix})
  421. end),
  422. mnesia:set_debug_level(OldLevel),
  423. ok.
  424. rdbms_ix_list(doc) ->
  425. [];
  426. rdbms_ix_list(Config) when is_list(Config) ->
  427. %%% ?line start_trace(),
  428. ?line {atomic,ok} = rdbms:create_table(
  429. ix_list,
  430. [{disc_copies, [node()]},
  431. {attributes, [key, value]},
  432. {rdbms,
  433. [
  434. {indexes,
  435. [{{value,ix},rdbms,ix_list,[],[{type,ordered}]}]}
  436. ]}
  437. ]),
  438. ?line mnesia:wait_for_tables([ix_list], 30000),
  439. OldLevel = mnesia:set_debug_level(trace),
  440. ?line trans(fun() ->
  441. mnesia:write({ix_list, 1, [a,b,c]}),
  442. mnesia:write({ix_list, 2, [c,d,e]}),
  443. mnesia:write({ix_list, 3, [c,d,e]})
  444. end),
  445. ?line trans(fun() ->
  446. [{ix_list,1,[a,b,c]}] =
  447. mnesia:index_read(ix_list,a,{value,ix}),
  448. [{ix_list,1,[a,b,c]},
  449. {ix_list,2,[c,d,e]},{ix_list,3,[c,d,e]}] =
  450. mnesia:index_read(ix_list,c,{value,ix}),
  451. [{ix_list,2,[c,d,e]},{ix_list,3,[c,d,e]}] =
  452. mnesia:index_read(ix_list,d,{value,ix})
  453. end),
  454. mnesia:set_debug_level(OldLevel),
  455. ok.
  456. rdbms_ix_vals(doc) ->
  457. [];
  458. rdbms_ix_vals(Config) when is_list(Config) ->
  459. %%% ?line start_trace(),
  460. ?line {atomic,ok} = rdbms:create_table(
  461. ix_vals,
  462. [{disc_copies, [node()]},
  463. {attributes, [key, v1,v2,v3]},
  464. {rdbms,
  465. [
  466. {indexes,
  467. [{{1,vals},rdbms,ix_vals,[3,4,5],
  468. [{type,ordered}]}]}
  469. ]}
  470. ]),
  471. ?line mnesia:wait_for_tables([ix_vals], 30000),
  472. ?line start_trace(),
  473. OldLevel = mnesia:set_debug_level(trace),
  474. ?line trans(fun() ->
  475. mnesia:write({ix_vals, 1, a,b,c}),
  476. mnesia:write({ix_vals, 2, b,c,d}),
  477. mnesia:write({ix_vals, 3, b,c,d})
  478. end),
  479. ?line trans(fun() ->
  480. [{ix_vals,1,a,b,c}] =
  481. mnesia:index_read(ix_vals,[a,b,c],{1,vals}),
  482. [{ix_vals,2,b,c,d},{ix_vals,3,b,c,d}] =
  483. mnesia:index_read(ix_vals,[b,c,d],{1,vals})
  484. end),
  485. mnesia:set_debug_level(OldLevel),
  486. ok.
  487. rdbms_ix(doc) ->
  488. [];
  489. rdbms_ix(Config) when is_list(Config) ->
  490. %%% ?line start_trace(),
  491. ?line dbg:stop(),
  492. ?line {atomic,ok} = rdbms:create_table(
  493. ix1,
  494. [{disc_copies, [node()]},
  495. {attributes, [key, value]},
  496. {rdbms,
  497. [
  498. {indexes,
  499. [{{value,words},?MODULE,word_attr_ix,[],[]}]}
  500. ]}
  501. ]),
  502. write_ix1(),
  503. test_ix1(),
  504. OldLevel = mnesia:set_debug_level(trace),
  505. write_ix1_2(),
  506. mnesia:set_debug_level(OldLevel),
  507. test_ix1_2().
  508. rdbms_ix_load(doc) ->
  509. "verify that index tables are loaded automatically at restart";
  510. rdbms_ix_load(Config) when is_list(Config) ->
  511. ?line catch mnesia:stop(),
  512. ?line io:format("mnesia stopped~n", []),
  513. %%% ?line start_trace(),
  514. ?line mnesia:start([{access_module,rdbms},{debug,false}]),
  515. ?line io:format("mnesia started~n", []),
  516. test_ix1_2().
  517. write_ix1() ->
  518. ?line mnesia:wait_for_tables([ix1], 3000),
  519. ?line Tab = ix1,
  520. O1 = {Tab,1,"a b c d"},
  521. O2 = {Tab,2,"a b"},
  522. O3 = {Tab,3,"b c d"},
  523. O4 = {Tab,4,"e f"},
  524. O5 = {Tab,5,"f g"},
  525. ?line trans(fun() ->
  526. lists:foreach(
  527. fun(O) ->
  528. mnesia:write(O)
  529. end, [O1,O2,O3,O4,O5]),
  530. [O1,O2] =
  531. lists:sort(
  532. mnesia:index_read(Tab, "a", {value,words}))
  533. end).
  534. test_ix1() ->
  535. ?line ok = mnesia:wait_for_tables([ix1], 30000),
  536. ?line Tab = ix1,
  537. O1 = {Tab,1,"a b c d"},
  538. O2 = {Tab,2,"a b"},
  539. O3 = {Tab,3,"b c d"},
  540. O4 = {Tab,4,"e f"},
  541. O5 = {Tab,5,"f g"},
  542. ?line trans(fun() ->
  543. [O1,O2,O3] =
  544. lists:sort(
  545. mnesia:index_read(Tab, "b", {value,words})),
  546. [O1,O3] =
  547. lists:sort(
  548. mnesia:index_read(Tab, "d", {value,words}))
  549. end).
  550. write_ix1_2() ->
  551. ?line Tab = ix1,
  552. O1 = {Tab,1,"a b c d"},
  553. O2 = {Tab,2,"a b"},
  554. O3 = {Tab,3,"b c d"},
  555. O4 = {Tab,4,"e f"},
  556. O5 = {Tab,5,"f g"},
  557. O6 = {Tab,1,"c d"},
  558. ?line trans(fun() ->
  559. lists:foreach(
  560. fun(Obj) ->
  561. mnesia:write(Obj)
  562. end, [O1,O2,O3,O4,O5,O6])
  563. end).
  564. test_ix1_2() ->
  565. ?line ok = mnesia:wait_for_tables([ix1], 30000),
  566. ?line Tab = ix1,
  567. O1 = {Tab,1,"a b c d"},
  568. O2 = {Tab,2,"a b"},
  569. O3 = {Tab,3,"b c d"},
  570. O4 = {Tab,4,"e f"},
  571. O5 = {Tab,5,"f g"},
  572. O6 = {Tab,1,"c d"},
  573. ?line trans(fun() ->
  574. [O2,O3] =
  575. lists:sort(
  576. mnesia:index_read(Tab, "b", {value,words})),
  577. [O6,O3] =
  578. lists:sort(
  579. mnesia:index_read(Tab, "d", {value,words}))
  580. end),
  581. ok.
  582. rdbms_add_ix(doc) ->
  583. "First creating a table and data, then creating an index";
  584. rdbms_add_ix(Config) when is_list(Config) ->
  585. ?line {atomic,ok} = rdbms:create_table(
  586. ix2,
  587. [{attributes, [key, value]}]),
  588. ?line mnesia:wait_for_tables([ix2], 3000),
  589. ?line Tab = ix2,
  590. O1 = {Tab,1,"a b c d"},
  591. O2 = {Tab,2,"a b"},
  592. O3 = {Tab,3,"b c d"},
  593. O4 = {Tab,4,"e f"},
  594. O5 = {Tab,5,"f g"},
  595. ?line trans(fun() ->
  596. lists:foreach(
  597. fun(O) ->
  598. mnesia:write(O)
  599. end, [O1,O2,O3,O4,O5])
  600. end),
  601. ?line mnesia_schema:schema_transaction(
  602. fun() ->
  603. rdbms_index:do_add_indexes(
  604. ix2, [{{value,words},?MODULE,word_attr_ix,[],[]}])
  605. end),
  606. ?line mnesia:wait_for_tables([ix2], 3000),
  607. ?line trans(fun() ->
  608. [O1,O2,O3] =
  609. lists:sort(
  610. mnesia:index_read(Tab, "b", {value,words})),
  611. [O1,O3] =
  612. lists:sort(
  613. mnesia:index_read(Tab, "d", {value,words}))
  614. end),
  615. ok.
  616. rdbms_unique_ix(doc) ->
  617. "Test the 'unique' option for indexes";
  618. rdbms_unique_ix(Config) when is_list(Config) ->
  619. ?line start_trace(),
  620. ?line {atomic,ok} = rdbms:create_table(
  621. u_ix,
  622. [{ram_copies, [node()]},
  623. {attributes, [key, value]},
  624. {rdbms,
  625. [
  626. {indexes,
  627. [{{value,value},?MODULE,ix_value,[],
  628. [{type,set},
  629. {unique, true}]}]}
  630. ]}
  631. ]),
  632. ?line trans(fun() ->
  633. mnesia:write({u_ix,1,a}),
  634. mnesia:write({u_ix,2,b})
  635. end),
  636. ?line trans(fun() ->
  637. [{u_ix,1,a}] =
  638. mnesia:index_read(u_ix,a,{value,value}),
  639. [{u_ix,2,b}] =
  640. mnesia:index_read(u_ix,b,{value,value})
  641. end),
  642. ?line fail_trans(fun() ->
  643. mnesia:write({u_ix,3,a})
  644. end).
  645. chk_codegen() ->
  646. true = rdbms_codegen:last_codegen_successful().
  647. trans(F) ->
  648. try mnesia:activity(transaction,
  649. fun() ->
  650. try F()
  651. catch
  652. error:Reason ->
  653. erlang:error(
  654. {Reason,
  655. erlang:get_stacktrace()});
  656. exit:Reason ->
  657. erlang:error(
  658. {Reason,
  659. erlang:get_stacktrace()})
  660. end
  661. end)
  662. catch
  663. error:Reason ->
  664. io:format("FAILED!!! ~p, ~p~n", [Reason,
  665. erlang:get_stacktrace()]),
  666. erlang:error({Reason, erlang:get_stacktrace()});
  667. exit:Reason ->
  668. io:format("FAILED!!! ~p, ~p~n", [Reason,
  669. erlang:get_stacktrace()]),
  670. erlang:error({Reason, erlang:get_stacktrace()})
  671. end,
  672. ok.
  673. fail_trans(F) ->
  674. try mnesia:activity(transaction, F) of
  675. Success ->
  676. erlang:error({should_have_failed, Success})
  677. catch
  678. error:Reason ->
  679. io:format("Failed with Reason = ~p (ok?)~n", [Reason]),
  680. ok;
  681. exit:Reason ->
  682. io:format("Failed with Reason = ~p (ok?)~n", [Reason]),
  683. ok
  684. end.
  685. word_attr_ix(Str, _) ->
  686. [to_lower(W) || W <- string:tokens(Str, " \t\rn")].
  687. to_lower(Word) ->
  688. lists:map(fun(C) when $A =< C, C =< $Z ->
  689. $a + (C - $A);
  690. (C) ->
  691. C
  692. end, Word).
  693. ix_value(V, _) ->
  694. [V].