1: %%
    2: %% %CopyrightBegin%
    3: %%
    4: %% Copyright Ericsson AB 2004-2013. All Rights Reserved.
    5: %%
    6: %% The contents of this file are subject to the Erlang Public License,
    7: %% Version 1.1, (the "License"); you may not use this file except in
    8: %% compliance with the License. You should have received a copy of the
    9: %% Erlang Public License along with this software. If not, it can be
   10: %% retrieved online at http://www.erlang.org/.
   11: %%
   12: %% Software distributed under the License is distributed on an "AS IS"
   13: %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
   14: %% the License for the specific language governing rights and limitations
   15: %% under the License.
   16: %%
   17: %% %CopyrightEnd%
   18: %%
   19: %%%----------------------------------------------------------------
   20: %%% Purpose:Test Suite for the 'qlc' module.
   21: %%%-----------------------------------------------------------------
   22: -module(qlc_SUITE).
   23: 
   24: -define(QLC, qlc).
   25: -define(QLCs, "qlc").
   26: 
   27: %-define(debug, true).
   28: 
   29: %% There are often many tests per testcase. Most tests are copied to a
   30: %% module, a file. The file is compiled and the test run. Should the
   31: %% test fail, the module file is not removed from ?privdir, but is
   32: %% kept for inspection. The name of the file is
   33: %% ?privdir/qlc_test_CASE.erl.
   34: -define(TESTMODULE, qlc_test).
   35: -define(TESTCASE, testcase_name).
   36: 
   37: -ifdef(debug).
   38: -define(line, put(line, ?LINE), ).
   39: -define(config(X,Y), foo).
   40: -define(datadir, ?QLCs ++  "_SUITE_data").
   41: -define(privdir, ?QLCs ++ "_SUITE_priv").
   42: -define(testcase, current_testcase). % don't know
   43: -define(t, test_server).
   44: -else.
   45: -include_lib("test_server/include/test_server.hrl").
   46: -define(datadir, ?config(data_dir, Config)).
   47: -define(privdir, ?config(priv_dir, Config)).
   48: -define(testcase, ?config(?TESTCASE, Config)).
   49: -endif.
   50: 
   51: -include_lib("stdlib/include/ms_transform.hrl").
   52: 
   53: -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, 
   54: 	 init_per_group/2,end_per_group/2, 
   55: 	 init_per_testcase/2, end_per_testcase/2]).
   56: 
   57: -export([ 
   58: 	  badarg/1, nested_qlc/1, unused_var/1, lc/1, fun_clauses/1,
   59: 	  filter_var/1, single/1, exported_var/1, generator_vars/1,
   60: 	  nomatch/1, errors/1, pattern/1, 
   61: 
   62: 	  eval/1, cursor/1, fold/1, eval_unique/1, eval_cache/1, append/1, 
   63: 	  evaluator/1, string_to_handle/1, table/1, process_dies/1, 
   64: 	  sort/1, keysort/1, filesort/1, cache/1, cache_list/1, filter/1, 
   65: 	  info/1, nested_info/1, lookup1/1, lookup2/1, lookup_rec/1, 
   66: 	  indices/1, pre_fun/1, skip_filters/1,
   67: 
   68: 	  ets/1, dets/1,
   69: 
   70: 	  join_option/1, join_filter/1, join_lookup/1, join_merge/1,
   71: 	  join_sort/1, join_complex/1,
   72: 
   73: 	  otp_5644/1, otp_5195/1, otp_6038_bug/1, otp_6359/1, otp_6562/1,
   74: 	  otp_6590/1, otp_6673/1, otp_6964/1, otp_7114/1, otp_7238/1,
   75: 	  otp_7232/1, otp_7552/1, otp_6674/1, otp_7714/1,
   76: 
   77: 	  manpage/1,
   78: 
   79: 	  backward/1, forward/1]).
   80: 
   81: %% Internal exports.
   82: -export([bad_table_throw/1, bad_table_exit/1, default_table/1, bad_table/1,
   83:          bad_table_format/1, bad_table_format_arity/1, bad_table_traverse/1,
   84:          bad_table_post/1, bad_table_lookup/1, bad_table_max_lookup/1,
   85:          bad_table_info_arity/1, bad_table_info_fun_n_objects/1,
   86:          bad_table_info_fun_indices/1, bad_table_info_fun_keypos/1,
   87:          bad_table_key_equality/1]).
   88: -export([evaluator_2/2]).
   89: -export([prep_scratchdir/1, truncate_tmpfile/2, crash/2, crash_tmpfile/2]).
   90: -export([etsc/2, etsc/3, create_ets/2, lookup_keys/1]).
   91: -export([strip_qlc_call/1, join_info/1, join_info_count/1]).
   92: -export([i/1, i/2, format_info/2]).
   93: 
   94: -export([table_kill_parent/2, table_parent_throws/2, 
   95:          table_parent_exits/2, table_bad_parent_fun/2]).
   96: -export([table/2, table/3, stop_list/2, table_error/2, table_error/3, 
   97:          table_lookup_error/1]).
   98: 
   99: %% error_logger
  100: -export([install_error_logger/0, uninstall_error_logger/0, 
  101:          read_error_logger/0]).
  102: -export([init/1,
  103: 	 handle_event/2, handle_call/2, handle_info/2,
  104: 	 terminate/2]).
  105: 
  106: % Default timetrap timeout (set in init_per_testcase).
  107: -define(default_timeout, ?t:minutes(5)).
  108: 
  109: init_per_testcase(Case, Config) ->
  110:     ?line Dog = ?t:timetrap(?default_timeout),
  111:     [{?TESTCASE, Case}, {watchdog, Dog} | Config].
  112: 
  113: end_per_testcase(_Case, _Config) ->
  114:     Dog = ?config(watchdog, _Config),
  115:     test_server:timetrap_cancel(Dog),
  116:     ok.
  117: 
  118: suite() -> [{ct_hooks,[ts_install_cth]}].
  119: 
  120: all() -> 
  121:     [{group, parse_transform}, {group, evaluation},
  122:      {group, table_impls}, {group, join}, {group, tickets},
  123:      manpage, {group, compat}].
  124: 
  125: groups() -> 
  126:     [{parse_transform, [],
  127:       [badarg, nested_qlc, unused_var, lc, fun_clauses,
  128:        filter_var, single, exported_var, generator_vars,
  129:        nomatch, errors, pattern]},
  130:      {evaluation, [],
  131:       [eval, cursor, fold, eval_unique, eval_cache, append,
  132:        evaluator, string_to_handle, table, process_dies, sort,
  133:        keysort, filesort, cache, cache_list, filter, info,
  134:        nested_info, lookup1, lookup2, lookup_rec, indices,
  135:        pre_fun, skip_filters]},
  136:      {table_impls, [], [ets, dets]},
  137:      {join, [],
  138:       [join_option, join_filter, join_lookup, join_merge,
  139:        join_sort, join_complex]},
  140:      {tickets, [],
  141:       [otp_5644, otp_5195, otp_6038_bug, otp_6359, otp_6562,
  142:        otp_6590, otp_6673, otp_6964, otp_7114, otp_7232,
  143:        otp_7238, otp_7552, otp_6674, otp_7714]},
  144:      {compat, [], [backward, forward]}].
  145: 
  146: init_per_suite(Config) ->
  147:     Config.
  148: 
  149: end_per_suite(_Config) ->
  150:     ok.
  151: 
  152: init_per_group(_GroupName, Config) ->
  153:     Config.
  154: 
  155: end_per_group(_GroupName, Config) ->
  156:     Config.
  157: 
  158: badarg(doc) ->
  159:     "Badarg.";
  160: badarg(suite) -> [];
  161: badarg(Config) when is_list(Config) ->
  162:     Ts =
  163:       [{badarg,
  164:        <<"-import(qlc, [q/1, q/2]).
  165:           q(_, _, _) -> ok.
  166: 
  167:           badarg() ->
  168:               qlc:q(foo),
  169:               qlc:q(foo, cache_all),
  170:               qlc:q(foo, cache_all, extra),
  171:               q(bar),
  172:               q(bar, cache_all),
  173:               q(bar, cache_all, extra).
  174:        ">>,
  175:        [],
  176:        {errors,[{5,?QLC,not_a_query_list_comprehension},
  177:                 {6,?QLC,not_a_query_list_comprehension},
  178:                 {8,?QLC,not_a_query_list_comprehension},
  179:                 {9,?QLC,not_a_query_list_comprehension}],
  180:         []}}],
  181:     ?line [] = compile(Config, Ts),
  182:     ok.
  183: 
  184: nested_qlc(doc) ->
  185:     "Nested qlc expressions.";
  186: nested_qlc(suite) -> [];
  187: nested_qlc(Config) when is_list(Config) ->
  188:     %% Nested QLC expressions. X is bound before the first one; Z and X
  189:     %% before the second one.
  190:     Ts = 
  191:      [{nested_qlc1,
  192:        <<"nested_qlc() ->
  193:               X = 3, % X unused
  194:               Q = qlc:q([Y || 
  195:                             X <- % X shadowed
  196:                                 begin Z = 3, 
  197:                                       qlc:q([Y || 
  198:                                                 Y <- [Z],
  199:                                                 X <- [1,2,3], % X shadowed
  200:                                                 X < Y])
  201:                                 end,
  202:                             Y <- 
  203:                                 [y],
  204:                             Y > X]),
  205:               [y, y] = qlc:e(Q),
  206:               ok.
  207:        ">>,
  208:        [warn_unused_vars],
  209:        {warnings,[{{2,15},erl_lint,{unused_var,'X'}},
  210:                   {{4,29},erl_lint,{shadowed_var,'X',generate}},
  211:                   {{8,49},erl_lint,{shadowed_var,'X',generate}}]}},
  212: 
  213:       {nested_qlc2,
  214:       <<"nested_qlc() ->
  215:              H0 = qlc:append([a,b], [c,d]),
  216:              qlc:q([{X,Y} || 
  217:                        X <- H0,
  218:                        Y <- qlc:q([{X,Y} || 
  219:                                       X <- H0, % X shadowed
  220:                                       Y <- H0])]),
  221:              ok.
  222:        ">>,
  223:        [warn_unused_vars],
  224:        {warnings,[{{6,39},erl_lint,{shadowed_var,'X',generate}}]}}
  225:     ],
  226:     ?line [] = compile(Config, Ts),
  227:     ok.
  228: 
  229: unused_var(doc) ->
  230:     "Unused variable with a name that should not be introduced.";
  231: unused_var(suite) -> [];
  232: unused_var(Config) when is_list(Config) ->
  233:     Ts = 
  234:      [{unused_var,
  235:        <<"unused_var() ->
  236:               qlc:q([X || begin Y1 = 3, true end, % Y1 unused
  237:                           Y <- [1,2,3],
  238:                           X <- [a,b,c],
  239:                           X < Y]).
  240:        ">>,
  241:        [warn_unused_vars],
  242:        {warnings,[{{2,33},erl_lint,{unused_var,'Y1'}}]}}],
  243:     ?line [] = compile(Config, Ts),
  244:     ok.
  245: 
  246: lc(doc) ->
  247:     "Ordinary LC expression.";
  248: lc(suite) -> [];
  249: lc(Config) when is_list(Config) ->
  250:     Ts = 
  251:      [{lc,
  252:        <<"lc() ->
  253:               [X || X <- [], X <- X]. % X shadowed
  254:         ">>,
  255:        [],
  256:        {warnings,[{{2,30},erl_lint,{shadowed_var,'X',generate}}]}}],
  257:     ?line [] = compile(Config, Ts),
  258:     ok.
  259:            
  260: fun_clauses(doc) ->
  261:     "Fun with several clauses.";
  262: fun_clauses(suite) -> [];
  263: fun_clauses(Config) when is_list(Config) ->
  264:     Ts = 
  265:      [{fun_clauses,
  266:        <<"fun_clauses() ->
  267:             {X,X1,X2} = {1,2,3},
  268:             F = fun({X}) -> qlc:q([X || X <- X]); % X shadowed (fun, generate)
  269:                    ([X]) -> qlc:q([X || X <- X])  % X shadowed (fun, generate)
  270:                 end,
  271:             {F,X,X1,X2}.
  272:         ">>,
  273:        [],
  274:        {warnings,[{{3,22},erl_lint,{shadowed_var,'X','fun'}},
  275:                   {{3,41},erl_lint,{shadowed_var,'X',generate}},
  276:                   {{4,22},erl_lint,{shadowed_var,'X','fun'}},
  277:                   {{4,41},erl_lint,{shadowed_var,'X',generate}}]}}],
  278:     ?line [] = compile(Config, Ts),
  279:     ok.
  280: 
  281: filter_var(doc) ->
  282:     "Variable introduced in filter.";
  283: filter_var(suite) -> [];
  284: filter_var(Config) when is_list(Config) ->
  285:     Ts = 
  286:      [{filter_var,
  287:        <<"filter_var() ->
  288:               qlc:q([X || 
  289:                   Y <- [X || 
  290:                            X <- [1,2,3]],
  291:                   begin X = Y, true end]).
  292:         ">>,
  293:        [],
  294:        []},
  295: 
  296:       {unsafe_filter_var,
  297:        <<"unsafe_filter_var() ->
  298:               qlc:q([{X,V} || X <- [1,2],
  299:                   case {a} of
  300:                       {_} ->
  301:                           true;
  302:                       V ->
  303:                           V
  304:                   end]).
  305:         ">>,
  306:        [],
  307:        {errors,[{{2,25},erl_lint,{unsafe_var,'V',{'case',{3,19}}}}],[]}}],
  308:     ?line [] = compile(Config, Ts),
  309:     ok.
  310: 
  311: 
  312: single(doc) ->
  313:     "Unused pattern variable.";
  314: single(suite) -> [];
  315: single(Config) when is_list(Config) ->
  316:     Ts = 
  317:      [{single,
  318:        <<"single() ->
  319:               qlc:q([X || {X,Y} <- [{1,2}]]), % Y unused
  320:               qlc:q([[] || [] <- [[]]]).
  321:         ">>,
  322:        [warn_unused_vars],
  323:        {warnings,[{{2,30},erl_lint,{unused_var,'Y'}}]}}],
  324:     ?line [] = compile(Config, Ts),
  325:     ok.
  326: 
  327: exported_var(doc) ->
  328:     "Exported variable in list expression (rhs of generator).";
  329: exported_var(suite) -> [];
  330: exported_var(Config) when is_list(Config) ->
  331:     Ts = 
  332:      [{exported_var,
  333:        <<"exported() ->
  334:               qlc:q([X || X <- begin
  335:                                    case foo:bar() of
  336:                                        1 -> Z = a;
  337:                                        2 -> Z = b
  338:                                    end,
  339:                                    [Z = 3, Z = 3] % Z exported (twice...)
  340:                                end
  341:                          ]).
  342:        ">>,
  343:        [warn_export_vars],
  344:        {warnings,[{{7,37},erl_lint,{exported_var,'Z',{'case',{3,36}}}},
  345:                   {{7,44},erl_lint,{exported_var,'Z',{'case',{3,36}}}}]}}],
  346:     ?line [] = compile(Config, Ts),
  347:     ok.
  348: 
  349: generator_vars(doc) ->
  350:     "Errors for generator variable used in list expression.";
  351: generator_vars(suite) -> [];
  352: generator_vars(Config) when is_list(Config) ->
  353:     Ts = 
  354:       [{generator_vars,
  355:         <<"generator_vars() ->
  356:                qlc:q([X ||
  357:                       Z <- [1,2],
  358:                       X <- begin
  359:                                case 1 of
  360:                                    1 -> Z = a; % used_generator_variable
  361:                                    2 -> Z = b % used_generator_variable
  362:                                end,
  363:                                [Z = 3, Z = 3] % used_generator_variable (2)
  364:                            end
  365:                      ]).
  366:         ">>,
  367:         [],
  368:         {errors,[{{6,41},?QLC,{used_generator_variable,'Z'}},
  369:                  {{7,41},?QLC,{used_generator_variable,'Z'}},
  370:                  {{9,33},?QLC,{used_generator_variable,'Z'}},
  371:                  {{9,40},?QLC,{used_generator_variable,'Z'}}],
  372:          []}}],
  373:     ?line [] = compile(Config, Ts),
  374:     ok.
  375: 
  376: nomatch(doc) ->
  377:     "Unreachable clauses also found when compiling.";
  378: nomatch(suite) -> [];
  379: nomatch(Config) when is_list(Config) ->
  380:     Ts =
  381:       [{unreachable1,
  382:         <<"unreachable1() ->
  383:                qlc:q([X || X <- [1,2],
  384:                    case X of
  385:                        true -> false;
  386:                        true -> true   % clause cannot match
  387:                     end]).
  388:         ">>,
  389:         [],
  390:         {warnings,[{5,v3_kernel,{nomatch_shadow,4}}]}},
  391: 
  392:        {nomatch1,
  393:         <<"generator1() ->
  394:               qlc:q([3 || {3=4} <- []]).
  395:         ">>,
  396:         [],
  397:         {warnings,[{{2,27},qlc,nomatch_pattern}]}},
  398: 
  399:        {nomatch2,
  400:         <<"nomatch() ->
  401:                 etsc(fun(E) ->
  402:                 Q = qlc:q([3 || {3=4} <- ets:table(E)]),
  403:                 [] = qlc:eval(Q),
  404:                 false = lookup_keys(Q) 
  405:           end, [{1},{2}]).
  406:         ">>,
  407:         [],
  408:         {warnings,[{{3,33},qlc,nomatch_pattern}]}},
  409:  
  410:        {nomatch3,
  411:         <<"nomatch() ->
  412:               etsc(fun(E) ->
  413:                           Q = qlc:q([{A,B,C,D} || A=B={C=D}={_,_} <- 
  414:                                                     ets:table(E)]),
  415:                           [] = qlc:eval(Q),
  416:                           false = lookup_keys(Q)
  417:                     end, [{1,2},{2,3}]).
  418:         ">>,
  419:         [],
  420:         {warnings,[{{3,52},qlc,nomatch_pattern}]}},
  421: 
  422:        {nomatch4,
  423:         <<"nomatch() ->
  424:               etsc(fun(E) ->
  425:                           Q = qlc:q([{X,Y} || {<<X>>} = {<<Y>>} <- 
  426:                                                     ets:table(E)]),
  427:                           [] = qlc:eval(Q),
  428:                           false = lookup_keys(Q)
  429:                     end, [{<<34>>},{<<40>>}]).
  430:         ">>,
  431:         [],
  432:         {errors,[{{3,48},erl_lint,illegal_bin_pattern}],[]}},
  433: 
  434:        {nomatch5,
  435:         <<"nomatch() ->
  436:                etsc(fun(E) ->
  437:                            Q = qlc:q([t || {\"a\"++\"b\"} = {\"ac\"} <- 
  438:                                                     ets:table(E)]),
  439:                            [t] = qlc:eval(Q),
  440:                            [\"ab\"] = lookup_keys(Q)
  441:                      end, [{\"ab\"}]).
  442:         ">>,
  443:         [],
  444:         {warnings,[{3,v3_core,nomatch}]}}
  445: 
  446:       ],
  447:     ?line [] = compile(Config, Ts),
  448:     ok.
  449:     
  450: 
  451: errors(doc) ->
  452:     "Errors within qlc expressions also found when compiling.";
  453: errors(suite) -> [];
  454: errors(Config) when is_list(Config) ->
  455:     Ts =
  456:       [{errors1,
  457:         <<"errors1() ->
  458:                qlc:q([X || X <- A]). % A unbound
  459:         ">>,
  460:         [],
  461:         {errors,[{{2,33},erl_lint,{unbound_var,'A'}}],[]}}],
  462:     ?line [] = compile(Config, Ts),
  463:     ok.
  464: 
  465: pattern(doc) ->
  466:     "Patterns.";
  467: pattern(suite) -> [];
  468: pattern(Config) when is_list(Config) ->
  469:     Ts = [
  470:       <<"%% Records in patterns. No lookup.
  471:          L = [#a{k=#k{v=91}}],
  472:          H = qlc:q([Q || Q = #a{k=#k{v=91}} <- qlc_SUITE:table(L, 2, [])]),
  473:          {qlc,_,[{generate,_,{table,{call,_,_,_}}}], []} = i(H),
  474:          L = qlc:e(H),
  475:          {call, _, _q, [{lc,_,{var,_,'Q'}, 
  476:                          [{generate,_,
  477:                            {match,_,_,_},
  478:                            {call,_,_,_}}]}]}
  479:               = i(H, {format,abstract_code})">>,
  480: 
  481:       <<"%% No matchspec since there is a binary in the pattern.
  482:          etsc(fun(E) ->
  483:              Q = qlc:q([A || {<<A:3/unit:8>>} <- ets:table(E)]),
  484:              [_] = qlc:eval(Q),
  485:              {qlc,_,[{generate,_,{table,_}}], []} = i(Q)
  486:          end, [{<<\"hej\">>}])">>
  487: 
  488:        ],
  489:     ?line run(Config, <<"-record(a, {k,v}).
  490:                          -record(k, {t,v}).\n">>, Ts),
  491:     ok.
  492: 
  493: 
  494: eval(doc) ->
  495:     "eval/2";
  496: eval(suite) -> [];
  497: eval(Config) when is_list(Config) ->
  498:     ScratchDir = filename:join([?privdir, "scratch","."]),
  499: 
  500:     Ts = [<<"{'EXIT',{badarg,_}} = (catch qlc:eval(not_a_qlc)),
  501:              H = qlc:q([X || X <- [1,2]]),
  502:              {'EXIT',{{unsupported_qlc_handle,{qlc_handle,foo}},_}}=
  503:                        (catch qlc:e({qlc_handle,foo})),
  504:              {'EXIT',{badarg,_}} = (catch qlc:eval(H, [{unique_all,badarg}])),
  505:              {'EXIT',{badarg,_}} = 
  506:                       (catch qlc:eval(H, [{spawn_options,badarg}])),
  507:              {'EXIT',{badarg,_}} = 
  508:                       (catch qlc:eval(H, [{unique_all,true},{bad,arg}])),
  509:              {throw,t} = 
  510:                 (catch {any_term,qlc:e(qlc:q([X || X <- throw({throw,t})]))}),
  511:              M = qlc,
  512:              {'EXIT',{badarg,_}} = (catch M:q(bad))">>,
  513: 
  514:           [<<"Dir = \"">>,ScratchDir,<<"\",
  515:               qlc_SUITE:prep_scratchdir(Dir),
  516: 
  517:               E = ets:new(foo, []),
  518:               [true || I <- lists:seq(1, 50000), not ets:insert(E, {I, I})],
  519:               H = qlc:q([{X,Y} || Y <- [1,2], 
  520:                                   X <- qlc:sort(ets:table(E),{tmpdir,Dir}),
  521:                                   qlc_SUITE:truncate_tmpfile(Dir, 0)]),
  522:               R = qlc:eval(H),
  523:               ets:delete(E),
  524:               {error,_,{bad_object,_}} = R,
  525:               \"the tempo\" ++ _ = lists:flatten(qlc:format_error(R))">>],
  526: 
  527:           [<<"Dir = \"">>,ScratchDir,<<"\",
  528:               qlc_SUITE:prep_scratchdir(Dir),
  529: 
  530:               E = ets:new(foo, []),
  531:               Bin = term_to_binary(lists:seq(1,20000)),
  532:               [true || I <- lists:seq(1, 10), not ets:insert(E, {I, I, Bin})],
  533:               H = qlc:q([{X,Y} || Y <- [1,2], 
  534:                                   X <- qlc:sort(ets:table(E),{tmpdir,Dir}),
  535:                                   qlc_SUITE:crash_tmpfile(Dir, 5)]),
  536:               R = qlc:eval(H),
  537:               ets:delete(E),
  538:               {error,_,{bad_object,_}} = R">>],
  539: 
  540:           <<"E = ets:new(test, []),
  541:              H = qlc:q([{X,Y} || X <- qlc_SUITE:bad_table_throw(E), 
  542:                                  Y <- ets:table(E)]),
  543:              R1 = (catch {any_term,qlc:eval(H, {unique_all,false})}),
  544:              R2 = (catch {any_term,qlc:eval(H, {unique_all,true})}),
  545:              ets:delete(E),
  546:              true = {throw,bad_pre_fun} == R1,
  547:              true = {throw,bad_pre_fun} == R2">>,
  548: 
  549:           <<"E = ets:new(test, []),
  550:              H = qlc:q([{X,Y} || X <- qlc_SUITE:bad_table_exit(E), 
  551:                                  Y <- ets:table(E)]),
  552:              R1 = (catch qlc:eval(H, {unique_all,false})),
  553:              R2 = (catch qlc:eval(H, {unique_all,true})),
  554:              ets:delete(E),
  555:              {'EXIT',{bad_pre_fun,_}} = R1,
  556:              {'EXIT',{bad_pre_fun,_}} = R2">>,
  557: 
  558:           <<"Q = qlc:q([X || X <- [4,3,2,1,0,-1], begin 3/X > 0 end]),
  559:              {'EXIT',{badarith,_}} = (catch qlc:eval(Q, {unique_all,false})),
  560:              {'EXIT',{badarith,_}} = (catch qlc:eval(Q, {unique_all,true}))
  561:             ">>,
  562: 
  563:           <<"[1,2] = qlc:eval(qlc:q([X || X <- [1,2]])),
  564:              [1,2,3,4] = qlc:eval(qlc:append([1,2],[3,4])),
  565:              [1,2] = qlc:eval(qlc:sort([2,1])),
  566:              E = ets:new(foo, []),
  567:              ets:insert(E, [{1},{2}]),
  568:              [{1},{2}] = lists:sort(qlc:eval(ets:table(E))),
  569:              true = ets:delete(E)">>,
  570: 
  571:           <<"H = qlc:q([X || X <- [1,2], 
  572:                              begin F = fun() -> 
  573:                                 qlc:e(qlc:q([Y || Y <- [1,2]])) end, 
  574:                                 F() == (fun f/0)() end]),
  575:              [1,2] = qlc:e(H),
  576:              ok.
  577: 
  578:              f() -> [1,2].
  579:              foo() -> bar">>,
  580: 
  581:           <<"C1_0_1 = [1,2],
  582:              %% The PT cannot rename C to C1_0_1; another name is chosen.
  583:              [1,2] = qlc:eval(qlc:q([C || C <- C1_0_1]))">>,
  584: 
  585:           <<"H = qlc:q([X || {X,X} <- [{1,a},{2,2},{b,b},{3,4}]]),
  586:              [2,b] = qlc:e(H),
  587:              H1 = qlc:q([3 || {X,X} <- [{1,a},{2,2},{b,b},{3,4}]]),
  588:              [3,3] = qlc:e(H1)">>,
  589: 
  590:           %% Just to cover a certain line in qlc.erl (avoids returning [])
  591:           <<"E = ets:new(foo, []),
  592:              Bin = term_to_binary(lists:seq(1,20000)),
  593:              [true || I <- lists:seq(1, 10), not ets:insert(E, {I, I, Bin})],
  594:              H = qlc:q([{X,Y} || Y <- [1,2], X <- qlc:sort(ets:table(E))]),
  595:              R = qlc:eval(H),
  596:              ets:delete(E),
  597:              20 = length(R)">>,
  598: 
  599:           <<"H = qlc:q([{A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W} ||
  600:                  {A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W} <- 
  601:                   [{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w}]]),
  602:              [_] = qlc:e(H)">>,
  603: 
  604:           <<"H = qlc:q([Y || Y <- [1,2]], 
  605:                        {unique, begin [T] = qlc:e(qlc:q([X || X <- [true]],
  606:                                                         cache)), 
  607:                                       T end}),
  608:              [1,2] = qlc:e(H)">>
  609: 
  610:           ],
  611:     
  612:     ?line run(Config, Ts),
  613:     ok.
  614: 
  615: cursor(doc) ->
  616:     "cursor/2";
  617: cursor(suite) -> [];
  618: cursor(Config) when is_list(Config) ->
  619:     ScratchDir = filename:join([?privdir, "scratch","."]),
  620:     Ts = [<<"{'EXIT',{badarg,_}} = 
  621:                    (catch qlc:cursor(fun() -> not_a_cursor end)),
  622:              H0 = qlc:q([X || X <- throw({throw,t})]),
  623:              {throw,t} = (catch {any_term,qlc:cursor(H0)}),
  624:              H = qlc:q([X || X <- [1,2]]),
  625:              {'EXIT',{badarg,_}} = 
  626:                        (catch qlc:cursor(H,{spawn_options, [a|b]})),
  627:              {'EXIT',{badarg,_}} = 
  628:                        (catch qlc:cursor(H,{bad_option,true}))">>,
  629: 
  630:           <<"{'EXIT',{badarg,_}} = (catch qlc:delete_cursor(not_a_cursor))">>,
  631: 
  632:           [<<"Dir = \"">>,ScratchDir,<<"\",
  633:               qlc_SUITE:prep_scratchdir(Dir), % kludge
  634:               E = ets:new(foo, []),
  635:               [true || I <- lists:seq(1, 50000), not ets:insert(E, {I, I})],
  636:               H = qlc:q([{X,Y} || begin put('$qlc_tmpdir', true), true end,
  637:                                   Y <- [1,2], 
  638:                                   X <- qlc:sort(ets:table(E),{tmpdir,Dir}),
  639:                                   qlc_SUITE:truncate_tmpfile(Dir, 0)]),
  640:               C = qlc:cursor(H),
  641:               R = qlc:next_answers(C, all_remaining),
  642:               qlc:delete_cursor(C),
  643:               erase('$qlc_tmpdir'),
  644:               ets:delete(E),
  645:               {error,_,{bad_object,_}} = R">>],
  646: 
  647:           <<"H1 = qlc:q([X || X <- [1,2]]),
  648:              C1 = qlc:cursor(H1),
  649:              [1,2] = qlc:next_answers(C1, all_remaining),
  650:              [] = qlc:next_answers(C1),
  651:              [] = qlc:next_answers(C1),
  652:              ok = qlc:delete_cursor(C1),
  653: 
  654:              H2 = qlc:append([1,2],[3,4]),
  655:              C2 = qlc:cursor(H2),
  656:              [1,2,3,4] = qlc:next_answers(C2, all_remaining),
  657:              ok = qlc:delete_cursor(C2),
  658: 
  659:              H3 = qlc:sort([2,1]),
  660:              C3 = qlc:cursor(H3),
  661:              [1,2] = qlc:next_answers(C3, all_remaining),
  662:              ok = qlc:delete_cursor(C3),
  663:              
  664:              E = ets:new(foo, []),
  665:              ets:insert(E, [{1},{2}]),
  666:              H4 = ets:table(E),
  667:              C4 = qlc:cursor(H4),
  668:              [{1},{2}] = lists:sort(qlc:next_answers(C4, all_remaining)),
  669:              ok = qlc:delete_cursor(C4),
  670:              true = ets:delete(E)">>,
  671: 
  672:           <<"H = qlc:q([{X,Y} || X <- [1,2], Y <- [a,b]]),
  673:              C = qlc:cursor(H, []),
  674:              [{1,a},{1,b}] = qlc:next_answers(C, 2),
  675:              [{2,a}] = qlc:next_answers(C, 1),
  676:              [{2,b}] = qlc:next_answers(C, all_remaining),
  677:              {'EXIT',{badarg,_}} = (catch qlc:next_answers(C, -1)),
  678:              P = self(),
  679:              Pid1 = spawn_link(fun() -> 
  680:                           {'EXIT',{not_cursor_owner,_}} = 
  681:                                 (catch qlc:delete_cursor(C)),
  682:                           P ! {self(), done} end),
  683:              Pid2 = spawn_link(fun() -> 
  684:                           {'EXIT',{not_cursor_owner,_}} = 
  685:                                 (catch qlc:next_answers(C)),
  686:                           P ! {self(), done} end),
  687:              receive {Pid1, done} -> ok end,
  688:              receive {Pid2, done} -> ok end,
  689:              ok = qlc:delete_cursor(C),
  690:              {'EXIT',{badarg,_}} = (catch qlc:next_answers(not_a_cursor)),
  691:              ok = qlc:delete_cursor(C)">>,
  692: 
  693:           <<"Q = qlc:q([X || X <- [1,2,1,2,1]]),
  694:              C1 = qlc:cursor(Q, [{unique_all,true}]),
  695:              [1,2] = qlc:next_answers(C1, all_remaining),
  696:              ok = qlc:delete_cursor(C1),
  697:              C2 = qlc:cursor(Q, [{unique_all,true}]),
  698:              [1,2] = qlc:next_answers(C2, all_remaining),
  699:              ok = qlc:delete_cursor(C2)">>,
  700: 
  701:           <<"Q = qlc:q([X || X <- [1,2,1,2,1]]),
  702:              C1 = qlc:cursor(Q, [{unique_all,true},{spawn_options, []}]),
  703:              [1,2] = qlc:next_answers(C1, all_remaining),
  704:              ok = qlc:delete_cursor(C1),
  705:              C2 = qlc:cursor(Q, [{unique_all,true},{spawn_options, default}]),
  706:              [1,2] = qlc:next_answers(C2, all_remaining),
  707:              ok = qlc:delete_cursor(C2)">>,
  708: 
  709:           <<"Q = qlc:q([X || X <- [1,2,1,2,1]]),
  710:              C1 = qlc:cursor(Q, [{unique_all,false},{spawn_options, []}]),
  711:              [1,2,1,2,1] = qlc:next_answers(C1, all_remaining),
  712:              ok = qlc:delete_cursor(C1),
  713:              C2 = qlc:cursor(Q, [{unique_all,false},{spawn_options, []}]),
  714:              [1,2,1,2,1] = qlc:next_answers(C2, all_remaining),
  715:              ok = qlc:delete_cursor(C2)">>,
  716: 
  717:           <<"Q = qlc:q([X || X <- [1,2,1,2,1]]),
  718:              C1 = qlc:cursor(Q, [{unique_all,false}]),
  719:              [1,2,1,2,1] = qlc:next_answers(C1, all_remaining),
  720:              ok = qlc:delete_cursor(C1),
  721:              C2 = qlc:cursor(Q, [{unique_all,false}]),
  722:              [1,2,1,2,1] = qlc:next_answers(C2, all_remaining),
  723:              ok = qlc:delete_cursor(C2)">>
  724: 
  725:          ],
  726:     ?line run(Config, Ts),
  727:     ok.
  728: 
  729: fold(doc) ->
  730:     "fold/4";
  731: fold(suite) -> [];
  732: fold(Config) when is_list(Config) ->
  733:     ScratchDir = filename:join([?privdir, "scratch","."]),
  734:     Ts = [<<"Q = qlc:q([X || X <- [1,2,1,2,1]]),
  735:              F = fun(Obj, A) -> A++[Obj] end,
  736:              {'EXIT',{badarg,_}} = (catch qlc:fold(F, [], Q, {bad,arg})),
  737:              {'EXIT',{badarg,_}} = (catch qlc:fold(F, [], badarg)),
  738:              {'EXIT',{badarg,_}} = 
  739:                (catch qlc:fold(F, [], {spawn_options, [a|b]})),
  740:              H = qlc:q([X || X <- throw({throw,t})]),
  741:              {throw,t} = (catch {any_term,qlc:fold(F, [], H)}),
  742:              [1,2] = qlc:fold(F, [], Q, {unique_all,true}),
  743:              {'EXIT',{badarg,_}} = 
  744:                (catch qlc:fold(F, [], Q, [{unique_all,bad}])),
  745:              [1,2,1,2,1] = 
  746:                   qlc:fold(F, [], Q, [{unique_all,false}])">>,
  747: 
  748:           [<<"Dir = \"">>,ScratchDir,<<"\",
  749:               qlc_SUITE:prep_scratchdir(Dir),
  750: 
  751:               E = ets:new(foo, []),
  752:               [true || I <- lists:seq(1, 50000), not ets:insert(E, {I, I})],
  753:               H = qlc:q([{X,Y} || Y <- [1,2], 
  754:                                   X <- qlc:sort(ets:table(E),{tmpdir,Dir}),
  755:                                   qlc_SUITE:truncate_tmpfile(Dir, 0)]),
  756:               F = fun(Obj, A) -> A++[Obj] end,
  757:               R = qlc:fold(F, [], H),
  758:               ets:delete(E),
  759:               {error,_,{bad_object,_}} = R">>],
  760: 
  761:           <<"E = ets:new(test, []),
  762:              H = qlc:q([{X,Y} || X <- qlc_SUITE:bad_table_throw(E), 
  763:                                  Y <- ets:table(E)]),
  764:              F = fun(Obj, A) -> A++[Obj] end,
  765:              R1 = (catch {any_term,qlc:fold(F, [], H, {unique_all,false})}),
  766:              R2 = (catch {any_term,qlc:fold(F, [], H, {unique_all,true})}),
  767:              ets:delete(E),
  768:              true = {throw,bad_pre_fun} == R1,
  769:              true = {throw,bad_pre_fun} == R2">>,
  770: 
  771:           <<"E = ets:new(test, []),
  772:              H = qlc:q([{X,Y} || X <- qlc_SUITE:bad_table_exit(E), 
  773:                                  Y <- ets:table(E)]),
  774:              F = fun(Obj, A) -> A++[Obj] end,
  775:              R1 = (catch qlc:fold(F, [], H, {unique_all,false})),
  776:              R2 = (catch qlc:fold(F, [], H, {unique_all,true})),
  777:              ets:delete(E),
  778:              {'EXIT',{bad_pre_fun,_}} = R1,
  779:              {'EXIT',{bad_pre_fun,_}} = R2">>,
  780: 
  781:           <<"F = fun(Obj, A) -> A++[Obj] end,
  782:              Q = qlc:q([X || X <- [1,2,1,2,1], throw({throw,wrong})]),
  783:              {throw,wrong} = 
  784:                  (catch {any_term,qlc:fold(F, [], Q, {unique_all,true})}),
  785:              {throw,wrong} = 
  786:                  (catch {any_term,qlc:fold(F, [], Q)})">>,
  787: 
  788:           <<"F = fun(Obj, A) -> A++[Obj] end,
  789:              Q = qlc:q([X || X <- [4,3,2,1,0,-1], begin 3/X > 0 end]),
  790:              {'EXIT',{badarith,_}} = 
  791:                        (catch qlc:fold(F, [], Q, {unique_all,true})),
  792:              {'EXIT',{badarith,_}} = 
  793:                  (catch qlc:fold(F, [], Q, [{unique_all,false}]))
  794:             ">>,
  795: 
  796:           <<"F = fun(Obj, A) -> A++[Obj] end,
  797:              [1,2] = qlc:fold(F, [], qlc:q([X || X <- [1,2]])),
  798:              [1,2,3,4] = qlc:fold(F, [], qlc:append([1,2],[3,4])),
  799:              [1,2] = qlc:fold(F, [], qlc:sort([2,1])),
  800:              E = ets:new(foo, []),
  801:              ets:insert(E, [{1},{2}]),
  802:              [{1},{2}] = lists:sort(qlc:fold(F, [], ets:table(E))),
  803:              true = ets:delete(E)">>,
  804: 
  805:           <<"F = fun(_Obj, _A) -> throw({throw,fatal}) end,
  806:              Q = qlc:q([X || X <- [4,3,2]]),
  807:              {throw,fatal} = 
  808:               (catch {any_term,qlc:fold(F, [], Q, {unique_all,true})}),
  809:              {throw,fatal} = 
  810:                (catch {any_term,qlc:fold(F, [], Q, [{unique_all,false}])})">>,
  811: 
  812:           <<"G = fun(_Obj, _A, D) -> 17/D  end,
  813:              F = fun(Obj, A) -> G(Obj, A, 0) end,
  814:              Q = qlc:q([X || X <- [4,3,2]]),
  815:              {'EXIT',{badarith,_}} = 
  816:                     (catch qlc:fold(F, [], Q, {unique_all,true})),
  817:              {'EXIT',{badarith,_}} = 
  818:                (catch qlc:fold(F, [], Q, [{unique_all,false}]))
  819:             ">>
  820:          ],
  821:     ?line run(Config, Ts),
  822:     ok.
  823: 
  824: eval_unique(doc) ->
  825:     "Test the unique_all option of eval.";
  826: eval_unique(suite) -> [];
  827: eval_unique(Config) when is_list(Config) ->
  828:     Ts = [<<"QLC1 = qlc:q([X || X <- qlc:append([[1,1,2], [1,2,3,2,3]])]),
  829:              [1,2,3] = qlc:eval(QLC1, {unique_all,true}),
  830:              QLC2 = qlc:q([X || X <- [1,2,1,2,1,2,1]]),
  831:              [1,2] = qlc:e(QLC2, {unique_all,true})">>,
  832: 
  833:           <<"E = ets:new(test, []),
  834:              true = ets:insert(E, [{1,a},{2,b},{3,c}]),
  835:              H = qlc:q([X || X <- qlc:append([ets:table(E), ets:table(E)])]),
  836:              R1 = qlc:e(H, {unique_all,false}),
  837:              R2 = qlc:e(H, {unique_all,true}),
  838:              ets:delete(E),
  839:              true = lists:sort(R1) == [{1,a},{1,a},{2,b},{2,b},{3,c},{3,c}],
  840:              true = lists:sort(R2) == [{1,a},{2,b},{3,c}]
  841:             ">>,
  842: 
  843:           <<"Q1 = qlc:q([{X,make_ref()} || X <- [1,2,1,2]]),
  844:              [_,_] = qlc:e(Q1, {unique_all,true}),
  845:              [_,_,_,_] = qlc:e(Q1, {unique_all,false}),
  846:              [_,_] = qlc:e(Q1, [{unique_all,true}]),
  847:              Q2 = qlc:q([{X,make_ref()} || X <- qlc:append([[1,2,1,2]])]),
  848:              [_,_] = qlc:e(Q2, {unique_all,true}),
  849:              [_,_,_,_] = qlc:e(Q2, {unique_all,false}),
  850:              [_,_] = qlc:e(Q2, [{unique_all,true}])
  851:             ">>,
  852: 
  853:           <<"Q = qlc:q([{X,make_ref()} || X <- qlc:sort([1,2,1,2])]),
  854:              [_, _] = qlc:e(Q, {unique_all,true}),
  855:              Q1 = qlc:q([X || X <- [1,2,1,2]]),
  856:              Q2 = qlc:q([{X,make_ref()} || X <- qlc:sort(Q1)]),
  857:              [_, _] = qlc:e(Q2, {unique_all,true})
  858:             ">>,
  859: 
  860:           <<"E = ets:new(test, []),
  861:              true = ets:insert(E, [{1,a},{2,b},{3,c}]),
  862:              H = qlc:q([X || X <- qlc:append([[1,2,1,2]])]),
  863:              [1,2,1,2] = qlc:e(H, {unique_all,false}),
  864:              [1,2] = qlc:e(H, {unique_all,true}),
  865:              ets:delete(E)">>,
  866: 
  867:           <<"E = ets:new(foo, [duplicate_bag]),
  868:              true = ets:insert(E, [{1,a},{1,a},{2,b},{3,c},{4,c},{4,d}]),
  869:              Q1 = qlc:q([{X,make_ref()} || {_, X} <- ets:table(E)]),
  870:              true = length(qlc:eval(Q1, {unique_all, true})) =:= 5,
  871:              Q2 = qlc:q([X || {_, X} <- ets:table(E)]),
  872:              true = length(qlc:eval(Q2, {unique_all, true})) =:= 4,
  873:              Q3 = qlc:q([element(2, X) || X <- ets:table(E)]),
  874:              true = length(qlc:eval(Q3, {unique_all, true})) =:= 4,
  875:              Q4 = qlc:q([1 || _X <- ets:table(E)]),
  876:              true = length(qlc:eval(Q4, {unique_all, true})) =:= 1,
  877:              true = ets:delete(E)
  878:             ">>,
  879: 
  880:           <<"Q1 = qlc:q([X || X <- qlc:append([[1], [2,1]])]),
  881:              Q2 = qlc:q([X || X <- qlc:append([[2,1], [2]])]),
  882:              Q3 = qlc:q([{X,Y} || X <- Q1, Y <- Q2]),
  883:              [{1,2},{1,1},{2,2},{2,1}] = qlc:e(Q3, {unique_all,true}),
  884:              Q4 = qlc:q([{X,Y,make_ref()} || X <- Q1, Y <- Q2]),
  885:              [{1,2,_},{1,1,_},{2,2,_},{2,1,_}] = qlc:e(Q4, {unique_all,true})
  886:             ">>,
  887: 
  888:           <<"Q1 = qlc:q([X || X <- [1,2,1]]),
  889:              Q2 = qlc:q([X || X <- [2,1,2]]),
  890:              Q3 = qlc:q([{X,Y} || X <- Q1, Y <- Q2]),
  891:              [{1,2},{1,1},{2,2},{2,1}] = qlc:e(Q3,{unique_all,true}),
  892:              Q4 = qlc:q([{X,Y,make_ref()} || X <- Q1, Y <- Q2]),
  893:              [{1,2,_},{1,1,_},{2,2,_},{2,1,_}] = qlc:e(Q4, {unique_all,true})
  894:             ">>,
  895: 
  896:           <<"Q1 = qlc:q([X || {X,_} <- [{1,a},{1,b}]]),
  897:              [1] = qlc:e(Q1, {unique_all, true}),
  898:              Q2 = qlc:q([a || _ <- [{1,a},{1,b}]]),
  899:              [a] = qlc:e(Q2, {unique_all, true})
  900:             ">>,
  901: 
  902:           <<"Q = qlc:q([SQV || SQV <- qlc:q([X || X <- [1,2,1]],unique)],
  903:                        unique),
  904:              {call,_,_,[{lc,_,{var,_,'X'},[{generate,_,{var,_,'X'},_}]},_]} =
  905:                  qlc:info(Q, [{format,abstract_code},unique_all]),
  906:              [1,2] = qlc:e(Q)">>,
  907: 
  908:           <<"Q = qlc:q([X || X <- [1,2,1]]),
  909:              {call,_,_,[{lc,_,{var,_,'X'},[{generate,_,{var,_,'X'},_}]},_]} =
  910:                  qlc:info(Q, [{format,abstract_code},unique_all]),
  911:              [1,2] = qlc:e(Q, unique_all)">>,
  912: 
  913:           <<"Q1 = qlc:sort([{1},{2},{3},{1}], [{unique,true}]),
  914:              Q = qlc:sort(Q1,[{unique,true}]),
  915:              {sort,{sort,{list,_},[{unique,true}]},[]} = i(Q)">>
  916: 
  917:          ],
  918:     ?line run(Config, Ts),
  919:     ok.
  920: 
  921: eval_cache(doc) ->
  922:     "Test the cache_all and unique_all options of eval.";
  923: eval_cache(suite) -> [];
  924: eval_cache(Config) when is_list(Config) ->
  925:     Ts = [
  926:        <<"E = ets:new(apa, [ordered_set]),
  927:           ets:insert(E, [{1},{2}]),
  928:           H = qlc:q([X || Y <- [3,4], 
  929:                           ets:insert(E, {Y}),
  930:                           X <- ets:table(E)]), % already unique, no cache...
  931:           {qlc, _,
  932:            [{generate, _, {qlc, _,
  933:                            [{generate, _, {list, [3,4]}}],
  934:                            [{unique,true}]}}, 
  935:             _,
  936:             {generate, _, {table,_}}],
  937:            [{unique,true}]} = i(H, [cache_all, unique_all]),
  938:           [{1},{2},{3},{4}] = qlc:e(H,  [cache_all, unique_all]),
  939:           ets:delete(E)">>,
  940: 
  941:        <<"E = ets:new(apa, [ordered_set]),
  942:           ets:insert(E, [{1},{2}]),
  943:           H = qlc:q([X || Y <- [3,4], 
  944:                           ets:insert(E, {Y}),
  945:                           X <- ets:table(E)]), % no cache...
  946:           {qlc, _,
  947:            [{generate, _,{list, [3,4]}}, 
  948:             _,
  949:             {generate, _, {table,_}}],
  950:            []} = i(H, cache_all),
  951:           [{1},{2},{3},{1},{2},{3},{4}] = qlc:e(H,  [cache_all]),
  952:           ets:delete(E)">>,
  953: 
  954:        <<"E = ets:new(apa, [ordered_set]),
  955:           ets:insert(E, [{1},{2}]),
  956:           H = qlc:q([X || Y <- [3,4], 
  957:                           ets:insert(E, {Y}),
  958:                           X <- qlc:q([X || X <- ets:table(E)], cache)]),
  959:           {qlc, _,
  960:            [{generate, _, {list, [3,4]}}, 
  961:             _,
  962:             {generate, _, {qlc, _,
  963:                            [{generate, _, {table,_}}],
  964:                            [{cache,ets}]}}],
  965:            []} = i(H, cache_all),
  966:           [{1},{2},{3},{1},{2},{3}] = qlc:e(H,  [cache_all]),
  967:           ets:delete(E)">>,
  968: 
  969:        <<"%% {cache_all,no} does not override {cache,true}.
  970:           E = ets:new(apa, [ordered_set]),
  971:           ets:insert(E, [{1},{2}]),
  972:           H = qlc:q([X || Y <- [3,4], 
  973:                           ets:insert(E, {Y}),
  974:                           X <- qlc:q([X || X <- ets:table(E)], cache)]),
  975:           {qlc, _,
  976:            [{generate, _, {list, [3,4]}}, 
  977:             _,
  978:             {generate, _, {qlc, _,
  979:                            [{generate, _, {table,_}}],
  980:                            [{cache,ets}]}}],
  981:            []} = i(H, {cache_all,no}),
  982:           [{1},{2},{3},{1},{2},{3}] = qlc:e(H,  [cache_all]),
  983:           ets:delete(E)">>,
  984: 
  985:        <<"E = ets:new(apa, [ordered_set]),
  986:           ets:insert(E, [{1},{2}]),
  987:           H = qlc:q([X || Y <- [3,4], 
  988:                           ets:insert(E, {Y}),
  989:                           X <- ets:table(E)]),
  990:           {qlc, _,
  991:            [{generate, _, {qlc, _, [{generate, _,{list, [3,4]}}],
  992:                            [{unique,true}]}}, 
  993:             _,
  994:             {generate, _,{table,_}}],
  995:            [{unique,true}]} = i(H, unique_all),
  996:           [{1},{2},{3},{4}] = qlc:e(H, [unique_all]),
  997:           ets:delete(E)">>,
  998: 
  999:           %% cache_all is ignored 
 1000:        <<"E = ets:new(apa, [ordered_set]),
 1001:           ets:insert(E, [{1},{2},{0}]),
 1002:           H = qlc:q([X || X <- qlc:sort(ets:table(E))]),
 1003:           {sort,_Table,[]} = i(H, cache_all),
 1004:           [{0},{1},{2}] = qlc:e(H, cache_all),
 1005:           ets:delete(E)">>,
 1006: 
 1007:        <<"F = fun(Obj, A) -> A++[Obj] end,
 1008:           E = ets:new(apa, [duplicate_bag]),
 1009:           true = ets:insert(E, [{1,a},{2,b},{1,a}]),
 1010:           Q = qlc:q([X || X <- ets:table(E)], cache),
 1011:           {table, _} = i(Q, []),
 1012:           R = qlc:fold(F, [], Q, []),
 1013:           ets:delete(E),
 1014:           true = [{1,a},{1,a},{2,b}] == lists:sort(R)">>,
 1015: 
 1016:        <<"E = ets:new(apa, [ordered_set]),
 1017:           ets:insert(E, [{1},{2},{0}]),
 1018:           H = qlc:q([X || X <- ets:table(E)], cache),
 1019:           {table, _} = i(H, cache_all),
 1020:           [{0},{1},{2}]= qlc:e(H, cache_all),
 1021:           ets:delete(E)">>,
 1022: 
 1023:        <<"E = ets:new(foo, []),
 1024:           true = ets:insert(E, [{1}, {2}]),
 1025:           Q1 = qlc:q([{X} || X <- ets:table(E)]),
 1026:           Q2 = qlc:q([{X,Y} || {X} <- Q1, {Y} <- Q1]),
 1027:           {qlc, _, [{generate, _, {table, _}},
 1028:                     {generate, _, {qlc, _, [{generate, _, {table, _}}],
 1029:                                    [{cache,ets}]}}],
 1030:            []} = i(Q2, cache_all),
 1031:           [{{1},{1}},{{1},{2}},{{2},{1}},{{2},{2}}] = 
 1032:               lists:sort(qlc:e(Q2, cache_all)),
 1033:           ets:delete(E)">>,
 1034: 
 1035:        <<"L1 = [1,2,3], 
 1036:           L2 = [4,5,6],
 1037:           Q1 = qlc:append(L1, L2),
 1038:           Q2 = qlc:q([{X} || X <- Q1]),
 1039:           {qlc, _,[{generate, _,{append, [{list, L1}, {list, L2}]}}], []} = 
 1040:               i(Q2, [cache_all]),
 1041:           [{1},{2},{3},{4},{5},{6}] = qlc:e(Q2, [cache_all])">>,
 1042: 
 1043:        <<"H = qlc:sort(qlc:q([1 || _ <- [a,b]])),
 1044:           {sort, {qlc, _, [{generate, _, {qlc, _, [{generate, _, 
 1045:                                                     {list, [a,b]}}],
 1046:                                           [{unique,true}]}}],
 1047:                   [{unique,true}]},
 1048:                  []} = i(H, unique_all),
 1049:           [1] = qlc:e(H, unique_all)">>
 1050: 
 1051:          ],
 1052:     ?line run(Config, Ts),
 1053:     ok.
 1054: 
 1055: append(doc) ->
 1056:     "Test the append function.";
 1057: append(suite) -> [];
 1058: append(Config) when is_list(Config) ->
 1059:     Ts = [<<"C = qlc:cursor(qlc:q([X || X <- [0,1,2,3], begin 10/X > 0.0 end])),
 1060:              R = (catch qlc:next_answers(C)),
 1061:              {'EXIT',{badarith,_}} = R">>,
 1062: 
 1063:           <<"C = qlc:cursor(qlc:q([X || X <- [0 | fun() -> exit(bad) end]])),
 1064:              R = (catch qlc:next_answers(C)),
 1065:              {'EXIT',bad} = R">>,
 1066: 
 1067:           <<"{'EXIT',{badarg,_}} = (catch qlc:append([a], a)),
 1068:              {'EXIT',{badarg,_}} = (catch qlc:append([[a],a]))">>,
 1069: 
 1070:           <<"C = qlc:cursor(qlc:q([X || X <- [0,1,2,3], 
 1071:                                      begin throw({throw,wrong}), true end])),
 1072:              {throw,wrong} = (catch {any_term,qlc:next_answers(C)})">>,
 1073: 
 1074:           <<"QLC = qlc:q([X || X <- [0,1,2,3], 
 1075:                                begin throw({throw,wrong}), true end]),
 1076:              {throw,wrong} = (catch {any_term,qlc:eval(QLC)}),
 1077:              {throw,wrong} = 
 1078:                  (catch {any_term,qlc:e(QLC, {unique_all,true})})">>,
 1079: 
 1080:           <<"H1 = qlc:q([X || X <- [1,2,3]]),
 1081:              H2 = qlc:q([X || X <- [4,5,6]]),
 1082:              R = qlc:e(qlc:q([X || X <- qlc:append([H1, H2])])),
 1083:              true = R == [1,2,3,4,5,6]">>,
 1084: 
 1085:           <<"H1 = [1,2,3],
 1086:              H2 = qlc:q([X || X <- [4,5,6]]),
 1087:              R = qlc:e(qlc:q([X || X <- qlc:append(H1, H2)])),
 1088:              true = R == [1,2,3,4,5,6]">>,
 1089: 
 1090:           <<"H1 = qlc:q([X || X <- [1,2,3]]),
 1091:              H2 = qlc:q([X || X <- [4,5,6]]),
 1092:              R = qlc:e(qlc:q([X || X <- qlc:append(qlc:e(H1), H2)])),
 1093:              true = R == [1,2,3,4,5,6]">>,
 1094: 
 1095:           <<"H1 = qlc:q([X || X <- [1,2,3]]),
 1096:              H2 = [4,5,6],
 1097:              R = qlc:e(qlc:q([X || X <- qlc:append(H1, H2)])),
 1098:              true = R == [1,2,3,4,5,6]">>,
 1099: 
 1100:           <<"H1 = qlc:q([X || X <- [1,2,3]]),
 1101:              H2 = qlc:q([X || X <- [4,5,6]]),
 1102:              R = qlc:e(qlc:q([X || X <- qlc:append([H1, H2, H1]), X < 5])),
 1103:              true = R == [1,2,3,4,1,2,3]">>,
 1104: 
 1105:           <<"R = qlc:e(qlc:q([X || X <- qlc:append([lista(), anrop()])])),
 1106:              true = R == [a,b,1,2],
 1107:              ok.
 1108: 
 1109:              lista() ->
 1110:                  [a,b].
 1111: 
 1112:              anrop() ->
 1113:                   qlc:q([X || X <- [1,2]]).
 1114:              foo() -> bar">>,
 1115: 
 1116:           %% Used to work up to R11B.
 1117:           % <<"apa = qlc:e(qlc:q([X || X <- qlc:append([[1,2,3], ugly()])])),
 1118:           %   ok.
 1119:           %
 1120:           %   ugly() ->
 1121:           %       [a | apa].
 1122:           %   foo() -> bar">>,
 1123: 
 1124:           
 1125:           %% Maybe this one should fail.
 1126:           <<"[a|b] = qlc:e(qlc:q([X || X <- qlc:append([[a|b]])])),
 1127:              ok">>,
 1128: 
 1129:           <<"17 = qlc:e(qlc:q([X || X <- qlc:append([[1,2,3],ugly2()])])),
 1130:              ok.
 1131: 
 1132:              ugly2() ->
 1133:                  [a | fun() -> 17 end].
 1134:              foo() -> bar">>,
 1135: 
 1136:           <<"E = ets:new(test, []),
 1137:              true = ets:insert(E, [{1,a},{2,b},{3,c}]),
 1138:              H = qlc:q([X || X <- qlc:append([ets:table(E), apa])]),
 1139:              {'EXIT',{badarg,_}} = (catch qlc:e(H)),
 1140:              false = ets:info(E, safe_fixed),
 1141:              {'EXIT',{badarg,_}} = (catch qlc:e(H)),
 1142:              false = ets:info(E, safe_fixed),
 1143:              {'EXIT',{badarg,_}} = (catch qlc:cursor(H)),
 1144:              false = ets:info(E, safe_fixed),
 1145:              F = fun(Obj, A) -> A++[Obj] end,
 1146:              {'EXIT',{badarg,_}} = (catch qlc:fold(F, [], H)),
 1147:              false = ets:info(E, safe_fixed),
 1148:              ets:delete(E)">>,
 1149: 
 1150:           <<"H1 = qlc:q([X || X <- [1,2,3]]),
 1151:              H2 = qlc:q([X || X <- [a,b,c]]),
 1152:              R = qlc:e(qlc:q([X || X <- qlc:append(H1,qlc:append(H1,H2))])),
 1153:              true = R == [1,2,3,1,2,3,a,b,c]">>,
 1154: 
 1155:           <<"H = qlc:q([X || X <- qlc:append([],qlc:append([[], []]))]),
 1156:              [] = qlc:e(H)">>,
 1157: 
 1158:           <<"Q1 = qlc:q([X || X <- [3,4,4]]),
 1159:              Q2 = qlc:q([X || X <- qlc:sort(qlc:append([[1,2], Q1]))]),
 1160:              [1,2,3,4,4] = qlc:e(Q2),
 1161:              [1,2,3,4] = qlc:e(Q2, {unique_all,true})">>,
 1162: 
 1163:           <<"[] = qlc:e(qlc:q([X || X <- qlc:append([])]))">>,
 1164: 
 1165:           <<"Q1 = qlc:q([X || X <- [a,b]]),
 1166:              Q2 = qlc:q([X || X <- [1,2]]),
 1167:              Q3 = qlc:append([Q1, Q2, qlc:sort([2,1])]),
 1168:              Q = qlc:q([X || X <- Q3]),
 1169:              {append, [{list, [a,b]}, 
 1170:                        {list, [1,2]}, 
 1171:                        {sort,{list, [2,1]},[]}]} = i(Q),
 1172:              [a,b,1,2,1,2] = qlc:e(Q)">>
 1173: 
 1174:           ],
 1175:     ?line run(Config, Ts),
 1176:     ok.
 1177: 
 1178: evaluator(doc) ->
 1179:     "Simple call from evaluator.";
 1180: evaluator(suite) -> [];
 1181: evaluator(Config) when is_list(Config) ->
 1182:     ?line true = is_alive(),
 1183:     evaluator_2(Config, []),
 1184:     ?line {ok, Node} = start_node(qlc_SUITE_evaluator),
 1185:     ?line ok = rpc:call(Node, ?MODULE, evaluator_2, [Config, [compiler]]),
 1186:     ?line ?t:stop_node(Node),
 1187:     ok.
 1188: 
 1189: evaluator_2(Config, Apps) ->
 1190:     ?line lists:foreach(fun(App) -> true = code:del_path(App) end, Apps),
 1191:     FileName = filename:join(?privdir, "eval"),
 1192:     ?line ok = file:write_file(FileName, 
 1193:                          <<"H = qlc:q([X || X <- L]),
 1194:                             [1,2,3] = qlc:e(H).">>),
 1195:     ?line Bs = erl_eval:add_binding('L', [1,2,3], erl_eval:new_bindings()),
 1196:     ?line ok = file:eval(FileName, Bs),
 1197: 
 1198:     %% The error message is "handled" a bit too much... 
 1199:     %% (no trace of erl_lint left)
 1200:     ?line ok = file:write_file(FileName, 
 1201:              <<"H = qlc:q([X || X <- L]), qlc:e(H).">>),
 1202:     ?line {error,_} = file:eval(FileName),
 1203: 
 1204:     %% Ugly error message; badarg is caught by file.erl.
 1205:     ?line ok = file:write_file(FileName, 
 1206:              <<"H = qlc:q([Z || {X,Y} <- [{a,2}], Z <- [Y]]), qlc:e(H).">>),
 1207:     ?line {error,_} = file:eval(FileName),
 1208: 
 1209:     _ = file:delete(FileName),
 1210:     ok.
 1211: 
 1212: start_node(Name) ->
 1213:     ?line PA = filename:dirname(code:which(?MODULE)),
 1214:     ?t:start_node(Name, slave, [{args, "-pa " ++ PA}]).
 1215: 
 1216: string_to_handle(doc) ->
 1217:     "string_to_handle/1,2.";
 1218: string_to_handle(suite) -> [];
 1219: string_to_handle(Config) when is_list(Config) ->
 1220:     ?line {'EXIT',{badarg,_}} = (catch qlc:string_to_handle(14)),
 1221:     ?line {'EXIT',{badarg,_}} = 
 1222:         (catch qlc:string_to_handle("[X || X <- [a].", unique_all)),
 1223:     ?line R1 = {error, _, {_,erl_scan,_}} = qlc:string_to_handle("'"),
 1224:     ?line "1: unterminated " ++ _ = lists:flatten(qlc:format_error(R1)),
 1225:     ?line {error, _, {_,erl_parse,_}} = qlc:string_to_handle("foo"),
 1226:     ?line {'EXIT',{badarg,_}} = (catch qlc:string_to_handle("foo, bar.")),
 1227:     ?line R3 = {error, _, {_,?QLC,not_a_query_list_comprehension}} = 
 1228:         qlc:string_to_handle("bad."),
 1229:     ?line "1: argument is not" ++ _ = lists:flatten(qlc:format_error(R3)),
 1230:     ?line R4 = {error, _, {_,?QLC,{used_generator_variable,'Y'}}} = 
 1231:         qlc:string_to_handle("[X || begin Y = [1,2], true end, X <- Y]."),
 1232:     ?line "1: generated variable 'Y'" ++ _ = 
 1233:         lists:flatten(qlc:format_error(R4)),
 1234:     ?line {error, _, {_,erl_lint,_}} = qlc:string_to_handle("[X || X <- A]."),
 1235:     ?line H1 = qlc:string_to_handle("[X || X <- [1,2]]."),
 1236:     ?line [1,2] = qlc:e(H1),
 1237:     ?line H2 = qlc:string_to_handle("[X || X <- qlc:append([a,b],"
 1238:                                     "qlc:e(qlc:q([X || X <- [c,d,e]])))]."),
 1239:     ?line [a,b,c,d,e] = qlc:e(H2),
 1240:     %% The generated fun has many arguments (erl_eval has a maximum of 20).
 1241:     ?line H3 = qlc:string_to_handle(
 1242:            "[{A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W} ||"
 1243:            " {A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W} <- []]."),
 1244:     ?line [] = qlc:e(H3),
 1245:     ?line Bs1 = erl_eval:add_binding('L', [1,2,3], erl_eval:new_bindings()),
 1246:     ?line H4 = qlc:string_to_handle("[X || X <- L].", [], Bs1),
 1247:     ?line [1,2,3] = qlc:e(H4),
 1248:     ?line H5 = qlc:string_to_handle("[X || X <- [1,2,1,2]].", [unique, cache]),
 1249:     ?line [1,2] = qlc:e(H5),
 1250: 
 1251:     ?line Ets = ets:new(test, []),
 1252:     ?line true = ets:insert(Ets, [{1}]),
 1253:     ?line Bs2 = erl_eval:add_binding('E', Ets, erl_eval:new_bindings()),
 1254:     ?line Q = "[X || {X} <- ets:table(E)].",
 1255:     ?line [1] = qlc:e(qlc:string_to_handle(Q, [], Bs2)),
 1256:     ?line [1] = qlc:e(qlc:string_to_handle(Q, {max_lookup,1000}, Bs2)),
 1257:     ?line [1] = qlc:e(qlc:string_to_handle(Q, {max_lookup,infinity}, Bs2)),
 1258:     ?line {'EXIT',{badarg,_}} = 
 1259:         (catch qlc:string_to_handle(Q, {max_lookup,-1}, Bs2)),
 1260:     ?line {'EXIT', {no_lookup_to_carry_out, _}} = 
 1261:         (catch qlc:e(qlc:string_to_handle(Q, {lookup,true}, Bs2))),
 1262:     ?line ets:delete(Ets),
 1263:     ok.
 1264: 
 1265: table(doc) ->
 1266:     "table";
 1267: table(suite) -> [];
 1268: table(Config) when is_list(Config) ->
 1269:     dets:start(),
 1270:     Ts = [
 1271:        <<"E = ets:new(test, []),
 1272:           {'EXIT',{badarg,_}} = 
 1273:                (catch qlc:e(qlc:q([X || X <- ets:table(E, [badarg])]))),
 1274:           [] = qlc:e(qlc:q([X || X <- ets:table(E)])),
 1275:           ets:delete(E)">>,
 1276: 
 1277:        <<"{'EXIT',{badarg,_}} = (catch qlc:table(not_a_fun, []))">>,
 1278: 
 1279:        <<"E = ets:new(test, []),
 1280:           true = ets:insert(E, [{1,a},{2,b},{3,c}]),
 1281:           H = qlc:q([{X,Y} || X <- ets:table(E), Y <- ets:table(E)]),
 1282:           R = qlc:e(H),
 1283:           ets:delete(E),
 1284:           [{{1,a},{1,a}},{{1,a},{2,b}},{{1,a},{3,c}},
 1285:            {{2,b},{1,a}},{{2,b},{2,b}},{{2,b},{3,c}},
 1286: 
 1287:            {{3,c},{1,a}},{{3,c},{2,b}},{{3,c},{3,c}}] = lists:sort(R)">>,
 1288: 
 1289:        <<"E = ets:new(test, []),
 1290:           true = ets:insert(E, [{1,a},{2,b},{3,c}]),
 1291:           H = qlc:q([X || X <- qlc:append([ets:table(E), [a,b,c], 
 1292:                                            ets:table(E)])]),
 1293:           R = qlc:e(H),
 1294:           ets:delete(E),
 1295:           [a,b,c,{1,a},{1,a},{2,b},{2,b},{3,c},{3,c}] = lists:sort(R)">>,
 1296: 
 1297:        <<"E = ets:new(test, []),
 1298:           true = ets:insert(E, [{1,a},{2,b},{3,c}]),
 1299:           false = ets:info(E, safe_fixed),
 1300:           H = qlc:q([{X,Y} || X <- ets:table(E, {n_objects, default}), 
 1301:                               Y <- ets:table(E, {n_objects, 2}), 
 1302:                               false =/= ets:info(E, safe_fixed), 
 1303:                               throw({throw,apa})]),
 1304:           {throw,apa} = (catch {any_term,qlc:e(H)}),
 1305:           false = ets:info(E, safe_fixed),
 1306:           ets:delete(E)">>,
 1307: 
 1308:        <<"E = ets:new(test, []),
 1309:           true = ets:insert(E, [{1,a},{2,b},{3,c}]),
 1310:           false = ets:info(E, safe_fixed),
 1311:           H = qlc:q([{X,Y} || X <- ets:table(E), Y <- ets:table(E), 
 1312:                               false =/= ets:info(E, safe_fixed), exit(apa)]),
 1313:           {'EXIT',apa} = (catch {any_term,qlc:e(H)}),
 1314:           false = ets:info(E, safe_fixed),
 1315:           ets:delete(E)">>,
 1316: 
 1317:        <<"E = ets:new(test, []),
 1318:           true = ets:insert(E, [{1,a},{2,b},{3,c}]),
 1319:           H = qlc:q([{X,Y} || X <- qlc_SUITE:bad_table_throw(E), 
 1320:                               Y <- ets:table(E)]),
 1321:           R = (catch {any_term,qlc:cursor(H)}),
 1322:           false = ets:info(E, safe_fixed),
 1323:           ets:delete(E),
 1324:           {throw,bad_pre_fun} = R">>,
 1325: 
 1326:        <<"E = ets:new(test, []),
 1327:           true = ets:insert(E, [{1,a},{2,b},{3,c}]),
 1328:           H = qlc:q([{X,Y} || X <- qlc_SUITE:bad_table_exit(E), 
 1329:                               Y <- ets:table(E)]),
 1330:           R = (catch {any_term,qlc:cursor(H)}),
 1331:           false = ets:info(E, safe_fixed),
 1332:           ets:delete(E),
 1333:           {'EXIT',{bad_pre_fun,_}} = R">>,
 1334: 
 1335:        <<"E = ets:new(test, [ordered_set]),
 1336:           true = ets:insert(E, [{1,a},{2,b},{3,c}]),
 1337:           H = qlc:q([X || X <- qlc_SUITE:default_table(E)]),
 1338:           R = qlc:e(H),
 1339:           ets:delete(E),
 1340:           [{1,a},{2,b},{3,c}] = R">>,
 1341: 
 1342:        <<"E = ets:new(test, [ordered_set]),
 1343:           true = ets:insert(E, [{1,a},{2,b},{3,c}]),
 1344:           H = qlc:q([X || X <- qlc_SUITE:bad_table(E)]),
 1345:           {'EXIT', {badarg, _}} = (catch qlc:e(H)),
 1346:           ets:delete(E)">>,
 1347: 
 1348:        %% The info tag num_of_objects is currently not used.
 1349: %        <<"E = ets:new(test, [ordered_set]),
 1350: %           true = ets:insert(E, [{1,a},{2,b},{3,c}]),
 1351: %           H = qlc:q([X || X <- qlc_SUITE:bad_table_info_fun_n_objects(E)]),
 1352: %           {'EXIT', finito} = (catch {any_term,qlc:e(H)}),
 1353: %           ets:delete(E)">>,
 1354: 
 1355:        <<"E = ets:new(test, [ordered_set]),
 1356:           true = ets:insert(E, [{1,a},{2,b},{3,c}]),
 1357:           H = qlc:q([Y || {X,Y} <- qlc_SUITE:bad_table_info_fun_indices(E),
 1358:                           X =:= a]),
 1359:           %% This is due to lookup. If the table were traversed there
 1360:           %% would be no failure.
 1361:           {throw, apa} = (catch {any_term,qlc:e(H)}),
 1362:           ets:delete(E)">>,
 1363: 
 1364:        <<"E = ets:new(test, [ordered_set]),
 1365:           true = ets:insert(E, [{1,a},{2,b},{3,c}]),
 1366:           H = qlc:q([Y || {X,Y} <- qlc_SUITE:bad_table_info_fun_keypos(E),
 1367:                           X =:= a]),
 1368:           {'EXIT',{keypos,_}} = (catch {any_term,qlc:info(H)}),
 1369:           {'EXIT',{keypos,_}} = (catch {any_term,qlc:e(H)}),
 1370:           ets:delete(E)">>,
 1371: 
 1372:        begin
 1373:        MS = ets:fun2ms(fun(X) when element(1, X) > 1 -> X end),
 1374:        [<<"E = ets:new(test, []),
 1375:            true = ets:insert(E, [{1,a},{2,b},{3,c}]),
 1376:            MS = ">>, io_lib:format("~w", [MS]), <<",
 1377:            H = qlc:q([{X,Y} || X <- ets:table(E,{traverse,{select, MS}}), 
 1378:                                Y <- ets:table(E)]),
 1379:            R = qlc:e(H),
 1380:            ets:delete(E),
 1381:            [{{2,b},{1,a}},{{2,b},{2,b}},{{2,b},{3,c}},
 1382:             {{3,c},{1,a}},{{3,c},{2,b}},{{3,c},{3,c}}] = lists:sort(R)">>]
 1383:        end,
 1384: 
 1385:        begin % a short table
 1386:        MS = ets:fun2ms(fun(X) when element(1, X) > 1 -> X end),
 1387:        [<<"E = ets:new(test, []),
 1388:            true = ets:insert(E, [{0,b}]),
 1389:            MS =  ">>, io_lib:format("~w", [MS]), <<",
 1390:            H1 = qlc:q([X || X <- ets:table(E)]),
 1391:            R1 = qlc:e(H1),
 1392:            H2 = qlc:q([X || X <- ets:table(E, {traverse, {select, MS}})]),
 1393:            R2 = qlc:e(H2),
 1394:            ets:delete(E),
 1395:            [_] = R1,
 1396:            [] = R2">>]
 1397:        end,
 1398: 
 1399:        begin
 1400:        File = filename:join(?privdir, "detsfile"),
 1401:        _ = file:delete(File),
 1402:        [<<"{ok, Tab} = dets:open_file(apa, [{file,\"">>, File, <<"\"}, 
 1403:                                            {type,bag}]),
 1404:            ok = dets:insert(Tab, [{1,a},{1,b}]),
 1405:            R = qlc:e(qlc:q([X || X <- dets:table(Tab)])),
 1406:            dets:close(Tab),
 1407:            file:delete(\"">>, File, <<"\"),
 1408:            R">>]
 1409:        end,
 1410: 
 1411:        %% [T || P <- Table, F] turned into a match spec.
 1412:        <<"E = ets:new(apa, [duplicate_bag]),
 1413:           true = ets:insert(E, [{1,a},{2,b},{3,c},{4,d}]),
 1414:           QH = qlc:q([X || {X,_} <- ets:table(E), X > 2], unique),
 1415:           {qlc, _, [{generate, _, {table, _}}], [{unique,true}]} = i(QH),
 1416:           [3,4] = lists:sort(qlc:e(QH)),
 1417:           ets:delete(E)">>,
 1418: 
 1419:        <<"E = ets:new(apa, []),
 1420:           true = ets:insert(E, [{1,a},{2,b}]),
 1421:           {'EXIT', {badarg, _}} = (catch qlc_SUITE:bad_table_format(E)),
 1422:           ets:delete(E)">>,
 1423: 
 1424:        <<"E = ets:new(apa, []),
 1425:           true = ets:insert(E, [{1,a},{2,b}]),
 1426:           {'EXIT', {badarg, _}} = (catch qlc_SUITE:bad_table_format_arity(E)),
 1427:           ets:delete(E)">>,
 1428: 
 1429:        <<"E = ets:new(apa, []),
 1430:           true = ets:insert(E, [{1,a},{2,b}]),
 1431:           {'EXIT', {badarg, _}} = (catch qlc_SUITE:bad_table_info_arity(E)),
 1432:           ets:delete(E)">>,
 1433: 
 1434:        <<"E = ets:new(apa, []),
 1435:           true = ets:insert(E, [{1,a},{2,b}]),
 1436:           {'EXIT', {badarg, _}} = (catch qlc_SUITE:bad_table_traverse(E)),
 1437:           ets:delete(E)">>,
 1438: 
 1439:        <<"E = ets:new(apa, []),
 1440:           true = ets:insert(E, [{1,a},{2,b}]),
 1441:           {'EXIT', {badarg, _}} = (catch qlc_SUITE:bad_table_post(E)),
 1442:           ets:delete(E)">>,
 1443: 
 1444:        <<"E = ets:new(apa, []),
 1445:           true = ets:insert(E, [{1,a},{2,b}]),
 1446:           {'EXIT', {badarg, _}} = (catch qlc_SUITE:bad_table_max_lookup(E)),
 1447:           ets:delete(E)">>,
 1448: 
 1449:        <<"E = ets:new(apa, []),
 1450:           true = ets:insert(E, [{1,a},{2,b}]),
 1451:           {'EXIT', {badarg, _}} = (catch qlc_SUITE:bad_table_lookup(E)),
 1452:           ets:delete(E)">>,
 1453: 
 1454:        <<"L = [{1,a},{2,b},{3,c}],
 1455:           QH = qlc:q([element(2, X) || X <- qlc_SUITE:table(L, [2]),
 1456:                                        (element(1, X) =:= 1)
 1457:                                         or (2 =:= element(1, X))]),
 1458:           [a,b] = lists:sort(qlc:e(QH))">>,
 1459: 
 1460:        <<"etsc(fun(E) ->
 1461:               Q = qlc:q([{A,B} || {A,B} <- 
 1462:                                 qlc:q([{B,A} || {A,B} <- ets:table(E), 
 1463:                                                 (A =:= 1) or (A =:= 2),
 1464:                                                 math:sqrt(B) < A])]),
 1465:               [{2,2}] = qlc:eval(Q),
 1466:               [1,2] = lookup_keys(Q)
 1467:            end, [{1,1},{2,2}])">>
 1468:        ],
 1469:     ?line run(Config, Ts),
 1470: 
 1471:     Ts2 = [
 1472:        %% [T || P <- Table, F] turned into a match spec. Records needed.
 1473:        <<"E = ets:new(foo, [bag]),
 1474:           ets:insert(E, [{a,1,2},#a{b=3,c=4},{a,3}]),
 1475:           QH = qlc:q([X || X <- ets:table(E), is_record(X, a)]),
 1476:           {list,{table,_}, _} = i(QH),
 1477:           [{a,1,2},{a,3,4}] = lists:sort(qlc:eval(QH)),
 1478:           ets:delete(E)">>
 1479:        ],
 1480:     ?line run(Config, <<"-record(a, {b,c}).\n">>, Ts2),
 1481: 
 1482:     ok.
 1483: 
 1484: process_dies(doc) ->
 1485:     "Caller or cursor process dies.";
 1486: process_dies(suite) -> [];
 1487: process_dies(Config) when is_list(Config) ->
 1488:     Ts = [
 1489:        <<"E = ets:new(test, []),
 1490:           true = ets:insert(E, [{1,a},{2,b},{3,c}]),
 1491:           false = ets:info(E, safe_fixed),
 1492:           Parent = self(),
 1493:           F = fun() -> 
 1494:                       H = qlc:q([X || X <- ets:table(E)]),
 1495:                       qlc:cursor(H),
 1496:                       Parent ! {self(),ok}                
 1497:               end,
 1498:           Pid = spawn_link(F),
 1499:           receive {Pid,ok} -> ok end,
 1500:           timer:sleep(10),
 1501:           false = ets:info(E, safe_fixed),    
 1502:           ets:delete(E)">>,
 1503: 
 1504:        <<"%% This is not nice. The cursor's monitor kicks in.
 1505:           E = ets:new(test, []),
 1506:           true = ets:insert(E, [{1,a},{2,b},{3,c}]),
 1507:           false = ets:info(E, safe_fixed),
 1508:           Parent = self(),
 1509:           F = fun() -> 
 1510:                       H = qlc:q([X || begin
 1511:                                           process_flag(trap_exit, false),
 1512:                                           {links, [Pid]} = 
 1513:                                               process_info(self(), links),
 1514:                                           unlink(Pid),
 1515:                                           timer:sleep(1),
 1516:                                           {links, []} =
 1517:                                               process_info(self(), links),
 1518:                                           true 
 1519:                                       end, 
 1520:                                       X <- ets:table(E)]),
 1521:                       C = qlc:cursor(H),
 1522:                       qlc:next_answers(C),
 1523:                       Parent ! {self(),ok}                
 1524:               end,
 1525:           Pid = spawn_link(F),
 1526:           receive {Pid,ok} -> ok end,
 1527:           timer:sleep(10),
 1528:           false = ets:info(E, safe_fixed),    
 1529:           ets:delete(E)">>,
 1530: 
 1531:        <<"H = qlc:q([X || X <- [1,2]]),
 1532:           {qlc_cursor, Term} = C = qlc:cursor(H),
 1533:           PF = process_flag(trap_exit, true),
 1534:           F = fun(T) -> not is_pid(T) end,
 1535:           [Pid|_] = lists:dropwhile(F, tuple_to_list(Term)),
 1536:           exit(Pid, kill),
 1537:           timer:sleep(1),
 1538:           {'EXIT', {{qlc_cursor_pid_no_longer_exists, Pid}, _}} =
 1539:                 (catch qlc:next_answers(C)),
 1540:           process_flag(trap_exit, PF)">>,
 1541:        <<"H = qlc:q([X || begin process_flag(trap_exit, true), true end, 
 1542:                           X <- [1,2]]),
 1543:           {qlc_cursor, Term} = C = qlc:cursor(H),
 1544:           PF = process_flag(trap_exit, true),
 1545:           F = fun(T) -> not is_pid(T) end,
 1546:           [Pid|_] = lists:dropwhile(F, tuple_to_list(Term)),
 1547:           [1] = qlc:next_answers(C, 1),
 1548:           exit(Pid, stop),
 1549:           timer:sleep(1),
 1550:           {'EXIT', {{qlc_cursor_pid_no_longer_exists, Pid}, _}} =
 1551:               (catch qlc:next_answers(C)),
 1552:           process_flag(trap_exit, PF)">>,
 1553:        <<"%% This is not nice. No cleanup is done...
 1554:           H = qlc:q([X || begin process_flag(trap_exit, false), true end, 
 1555:                      X <- [1,2]]),
 1556:           {qlc_cursor, Term} = C = qlc:cursor(H),
 1557:           PF = process_flag(trap_exit, true),
 1558:           F = fun(T) -> not is_pid(T) end,
 1559:           [Pid|_] = lists:dropwhile(F, tuple_to_list(Term)),
 1560:           [1] = qlc:next_answers(C, 1),
 1561:           exit(Pid, stop),
 1562:           timer:sleep(1),
 1563:           {'EXIT', {{qlc_cursor_pid_no_longer_exists, Pid}, _}} =
 1564:               (catch qlc:next_answers(C)),
 1565:           process_flag(trap_exit, PF)">>,
 1566: 
 1567:        <<"PF = process_flag(trap_exit, true),
 1568:           E = ets:new(test, []),
 1569:           %% Hard kill. No cleanup will be done.
 1570:           H = qlc:q([X || begin exit(self(), kill), true end, 
 1571:                           X <- ets:table(E)]),
 1572:           C = qlc:cursor(H),
 1573:           {'EXIT', {{qlc_cursor_pid_no_longer_exists, _}, _}} =
 1574:                (catch qlc:next_answers(C)),
 1575:           false = ets:info(E, safe_fixed), % - but Ets cleans up anyway.
 1576:           true = ets:delete(E),
 1577:           process_flag(trap_exit, PF)">>,
 1578: 
 1579:        <<"E = ets:new(test, []),
 1580:           true = ets:insert(E, [{1,a}]),
 1581:           %% The signal is caught by trap_exit. No process dies...
 1582:           H = qlc:q([X || begin exit(self(), normal), true end, 
 1583:                           X <- ets:table(E)]),
 1584:           C = qlc:cursor(H, {spawn_options, []}),
 1585:           [{1,a}] = qlc:next_answers(C),
 1586:           qlc:delete_cursor(C),
 1587:           false = ets:info(E, safe_fixed),
 1588:           true = ets:delete(E)">>,
 1589:        <<"E = ets:new(test, []),
 1590:           true = ets:insert(E, [{1,a}]),
 1591:           %% The same as last example.
 1592:           H = qlc:q([X || begin 
 1593:                               process_flag(trap_exit, true), 
 1594:                               exit(self(), normal), true 
 1595:                           end, 
 1596:                           X <- ets:table(E)]),
 1597:           C = qlc:cursor(H, {spawn_options, []}),
 1598:           [{1,a}] = qlc:next_answers(C),
 1599:           qlc:delete_cursor(C),
 1600:           false = ets:info(E, safe_fixed),
 1601:           true = ets:delete(E), ok">>,
 1602:        <<"E = ets:new(test, []),
 1603:           true = ets:insert(E, [{1,a}]),
 1604:           H = qlc:q([X || X <- ets:table(E)]),
 1605:           SpawnOpts = [link, monitor], % monitor is ignored
 1606:           {qlc_cursor, Term} = C = qlc:cursor(H, {spawn_options, SpawnOpts}),
 1607:           F = fun(T) -> not is_pid(T) end,
 1608:           [Pid|_] = lists:dropwhile(F, tuple_to_list(Term)),
 1609:           Me = self(),
 1610:           qlc_SUITE:install_error_logger(),
 1611:           Tuple = {this, tuple, is, writton, onto, the, error_logger},
 1612:           SP = spawn(fun() ->
 1613:                   Pid ! Tuple,
 1614:                   Me ! {self(), done}
 1615:                 end),
 1616:           receive {SP, done} -> ok end,
 1617:           [{1,a}] = qlc:next_answers(C),
 1618:           qlc:delete_cursor(C),
 1619:           {error, _Pid, Tuple} = qlc_SUITE:read_error_logger(),
 1620:           qlc_SUITE:uninstall_error_logger(),
 1621:           false = ets:info(E, safe_fixed),
 1622:           true = ets:delete(E), ok">>
 1623: 
 1624:         ],
 1625:     ?line run(Config, Ts),
 1626:     ok.
 1627: 
 1628: sort(doc) ->
 1629:     "The sort option.";
 1630: sort(suite) -> [];
 1631: sort(Config) when is_list(Config) ->
 1632:     Ts = [
 1633:        <<"H = qlc:q([X || X <- qlc:sort([1,2,3,2], {unique,true})]),
 1634:           [1,2,3] = qlc:e(H),
 1635:           C1 = qlc:cursor(H),
 1636:           [1,2,3] = qlc:next_answers(C1, all_remaining),
 1637:           qlc:delete_cursor(C1)">>,
 1638: 
 1639:        <<"H = qlc:q([{X,Y} || X <- qlc:sort(qlc:q([X || X <- [1,2,3,2]]), 
 1640:                                             {unique,true}),
 1641:                               Y <- [a,b]]),
 1642:           [{1,a},{1,b},{2,a},{2,b},{3,a},{3,b}] = qlc:e(H),
 1643:           C = qlc:cursor(H),
 1644:           [{1,a},{1,b},{2,a},{2,b},{3,a},{3,b}] = 
 1645:               qlc:next_answers(C, all_remaining),
 1646:           qlc:delete_cursor(C)">>,
 1647: 
 1648:        <<"H = qlc:q([X || X <- qlc:sort(qlc:q([X || X <- apa]))]),
 1649:           {'EXIT',{badarg,_}} = (catch qlc:e(H))">>,
 1650: 
 1651:           %% An example with a side effect. The result may vary...
 1652:        <<"E = ets:new(test, [duplicate_bag]),
 1653:           true = ets:insert(E, [{1,17},{1,a}]),
 1654:           H_1 = qlc:q([X || X <- ets:table(E)]),
 1655:           H = qlc:q([X || X <- [1,2,3], ets:insert(E, {1,-X}), 
 1656:                           {_,Y} <- H_1, 
 1657:                           X > Y]),
 1658:           true = lists:sort(qlc:e(H)) == [1,2,2,3,3,3],
 1659:           true = ets:delete(E)">>,
 1660: 
 1661:        <<"E = ets:new(test, [duplicate_bag]),
 1662:           true = ets:insert(E, [{1,17}]),
 1663:           H_1 = qlc:q([X || X <- qlc:sort(ets:tab2list(E))]),
 1664:           %% Note: side effect in filter!
 1665:           H = qlc:q([X || X <- [1,2,3], ets:insert(E, {1,-X}),
 1666:                           {_,Y} <- H_1, X > Y]),
 1667:           [] = qlc:e(H),
 1668:           true = ets:delete(E)">>,
 1669: 
 1670:        <<"H = qlc:q([X || X <- qlc:sort([1,2,3], {fopp,la})]),
 1671:           {'EXIT',{badarg,_}} = (catch qlc:e(H)),
 1672:           {'EXIT',{badarg,_}} = (catch qlc:cursor(H)),
 1673:           F = fun(Obj, A) -> A++[Obj] end,
 1674:           {'EXIT',{badarg,_}} = (catch qlc:fold(F, [], H))">>,
 1675: 
 1676:        <<"Q1 = qlc:q([X || X <- [1,2]]),
 1677:           AL = [Q1, [1,2,3]],
 1678:           Q2 = qlc:q([X || X <- qlc:sort(qlc:append(AL))]),
 1679:           [1,1,2,2,3] = qlc:e(Q2)">>,
 1680: 
 1681:        <<"H = qlc:q([{X,Y} || X <- qlc:sort(qlc:q([X || X <- [1,2,3,2]]), 
 1682:                                             {unique,true}),
 1683:                               Y <- [a,b]]),
 1684:           {qlc, _,
 1685:            [{generate, _, {sort, {qlc, _, [{generate, _, {list, [1,2,3,2]}}],
 1686:                                   [{unique,true}]},
 1687:                            []}},
 1688:             {generate, _, {qlc, _, [{generate, _, {list, [a,b]}}],
 1689:                            [{unique,true}]}}],
 1690:            [{unique,true}]} = i(H, unique_all),
 1691:           [{1,a},{1,b},{2,a},{2,b},{3,a},{3,b}] = qlc:e(H, unique_all)">>,
 1692: 
 1693:        <<"L = [1,2,1,3,4,3,1],
 1694:           true = lists:sort(L) == qlc:e(qlc:q([X || X <- qlc:sort(L)])),
 1695:           true = lists:usort(L) == 
 1696:                  qlc:e(qlc:q([X || X <- qlc:sort(L, {unique,true})])),
 1697:           true = lists:reverse(lists:sort(L)) ==
 1698:                  qlc:e(qlc:q([X || X <- qlc:sort(L, {order, descending})])),
 1699:           true = lists:reverse(lists:usort(L)) ==
 1700:                  qlc:e(qlc:q([X || X <- qlc:sort(L, [{order, descending}, 
 1701:                                                      {unique, true}])])),
 1702:           CF = fun(X, Y) -> X =< Y end,
 1703:           true = lists:sort(L) == 
 1704:                  qlc:e(qlc:q([X || X <- qlc:sort(L, {order, CF})])),
 1705:           true = lists:usort(L) ==
 1706:                  qlc:e(qlc:q([X || X <- qlc:sort(L, [{order, CF}, 
 1707:                                                     {unique, true}])]))">>,
 1708: 
 1709:        <<"E = ets:new(foo, []),
 1710:           [true || I <- lists:seq(1, 50000), not ets:insert(E, {I, I})],
 1711:           H = qlc:q([{X,Y} || X <- [a,b], Y <- qlc:sort(ets:table(E))]),
 1712:           100000 = length(qlc:e(H)),
 1713:           ets:delete(E)">>,
 1714: 
 1715:        begin
 1716:        TmpDir = ?privdir,
 1717:        [<<"TE = process_flag(trap_exit, true),
 1718:            E = ets:new(foo, []),
 1719:            [true || I <- lists:seq(1, 50000), not ets:insert(E, {I, I})],
 1720:            Ports = erlang:ports(),
 1721:            H = qlc:q([{X,Y} || X <- [a,b], 
 1722:                                begin
 1723:                                    [P] = erlang:ports() -- Ports,
 1724:                                    exit(P, port_exit),
 1725:                                    true
 1726:                                end,
 1727:                                Y <- qlc:sort(ets:table(E),
 1728:                                              [{tmpdir,\"">>, 
 1729:                                                TmpDir, <<"\"}])]),
 1730:            {error, qlc, {file_error, _, _}} = (catch qlc:e(H)),
 1731:            receive {'EXIT', _, port_exit} -> ok end,
 1732:            ets:delete(E),
 1733:            process_flag(trap_exit, TE)">>]
 1734:        end
 1735: 
 1736:         ],
 1737:     ?line run(Config, Ts),
 1738:     ok.
 1739: 
 1740: keysort(doc) ->
 1741:     "The sort option.";
 1742: keysort(suite) -> [];
 1743: keysort(Config) when is_list(Config) ->
 1744: 
 1745:     Ts = [
 1746:        <<"OF = fun(X, Y) -> X =< Y end,
 1747:           F = fun(Obj, A) -> A++[Obj] end,
 1748:           H = qlc:q([X || X <- qlc:keysort(1, [{2,a},{1,b}], {order,OF})]),
 1749:           {'EXIT',{{badarg,order},_}} = (catch qlc:e(H)),
 1750:           {'EXIT',{{badarg,order},_}} = (catch qlc:fold(F, [], H)),
 1751:           {'EXIT',{{badarg,order},_}} = (catch qlc:cursor(H))">>,
 1752: 
 1753:        <<"E = create_ets(1, 2),
 1754:           H = qlc:q([X || X <- qlc:keysort([1], ets:table(E), 
 1755:                                            [{size,1},{tmpdir,\"/a/b/c\"}])]),
 1756:           H1 = qlc:q([X || {X,_} <- qlc:e(H), X < 4]),
 1757:           {error,_,{file_error,_,_}} = qlc:info(H1),
 1758:           {error,_,{file_error,_,_}} = qlc:e(H1),
 1759:           ets:delete(E)">>,
 1760: 
 1761:        <<"L = [{1,a},{2,b},{3,c},{2,b}],
 1762:           H = qlc:q([{X,Y} || {X,_} <- qlc:keysort(1, qlc:q([X || X <- L]), 
 1763:                                                    {unique,true}),
 1764:                               Y <- [a,b]]),
 1765:           [{1,a},{1,b},{2,a},{2,b},{3,a},{3,b}] = qlc:e(H),
 1766:           C = qlc:cursor(H),
 1767:           [{1,a},{1,b},{2,a},{2,b},{3,a},{3,b}] = 
 1768:               qlc:next_answers(C, all_remaining),
 1769:           qlc:delete_cursor(C)">>,
 1770: 
 1771:        <<"H1 = qlc:q([X || X <- qlc:keysort(0, [])]),
 1772:           {'EXIT',{badarg,_}} = (catch qlc:e(H1)),
 1773:           H2 = qlc:q([X || X <- qlc:keysort(1, [], {bad,arg})]),
 1774:           {'EXIT',{badarg,_}} = (catch qlc:e(H2)),
 1775:           H3 = qlc:q([X || X <- qlc:keysort([], [])]),
 1776:           {'EXIT',{badarg,_}} = (catch qlc:e(H3))">>,
 1777: 
 1778:        <<"H = qlc:q([X || X <- qlc:keysort(1, [{1,a},{2,b}], 
 1779:                                            [{order,descending},
 1780:                                            {compressed,true}])]),
 1781:           [{2,b},{1,a}] = qlc:e(H),
 1782:           H2 = qlc:q([X || X <- qlc:keysort(1, [{1},{2}], compressed)]),
 1783:           {'EXIT', {badarg, _}} = (catch qlc:e(H2))">>,
 1784: 
 1785:        <<"H = qlc:q([X || X <- qlc:keysort(1, [{1,a},{2,b}], {compressed,false})]),
 1786:           [{1,a},{2,b}] = qlc:e(H)">>,
 1787: 
 1788:        <<"E = create_ets(1, 2),
 1789:           H = qlc:q([X || X <- qlc:keysort([1], ets:table(E), 
 1790:                                            [{size,1},{tmpdir,\"/a/b/c\"}])]),
 1791:           F = fun(Obj, A) -> A++[Obj] end,
 1792:           {error,_,{file_error,_,_}} = qlc:e(H),
 1793:           \" \\\"no such\" ++ _ = lists:dropwhile(fun(A) -> A =/= $\s end, 
 1794:                                  lists:flatten(qlc:format_error(qlc:e(H)))),
 1795:           {error,_,{file_error,_,_}} = qlc:e(H, {unique_all,true}),
 1796:           {error,_,{file_error,_,_}} = qlc:cursor(H),
 1797:           {error,_,{file_error,_,_}} = qlc:cursor(H, {unique_all,true}),
 1798:           {error,_,{file_error,_,_}} = qlc:cursor(H, {spawn_options, []}),
 1799:           {error,_,{file_error,_,_}} = qlc:cursor(H, {spawn_options,default}),
 1800:           {error,_,{file_error,_,_}} = 
 1801:                qlc:cursor(H, [{unique_all,true},{spawn_options, []}]),
 1802:           {error,_,{file_error,_,_}} = qlc:fold(F, [], H),
 1803:           {error,_,{file_error,_,_}} = qlc:fold(F, [],H, {unique_all,true}),
 1804:           ets:delete(E)">>,
 1805: 
 1806:        <<"L = [{1,b,a},{1,b,b},{1,a,a}],
 1807:           H = qlc:q([X || X <- qlc:keysort([4,1], L)]),
 1808:           {error,_,bad_object} = qlc:e(H),
 1809:           \"the keys\" ++ _ = qlc:format_error(qlc:e(H))">>,
 1810: 
 1811:        begin
 1812:        File = filename:join(?privdir, "afile"),
 1813:        ok = file:write_file(File, <<>>),
 1814:        [<<"H = qlc:q([X || X <- qlc:keysort([1], [{1},{2},{1}],
 1815:                                             [{tmpdir,\"">>, File, <<"\"},
 1816:                                              {size,1}])]),
 1817:            {error,_,{file_error,_,_}} = qlc:e(H),
 1818:            file:delete(\"">>, File, <<"\")">>]
 1819:        end,
 1820: 
 1821:        <<"H0 = qlc:q([X || X <- [1,2,3]]),
 1822:           H = qlc:q([X || X <- qlc:sort(H0,{tmpdir,\".\"})]),
 1823:           [1,2,3] = qlc:e(H)">>,
 1824: 
 1825:        %% The global option 'tmpdir' takes precedence.
 1826:        begin
 1827:        PrivDir = ?privdir,
 1828:        [<<"L = [{1,a},{2,b}],
 1829:            H = qlc:q([X || X <- qlc:keysort([1], L, {tmpdir,\"/a/b/c\"})]),
 1830:            H1 = qlc:q([X || X <- H, X > 3]),
 1831:            Dir = \"">>, PrivDir, <<"\",
 1832:            Options = [{tmpdir, Dir}],
 1833:            {qlc,_,[{generate,_,{keysort,{list,L},[1],[{tmpdir,Dir}]}},_],[]} =
 1834:                 i(H1, Options),
 1835:            [{1,a},{2,b}] = qlc:e(H1, Options)">>] % no check of "/a/b/c"
 1836:        end,
 1837: 
 1838:        <<"L = [{2,c},{1,b},{1,a},{3,a},{1,c},{2,b}],
 1839:           true = lists:sort(L) == 
 1840:                  qlc:e(qlc:q([X || X <- qlc:keysort([1,2], L)]))">>,
 1841: 
 1842:        <<"L = [{1,b},{2,c},{1,a},{3,e},{4,f},{3,d}],
 1843:           true = lists:keysort(1, L) ==
 1844:                  qlc:e(qlc:q([X || X <- qlc:keysort(1,L)])),
 1845:           true = lists:ukeysort(1, L) ==
 1846:                  qlc:e(qlc:q([X || X <- qlc:keysort(1, L, {unique,true})])),
 1847:           true = lists:reverse(lists:keysort(1, L)) ==
 1848:                  qlc:e(qlc:q([X || X <- qlc:keysort(1,L, 
 1849:                                                     {order, descending})])),
 1850:           true = lists:reverse(lists:ukeysort(1, L)) ==
 1851:                  qlc:e(qlc:q([X || X <- qlc:keysort(1, L, [{unique,true},
 1852:                                                 {order, descending}])]))">>,
 1853: 
 1854:        <<"L = [{X} || X <- lists:seq(1,100000)],
 1855:           H1 = qlc:append([L,[{1,2},{2,3},{3,4}]]),
 1856:           H = qlc:keysort([1], qlc:keysort([1], H1, [{compressed,true}])),
 1857:           R = qlc:e(H),
 1858:           100003 = length(R)">>
 1859: 
 1860:         ],
 1861:     ?line run(Config, Ts),
 1862: 
 1863:     ok.
 1864: 
 1865: filesort(doc) ->
 1866:     "keysort/1,2, using a file.";
 1867: filesort(suite) -> [];
 1868: filesort(Config) when is_list(Config) ->
 1869:     Ts = [
 1870:        <<"Q = qlc:q([X || X <- [{3},{1},{2}]]),
 1871:           Opts = [{size,10},{no_files,3}],
 1872:           Q2 = qlc:q([{X,Y} || Y <- [1,2], X <- qlc:keysort([1],Q,Opts)]),
 1873:           [{{1},1},{{2},1},{{3},1},{{1},2},{{2},2},{{3},2}] = qlc:e(Q2)">>
 1874:         ],
 1875:     ?line run(Config, Ts),
 1876:     ok.
 1877: 
 1878: 
 1879: cache(doc) ->
 1880:     "The cache option.";
 1881: cache(suite) -> [];
 1882: cache(Config) when is_list(Config) ->
 1883:     Ts = [
 1884:        <<"{'EXIT', {badarg, _}} = (catch qlc:q([X || X <- [1,2]], badarg))">>,
 1885: 
 1886:        <<"Q1 = qlc:q([X || X <- [1,2,1,2,1]], {unique,true}),
 1887:           [1,2] = qlc:e(Q1),
 1888:           [1,2] = qlc:e(Q1, {unique_all,true}),
 1889:           Q2 = qlc:q([X || X <- qlc:q([X || X <- [1,2,1,2,1]],
 1890:                                       {unique,true})]),
 1891:           [1,2] = qlc:e(Q2),
 1892:           [1,2] = qlc:e(Q2, {unique_all,true}),
 1893:           Q3 = qlc:q([X || X <- qlc:append([[1,2,3], [4,5,6]])]),
 1894:           [1,2,3,4,5,6] = qlc:e(Q3)">>,
 1895: 
 1896:        <<"Q1 = qlc:q([X || {X,_} <- [{1,a},{2,a},{1,b},{2,b}]]),
 1897:           Q2 = qlc:q([{X,make_ref()} || X <- Q1]),
 1898:           [{1,_},{2,_},{1,_},{2,_}] = qlc:e(Q2, {unique_all,false}),
 1899:           [{1,_},{2,_}] = qlc:e(Q2, {unique_all,true})">>,
 1900: 
 1901:        <<"E = ets:new(test, [duplicate_bag]),
 1902:           true = ets:insert(E, [{1,a},{2,a},{1,b},{2,b}]),
 1903:           Q1 = qlc:q([X || {X,_} <- ets:table(E)]),
 1904:           Q2 = qlc:q([{X,make_ref()} || X <- Q1]),
 1905:           [{1,_},{1,_},{2,_},{2,_}] = lists:sort(qlc:e(Q2, {unique_all,false})),
 1906:           [{1,_},{2,_}] = lists:sort(qlc:e(Q2, {unique_all,true})),
 1907:           ets:delete(E)">>,
 1908: 
 1909:        <<"Q1 = qlc:q([X || {X,_} <- [{1,a},{2,a},{1,b},{2,b}]]),
 1910:           Q2 = qlc:q([{X,make_ref()} || X <- qlc:append([Q1, Q1])]),
 1911:           [{1,_},{2,_},{1,_},{2,_},{1,_},{2,_},{1,_},{2,_}] = 
 1912:                 qlc:e(Q2, {unique_all,false}),
 1913:           [{1,_},{2,_}] = qlc:e(Q2, {unique_all,true})">>,
 1914: 
 1915:        <<"[] = qlc:e(qlc:q([X || X <- []], {unique, true})),
 1916:           [] = qlc:e(qlc:q([X || X <- qlc:q([X || X <- qlc:append([])], 
 1917:                                              {unique,true})]))">>,
 1918: 
 1919:        <<"Q1 = qlc:q([{X,make_ref()} || {X,_} <- [{1,a},{1,b}]]),
 1920:           [{1,_},{1,_}] = qlc:e(Q1, {unique_all, true}),
 1921:           Q2 = qlc:q([Y || {X,_} <- [{1,a},{1,b}],
 1922:                            begin Y = {X,make_ref()}, true end]),
 1923:           [{1,_},{1,_}] = qlc:e(Q2, {unique_all,true}),
 1924:           Q3 = qlc:q([Y || X <- [{1,a},{2,a}], 
 1925:                            begin {_,Z} = X, Y = {Z,make_ref()}, true end]),
 1926:           [{a,_},{a,_}] = qlc:e(Q3, {unique_all, true})">>,
 1927: 
 1928:        <<"E = ets:new(apa, [duplicate_bag]),
 1929:           ets:insert(E, [{1,a},{2,a},{1,a}]),
 1930:           H1 = qlc:q([X || X <- qlc:append(ets:table(E),[7,3,5])], 
 1931:                           {cache, true}),
 1932:           [{_,a},{_,a},{_,a},7,3,5] = qlc:e(H1),
 1933:           ets:delete(E)">>,
 1934:           
 1935:        <<"F = fun(Obj, A) -> A++[Obj] end,
 1936:           H = qlc:q([X || X <- [1,3,2,4]], cache),
 1937:           Q = qlc:q([X || X <- H]),
 1938:           [1,3,2,4] = qlc:fold(F, [], Q, [])">>,
 1939: 
 1940:        <<"F = fun(Obj, A) -> A++[Obj] end,
 1941:           E = ets:new(apa, [duplicate_bag]),
 1942:           true = ets:insert(E, [{1,a},{2,b},{1,a}]),
 1943:           Q1 = qlc:q([X || X <- ets:table(E)], [cache, unique]),
 1944:           Q = qlc:q([X || X <- Q1], [cache, unique]),
 1945:           {qlc, _, [{generate, _,{table,_}}], [{unique,true}]} = i(Q),
 1946:           R = qlc:fold(F, [], Q, []),
 1947:           ets:delete(E),
 1948:           true = [{1,a},{2,b}] == lists:sort(R)">>,
 1949: 
 1950:        <<"E = ets:new(apa, [duplicate_bag]),
 1951:           ets:insert(E, [{1,a},{2,b},{1,a}]),
 1952:           H1 = qlc:q([X || X <- qlc:append(ets:table(E),[7,3])], cache),
 1953:           H2 = qlc:q([{Y,X} || Y <- [2,1,3], X <- H1]),
 1954:           [{2,_},{2,_},{2,_},{2,7},{2,3},
 1955:            {1,_},{1,_},{1,_},{1,7},{1,3},
 1956:            {3,_},{3,_},{3,_},{3,7},{3,3}] = qlc:e(H2),
 1957:           ets:delete(E)">>,
 1958: 
 1959:           %% This case is not 100 percent determined. An Ets table
 1960:           %% is updated in a filter and later used in a generator.
 1961:        <<"E = ets:new(apa, [bag]),
 1962:           true = ets:insert(E, [{1,a},{2,b}]),
 1963:           H1 = qlc:q([Y || Y <- ets:table(E)], 
 1964:                      [{cache, no}, {unique, true}]),
 1965:           H = qlc:q([{X,Y} || X <- [{1,a},{2,d},{3,e}],
 1966:                               ets:insert(E, X),
 1967:                               Y <- H1]),
 1968:           [{{1,a},_}, {{1,a},_}, {{2,d},_}, {{2,d},_}, {{2,d},_}, 
 1969:            {{3,e},_}, {{3,e},_}, {{3,e},_}, {{3,e},_}] = qlc:e(H),
 1970:           ets:delete(E)">>,
 1971: 
 1972:           %% This case is not 100 percent determined. An Ets table
 1973:           %% is updated in a filter and later used in a generator.
 1974:        <<"E = ets:new(apa, [bag]),
 1975:           true = ets:insert(E, [{1,a},{2,b}]),
 1976:           H1 = qlc:q([Y || Y <- ets:table(E)], 
 1977:                      [{cache, true}, {unique, true}]),
 1978:           H = qlc:q([{X,Y} || X <- [{1,a},{2,d},{3,e}],
 1979:                               ets:insert(E, X),
 1980:                               Y <- H1]),
 1981:           [{{1,a},_}, {{1,a},_}, {{2,d},_}, {{2,d},_}, {{3,e},_}, {{3,e},_}] = 
 1982:               qlc:e(H),
 1983:           ets:delete(E)">>,
 1984: 
 1985:        <<"%% {5979} and {5549} are both hashed to 28244 by phash2/1
 1986:           E = ets:new(apa, [duplicate_bag]),
 1987:           true = ets:insert(E, [{5979},{5549},{5979},{5549},{0}]),
 1988:           H1 = qlc:q([X || X <- ets:table(E)], 
 1989:                      [{cache, true}, {unique, true}]),
 1990:           H = qlc:q([Y || _ <- [1,2], Y <- H1]),
 1991:           {qlc, _, [{generate, _, {list, [1,2]}},
 1992:                     {generate, _, {qlc, _, [{generate, _, {table,_}}],
 1993:                                    [{cache,ets},{unique,true}]}}],
 1994:            []} = i(H),
 1995:           [{0},{0},{5549},{5549},{5979},{5979}] = lists:sort(qlc:e(H)),
 1996:           ets:delete(E)">>,
 1997: 
 1998:        <<"E = ets:new(apa, [ordered_set]),
 1999:           ets:insert(E, [{1},{2}]),
 2000:           H1 = qlc:q([X || X <- ets:table(E)], [cache, unique]),
 2001:           H2 = qlc:q([X || Y <- [3,4], ets:insert(E, {Y}), X <- H1]),
 2002:           {qlc, _, [{generate, _, {list, [3,4]}}, _, 
 2003:                     {generate, _, {qlc, _, [{generate, _, 
 2004:                                              {table, _}}], 
 2005:                                    [{cache, ets}]}}], 
 2006:            []} = i(H2),
 2007:           [{1},{2},{3},{1},{2},{3}] = qlc:e(H2),
 2008:           ets:delete(E)">>,
 2009: 
 2010:        <<"E = ets:new(apa, [ordered_set]),
 2011:           ets:insert(E, [{1},{2}]),
 2012:           H1 = qlc:q([X || X <- ets:table(E)], [unique]),
 2013:           H2 = qlc:q([X || Y <- [3,4], ets:insert(E, {Y}), X <- H1]),
 2014:           [{1},{2},{3},{1},{2},{3},{4}] = qlc:e(H2),
 2015:           ets:delete(E)">>,
 2016: 
 2017:        <<"H0 = qlc:append([a,b], [c,d]),
 2018:           H = qlc:q([{X,Y} || 
 2019:                         X <- H0,
 2020:                         Y <- qlc:q([{X1,Y} || 
 2021:                                        X1 <- H0,
 2022:                                        Y <- qlc:q([{X2,Y} || 
 2023:                                                       X2 <- H0,
 2024:                                                       Y <- H0])])]),
 2025:           {qlc, _,
 2026:            [{generate, _,{append, [{list, [a,b]}, {list, [c,d]}]}},
 2027:             {generate, _, 
 2028:              {qlc, _,
 2029:               [{generate, _, {append,[{list, [a,b]},{list, [c,d]}]}},
 2030:                {generate, _, 
 2031:                 {qlc, _,
 2032:                  [{generate, _,{append,[{list, [a,b]}, {list, [c,d]}]}},
 2033:                   {generate, _,{append,[{list, [a,b]}, {list, [c,d]}]}}],
 2034:                  [{cache,ets}]}}],
 2035:               [{cache,ets}]}}],
 2036:            []} = i(H, cache_all)">>
 2037:        
 2038:        ],
 2039:     ?line run(Config, Ts),
 2040:     ok.
 2041: 
 2042: cache_list(doc) ->
 2043:     "OTP-6038. The {cache,list} option.";
 2044: cache_list(suite) -> [];
 2045: cache_list(Config) when is_list(Config) ->
 2046:     Ts = [
 2047:        begin
 2048:        PrivDir = ?privdir,
 2049:        [<<"%% unique, cache list. A simple qlc.
 2050:           Options = [{cache,list}, unique],
 2051:           L0 = [1,2,3,4,1,2,3,4],
 2052:           L = qlc_SUITE:table(L0, []),
 2053:           Q1 = qlc:q([X || X <- L], Options),
 2054:           Q = qlc:q([{X,Y} || X <- [a,b], Y <- Q1]),
 2055:           GOptions = [{tmpdir,\"">>, PrivDir, <<"\"}],
 2056:           {qlc,_,[{generate,_,{list,[a,b]}},
 2057:                   {generate,_,{qlc,_,
 2058:                                [{generate,_,{table,_}}],
 2059:                                [{cache,list},{unique,true}]}}],
 2060:            []} = i(Q, GOptions),
 2061:           true = [{X,Y} || X <- [a,b], Y <- [1,2,3,4]] =:= 
 2062:                  qlc:e(Q, GOptions)">>]
 2063:        end,
 2064: 
 2065:        begin
 2066:        MS = ets:fun2ms(fun({X,_}) when X > 1 -> X end),
 2067:        [<<"%% No cache, even if explicit match specification.
 2068:           etsc(fun(E) ->
 2069:                    MS =  ">>, io_lib:format("~w", [MS]), <<",
 2070:                    Options = [{cache,list}, unique],
 2071:                    Q = qlc:q([{X,Y} || 
 2072:                                  X <- ets:table(E, {traverse, {select, MS}}),
 2073:                                  Y <- [1,2,3]], 
 2074:                              Options),
 2075:                    {qlc,_,[{generate,_,{table,{ets,table,_}}},
 2076:                            {generate,_,{list,[1,2,3]}}],
 2077:                     [{unique,true}]} = i(Q),
 2078:                    true = [{X,Y} || X <- lists:seq(2,10), Y <- [1,2,3]] =:=
 2079:                        lists:sort(qlc:e(Q))
 2080:                end, [{keypos,1}], [{I,a} || I <- lists:seq(1, 10)])">>]
 2081:        end,
 2082: 
 2083:        <<"%% Temporary files.
 2084:           %% Remove list expression caches when possible. (no visible effect)
 2085:           T = lists:seq(1, 100000), % Huge terms on file
 2086:           F = fun(C) ->
 2087:                       Q0 = qlc:q([{X} || X <- [T,T,T], begin X > 0 end], 
 2088:                                  {cache,C}),
 2089:                       Q1 = qlc:q([{X,Y,Z} ||
 2090:                                      X <- Q0,
 2091:                                      Y <- Q0,
 2092:                                      Z <- Q0],
 2093:                                  {cache,C}),
 2094:                       qlc:q([{X, Y} || Y <- [1], X <- Q1])
 2095:               end,
 2096:           Ql = F(list),
 2097:           Rl = qlc:e(Ql, {max_list_size, 64*1024}),
 2098:           Qe = F(ets),
 2099:           Re = qlc:e(Qe),
 2100:           Qf = F(no),
 2101:           Rf = qlc:e(Qf),
 2102:           Ri = qlc:e(Ql, {max_list_size, 1 bsl 35}), % heavy
 2103:           {27,27,27,27,true,true,true} = 
 2104:               {length(Rl), length(Re), length(Rf), length(Ri),
 2105:                Rl =:= Re, Re =:= Rf, Rf =:= Ri}">>,
 2106: 
 2107:        <<"%% File sorter.
 2108:           T = lists:seq(1, 10000),
 2109:           F = fun(C) ->
 2110:                       Q0 = qlc:q([{X} || X <- [T,T,T], begin X > 0 end], 
 2111:                                  [{cache,C},unique]),
 2112:                       Q1 = qlc:q([{X,Y,Z} ||
 2113:                                      X <- Q0,
 2114:                                      Y <- Q0,
 2115:                                      Z <- Q0],
 2116:                                  [{cache,C},unique]),
 2117:                       qlc:q([{X, Y} || Y <- [1], X <- Q1])
 2118:               end,
 2119:           GOpt = [{max_list_size, 10000}],
 2120:           Ql = F(list),
 2121:           Rl = qlc:e(Ql, GOpt),
 2122:           Qe = F(ets),
 2123:           Re = qlc:e(Qe, GOpt),
 2124:           Qf = F(no),
 2125:           Rf = qlc:e(Qf, GOpt),
 2126:           {1,1,1,true,true} = 
 2127:               {length(Rl), length(Re), length(Rf), Rl =:= Re, Re =:= Rf}">>,
 2128: 
 2129:        <<"%% Remove list expression caches when possible. (no visible effect)
 2130:           Q0 = qlc:q([{X} || X <- [1,2,3], begin X > 0 end], {cache,list}),
 2131:           Q1 = qlc:q([{X,Y,Z} ||
 2132:                          X <- Q0,
 2133:                          Y <- Q0,
 2134:                          Z <- Q0],
 2135:                      {cache,list}),
 2136:           Q = qlc:q([{X, Y} || Y <- [1], X <- Q1]),
 2137:           R = qlc:e(Q),
 2138:           L0 = [{X} || X <- [1,2,3], begin X > 0 end],
 2139:           L1 = [{X,Y,Z} ||
 2140:                    X <- L0,
 2141:                    Y <- L0,
 2142:                    Z <- L0],
 2143:           L = [{X, Y} || Y <- [1], X <- L1],
 2144:           true = R =:= L">>,
 2145: 
 2146:        <<"%% No temporary file.
 2147:           L = [{I,a} || I <- lists:seq(1, 10)],
 2148:           Q0 = qlc:q([X || X <- qlc_SUITE:table_error(L, 1, err),
 2149:                            begin element(1, X) > 5 end],
 2150:                      {cache,list}),
 2151:           Q = qlc:q([{X, element(1,Y)} || 
 2152:                         X <- lists:seq(1, 5),
 2153:                         Y <- Q0]),
 2154:           err = qlc:e(Q)">>,
 2155: 
 2156:        <<"%% Sort internally.
 2157:           L = [{I,a} || I <- lists:seq(1, 10)],
 2158:           Q0 = qlc:q([X || X <- qlc_SUITE:table_error(L, 1, err),
 2159:                            begin element(1, X) > 5 end],
 2160:                      [unique,{cache,list}]),
 2161:           Q = qlc:q([{X, element(1,Y)} || 
 2162:                         X <- lists:seq(1, 5),
 2163:                         Y <- Q0]),
 2164:           err = qlc:e(Q, {max_list_size,0})">>,
 2165: 
 2166:        <<"%% No temporary file.
 2167:           etsc(fun(E) ->
 2168:                        Q0 = qlc:q([X || X <- ets:table(E),
 2169:                                         begin element(1, X) > 5 end],
 2170:                                   {cache,list}),
 2171:                        Q = qlc:q([{X, element(1,Y)} || X <- lists:seq(1, 5),
 2172:                                                        Y <- Q0]),
 2173:                        R = [{X,Y} || X <- lists:seq(1, 5), 
 2174:                                      Y <- lists:seq(6, 10)],
 2175:                        R = lists:sort(qlc:e(Q))
 2176:                end, [{keypos,1}], [{I,a} || I <- lists:seq(1, 10)])">>,
 2177: 
 2178:        <<"%% Sort internally
 2179:           etsc(fun(E) ->
 2180:                        Q0 = qlc:q([X || X <- ets:table(E),
 2181:                                         begin element(1, X) > 5 end],
 2182:                                   [{cache,list},unique]),
 2183:                        Q = qlc:q([{X, element(1,Y)} || X <- lists:seq(1, 5),
 2184:                                                        Y <- Q0]),
 2185:                        R = [{X,Y} || X <- lists:seq(1, 5), 
 2186:                                      Y <- lists:seq(6, 10)],
 2187:                        R = lists:sort(qlc:e(Q))
 2188:                end, [{keypos,1}], [{I,a} || I <- lists:seq(1, 10)])">>,
 2189: 
 2190:        <<"%% A few more tests of unique and {cache,list}.
 2191:           F = fun(CU) ->
 2192:                       H1 = qlc:q([{X,Y} || 
 2193:                                      Y <- [a,b], 
 2194:                                      X <- [1,2]],
 2195:                                  CU),
 2196:                       qlc:q([{X,Y,Z} || X <- [3,4], {Y,Z} <- H1])
 2197:               end,
 2198:           Q1 = F([]),
 2199:           Q2 = F([{cache,list}, unique]),
 2200:           R1 = qlc:e(Q1),
 2201:           R2 = qlc:e(Q2),
 2202:           R3 = qlc:e(Q2, {max_list_size, 0}), % still in RAM
 2203:           true = R1 =:= R2,
 2204:           true = R2 =:= R3">>,
 2205: 
 2206:        <<"E = ets:new(t, [duplicate_bag]),
 2207:           true = ets:insert(E, [{2},{1},{2}]),
 2208:           H1 = qlc:q([{X,Y} || 
 2209:                          Y <- [a,b], 
 2210:                          {X} <- ets:table(E)], 
 2211:                      [{cache,list}, unique]),
 2212:           H2 = qlc:q([{X,Y,Z} || X <- [3,4], {Y,Z} <- H1]),
 2213:           {qlc,_,[{generate,_,{list,[3,4]}},
 2214:                   {generate,_,{qlc,_,
 2215:                                [{generate,_,{list,[a,b]}},
 2216:                                 {generate,_,
 2217:                                  {qlc,_,[{generate,_,{table,{ets,table,_}}}],
 2218:                                   [{cache,list},{unique,true}]}}],
 2219:                                [{cache,list},{unique,true}]}}], []} = i(H2),
 2220:           L1s = [[{X,Y} || Y <- [a,b], X <- Xs] || Xs <- [[1,2], [2,1]]],
 2221:           L2s = [[{X,Y,Z} || X <- [3,4], {Y,Z} <- L1] || L1 <- L1s],
 2222:           R1 = qlc:e(H2),
 2223:           R2 = qlc:e(H2, {max_list_size, 0}), % on temporary file
 2224:           ets:delete(E),
 2225:           true = lists:member(R1, L2s),
 2226:           true = R1 =:= R2">>,
 2227: 
 2228:        <<"E = ets:new(t, [duplicate_bag]),
 2229:           true = ets:insert(E, [{2},{1},{2}]),
 2230:           H1 = qlc:q([{X,Y} || 
 2231:                          Y <- [a,b], 
 2232:                          {X} <- ets:table(E)], 
 2233:                      [{cache,list}]),
 2234:           H2 = qlc:q([{X,Y,Z} || X <- [3,4], {Y,Z} <- H1]),
 2235:           L1s = [[{X,Y} || Y <- [a,b], X <- Xs] || Xs <- [[1,2,2], [2,2,1]]],
 2236:           L2s = [[{X,Y,Z} || X <- [3,4], {Y,Z} <- L1] || L1 <- L1s],
 2237:           R1 = qlc:e(H2),
 2238:           R2 = qlc:e(H2, {max_list_size, 0}), % on temporary file
 2239:           ets:delete(E),
 2240:           true = lists:member(R1, L2s),
 2241:           true = R1 =:= R2">>,
 2242: 
 2243:        <<"Q1 = qlc:q([{X,Y} || 
 2244:                          Y <- [a,b], 
 2245:                          {X,_} <- qlc_SUITE:table_error([{a,1}], 2, err)],
 2246:                      [{cache,list}, unique]),
 2247:           Q = qlc:q([{X,Y,Z} || X <- [3,4], {Y,Z} <- Q1]),
 2248:           {qlc,_,[{generate,_,{list,[3,4]}},
 2249:                   {generate,_,{qlc,_,
 2250:                                [{generate,_,{list,[a,b]}},
 2251:                                 {generate,_,{table,_}}],
 2252:                                [{cache,list},{unique,true}]}}],
 2253:            []} = i(Q),
 2254:           err = qlc:e(Q,{max_list_size,0})">>,
 2255: 
 2256:        begin
 2257:        Privdir = ?privdir,
 2258:        [<<"
 2259:           E = ets:new(t, [duplicate_bag]),
 2260:           N = 17000,
 2261:           true = ets:insert(E, [{X,X} || X <- lists:seq(1, N)]),
 2262:           N = ets:info(E, size),
 2263:           RF = fun(GOpts) ->
 2264:                        F = fun(CU) ->
 2265:                                    H1 = qlc:q([{X,Y} || 
 2266:                                                   Y <- [a,b], 
 2267:                                                   {X,_} <- ets:table(E)], 
 2268:                                               CU),
 2269:                                    qlc:q([{X,Y,Z} || X <- [3,4], {Y,Z} <- H1])
 2270:                            end,
 2271:                        Q1 = F([{cache,list}, unique]),
 2272:                        _ = qlc:info(Q1, GOpts),
 2273:                        R1 = qlc:e(Q1, GOpts),
 2274:                        Q2 = F([unique]),
 2275:                        R2 = qlc:e(Q2, GOpts),
 2276:                        true = lists:sort(R1) =:= lists:sort(R2)
 2277:                end,
 2278:           GOpts = [{tmpdir,\"">>,Privdir,<<"\"}],
 2279:           RF([{max_list_size, 1 bsl 35} | GOpts]),
 2280:           RF(GOpts),
 2281:           RF([{max_list_size, 40000} | GOpts]),
 2282:           true = ets:insert(E, [{X,X} || X <- lists:seq(1, N)]),
 2283:           true = N+N =:= ets:info(E, size),
 2284:           RF([{max_list_size, 1 bsl 30} | GOpts]),
 2285:           RF(GOpts),
 2286:           RF([{max_list_size, 40000} | GOpts]),
 2287:           ets:delete(E)">>]
 2288:        end,
 2289: 
 2290:        <<"%% Temporary file employed.
 2291:           etsc(fun(E) ->
 2292:                        Q0 = qlc:q([X || X <- ets:table(E),
 2293:                                         begin element(1, X) > 5 end],
 2294:                                   {cache,list}),
 2295:                        Q = qlc:q([{X, element(1,Y)} || X <- lists:seq(1, 5),
 2296:                                                        Y <- Q0]),
 2297:                        R = [{X,Y} || X <- lists:seq(1, 5), 
 2298:                                      Y <- lists:seq(6, 10)],
 2299:                        R = lists:sort(qlc:e(Q, {max_list_size, 100*1024}))
 2300:                end, [{keypos,1}], [{I,a,lists:duplicate(100000,1)} || 
 2301:                                         I <- lists:seq(1, 10)])">>,
 2302: 
 2303:        <<"%% Temporary file employed. The file is removed after error.
 2304:           L = [{I,a,lists:duplicate(100000,1)} || I <- lists:seq(1, 10)],
 2305:           Q0 = qlc:q([X || X <- qlc_SUITE:table_error(L, 1, err),
 2306:                            begin element(1, X) > 5 end],
 2307:                      {cache,list}),
 2308:           Q = qlc:q([{X, element(1,Y)} || 
 2309:                         X <- lists:seq(1, 5),
 2310:                         Y <- Q0]),
 2311:           err = qlc:e(Q)">>,
 2312: 
 2313:        <<"%% Temporary file employed. The file is removed after error.
 2314:           L = [{I,a,lists:duplicate(100000,1)} || I <- lists:seq(1, 10)],
 2315:           Q0 = qlc:q([X || X <- qlc_SUITE:table(L, 1, []),
 2316:                            begin element(1, X) > 5 end],
 2317:                      {cache,list}),
 2318:           Q = qlc:q([{X, element(1,Y)} || 
 2319:                         X <- lists:seq(1, 5),
 2320:                         Y <- Q0]),
 2321:           {error, _, {file_error,_,_}} = qlc:e(Q, {tmpdir, \"/a/b/c\"})">>,
 2322: 
 2323:        <<"Q = qlc:q([X || X <- [1,2]]),
 2324:           {'EXIT', {badarg, _}} = (catch qlc:e(Q, {max_list_size, -1}))">>,
 2325: 
 2326:        <<"Q = qlc:q([X || X <- [1,2]]),
 2327:           {'EXIT', {badarg, _}} = (catch qlc:e(Q, {max_list_size, foo}))">>
 2328: 
 2329:        ],
 2330:     ?line run(Config, Ts),
 2331:     ok.
 2332: 
 2333: filter(doc) ->
 2334:     "Filters and match specs.";
 2335: filter(suite) -> [];
 2336: filter(Config) when is_list(Config) ->
 2337:     Ts = [
 2338:        <<"L = [1,2,3,4,5],
 2339:           QH1 = qlc:q([X || X <- L, X > 1, X < 4]),
 2340:           [2,3] = qlc:e(QH1),
 2341:           {list,{list,L},_MS} = i(QH1)
 2342:          ">>,
 2343: 
 2344:        <<"L = [1,2,3,4,5],
 2345:           QH2 = qlc:q([X || X <- L, X > 1, X < 4, X > 2]),
 2346:           [3] = qlc:e(QH2),
 2347:           {list,{list,L},_MS} = i(QH2)
 2348:          ">>,
 2349: 
 2350:           %% "X > 1" is skipped since the matchspec does the job
 2351:        <<"QH3 = qlc:q([X || X <- [1,2,3,4,5], X > 1, begin X < 4 end]),
 2352:           [2,3] = qlc:e(QH3),
 2353:           {qlc,_,[{generate,_,{list,{list,[1,2,3,4,5]},_MS}},_],[]} = i(QH3)
 2354:          ">>,
 2355: 
 2356:        <<"QH4 = qlc:q([{X,Y} || X <- [1,2], Y <- [1,2]]),
 2357:           [{1,1},{1,2},{2,1},{2,2}] = qlc:e(QH4),
 2358:           {qlc,_,[{generate,_,{list,[1,2]}},{generate,_,{list,[1,2]}}],[]} =
 2359:               i(QH4)">>,
 2360: 
 2361:           %% "X > 1" is skipped since the matchspec does the job
 2362:        <<"QH5 = qlc:q([{X,Y} || X <- [1,2], X > 1, Y <- [1,2]]),
 2363:           [{2,1},{2,2}] = qlc:e(QH5),
 2364:           {qlc,_,[{generate,_,{list,{list,[1,2]},_MS}},
 2365:                   {generate,_,{list,[1,2]}}],[]} = 
 2366:               i(QH5)">>,
 2367: 
 2368:        <<"%% Binaries are not handled at all when trying to find lookup values
 2369:           etsc(fun(E) ->
 2370:                       A = 2, 
 2371:                       Q = qlc:q([X || {X} <- ets:table(E), <<A>> =:= <<X>>]),
 2372:                       [2] = lists:sort(qlc:e(Q)),
 2373:                       false = lookup_keys(Q)
 2374:               end, [{1},{2},{3}])">>,
 2375: 
 2376:        <<"etsc(fun(E) ->
 2377:                       Q = qlc:q([X || {X,_} <- ets:table(E), 
 2378:                                    qlc:e(qlc:q([Y || {Y,_} <- ets:table(E), 
 2379:                                                               Y > X])) == []]),
 2380:                       [3] = qlc:e(Q)
 2381:               end, [{1,a},{2,b},{3,c}])">>,
 2382: 
 2383:        <<"Q = qlc:q([X || {X} <- [], (false or (X/0 > 3))]),
 2384:           \"[]\" = qlc:info(Q),
 2385:           [] = qlc:e(Q)">>,
 2386: 
 2387:        <<"%% match spec
 2388:           [] = qlc:e(qlc:q([X || {X} <- [{1},{2}], 
 2389:                                  (false orelse (X/0 > 3))])),
 2390:           %% generated code
 2391:           {'EXIT', {badarith, _}} = 
 2392:             (catch qlc:e(qlc:q([X || {X} <- [{1}], 
 2393:                                      begin (false orelse (X/0 > 3)) end])))">>,
 2394: 
 2395:        <<"%% Partial evaluation in filter.
 2396:           etsc(fun(E) ->
 2397:                      QH = qlc:q([{X+1,Y} || {X,Y} <- ets:table(E), 
 2398:                                             X =:= 1-1+1+(+1)]),
 2399:                      [{3,2}] = qlc:e(QH),
 2400:                      [2] = lookup_keys(QH)
 2401:               end, [{1,1},{2,2},{3,3}])">>,
 2402: 
 2403:        <<"%% =/2 in filters must not be recognized when 'badmatch' is
 2404:           %% possible.
 2405:           etsc(fun(E) ->
 2406:                      QH = qlc:q([{X,Y} || {X,Y} <- ets:table(E),
 2407:                                           ((Y = X) =:= 3)]),
 2408:                      {'EXIT', {{badmatch,4},_}} = (catch qlc:e(QH)),
 2409:                      false = lookup_keys(QH)
 2410:                end, [{3,3},{4,true}])">>,
 2411: 
 2412:        <<"%% One more of the same kind.
 2413:           etsc(fun(E) ->
 2414:                       QH = qlc:q([{X,Y} || {X,_} <- ets:table(E), 
 2415:                                            (Y=X) =:= (Y=1+1)]),
 2416:                       {'EXIT', {{badmatch,2},_}} = (catch qlc:e(QH)),
 2417:                       false = lookup_keys(QH)
 2418:               end, [{1,1},{2,2},{3,3}])">>,
 2419: 
 2420:        <<"%% OTP-5195. Used to return a value, but badarith is correct.
 2421:           etsc(fun(E) ->
 2422:                       QH = qlc:q([X || {X,_} <- ets:table(E), 
 2423:                                        (X =:= 1) and
 2424:                                     if X =:= 1 -> true;
 2425:                                        true -> X/0
 2426:                                     end]),
 2427:                       {'EXIT',{badarith,_}} = (catch qlc:e(QH)),
 2428:                       false = lookup_keys(QH)
 2429:               end, [{1,1},{2,2},{3,3}])">>,
 2430: 
 2431:        <<"fun(Z) ->
 2432:             Q = qlc:q([X || Z < 2, X <- [1,2,3]]),
 2433:             [] = qlc:e(Q)
 2434:           end(3)">>,
 2435: 
 2436:        <<"H = qlc:q([{P1,A,P2,B,P3,C} ||
 2437:                   P1={A,_} <- [{1,a},{2,b}],
 2438:                   {_,B}=P2 <- [{1,a},{2,b}],
 2439:                   C=P3 <- [1],
 2440:                   {[X,_],{_,X}} <- [{[1,2],{3,1}}, {[a,b],{3,4}}],
 2441:                   A > 0,
 2442:                   B =/= c,
 2443:                   C > 0]),
 2444:           L = [{{1,a},1,{1,a},a,1,1}, {{1,a},1,{2,b},b,1,1},
 2445:                {{2,b},2,{1,a},a,1,1}, {{2,b},2,{2,b},b,1,1}],
 2446:           L = qlc:e(H)">>,
 2447: 
 2448:        <<"H = qlc:q([{X,Y} ||
 2449:                   X = _ <- [1,2,3],
 2450:                   _ = Y <- [a,b,c],
 2451:                   _ = _ <- [foo],
 2452:                   X > 1,
 2453:                   Y =/= a]),
 2454:           [{2,b},{2,c},{3,b},{3,c}] = qlc:e(H)">>
 2455: 
 2456:        ],
 2457:     ?line run(Config, Ts),
 2458:     ok.
 2459: 
 2460: info(doc) ->
 2461:     "info/2.";
 2462: info(suite) -> [];
 2463: info(Config) when is_list(Config) ->
 2464:     Ts = [
 2465:        <<"{list, [1,2]} = i(qlc:q([X || X <- [1,2]])),
 2466:           {append,[{list, [1,2]}, {list, [3,4]}]} = 
 2467:                i(qlc:append([1,2],[3,4])),
 2468:           {sort,{list, [1,2]},[]} = i(qlc:sort([1,2])),
 2469:           E = ets:new(foo, []),
 2470:           ets:insert(E, [{1},{2}]),
 2471:           {table, _} = i(ets:table(E)),
 2472:           true = ets:delete(E),
 2473:           {list, [1,2]} = i([1,2]),
 2474:           {append, [{list, [1,2]}, {list, [3,4]}]} =
 2475:              i(qlc:q([X || X <- qlc:append([1,2],[3,4])])),
 2476:           
 2477:           H0 = qlc:q([X || X <- throw({throw,t})]),
 2478:           {throw,t} = (catch {any_term,qlc:info(H0)}),
 2479:           {'EXIT', {badarg, _}} = 
 2480:                (catch qlc:info(foobar)),
 2481:           {'EXIT', {badarg, _}} = 
 2482:                (catch qlc:info(qlc:q([X || X <- [1,2]]), badarg))">>,
 2483: 
 2484:        <<"{'EXIT', {badarg, _}} = 
 2485:                (catch qlc:info([X || {X} <- []], {n_elements, 0})),
 2486:           L = lists:seq(1, 1000),
 2487:           \"[1,2,3,4,5,6,7,8,9,10|'...']\" = qlc:info(L, {n_elements, 10}),
 2488:           {cons,1,{integer,1,1},{atom,1,'...'}} = 
 2489:             qlc:info(L, [{n_elements, 1},{format,abstract_code}]),
 2490:           Q = qlc:q([{X} || X <- [a,b,c,d,e,f]]),
 2491:           {call,_,_,[{cons,_,{atom,_,a},{cons,_,{atom,_,b},{cons,_,{atom,_,c},
 2492:                                                             {atom,_,'...'}}}},
 2493:                      {call,_,_,_}]} = 
 2494:           qlc:info(Q, [{n_elements, 3},{format,abstract_code}]),
 2495:           \"ets:match_spec_run([a,b,c,d,e,f],\n\"
 2496:           \"                   ets:match_spec_compile([{'$1',[true],\"
 2497:           \"[{{'$1'}}]}]))\" = 
 2498:              qlc:info(Q, [{n_elements, infinity}])">>,
 2499: 
 2500:        <<"Q1 = qlc:q([{X} || X <- qlc:q([X || X <- [1,2]])]),
 2501:           {qlc, _, [{generate, _, {list, [1,2]}}],[]} = i(Q1),
 2502:           Q2 = qlc:q([X || X <- qlc:q([{X} || X <- [1,2]])]),
 2503:           {list,{list,[1,2]},_} = i(Q2),
 2504:           [{1},{2}] = qlc:eval(Q2),
 2505:           Q3 = qlc:q([{X,Y} || X <- qlc:q([X || X <- [a,b]]),       
 2506:                                Y <- qlc:q([Z || Z <- [a,b]])]),
 2507:           {qlc, _, [{generate, _, {list, [a,b]}}, 
 2508:                     {generate, _, {list, [a,b]}}], []} = i(Q3),
 2509:           Q4 = qlc:q([X || X <- [a]]),
 2510:           {list, [a]} = i(Q4),
 2511:           Q5 = qlc:q([X || X <- qlc:q([Y || Y <- [a,b]], unique)]),
 2512:           {qlc, _, [{generate, _, {list, [a,b]}}], [{unique,true}]} = 
 2513:              i(Q5)">>,
 2514: 
 2515:        <<"H = qlc:q([X || X <- qlc:append([qlc:q([X || X <- [1,2]]),[1,2]])]),
 2516:           {append, [{list, [1,2]},{list, [1,2]}]} = i(H),
 2517:           [1,2,1,2] = qlc:e(H)">>,
 2518: 
 2519:        <<"H = qlc:q([{X} || X <- [], X > 1]),
 2520:           {list, []} = i(H),
 2521:           [] = qlc:e(H)">>,
 2522: 
 2523:        <<"H1 = qlc:q([{X} || X <- [], X > 1]),
 2524:           H = qlc:q([{X} || X <- H1, X < 10]),
 2525:           {list, []} = i(H),
 2526:           [] = qlc:e(H)">>,
 2527: 
 2528:        <<"L = [1,2,3],
 2529:           QH1 = qlc:q([{X} || X <- L, X > 1]),
 2530:           QH2 = qlc:q([{X} || X <- QH1]),
 2531:           [{{2}},{{3}}] = qlc:e(QH2),
 2532:           {list,{list,{list,L},_},_} = i(QH2)">>,
 2533: 
 2534:        <<"H = qlc:q([X || X <- qlc:q([Y || Y <- qlc:q([Z || Z <-[1,2,1]])])]),
 2535:           {list, [1,2,1]} = i(H),
 2536:           [1,2,1] = qlc:eval(H)">>,
 2537: 
 2538:        <<"%% Used to replace empty ETS tables with [], but that won't work.
 2539:           E = ets:new(apa,[]),
 2540:           QH1 = qlc:q([{X} || X <- ets:table(E), X > 1]),
 2541:           QH2 = qlc:q([{X} || X <- QH1], cache),
 2542:           [] = qlc:e(QH2),
 2543:           {qlc,_,[{generate,_,{table,{ets,table,_}}}],[]} = i(QH2),
 2544:           ets:delete(E)">>,
 2545: 
 2546:        <<"Q1 = qlc:q([W || W <- [a,b]]),
 2547:           Q2 = qlc:q([Z || Z <- qlc:sort([1,2,300])], unique),
 2548:           Q3 = qlc:q([{X,Y} || X <- qlc:keysort([2], [{1,a}]),
 2549:                                Y <- qlc:append([Q1, Q2]),
 2550:                                X > Y]),
 2551:           {qlc, T1,
 2552:            [{generate, P1, {list, [{1,a}]}},
 2553:             {generate, P2, {append, [{list, [a,b]},
 2554:                                     {qlc, T2, [{generate, P3,
 2555:                                                 {sort, {list,[1,2,300]},[]}}],
 2556:                                      [{cache,ets},{unique,true}]}]}},F],
 2557:            []} = i(Q3, cache_all),
 2558:           {tuple, _, [{var,_,'X'}, {var,_,'Y'}]} = binary_to_term(T1),
 2559:           {var, _, 'X'} = binary_to_term(P1),
 2560:           {var, _, 'Y'} = binary_to_term(P2),
 2561:           {var, _, 'Z'} = binary_to_term(P3),
 2562:           {var, _, 'Z'} = binary_to_term(T2),
 2563:           {op, _, '>', {var, _, 'X'}, {var, _, 'Y'}} = binary_to_term(F),
 2564:           true = binary_to_list(<<
 2565:            \"beginV1=qlc:q([Z||Z<-qlc:sort([1,2,300],[])],[{unique,true}]),\"
 2566:            \"qlc:q([{X,Y}||X<-[{1,a}],Y<-qlc:append([[a,b],V1]),X>Y])end\"
 2567:               >>) == format_info(Q3, true)">>,
 2568: 
 2569:        <<"Q1 = qlc:q([{X} || X <- qlc:q([X || X <- [a,b]])]),
 2570:           {qlc, _, [{generate, _, {list, [a,b]}}], []} = i(Q1),
 2571:           Q2 = qlc:q([X || X <- qlc:q([{X} || X <- [a,b]])]),
 2572:           {list,{list,[a,b]},_} = i(Q2),
 2573:           [{a},{b}] = qlc:eval(Q2)">>,
 2574: 
 2575:        <<"Q = qlc:keysort(2, [{1,a,b},{2,b,c},{3,4,c}]),
 2576:           {keysort,{list,[{1,a,b},{2,b,c},{3,4,c}]},2,[]} = i(Q),
 2577:           true = binary_to_list(<<
 2578:              \"qlc:keysort(2,[{1,a,b},{2,b,c},{3,4,c}],[])\">>) 
 2579:               == format_info(Q, true),
 2580:           [{3,4,c},{1,a,b},{2,b,c}] = qlc:e(Q)">>,
 2581: 
 2582:        <<"E = ets:new(foo, []),
 2583:           ets:insert(E, [{1},{2}]),
 2584:           Q = qlc_SUITE:default_table(E),
 2585:           {table,{'$MOD','$FUN',[]}} = i(Q),
 2586:           true = binary_to_list(<<\"'$MOD':'$FUN'()\">>) 
 2587:                 == format_info(Q, true),
 2588:           true = ets:delete(E)">>,
 2589: 
 2590:        <<"\"[]\" = qlc:info([], flat),
 2591:           \"[]\" = qlc:info([]),
 2592:           \"[]\" = qlc:info([], {flat, true})">>,
 2593: 
 2594:        <<"H = qlc:q([{X} || X <- [a,b]]),
 2595:          \"ets:match_spec_run([a,b],ets:match_spec_compile(\" ++ _ =
 2596:                 format_info(H, true),
 2597:          \"ets:match_spec_run([a,b],ets:match_spec_compile(\" ++ _ =
 2598:                 format_info(H, false)">>,
 2599: 
 2600:        <<"H = qlc:q([{X} || X <- [a,b], begin true end]),
 2601:           true = binary_to_list(<<\"qlc:q([{X}||X<-[a,b],begintrueend])\">>) 
 2602:              == format_info(H, true),
 2603:           true = binary_to_list(<<\"qlc:q([{X}||X<-[a,b],begintrueend])\">>)
 2604:              == format_info(H, false)">>,
 2605: 
 2606:        <<"H = qlc:q([A || {A} <- [{1},{2}], (A =:= 2) andalso true]),
 2607:           {call,_,{remote,_,{atom,_,ets},{atom,_,match_spec_run}},_} = 
 2608:              qlc:info(H, {format,abstract_code})">>,
 2609: 
 2610:        <<"H = qlc:q([{X} || X <- qlc:q([{X} || X <- [a,b], begin true end],
 2611:                                        unique), 
 2612:                             begin true end]),
 2613:           true = binary_to_list(<< 
 2614:          \"beginV1=qlc:q([{X}||X<-[a,b],begintrueend],[{unique,true}]),\"
 2615:          \"qlc:q([{X}||X<-V1,begintrueend])end\">>) == 
 2616:               format_info(H, true),
 2617:           true = binary_to_list(<<
 2618:          \"qlc:q([{X}||X<-qlc:q([{X}||X<-[a,b],begintrueend],\"
 2619:          \"[{unique,true}]),begintrueend])\">>) == format_info(H, false)">>,
 2620: 
 2621:        <<"H0 = qlc:q([{V3} || V3 <- qlc:q([{V1} || V1 <- [a,b], 
 2622:                                                    begin true end], unique), 
 2623:                               begin true end]),
 2624:           H = qlc:sort(H0),
 2625:           true = binary_to_list(<<
 2626:           \"qlc:sort(qlc:q([{V3}||V3<-qlc:q([{V1}||\"
 2627:           \"V1<-[a,b],begintrueend],[{unique,true}]),begintrueend]),[])\">>) 
 2628:               == format_info(H, false),
 2629:           true = binary_to_list(<<
 2630:           \"beginV2=qlc:q([{V1}||V1<-[a,b],begintrueend],[{unique,true}]),\"
 2631:           \"V4=qlc:q([{V3}||V3<-V2,begintrueend]),qlc:sort(V4,[])end\">>) 
 2632:               == format_info(H, true)">>,
 2633: 
 2634:        <<"H0 = qlc:q([X || X <- [true], begin true end]),
 2635:           H1 = qlc:q([{X} || X <- [a,b], begin true end], 
 2636:                      [{unique,begin [T] = qlc:e(H0), T end}]),
 2637:           {call,_,{remote,_,{atom,_,qlc},{atom,_,q}},
 2638:                   [{lc,_,{tuple,_,[{var,_,'X'}]},
 2639:                          [{generate,_,{var,_,'X'},
 2640:                                       {cons,_,{atom,_,a},_}},
 2641:                           {block, _, [{atom, _, true}]}]},
 2642:                    {cons,_,_,_}]} = i(H1, {format, abstract_code})">>,
 2643: 
 2644:        <<"E = ets:new(apa, [duplicate_bag]),
 2645:           true = ets:insert(E, [{1,a},{2,b},{3,c},{4,d}]),
 2646:           QH = qlc:q([X || {X,_} <- ets:tab2list(E), X > 2], unique),
 2647:           {qlc, _, [{generate, _, {list, _, _MS}}], [{unique, true}]} = 
 2648:                 i(QH),
 2649:           [3,4] = lists:sort(qlc:e(QH)),
 2650:           ets:delete(E)">>,
 2651: 
 2652:        %% "Imported" variable.
 2653:        <<"F = fun(U) -> qlc:q([{X} || X <- [1,2,3,4,5,6], X > U]) end,
 2654:           QH = F(4),
 2655:           {call, _ ,
 2656:                 {remote, _, {atom, _, ets},{atom, _, match_spec_run}},
 2657:                 [{string, _, [1,2,3,4,5,6]},
 2658:                  {call, _,
 2659:                        _compile,
 2660:                        [{cons, _,
 2661:                               {tuple, _,
 2662:                                      [{atom, _,'$1'},
 2663:                                       {cons, _,
 2664:                                             {tuple,
 2665:                                                  _,
 2666:                                                 [{atom, _,'>'},
 2667:                                                  {atom, _,'$1'},
 2668:                                                  {tuple,
 2669:                                                       _,
 2670:                                                      [{atom, _,const},
 2671:                                                       {integer, _,4}]}]},
 2672:                                             _},
 2673:                                       {cons, _, _, _}]},
 2674:                               {nil,_}}]}]} = i(QH, {format, abstract_code}),
 2675:           [{5},{6}] = qlc:e(QH),
 2676:           [{4},{5},{6}] = qlc:e(F(3))">>
 2677: 
 2678:        ],
 2679:     ?line run(Config, Ts),
 2680:     ok.
 2681: 
 2682: nested_info(doc) ->
 2683:     "Nested QLC expressions. QLC expressions in filter and template.";
 2684: nested_info(suite) -> [];
 2685: nested_info(Config) when is_list(Config) ->
 2686:     Ts = [
 2687:        <<"L = [{1,a},{2,b},{3,c}],
 2688:           Q = qlc:q(
 2689:                 [{X,R} || 
 2690:                     {X,_} <- qlc_SUITE:table(L, []),
 2691:                     begin % X imported
 2692:                         R = qlc:e(qlc:q([{X,Y} || {Y,_}
 2693:                                                     <- qlc_SUITE:table(L, []),
 2694:                                                   Y > X])),
 2695:                         true
 2696:                     end]),
 2697:           true = binary_to_list(<<
 2698:             \"qlc:q([{X,R}||{X,_}<-qlc_SUITE:the_list([{1,a},{2,b},{3,c}]),\"
 2699:             \"beginR=qlc:e(qlc:q([{X,Y}||{Y,_}<-qlc_SUITE:table(L,[]),Y>X]))\"
 2700:             \",trueend])\">>) == format_info(Q, true),
 2701:           [{1,[{1,2},{1,3}]},{2,[{2,3}]},{3,[]}] = qlc:e(Q)">>,
 2702: 
 2703:        <<"L = [{1,a},{2,b},{3,c}],
 2704:           Q = qlc:q( % X imported
 2705:                 [{X,qlc:e(qlc:q([{X,Y} || {Y,_} <- qlc_SUITE:table(L, []),
 2706:                                           Y > X]))} || 
 2707:                     {X,_} <- qlc_SUITE:table(L, [])]),
 2708:           true = binary_to_list(<<
 2709:             \"qlc:q([{X,qlc:e(qlc:q([{X,Y}||{Y,_}<-qlc_SUITE:table(L,[]),\"
 2710:             \"Y>X]))}||{X,_}<-qlc_SUITE:the_list([{1,a},{2,b},{3,c}])])\">>)
 2711:               == format_info(Q, true),
 2712:           [{1,[{1,2},{1,3}]},{2,[{2,3}]},{3,[]}] = qlc:e(Q)">>,
 2713: 
 2714:        <<"L = [{1,a},{2,b},{3,c}],
 2715:           Q = qlc:q(
 2716:                 [{X,R} || 
 2717:                     {X,_} <- qlc_SUITE:table(L, []),
 2718:                     begin % X imported
 2719:                         R = qlc:e(qlc:q([{X,Y} || {Y,_} 
 2720:                                                     <- qlc_SUITE:table(L, []),
 2721:                                                   Y =:= X])),
 2722:                         true
 2723:                     end]),
 2724:           true = binary_to_list(<<
 2725:             \"qlc:q([{X,R}||{X,_}<-qlc_SUITE:the_list([{1,a},{2,b},{3,c}]),\"
 2726:             \"beginR=qlc:e(qlc:q([{X,Y}||{Y,_}<-qlc_SUITE:table(L,[]),\"
 2727:             \"Y=:=X])),trueend])\">>) == format_info(Q, true),
 2728:           [{1,[{1,1}]},{2,[{2,2}]},{3,[{3,3}]}] = qlc:e(Q)">>,
 2729: 
 2730:        <<"L = [{1,a},{2,b},{3,c}],
 2731:           Q = qlc:q(
 2732:                 [{X, % X imported
 2733:                   qlc:e(qlc:q([{X,Y} || {Y,_} <- qlc_SUITE:table(L, []),
 2734:                                         Y =:= X]))} || 
 2735:                     {X,_} <- qlc_SUITE:table(L, [])]),
 2736:           true = binary_to_list(<<
 2737:             \"qlc:q([{X,qlc:e(qlc:q([{X,Y}||{Y,_}<-qlc_SUITE:table(L,[]),\"
 2738:             \"Y=:=X]))}||{X,_}<-qlc_SUITE:the_list([{1,a},{2,b},{3,c}])])\">>)
 2739:              == format_info(Q, true),
 2740:           [{1,[{1,1}]},{2,[{2,2}]},{3,[{3,3}]}] = qlc:e(Q)">>,
 2741: 
 2742:        <<"L = [{1,a},{2,b},{3,c}],
 2743:           Q = qlc:q(
 2744:                 [{X,R} || 
 2745:                     {X,_} <- qlc_SUITE:table(L, []),
 2746:                     begin
 2747:                         R = qlc:e(qlc:q([Y || Y <- [X]])),
 2748:                         true
 2749:                     end]),
 2750:           true = binary_to_list(<<
 2751:             \"qlc:q([{X,R}||{X,_}<-qlc_SUITE:the_list([{1,a},{2,b},{3,c}]),\"
 2752:             \"beginR=qlc:e(qlc:q([Y||Y<-[X]])),trueend])\">>)
 2753:              == format_info(Q, true),
 2754:           [{1,[1]},{2,[2]},{3,[3]}] = qlc:e(Q)">>,
 2755: 
 2756:        <<"L = [{1,a},{2,b},{3,c}],
 2757:           Q = qlc:q(
 2758:                 [{X,qlc:e(qlc:q([Y || Y <- [X]]))} || 
 2759:                     {X,_} <- qlc_SUITE:table(L, [])]),
 2760:           true = binary_to_list(<<
 2761:             \"qlc:q([{X,qlc:e(qlc:q([Y||Y<-[X]]))}||{X,_}<-qlc_SUITE:\"
 2762:             \"the_list([{1,a},{2,b},{3,c}])])\">>) == format_info(Q, true),
 2763:           [{1,[1]},{2,[2]},{3,[3]}] = qlc:e(Q)">>,
 2764:           
 2765:        <<"L = [{1,a},{2,b}],
 2766:           Q = qlc:q(
 2767:                 [{X,Y} ||
 2768:                     {X,_} <- qlc_SUITE:table(L, []),
 2769:                     {Y,_} <- qlc:q(
 2770:                                [{Z,V} || 
 2771:                                    {Z,_} <- qlc_SUITE:table(L, []),
 2772:                                    {V} <- qlc:q(
 2773:                                               [{W} || W 
 2774:                                                   <- qlc_SUITE:table(L, [])])
 2775:                                       ])
 2776:                        ]),
 2777:           true = binary_to_list(<<
 2778:            \"beginV1=qlc:q([{W}||W<-qlc_SUITE:the_list([{1,a},{2,b}])]),\"
 2779:            \"V2=qlc:q([{Z,V}||{Z,_}<-qlc_SUITE:the_list([{1,a},{2,b}]),\"
 2780:            \"{V}<-V1]),qlc:q([{X,Y}||{X,_}<-qlc_SUITE:the_list([{1,a},\"
 2781:            \"{2,b}]),{Y,_}<-V2])end\">>) == format_info(Q, true),
 2782:           [{1,1},{1,1},{1,2},{1,2},{2,1},{2,1},{2,2},{2,2}] = qlc:e(Q)">>
 2783: 
 2784:        ],
 2785:     ?line run(Config, Ts),
 2786:     ok.
 2787: 
 2788: 
 2789: lookup1(doc) ->
 2790:     "Lookup keys. Mostly test of patterns.";
 2791: lookup1(suite) -> [];
 2792: lookup1(Config) when is_list(Config) ->
 2793:     Ts = [
 2794:        <<"etsc(fun(E) ->
 2795:                 Q = qlc:q([A || {A=3} <- ets:table(E)]),
 2796:                 [3] = qlc:eval(Q),
 2797:                 [3] = lookup_keys(Q) 
 2798:           end, [{1},{2},{3},{4}])">>,
 2799: 
 2800:        <<"etsc(fun(E) ->
 2801:                 Q = qlc:q([A || {A=3} <- ets:table(E)],{max_lookup,0}),
 2802:                 [3] = qlc:eval(Q),
 2803:                 false = lookup_keys(Q) 
 2804:           end, [{1},{2},{3},{4}])">>,
 2805: 
 2806:        <<"%% The lookup and max_lookup options interact.
 2807:           etsc(fun(E) ->
 2808:                 Q = qlc:q([X || {X} <- ets:table(E),
 2809:                                 (X =:= 1) or (X =:= 2)],
 2810:                           [{lookup,true},{max_lookup,1}]),
 2811:                 {'EXIT', {no_lookup_to_carry_out, _}} = (catch qlc:e(Q))
 2812:          end, [{1},{2}])">>,
 2813: 
 2814:        <<"etsc(fun(E) ->
 2815:                 Q = qlc:q([{A,B,C,D} || {A,B}={C,D} <- ets:table(E)]),
 2816:                 [{1,2,1,2},{3,4,3,4}] = lists:sort(qlc:eval(Q)),
 2817:                 false = lookup_keys(Q)
 2818:           end, [{1,2},{3,4}])">>,
 2819: 
 2820:        <<"etsc(fun(E) ->
 2821:                 Q = qlc:q([{A,B,D} || {A,B}={D,A} <- ets:table(E)]),
 2822:                 [{1,1,1},{2,2,2}] = lists:sort(qlc:eval(Q)),
 2823:                 false = lookup_keys(Q)
 2824:           end, [{1,2},{2,2},{1,1}])">>,
 2825: 
 2826:        <<"etsc(fun(E) ->
 2827:                 Q = qlc:q([{A,B,D} || {A,B}={D,A} <- ets:table(E),
 2828:                                       (D =:= 2) or (B =:= 1)],
 2829:                           {max_lookup,infinity}),
 2830:                 [{1,1,1},{2,2,2}] = qlc:eval(Q),
 2831:                 [1,2] = lookup_keys(Q)
 2832:          end, [{1,2},{2,2},{1,1}])">>,
 2833: 
 2834:        <<"etsc(fun(E) ->
 2835:                 Q = qlc:q([{A,B,D} || {A,B}={D,A} <- ets:table(E),
 2836:                                       (D =:= 2) xor (B =:= 1)]),
 2837:                 [{1,1,1},{2,2,2}] = qlc:eval(Q),
 2838:                 [1,2] = lookup_keys(Q)
 2839:          end, [{1,2},{2,2},{1,1}])">>,
 2840: 
 2841:        <<"etsc(fun(E) ->
 2842:                 Q = qlc:q([3 || {{[3,4],apa}} <- ets:table(E)]),
 2843:                 [3] = qlc:e(Q),
 2844:                 [{[3,4],apa}] = lookup_keys(Q)
 2845:         end, [{{[4,3],foo}},{{[3,4],apa}}])">>,
 2846: 
 2847:        <<"etsc(fun(E) ->
 2848:                 Q = qlc:q([3 || {3} <- ets:table(E)]),
 2849:                 [3] = qlc:e(Q),
 2850:                 [3] = lookup_keys(Q)
 2851:         end, [{2},{3},{4}])">>,
 2852: 
 2853:        <<"etsc(fun(E) ->
 2854:                 Q = qlc:q([{X,Y,Z} || {{X,_},Y,Y={_,Z},X,Y} <- ets:table(E)]),
 2855:                 [] = qlc:e(Q),
 2856:                 false = lookup_keys(Q)
 2857:         end, [{{1,1},1,{1,1},1,1}])">>,
 2858: 
 2859:        <<"etsc(fun(E) ->
 2860:                 Q = qlc:q([X || {X,X=2} <- ets:table(E)]),
 2861:                 [2] = qlc:e(Q),
 2862:                 [2] = lookup_keys(Q)
 2863:         end, [{2,2},{3,3}])">>,
 2864: 
 2865:        <<"etsc(fun(E) ->
 2866:                 Q = qlc:q([X || {{_,3}={4,_}=X} <- ets:table(E)]),
 2867:                 [{4,3}] = qlc:e(Q),
 2868:                 [{4,3}] = lookup_keys(Q)
 2869:         end, [{{2,3}},{{4,3}}])">>,
 2870: 
 2871:        <<"U = 17.0,
 2872:           etsc(fun(E) ->
 2873:                 Q = qlc:q([X || {_=X=_} <- ets:table(E)]),
 2874:                 [U] = qlc:e(Q),
 2875:                 false = lookup_keys(Q)
 2876:         end, [{U},{U+U,U}])">>,
 2877: 
 2878:        <<"etsc(fun(E) ->
 2879:                 Q = qlc:q([{X,Y,Z,W} || {X=Y}=Z={V=W} <- ets:table(E), 
 2880:                                         V == {h,g}]),
 2881:                 [{{h,g},{h,g},{{h,g}},{h,g}}] = qlc:e(Q),
 2882:                 [{h,g}] = lookup_keys(Q)
 2883:         end, [{h,g},{{h,g}}])">>,
 2884: 
 2885:        <<"etsc(fun(E) ->
 2886:                 Q = qlc:q([{C,Y,Z,X} || {{X=Y}=Z}={{A=B}=C} <- ets:table(E), 
 2887:                                         A == a, B =/= c]),
 2888:                 [{{a},a,{a},a}] = qlc:e(Q),
 2889:                 [{a}] = lookup_keys(Q)
 2890:         end, [{{1}},{{a}}])">>,
 2891: 
 2892:        <<"etsc(fun(E) ->
 2893:                Q = qlc:q([{A,D,Y,X} || 
 2894:                              {{A={B=C}},{D={C}}} = {X,Y} <- ets:table(E),
 2895:                              [] == B]),
 2896:                 [{{[]},{[]},{{[]}},{{[]}}}] = qlc:e(Q),
 2897:                 [{{[]}}] = lookup_keys(Q)
 2898:         end, [{{{[]}},{{[]}}}])">>,
 2899: 
 2900:        {cres,
 2901:         <<"etsc(fun(E) ->
 2902:                  Q = qlc:q([X || {X}=X <- ets:table(E)]),
 2903:                  [] = qlc:e(Q),
 2904:                  false = lookup_keys(Q)
 2905:          end, [{1},{a}])">>,
 2906:        {warnings,[{{2,37},qlc,nomatch_pattern}]}},
 2907: 
 2908:        <<"etsc(fun(E) ->
 2909:                 Q = qlc:q([X || {X=X,Y=Y}={Y=Y,X=X} <- ets:table(E), 
 2910:                                 {} == X]),
 2911:                 [{}] = qlc:e(Q),
 2912:                 [{}] = lookup_keys(Q)
 2913:         end, [{{},{}},{[],[]}])">>,
 2914: 
 2915:        <<"etsc(fun(E) ->
 2916:                 Q = qlc:q([X || {3+4=7,X} <- ets:table(E), 
 2917:                                 X =:= 3+997]),
 2918:                 [1000] = qlc:e(Q),
 2919:                 [7] = lookup_keys(Q)
 2920:         end, [{7,1000},{8,1000}])">>,
 2921: 
 2922:        <<"etsc(fun(E) ->
 2923:                 Q = qlc:q([{X, Y} || [X]=[Y] <- ets:table(E)]),
 2924:                 [] = qlc:eval(Q),
 2925:                 false = lookup_keys(Q)
 2926:         end, [{a}])">>,
 2927: 
 2928:        {cres,
 2929:         <<"etsc(fun(E) ->
 2930:                  Q = qlc:q([X || X={1,2,3,X,5} <- ets:table(E)]),
 2931:                  [] = qlc:e(Q),
 2932:                  false = lookup_keys(Q)
 2933:          end, [{a},{b}])">>,
 2934:         {warnings,[{{2,35},qlc,nomatch_pattern}]}},
 2935: 
 2936:        {cres,
 2937:         <<"etsc(fun(E) ->
 2938:                  Q = qlc:q([X || X=[1,2,3,X,5] <- ets:table(E)]),
 2939:                  [] = qlc:e(Q),
 2940:                  false = lookup_keys(Q)
 2941:          end, [{a},{b}])">>,
 2942:         {warnings,[{{2,35},qlc,nomatch_pattern}]}},
 2943: 
 2944:        <<"etsc(fun(E) ->
 2945:                 Q = qlc:q([X || X = <<X>> <- ets:table(E)]),
 2946:                 [] = qlc:e(Q),
 2947:                 false = lookup_keys(Q)
 2948:         end, [{a},{b}])">>,
 2949: 
 2950:        <<"Tre = 3.0,
 2951:           etsc(fun(E) ->
 2952:                 Q = qlc:q([{A,B} || {A,B}={{a,C},{a,C}} <- ets:table(E), 
 2953:                                     C =:= Tre]),
 2954:                 [] = qlc:e(Q),
 2955:                 [{a,Tre}] = lookup_keys(Q)
 2956:         end, [{a,b}])">>,
 2957: 
 2958:        <<"A = 3,
 2959:           etsc(fun(E) ->
 2960:                 Q = qlc:q([X || X <- ets:table(E), A =:= element(1, X)]),
 2961:                 [{3,3}] = qlc:e(Q),
 2962:                 [3] = lookup_keys(Q)
 2963:         end, [{1,a},{3,3}])">>,
 2964: 
 2965:        <<"A = 3,
 2966:           etsc(fun(E) ->
 2967:                 Q = qlc:q([X || X <- ets:table(E), A =:= erlang:element(1, X)]),
 2968:                 [{3,3}] = qlc:e(Q),
 2969:                 [3] = lookup_keys(Q)
 2970:         end, [{1,a},{3,3}])">>,
 2971: 
 2972:        <<"etsc(fun(E) ->
 2973:                 A = 3,
 2974:                 Q = qlc:q([X || X <- ets:table(E), 
 2975:                                 A == element(1,X), 
 2976:                                 element(1,X) =:= a]),
 2977:                 [] = qlc:e(Q),
 2978:                 [a] = lookup_keys(Q)
 2979:         end, [{a},{b},{c}])">>,
 2980: 
 2981:        {cres,
 2982:         <<"etsc(fun(E) ->
 2983:                  Q = qlc:q([X || {X = {[a,Z]}, 
 2984:                                   Z = [foo, {[Y]}], 
 2985:                                   Y = {{foo,[X]}}} <- ets:table(E)]),
 2986:                  [] = qlc:e(Q),
 2987:                  false = lookup_keys(Q)
 2988:          end, [{a,b,c},{d,e,f}])">>,
 2989:         {warnings,[{{2,34},qlc,nomatch_pattern}]}}
 2990: 
 2991:        ],
 2992:     ?line run(Config, Ts),
 2993:     ok.
 2994: 
 2995: lookup2(doc) ->
 2996:     "Lookup keys. Mostly test of filters.";
 2997: lookup2(suite) -> [];
 2998: lookup2(Config) when is_list(Config) ->
 2999:     Ts = [
 3000:        <<"%% Only guards are inspected. No lookup.
 3001:           etsc(fun(E) ->
 3002:                  Q = qlc:q([{X,Y} || {X,Y} <- ets:table(E),
 3003:                                      ((Y = X) =:= 3)]),
 3004:                  {'EXIT', {{badmatch,4},_}} = (catch qlc:e(Q))
 3005:          end, [{3,3},{4,true}])">>,
 3006: 
 3007:        <<"%% Only guards are inspected. No lookup.
 3008:           etsc(fun(E) ->
 3009:                  Q = qlc:q([{X,Y} || {X,Y} <- ets:table(E),
 3010:                                      Y = (X =:= 3)]),
 3011:                  {'EXIT', {{badmatch,false},_}} = (catch qlc:e(Q))
 3012:          end, [{false,3},{true,3}])">>,
 3013: 
 3014:        <<"%% Only guards are inspected. No lookup.
 3015:           etsc(fun(E) ->
 3016:                  Q = qlc:q([{X,Y} || {X,Y} <- ets:table(E),
 3017:                                      Y = (X =:= 3)]),
 3018:                  {'EXIT', {{badmatch,false},_}} = (catch qlc:e(Q))
 3019:          end, [{3,true},{4,true}])">>,
 3020: 
 3021:        <<"%% Only guards are inspected. No lookup.
 3022:           E1 = create_ets(1, 10),
 3023:           E2 = ets:new(join, []),
 3024:           true = ets:insert(E2, [{true,1},{false,2}]),
 3025:           Q = qlc:q([{X,Z} || {_,X} <- ets:table(E1),
 3026:                               {Y,Z} <- ets:table(E2),
 3027:                               Y = (X =:= 3)]),
 3028:           {'EXIT', {{badmatch,false},_}} = (catch qlc:e(Q)),
 3029:           ets:delete(E1),
 3030:           ets:delete(E2)">>,
 3031: 
 3032:        <<"etsc(fun(E) ->
 3033:                 Q = qlc:q([{A,B,D} || {A,B}={D,A} <- ets:table(E), 
 3034:                                       (A =:= 3) or (4 =:= D)]),
 3035:                 [{3,3,3},{4,4,4}] = lists:sort(qlc:e(Q)),
 3036:                 [3,4] = lookup_keys(Q)
 3037:         end, [{2,2},{3,3},{4,4}])">>,
 3038: 
 3039:        <<"etsc(fun(E) ->
 3040:                Q = qlc:q([X || {X,U} <- ets:table(E), X =:= U]),
 3041:                [1] = qlc:e(Q),
 3042:                false = lookup_keys(Q)
 3043:        end, [{1,1}])">>,
 3044: 
 3045:        {cres,
 3046:         <<"etsc(fun(E) ->
 3047:                  Q = qlc:q([{X,Y} || {X=Y} <- ets:table(E), 
 3048:                                      {[X],4} =:= {[3],X}]),
 3049:                  [] = qlc:e(Q),
 3050:                  false = lookup_keys(Q)
 3051:          end, [{1}, {2}])">>,
 3052:         {warnings,[{{3,46},qlc,nomatch_filter}]}},
 3053: 
 3054:        {cres,
 3055:         <<"etsc(fun(E) ->
 3056:                 Q = qlc:q([X || {X} <- ets:table(E), 
 3057:                                 X == 1, X =:= 2]),
 3058:                 [] = qlc:e(Q),
 3059:                 false = lookup_keys(Q)
 3060:         end, [{1}, {2}])">>,
 3061:         {warnings,[{{3,43},qlc,nomatch_filter}]}},
 3062: 
 3063:        {cres,
 3064:         <<"etsc(fun(E) ->
 3065:                  Q = qlc:q([{X,Y} || {X=Y} <- ets:table(E), 
 3066:                                      {[X,Y],4} =:= {[3,X],X}]),
 3067:                  [] = qlc:e(Q),
 3068:                  false = lookup_keys(Q)
 3069:          end, [{1}, {2}])">>,
 3070:         {warnings,[{{3,48},qlc,nomatch_filter}]}},
 3071: 
 3072:        <<"etsc(fun(E) ->
 3073:                 Q = qlc:q([{X,Y} || {X,Y} <- ets:table(E), 
 3074:                                     ({X,3} =:= {Y,Y}) or (X =:= 4)]),
 3075:                 [{3,3},{4,4}] = lists:sort(qlc:e(Q)),
 3076:                 [3,4] = lookup_keys(Q)
 3077:         end, [{2,2},{3,3},{4,4},{5,5}])">>,
 3078: 
 3079:        {cres,
 3080:         <<"etsc(fun(E) ->
 3081:                  Q = qlc:q([X || {X} <- ets:table(E), {[X]} =:= {[3,4]}]),
 3082:                  [] = qlc:e(Q),
 3083:                  false = lookup_keys(Q)
 3084:          end, [{[3]},{[3,4]}])">>,
 3085:         {warnings,[{{2,61},qlc,nomatch_filter}]}},
 3086: 
 3087:        <<"etsc(fun(E) ->
 3088:                 U = 18, 
 3089:                 Q = qlc:q([{X,Y} || {X=Y} <- ets:table(E), [X|a] =:= [3|U]]),
 3090:                 [] = qlc:e(Q),
 3091:                 [3] = lookup_keys(Q)
 3092:         end, [{2}, {3}])">>,
 3093: 
 3094:        <<"etsc(fun(E) ->
 3095:                 U = 18, V = 19,
 3096:                 Q = qlc:q([{X,Y} || {X=Y} <- ets:table(E), 
 3097:                                     [X|V] =:= [3|U+1]]),
 3098:                 [{3,3}] = qlc:e(Q),
 3099:                 [3] = lookup_keys(Q)
 3100:         end, [{2},{3}])">>,
 3101: 
 3102:        <<"%% Blocks are not handled.
 3103:           etsc(fun(E) ->
 3104:                 Q = qlc:q([X || {X} <- ets:table(E), begin X == a end]),
 3105:                 [a] = qlc:e(Q),
 3106:                 false = lookup_keys(Q)
 3107:         end, [{a},{b}])">>,
 3108: 
 3109:        {cres,
 3110:         <<"etsc(fun(E) ->
 3111:                  Q = qlc:q([X || {X} <- ets:table(E), 
 3112:                                  (3 =:= X) or (X =:= 12), 
 3113:                                  (8 =:= X) or (X =:= 10)]),
 3114:                  [] = lists:sort(qlc:e(Q)),
 3115:                  false = lookup_keys(Q)
 3116:          end, [{2},{3},{4},{8}])">>,
 3117:         {warnings,[{{4,44},qlc,nomatch_filter}]}},
 3118: 
 3119:        {cres,
 3120:         <<"etsc(fun(E) ->
 3121:                  Q = qlc:q([X || {X} <- ets:table(E),
 3122:                                  ((3 =:= X) or (X =:= 12)) 
 3123:                                   and ((8 =:= X) or (X =:= 10))]),
 3124:                  [] = lists:sort(qlc:e(Q)),
 3125:                  false = lookup_keys(Q)
 3126:          end, [{2},{3},{4},{8}])">>,
 3127:         {warnings,[{{4,35},qlc,nomatch_filter}]}},
 3128: 
 3129:        <<"F = fun(U) ->
 3130:                 Q = qlc:q([X || {X} <- [a,b,c], 
 3131:                                  X =:= if U -> true; true -> false end]),
 3132:                 [] = qlc:eval(Q),
 3133:                 false = lookup_keys(Q)
 3134:               end,
 3135:           F(apa)">>,
 3136: 
 3137:        {cres,
 3138:         <<"etsc(fun(E) ->
 3139:                  Q = qlc:q([X || {X=1,X} <- ets:table(E), X =:= 2]),
 3140:                  [] = qlc:e(Q),
 3141:                  false = lookup_keys(Q)
 3142:            end, [{1,1},{2,1}])">>,
 3143:         {warnings,[{{2,61},qlc,nomatch_filter}]}},
 3144: 
 3145:        <<"Two = 2.0,
 3146:           etsc(fun(E) ->
 3147:                 Q = qlc:q([X || {X} <- ets:table(E), X =:= Two]),
 3148:                 [Two] = qlc:e(Q),
 3149:                 [Two] = lookup_keys(Q)
 3150:         end, [{2.0},{2}])">>,
 3151: 
 3152:        <<"etsc(fun(E) ->
 3153:                 %% This float is equal (==) to an integer. Not a constant!
 3154:                 Q = qlc:q([X || {X} <- ets:table(E), X == {a,b,c,[2.0]}]),
 3155:                 [_,_] = qlc:e(Q),
 3156:                 false = lookup_keys(Q)
 3157:         end, [{{a,b,c,[2]}},{{a,b,c,[2.0]}}])">>,
 3158: 
 3159:        <<"%% Must _not_ regard floats as constants. Check imported variables
 3160:           %% in runtime.
 3161:           etsc(fun(E) -> 
 3162:                 U = 3.0,
 3163:                 QH = qlc:q([X || {X,_} <- ets:table(E), X =:= U]),
 3164:                 [] = qlc:e(QH),
 3165:                 [U] = lookup_keys(QH)
 3166:         end, [{1,a},{2,b},{3,c},{4,d}])">>,
 3167: 
 3168:        <<"etsc(fun(E) ->
 3169:                 Q = qlc:q([X || {X} <- ets:table(E), 
 3170:                                 length(X) =:= 1]),
 3171:                 [[1]] = qlc:e(Q),
 3172:                 false = lookup_keys(Q)
 3173:         end, [{[1]},{[2,3]}])">>,
 3174: 
 3175:        <<"etsc(fun(E) ->
 3176:                 A=3, 
 3177:                 Q = qlc:q([X || {X,Y} <- ets:table(E), X =:= A, Y =:= 3]),
 3178:                 [3] = qlc:e(Q),
 3179:                 [3] = lookup_keys(Q)
 3180:         end, [{3,3},{4,3}])">>,
 3181: 
 3182:        <<"etsc(fun(E) ->
 3183:                 A = 1,
 3184:                 Q = qlc:q([X || {X} <- ets:table(E), 
 3185:                                 X =:= 1, <<X>> =:= <<A>>]),
 3186:                 [1] = qlc:e(Q),
 3187:                 [1] = lookup_keys(Q)
 3188:         end, [{1},{2}])">>,
 3189: 
 3190:        <<"etsc(fun(E) ->
 3191:                 Q = qlc:q([X || {X} <- ets:table(E), X == a]),
 3192:                 [a] = qlc:e(Q),
 3193:                 [a] = lookup_keys(Q)
 3194:         end, [{a},{b},{c}])">>,
 3195: 
 3196:        {cres,
 3197:         <<"etsc(fun(E) ->
 3198:                  Q = qlc:q([X || {X}=Y <- ets:table(E), 
 3199:                                  element(2, Y) == b, 
 3200:                                  X =:= 1]),
 3201:                  [] = qlc:e(Q),
 3202:                  false = lookup_keys(Q)
 3203:          end, [{1,b},{2,3}])">>,
 3204:         {warnings,[{2,sys_core_fold,nomatch_guard},
 3205: 		   {3,qlc,nomatch_filter},
 3206: 		   {3,sys_core_fold,{eval_failure,badarg}}]}},
 3207: 
 3208:        <<"etsc(fun(E) ->
 3209:                 Q = qlc:q([X || {X} <- ets:table(E), element(1,{X}) =:= 1]),
 3210:                 [1] = qlc:e(Q),
 3211:                 [1] = lookup_keys(Q)
 3212:         end, [{1}, {2}])">>,
 3213: 
 3214:        <<"etsc(fun(E) ->
 3215:                 Q = qlc:q([X || {X} <- ets:table(E), 1 =:= element(1,{X})]),
 3216:                 [1] = qlc:e(Q),
 3217:                 [1] = lookup_keys(Q)
 3218:         end, [{1}, {2}])">>,
 3219: 
 3220:        {cres,
 3221:         <<"etsc(fun(E) ->
 3222:                  Q = qlc:q([X || {X} <- ets:table(E), 
 3223:                                  X =:= {1}, 
 3224:                                  element(1,X) =:= 2]),
 3225:                  [] = qlc:e(Q),
 3226:                  false = lookup_keys(Q)
 3227:          end, [{{1}},{{2}}])">>,
 3228:         {warnings,[{{4,47},qlc,nomatch_filter}]}},
 3229: 
 3230:        {cres,
 3231:         <<"etsc(fun(E) ->
 3232:                  Q = qlc:q([X || {X} <- ets:table(E), 
 3233:                                  X =:= {1}, 
 3234:                                  element(1,X) =:= element(1, {2})]),
 3235:                  [] = qlc:e(Q),
 3236:                  false = lookup_keys(Q)
 3237:          end, [{{1}},{{2}}])">>,
 3238:         {warnings,[{{4,47},qlc,nomatch_filter}]}},
 3239: 
 3240:        <<"etsc(fun(E) ->
 3241:                 Q = qlc:q([X || {X} <- ets:table(E),
 3242:                                 element(1,X) =:= 1, X =:= {1}]),
 3243:                 [{1}] = qlc:e(Q),
 3244:                 [{1}] = lookup_keys(Q)
 3245:         end, [{{1}},{{2}}])">>,
 3246: 
 3247:        <<"etsc(fun(E) ->
 3248:                 Q = qlc:q([X || {X} <- ets:table(E),
 3249:                                 {{element(1,element(1,{{1}}))}} =:= {X}]),
 3250:                 [{1}] = qlc:e(Q),
 3251:                 [{1}] = lookup_keys(Q)
 3252:         end, [{{1}},{{2}}])">>,
 3253: 
 3254:        <<"etsc(fun(E) ->
 3255:                 Q = qlc:q([X || X <- ets:table(E),
 3256:                                 {element(1,element(1, {{1}}))} =:= 
 3257:                                       {element(1,X)}]),
 3258:                 [{1}] = qlc:e(Q),
 3259:                 [1] = lookup_keys(Q)
 3260:         end, [{1},{2}])">>,
 3261: 
 3262:        <<"etsc(fun(E) ->
 3263:                 Q = qlc:q([X || {{X,Y}} <- ets:table(E), 
 3264:                                 (X =:= 1) and (Y =:= 2) 
 3265:                                     or (X =:= 3) and (Y =:= 4)]),
 3266:                 [1,3] = lists:sort(qlc:e(Q)),
 3267:                 [{1,2}, {3,4}] = lookup_keys(Q)
 3268:         end, [{{1,2}}, {{3,4}}, {{2,3}}])">>,
 3269: 
 3270:        <<"etsc(fun(E) ->
 3271:                 Q = qlc:q([X || {{X,a}} <- ets:table(E), X =:= 3]),
 3272:                 [3] = qlc:e(Q),
 3273:                 [{3,a}] = lookup_keys(Q)
 3274:         end, [{{3,a}},{{3,b}}])">>,
 3275: 
 3276:        <<"etsc(fun(E) ->
 3277:                 Q = qlc:q([X || {{X,Y},_Z} <- ets:table(E), 
 3278:                                 X =:= 3, Y =:= a]),
 3279:                 [3] = qlc:e(Q),
 3280:                 [{3,a}] = lookup_keys(Q)
 3281:         end, [{{3,a},3}, {{4,a},3}])">>,
 3282: 
 3283:        <<"etsc(fun(E) ->
 3284:                 Q = qlc:q([X || {{X,Y},_Z} <- ets:table(E), 
 3285:                                 (X =:= 3) and (Y =:= a)
 3286:                                    or (X =:= 4) and (Y =:= a)]),
 3287:                 [3,4] = qlc:e(Q),
 3288:                 [{3,a}, {4,a}] = lookup_keys(Q)
 3289:         end, [{{3,a},3}, {{4,a},3}])">>,
 3290: 
 3291:        {cres, 
 3292:         <<"etsc(fun(E) ->
 3293:                  Q = qlc:q([X || {X} <- ets:table(E), 
 3294:                                  (X =:= 3) and (X =:= a)]),
 3295:                  [] = qlc:e(Q),
 3296:                  false = lookup_keys(Q)
 3297:          end, [{3}, {4}])">>,
 3298:         {warnings,[{{3,44},qlc,nomatch_filter}]}},
 3299: 
 3300:        <<"etsc(fun(E) ->
 3301:                 Q = qlc:q([X || {{X,Y}} <- ets:table(E), 
 3302:                                 X =:= 3, ((Y =:= a) or (Y =:= b))]),
 3303:                 [3,3] = qlc:e(Q),
 3304:                 [{3,a},{3,b}] = lists:sort(lookup_keys(Q))
 3305:         end, [{{3,a}},{{2,b}},{{3,b}}])">>,
 3306: 
 3307:        <<"etsc(fun(E) ->
 3308:                 Q = qlc:q([X || {X,Y} <- ets:table(E), 
 3309:                                 ((X =:= 3) or (Y =:= 4))  and (X == a)]),
 3310:                 [a] = qlc:e(Q),
 3311:                 [a] = lookup_keys(Q)
 3312:         end, [{a,4},{3,3}])">>,
 3313: 
 3314:        <<"etsc(fun(E) ->
 3315:                 Q = qlc:q([X || {X,Y} <- ets:table(E), 
 3316:                                 (X =:= 3) or ((Y =:= 4)  and (X == a))]),
 3317:                 [3,a] = lists:sort(qlc:e(Q)),
 3318:                 [3,a] = lookup_keys(Q)
 3319:         end, [{a,4},{3,3}])">>,
 3320: 
 3321:        <<"etsc(fun(E) ->
 3322:                 Q = qlc:q([X || {{X,Y}} <- ets:table(E), 
 3323:                                 (X =:= 3) or ((Y =:= 4)  and (X == a))]),
 3324:                 [3,a] = lists:sort(qlc:e(Q)),
 3325:                 false = lookup_keys(Q)
 3326:         end, [{{3,a}},{{2,b}},{{a,4}}])">>,
 3327: 
 3328:        <<"etsc(fun(E) ->
 3329:                 Q = qlc:q([X || {{X,Y}} <- ets:table(E), 
 3330:                                 ((X =:= 3) or (Y =:= 4))  and (X == a)]),
 3331:                 [a] = lists:sort(qlc:e(Q)),
 3332:                 [{a,4}] = lookup_keys(Q)
 3333:         end, [{{3,a}},{{2,b}},{{a,4}}])">>,
 3334: 
 3335:         <<"etsc(fun(E) ->
 3336:                 NoAnswers = 3*3*3+2*2*2,
 3337:                 Q = qlc:q([{X,Y,Z} || 
 3338:                               {{X,Y,Z}} <- ets:table(E), 
 3339:                               (((X =:= 4) or (X =:= 5)) and
 3340:                                ((Y =:= 4) or (Y =:= 5)) and
 3341:                                ((Z =:= 4) or (Z =:= 5))) or
 3342:                               (((X =:= 1) or (X =:= 2) or (X =:= 3)) and
 3343:                                ((Y =:= 1) or (Y =:= 2) or (Y =:= 3)) and
 3344:                                ((Z =:= 1) or (Z =:= 2) or (Z =:= 3)))],
 3345:                           {max_lookup, NoAnswers}),
 3346:                  {list, {table, _}, _} = i(Q),
 3347:                  [{1,1,1},{2,2,2},{3,3,3}] = lists:sort(qlc:e(Q)),
 3348:                  true = NoAnswers =:= length(lookup_keys(Q))
 3349:          end, [{{1,1,1}},{{2,2,2}},{{3,3,3}},{{3,3,4}},{{4,1,1}}])">>,
 3350: 
 3351:         <<"etsc(fun(E) ->
 3352:                 Q = qlc:q([{X,Y,Z} || 
 3353:                               {{X,Y,Z}} <- ets:table(E), 
 3354:                               (((X =:= 4) or (X =:= 5)) and
 3355:                                ((Y =:= 4) or (Y =:= 5)) and
 3356:                                ((Z =:= 4) or (Z =:= 5))) or
 3357:                               (((X =:= 1) or (X =:= 2) or (X =:= 3)) and
 3358:                                ((Y =:= 1) or (Y =:= 2) or (Y =:= 3)) and
 3359:                                ((Z =:= 1) or (Z =:= 2) or (Z =:= 3)))],
 3360:                           {max_lookup, 10}),
 3361:                  [{1,1,1},{2,2,2},{3,3,3}] = lists:sort(qlc:e(Q)),
 3362:                  {table,{ets,table,[_,[{traverse,{select,_}}]]}} = i(Q)
 3363:          end, [{{1,1,1}},{{2,2,2}},{{3,3,3}},{{3,3,4}},{{4,1,1}}])">>,
 3364: 
 3365:        <<"etsc(fun(E) ->
 3366:                 Q = qlc:q([X || X={_,_,_} <- ets:table(E), 
 3367:                                 element(1, X) =:= 3, element(2, X) == a]),
 3368:                 [{3,a,s}] = qlc:e(Q),
 3369:                 [3] = lookup_keys(Q)
 3370:         end, [{1,c,q},{2,b,r},{3,a,s}])">>,
 3371: 
 3372:        <<"etsc(fun(E) ->
 3373:                 Q = qlc:q([X || X <- ets:table(E), 
 3374:                                 element(0, X) =:= 3]),
 3375:                 [] = qlc:e(Q),
 3376:                 false = lookup_keys(Q)
 3377:         end, [{1},{2}])">>,
 3378: 
 3379:        <<"etsc(fun(E) ->
 3380:                 F = fun(_) -> 3 end, 
 3381:                 %% No occurs check; X =:= F(X) is ignored.
 3382:                 Q = qlc:q([X || {X} <- ets:table(E), 
 3383:                                 X =:= 3, X =:= F(X)]),
 3384:                 {qlc,_,[{generate,_,{list,{table,_},_}},_],[]} = i(Q),
 3385:                 [3] = lists:sort(qlc:e(Q)),
 3386:                 [3] = lookup_keys(Q)
 3387:         end, [{2},{3},{4}])">>,
 3388: 
 3389:        <<"etsc(fun(E) ->
 3390:                 A = a, B = a,
 3391:                 Q = qlc:q([X || {{X,Y}} <- ets:table(E), 
 3392:                                 ((X =:= A) and (Y =:= B))
 3393:                                  or ((X =:= B) and (Y =:= A))]),
 3394:                 [a] = qlc:e(Q),
 3395:                 %% keys are usorted, duplicate removed:
 3396:                 [{a,a}] = lookup_keys(Q) 
 3397:         end, [{{a,a}},{{b,b}}])">>,
 3398: 
 3399:        <<"etsc(fun(E) ->
 3400:                 A = a, B = b,
 3401:                 Q = qlc:q([X || {{X,Y}} <- ets:table(E), 
 3402:                                 ((X =:= A) and (Y =:= B))
 3403:                                  or ((X =:= B) and (Y =:= A))]),
 3404:                 [a,b] = lists:sort(qlc:e(Q)),
 3405:                 [{a,b},{b,a}] = lookup_keys(Q)
 3406:         end, [{{a,b}},{{b,a}},{{c,a}},{{d,b}}])">>,
 3407: 
 3408:        %% The atom 'fail' is recognized - lookup.
 3409:        <<"etsc(fun(E) ->
 3410:                 Q = qlc:q([A || {A} <- ets:table(E), 
 3411:                                 (A =:= 2) 
 3412:                                     orelse fail
 3413:                                    ]),
 3414:                 [2] = lists:sort(qlc:e(Q)),
 3415:                 [2] = lookup_keys(Q)
 3416:            end, [{1},{2}])">>
 3417: 
 3418:        ],
 3419:     ?line run(Config, Ts),
 3420: 
 3421:     TsR = [
 3422:        %% is_record/2,3:
 3423:        <<"etsc(fun(E) ->
 3424:                 Q = qlc:q([element(1, X) || X <- ets:table(E), 
 3425:                                             erlang:is_record(X, r, 2)]),
 3426:                  [r] = qlc:e(Q),
 3427:                  [r] = lookup_keys(Q)
 3428:          end, [{keypos,1}], [#r{}])">>,
 3429:        <<"etsc(fun(E) ->
 3430:                 Q = qlc:q([element(1, X) || X <- ets:table(E), 
 3431:                                             is_record(X, r, 2)]),
 3432:                  [r] = qlc:e(Q),
 3433:                  [r] = lookup_keys(Q)
 3434:          end, [{keypos,1}], [#r{}])">>,
 3435:        {cres,
 3436:         <<"etsc(fun(E) ->
 3437:                 Q = qlc:q([element(1, X) || X <- ets:table(E), 
 3438:                                             record(X, r)]),
 3439:                  [r] = qlc:e(Q),
 3440:                  [r] = lookup_keys(Q)
 3441:          end, [{keypos,1}], [#r{}])">>,
 3442:         {warnings,[{{4,45},erl_lint,{obsolete_guard,{record,2}}}]}},
 3443:        <<"etsc(fun(E) ->
 3444:                 Q = qlc:q([element(1, X) || X <- ets:table(E), 
 3445:                                             erlang:is_record(X, r)]),
 3446:                  [r] = qlc:e(Q),
 3447:                  [r] = lookup_keys(Q)
 3448:          end, [{keypos,1}], [#r{}])">>,
 3449:        <<"etsc(fun(E) ->
 3450:                 Q = qlc:q([element(1, X) || X <- ets:table(E), 
 3451:                                             is_record(X, r)]),
 3452:                  [r] = qlc:e(Q),
 3453:                  [r] = lookup_keys(Q)
 3454:          end, [{keypos,1}], [#r{}])">>
 3455: 
 3456:        ],
 3457:     ?line run(Config, <<"-record(r, {a}).\n">>, TsR),
 3458: 
 3459:     Ts2 = [
 3460:        <<"etsc(fun(E) ->
 3461:                  Q0 = qlc:q([X || 
 3462:                                 X <- ets:table(E),
 3463:                                 (element(1, X) =:= 1) or 
 3464:                                   (element(1, X) =:= 2)],
 3465:                            {cache,ets}),
 3466:                  Q = qlc:q([{X,Y} ||
 3467:                                X <- [1,2],
 3468:                                Y <- Q0]),
 3469:                  {qlc,_,[{generate,_,{list,[1,2]}},
 3470:                          {generate,_,{table,_}}], []} = i(Q),
 3471:                  [{1,{1}},{1,{2}},{2,{1}},{2,{2}}] = lists:sort(qlc:e(Q)),
 3472:                  [1,2] = lookup_keys(Q) 
 3473:           end, [{keypos,1}], [{1},{2}])">>,
 3474: 
 3475:        <<"etsc(fun(E) ->
 3476:                  Q0 = qlc:q([X || 
 3477:                                 X <- ets:table(E),
 3478:                                 (element(1, X) =:= 1) or 
 3479:                                   (element(1, X) =:= 2)]),
 3480:                  Q = qlc:q([{X,Y} ||
 3481:                                X <- [1,2],
 3482:                                Y <- Q0],
 3483:                            {cache,true}),
 3484:                  {qlc,_,[{generate,_,{list,[1,2]}},
 3485:                          {generate,_,{table,_}}],[]} = i(Q),
 3486:                  [1,2] = lookup_keys(Q) 
 3487:           end, [{keypos,1}], [{1},{2}])">>,
 3488: 
 3489:        %% One introduced QLC expression (join, ms), and the cache option.
 3490:        <<"%% Match spec and lookup. The lookup is done twice, which might
 3491:           %% be confusing...
 3492:           etsc(fun(E) ->
 3493:                        Q = qlc:q([{X,Y} ||
 3494:                                      X <- [1,2],
 3495:                                      {Y} <- ets:table(E),
 3496:                                      (Y =:= 1) or (Y =:= 2)],
 3497:                                  []),
 3498:                        [{1,1},{1,2},{2,1},{2,2}] = qlc:e(Q),
 3499:                        {qlc,_,[{generate,_,{list,[1,2]}},
 3500:                                {generate,_,{list,{table,_},_}}],[]} = i(Q),
 3501:                        [1,2] = lookup_keys(Q)
 3502:                end, [{keypos,1}], [{1},{2},{3}])">>,
 3503:        <<"%% The same as last example, but with cache. 
 3504:           %% No cache needed (always one lookup only).
 3505:           etsc(fun(E) ->
 3506:                        Q = qlc:q([{X,Y} ||
 3507:                                      X <- [1,2],
 3508:                                      {Y} <- ets:table(E),
 3509:                                      (Y =:= 1) or (Y =:= 2)],
 3510:                                  [cache]),
 3511:                        [{1,1},{1,2},{2,1},{2,2}] = qlc:e(Q),
 3512:                        {qlc,_,[{generate,_,{list,[1,2]}},
 3513:                                {generate,_,{list,{table,_},_}}],[]} = i(Q),
 3514:                        [1,2] = lookup_keys(Q)
 3515:                end, [{keypos,1}], [{1},{2},{3}])">>,
 3516: 
 3517:        <<"%% And again, this time only lookup, no mach spec.
 3518:           etsc(fun(E) ->
 3519:                        Q = qlc:q([{X,Y} ||
 3520:                                      X <- [1,2],
 3521:                                      Y <- ets:table(E),
 3522:                                      (element(1, Y) =:= 1) 
 3523:                                       or (element(1, Y) =:= 2)],
 3524:                                  []),
 3525:                        [{1,{1}},{1,{2}},{2,{1}},{2,{2}}] = qlc:e(Q),
 3526:                        {qlc,_,[{generate,_,{list,[1,2]}},
 3527:                                {generate,_,{table,_}}],[]} = i(Q),
 3528:                        [1,2] = lookup_keys(Q)
 3529:                end, [{keypos,1}], [{1},{2},{3}])">>,
 3530:        <<"%% As last one, but with cache.
 3531:           %% No cache needed (always one lookup only).
 3532:           etsc(fun(E) ->
 3533:                        Q = qlc:q([{X,Y} ||
 3534:                                      X <- [1,2],
 3535:                                      Y <- ets:table(E),
 3536:                                      (element(1, Y) =:= 1) 
 3537:                                       or (element(1, Y) =:= 2)],
 3538:                                  [cache]),
 3539:                        {qlc,_,[{generate,_,{list,[1,2]}},
 3540:                                {generate,_,{table,_}}],[]} = i(Q),
 3541:                        [{1,{1}},{1,{2}},{2,{1}},{2,{2}}] = qlc:e(Q),
 3542:                        [1,2] = lookup_keys(Q)
 3543:                end, [{keypos,1}], [{1},{2},{3}])">>,
 3544: 
 3545:        <<"%% Lookup only. No cache.
 3546:           etsc(fun(E) ->
 3547:                        Q = qlc:q([{X,Y} ||
 3548:                                      X <- [1,2],
 3549:                                      {Y=2} <- ets:table(E)],
 3550:                                  []),
 3551:                        {qlc,_,[{generate,_,{list,[1,2]}},
 3552:                                {generate,_,{table,_}}],[]} = i(Q),
 3553:                        [{1,2},{2,2}] = qlc:e(Q),
 3554:                        [2] = lookup_keys(Q)
 3555:                end, [{keypos,1}], [{1},{2},{3}])">>,
 3556:        <<"%% Lookup only. No cache.
 3557:           etsc(fun(E) ->
 3558:                        Q = qlc:q([{X,Y} ||
 3559:                                      X <- [1,2],
 3560:                                      {Y=2} <- ets:table(E)],
 3561:                                  [cache]),
 3562:                        {qlc,_,[{generate,_,{list,[1,2]}},
 3563:                                {generate,_,{table,_}}],[]} = i(Q),
 3564:                        [{1,2},{2,2}] = qlc:e(Q),
 3565:                        [2] = lookup_keys(Q)
 3566:                end, [{keypos,1}], [{1},{2},{3}])">>,
 3567: 
 3568:        <<"%% Matchspec only. No cache.
 3569:           etsc(fun(E) ->
 3570:                        Q = qlc:q([{X,Y} ||
 3571:                                      X <- [1,2],
 3572:                                      {Y} <- ets:table(E),
 3573:                                      Y > 1],
 3574:                                  []),
 3575:                        {qlc,_,[{generate,_,{list,[1,2]}},
 3576:                                {generate,_,
 3577:                                 {table,{ets,_,[_,[{traverse,_}]]}}}],[]} = 
 3578:                                        i(Q),
 3579:                        [{1,2},{1,3},{2,2},{2,3}] = qlc:e(Q),
 3580:                        false = lookup_keys(Q)
 3581:                end, [{keypos,1}], [{1},{2},{3}])">>,
 3582:        <<"%% Matchspec only. Cache
 3583:           etsc(fun(E) ->
 3584:                        Q = qlc:q([{X,Y} ||
 3585:                                      X <- [1,2],
 3586:                                      {Y} <- ets:table(E),
 3587:                                      Y > 1],
 3588:                                  [cache]),
 3589:                        {qlc,_,[{generate,_,{list,[1,2]}},
 3590:                             {generate,_,{qlc,_,
 3591:                            [{generate,_,{table,{ets,_,[_,[{traverse,_}]]}}}],
 3592:                           [{cache,ets}]}}],[]} = i(Q),
 3593:                        [{1,2},{1,3},{2,2},{2,3}] = qlc:e(Q),
 3594:                        false = lookup_keys(Q)
 3595:                end, [{keypos,1}], [{1},{2},{3}])">>,
 3596:        <<"%% An empty list. Always unique and cached.
 3597:           Q = qlc:q([X || {X} <- [], X =:= 1, begin X > 0 end],
 3598:                    [{cache,true},{unique,true}]),
 3599:           {qlc,_,[{generate,_,{list,[]}},_],[{unique,true}]} = i(Q),
 3600:           _ = qlc:info(Q),
 3601:           [] = qlc:e(Q)">>,
 3602:        <<"%% A list is always cached.
 3603:           Q = qlc:q([{X,Y} || Y <- [1,2], X <- [2,1,2]],
 3604:                     [cache]),
 3605:           {qlc,_,[{generate,_,{list,[1,2]}},
 3606:                   {generate,_,{list,[2,1,2]}}],[]} = i(Q),
 3607:           [{2,1},{1,1},{2,1},{2,2},{1,2},{2,2}] = qlc:e(Q)">>,
 3608:        <<"%% But a processed list is never cached.
 3609:           Q = qlc:q([{X,Y} || Y <- [1,2], X <- [2,1,2], X > 1],
 3610:                     [cache]),
 3611:           {qlc,_,[{generate,_, {list,[1,2]}},
 3612:                   {generate,_,{qlc,_,
 3613:                                [{generate,_,{list,{list,[2,1,2]},_}}],
 3614:                                [{cache,ets}]}}],[]} = i(Q),
 3615:           [{2,1},{2,1},{2,2},{2,2}] = qlc:e(Q)">>,
 3616:        <<"%% A bug fixed in R11B-2: coalescing simple_qlc:s works now.
 3617:           Q0 = qlc:q([X || {X} <- [{1},{2},{3}]],  {cache, ets}),
 3618:           Q1 = qlc:q([X || X <- Q0], {cache, list}),
 3619:           Q = qlc:q([{Y,X} || Y <- [1,2], X <- Q1, X < 2], {cache, list}),
 3620:           {qlc,_,[{generate,_,{list,_}},
 3621:                   {generate,_,{qlc,_,[{generate,_,{list,{list,_},_}}],
 3622:                                [{cache,ets}]}},_],[]} = i(Q),
 3623:           [{1,1},{2,1}] = qlc:e(Q)">>,
 3624:        <<"Q = qlc:q([{X,Y} || Y <- [1,2], X <- [1,2], X > 1],
 3625:                     [cache,unique]),
 3626:           {qlc,_,[{generate,_,{list,[1,2]}},
 3627:                   {generate,_,{qlc,_,
 3628:                                [{generate,_,{list,{list,[1,2]},_}}],
 3629:                                [{cache,ets},{unique,true}]}}],
 3630:            [{unique,true}]} = i(Q),
 3631:           [{2,1},{2,2}] = qlc:e(Q)">>,
 3632:        <<"L = [1,2,3],
 3633:           QH1 = qlc:q([{X} || X <- L, X > 1]),
 3634:           QH2 = qlc:q([{X} || X <- QH1, X > 0], [cache]),
 3635:           [{{2}},{{3}}] = qlc:e(QH2),
 3636:           {list,{list,{list,L},_},_} = i(QH2)">>,
 3637:        <<"L = [1,2,3,1,2,3],
 3638:           QH1 = qlc:q([{X} || X <- L, X > 1]),
 3639:           QH2 = qlc:q([{X} || X <- QH1, X > 0], [cache,unique]),
 3640:           [{{2}},{{3}}] = qlc:e(QH2),
 3641:           {qlc,_,[{generate,_,{list,{list,{list,L},_},_}}],
 3642:            [{unique,true}]} = i(QH2)">>
 3643: 
 3644:       ],
 3645: 
 3646:     ?line run(Config, Ts2),
 3647: 
 3648:     LTs = [
 3649:        <<"etsc(fun(E) ->
 3650:                        Q  = qlc:q([X || X <- ets:table(E), 
 3651:                                         element(1, X) =:= 1],
 3652:                                   {lookup,true}),
 3653:                        {table,L} = i(Q),
 3654:                        true = is_list(L),
 3655:                        [{1,a}] = qlc:e(Q),
 3656:                        [1] = lookup_keys(Q)
 3657:                end, [{1,a},{2,b}])">>,
 3658:        <<"%% No lookup, use the match spec for traversal instead.
 3659:           etsc(fun(E) ->
 3660:                        Q  = qlc:q([X || X <- ets:table(E), 
 3661:                                         element(1, X) =:= 1],
 3662:                                   {lookup,false}),
 3663:                        {table,{ets,table,_}} = i(Q),
 3664:                        [{1,a}] = qlc:e(Q),
 3665:                        false = lookup_keys(Q)
 3666:                end, [{1,a},{2,b}])">>,
 3667:        <<"%% As last one. {max_lookup,0} has the same effect.
 3668:           etsc(fun(E) ->
 3669:                        Q  = qlc:q([X || X <- ets:table(E), 
 3670:                                         element(1, X) =:= 1],
 3671:                                   {max_lookup,0}),
 3672:                        {table,{ets,table,_}} = i(Q),
 3673:                        [{1,a}] = qlc:e(Q),
 3674:                        false = lookup_keys(Q)
 3675:                end, [{1,a},{2,b}])">>
 3676: 
 3677:        ],
 3678:     ?line run(Config, LTs),
 3679: 
 3680:     ok.
 3681: 
 3682: lookup_rec(doc) ->
 3683:     "Lookup keys. With records.";
 3684: lookup_rec(suite) -> [];
 3685: lookup_rec(Config) when is_list(Config) ->
 3686:     Ts = [
 3687:        <<"etsc(fun(E) ->
 3688:                 Q = qlc:q([A || #r{a = A} <- ets:table(E), 
 3689:                                 (A =:= 3) or (4 =:= A)]),
 3690:                 [3] = qlc:e(Q),
 3691:                 [3,4] = lookup_keys(Q)
 3692:             end, [{keypos,2}], [#r{a = a}, #r{a = 3}, #r{a = 5}])">>,
 3693: 
 3694:        {cres, 
 3695:         <<"etsc(fun(E) ->
 3696:                  Q = qlc:q([A || #r{a = 17 = A} <- ets:table(E),
 3697:                                  (A =:= 3) or (4 =:= A)]),
 3698:                  [] = qlc:e(Q),
 3699:                  false = lookup_keys(Q)
 3700:              end, [{keypos,2}], [#r{a = 17}, #r{a = 3}, #r{a = 5}])">>,
 3701:         {warnings,[{{4,44},qlc,nomatch_filter}]}},
 3702: 
 3703:       <<"%% Compares an integer and a float.
 3704:          etsc(fun(E) ->
 3705:                 Q = qlc:q([A || #r{a = 17 = A} <- ets:table(E),
 3706:                                 (A == 17) or (17.0 == A)]),
 3707:                 [_] = qlc:e(Q),
 3708:                 [_] = lookup_keys(Q)
 3709:             end, [{keypos,2}], [#r{a = 17}, #r{a = 3}, #r{a = 5}])">>,
 3710: 
 3711:       <<"%% Compares an integer and a float.
 3712:          %% There is a test in qlc_pt.erl (Op =:= '=:=', C1 =:= C2), but
 3713:          %% that case is handled in an earlier clause (unify ... E, E).
 3714:          etsc(fun(E) ->
 3715:                 Q = qlc:q([A || #r{a = 17.0 = A} <- ets:table(E),
 3716:                                 (A =:= 17) or (17.0 =:= A)]),
 3717:                 [_] = qlc:e(Q),
 3718:                 [_] = lookup_keys(Q)
 3719:             end, [{keypos,2}], [#r{a = 17.0}, #r{a = 3}, #r{a = 5}])">>,
 3720: 
 3721:       <<"%% Matches an integer and a float.
 3722:          etsc(fun(E) ->
 3723:                 Q = qlc:q([A || #r{a = 17 = A} <- ets:table(E),
 3724:                                 (A =:= 17) or (17.0 =:= A)]),
 3725:                 [_] = qlc:e(Q),
 3726:                 [_] = lookup_keys(Q)
 3727:             end, [{keypos,2}], [#r{a = 17}, #r{a = 3}, #r{a = 5}])">>,
 3728: 
 3729:       <<"etsc(fun(E) ->
 3730:                 F = fun(_) -> 17 end,
 3731:                 Q = qlc:q([A || #r{a = A} <- ets:table(E),
 3732:                                 (F(A) =:= 3) and (A =:= 4)]),
 3733:                 [] = qlc:e(Q),
 3734:                 false = lookup_keys(Q) % F(A) could fail
 3735:             end, [{keypos,2}], [#r{a = 4}, #r{a = 3}, #r{a = 5}])">>,
 3736: 
 3737:       <<"etsc(fun(E) ->
 3738:                 Q = qlc:q([X || {X} <- ets:table(E), 
 3739:                                 #r{} == X]),
 3740:                 [#r{}] = lists:sort(qlc:e(Q)),
 3741:                 {call,_,_,[_,_]} = i(Q, {format, abstract_code}),
 3742:                 [#r{}] = lookup_keys(Q)
 3743:         end, [{#r{}},{#r{a=foo}}])">>,
 3744: 
 3745:       <<"etsc(fun(E) ->
 3746:                 Q = qlc:q([R#r.a || R <- ets:table(E), R#r.a =:= foo]),
 3747:                 [foo] = qlc:e(Q),
 3748:                 [_] = lookup_keys(Q)
 3749:         end, [{keypos,2}], [#r{a=foo}])">>
 3750:        ],
 3751:     ?line run(Config, <<"-record(r, {a}).\n">>, Ts),
 3752:     ok.
 3753: 
 3754: indices(doc) ->
 3755:     "Using indices for lookup.";
 3756: indices(suite) -> [];
 3757: indices(Config) when is_list(Config) ->
 3758:     Ts = [
 3759:        <<"L = [{1,a},{2,b},{3,c}],
 3760:           QH = qlc:q([element(1, X) || X <- qlc_SUITE:table(L, [2]),
 3761:                                        (element(2, X) =:= a)
 3762:                                            or (b =:= element(2, X))]),
 3763:           {list, {table,{qlc_SUITE,list_keys,[[a,b],2,L]}}, _MS} = i(QH),
 3764:           [1,2] = qlc:eval(QH)">>,
 3765: 
 3766:        <<"L = [{1,a},{2,b},{3,c}],
 3767:           QH = qlc:q([element(1, X) || X <- qlc_SUITE:table(L, [2]),
 3768:                                        begin (element(2, X) =:= a)
 3769:                                            or (b =:= element(2, X)) end]),
 3770:           {qlc,_,[{generate,_,{table,{call,_,
 3771:                                {remote,_,_,{atom,_,the_list}},_}}},_],[]}
 3772:                   = i(QH),
 3773:           [1,2] = qlc:eval(QH)">>,
 3774: 
 3775:        <<"L = [{1,a,q},{2,b,r},{3,c,s}],
 3776:           QH = qlc:q([element(1, X) || X <- qlc_SUITE:table(L, [2,3]),
 3777:                                        (element(3, X) =:= q)
 3778:                                            or (r =:= element(3, X))]),
 3779:           {list, {table,{qlc_SUITE,list_keys, [[q,r],3,L]}}, _MS} = i(QH),
 3780:           [1,2] = qlc:eval(QH)">>,
 3781: 
 3782:        <<"L = [{1,a,q},{2,b,r},{3,c,s}],
 3783:           QH = qlc:q([element(1, X) || X <- qlc_SUITE:table(L, 1, [2]),
 3784:                                        (element(3, X) =:= q)
 3785:                                            or (r =:= element(3, X))]),
 3786:           {qlc,_,[{generate,_,{table,{call,_,_,_}}},
 3787:                   _],[]} = i(QH),
 3788:           [1,2] = qlc:eval(QH)">>,
 3789: 
 3790:        <<"L = [{a,1},{b,2},{c,3}],
 3791:           QH = qlc:q([E || {K,I}=E <- qlc_SUITE:table(L, 1, [2]),
 3792:                            ((K =:= a) or (K =:= b) or (K =:= c))
 3793:                                and ((I =:= 1) or (I =:= 2))],
 3794:                      {max_lookup, 3}),
 3795:           {list, {table,{qlc_SUITE,list_keys,[[a,b,c],1,L]}}, _MS} = i(QH),
 3796:           [{a,1},{b,2}] = qlc:eval(QH)">>,
 3797: 
 3798:        <<"L = [{a,1},{b,2},{c,3}],
 3799:           QH = qlc:q([E || {K,I}=E <- qlc_SUITE:table(L, 1, [2]),
 3800:                            ((K =:= a) or (K =:= b) or (K =:= c))
 3801:                                and ((I =:= 1) or (I =:= 2))],
 3802:                      {max_lookup, 2}),
 3803:           {list, {table,{qlc_SUITE,list_keys, [[1,2],2,L]}}, _MS} = i(QH),
 3804:           [{a,1},{b,2}] = qlc:eval(QH)">>,
 3805: 
 3806:        <<"L = [{a,1,x,u},{b,2,y,v},{c,3,z,w}],
 3807:           QH = qlc:q([E || {K,I1,I2,I3}=E <- qlc_SUITE:table(L, 1, [2,3,4]),
 3808:                            ((K =/= a) or (K =/= b) or (K =/= c))
 3809:                              and ((I1 =:= 1) or (I1 =:= 2) or 
 3810:                                   (I1 =:= 3) or (I1 =:= 4))
 3811:                              and ((I2 =:= x) or (I2 =:= z)) 
 3812:                              and ((I3 =:= v) or (I3 =:= w))],
 3813:                      {max_lookup, 5}),
 3814:           {list, {table,{qlc_SUITE,list_keys, [[x,z],3,L]}}, _MS} = i(QH),
 3815:           [{c,3,z,w}] = qlc:eval(QH)">>
 3816: 
 3817:        ],
 3818:     ?line run(Config, <<"-record(r, {a}).\n">>, Ts),
 3819:     ok.
 3820: 
 3821: pre_fun(doc) ->
 3822:     "Test the table/2 callback functions parent_fun and stop_fun.";
 3823: pre_fun(suite) -> [];
 3824: pre_fun(Config) when is_list(Config) ->
 3825:     Ts = [
 3826:        <<"PF = process_flag(trap_exit, true),
 3827:           %% cursor: table killing parent
 3828:           L = [{1,a},{2,b},{3,c}],
 3829:           F1 = fun() ->
 3830:                    QH = qlc:q([element(1, X) || 
 3831:                                 X <- qlc_SUITE:table_kill_parent(L, [2]),
 3832:                                 (element(2, X) =:= a)
 3833:                                     or (b =:= element(2, X))]),
 3834:                    _ = qlc:info(QH),
 3835:                    _ = qlc:cursor(QH)
 3836:                end,
 3837:           Pid1 = spawn_link(F1),
 3838:           receive {'EXIT', Pid1, killed} ->
 3839:               ok
 3840:           end,
 3841:           timer:sleep(1),
 3842:           process_flag(trap_exit, PF)">>,
 3843: 
 3844:        <<"PF = process_flag(trap_exit, true),
 3845:           %% eval without cursor: table killing parent
 3846:           L = [{1,a},{2,b},{3,c}],
 3847:           F2 = fun() ->
 3848:                  QH = qlc:q([element(1, X) || 
 3849:                                 X <- qlc_SUITE:table_kill_parent(L, [2]),
 3850:                                 (element(2, X) =:= a)
 3851:                                     or (b =:= element(2, X))]),
 3852:                  _ = qlc:eval(QH)
 3853:                end,
 3854:           Pid2 = spawn_link(F2),
 3855:           receive {'EXIT', Pid2, killed} ->
 3856:               ok
 3857:           end,
 3858:           process_flag(trap_exit, PF)">>,
 3859: 
 3860:        <<"L = [{1,a},{2,b},{3,c}],
 3861:           QH = qlc:q([element(1, X) || 
 3862:                         X <- qlc_SUITE:table_parent_throws(L, [2]),
 3863:                         (element(2, X) =:= a)
 3864:                             or (b =:= element(2, X))]),
 3865:           _ = qlc:info(QH),
 3866:           {throw,thrown} = (catch {any_term,qlc:cursor(QH)}),
 3867:           {throw,thrown} = (catch {any_term,qlc:eval(QH)})">>,
 3868: 
 3869:        <<"L = [{1,a},{2,b},{3,c}],
 3870:           QH = qlc:q([element(1, X) || 
 3871:                         X <- qlc_SUITE:table_parent_exits(L, [2]),
 3872:                         (element(2, X) =:= a)
 3873:                             or (b =:= element(2, X))]),
 3874:           _ = qlc:info(QH),
 3875:           {'EXIT', {badarith,_}} = (catch qlc:cursor(QH)),
 3876:           {'EXIT', {badarith,_}} = (catch qlc:eval(QH))">>,
 3877: 
 3878:        <<"L = [{1,a},{2,b},{3,c}],
 3879:           QH = qlc:q([element(1, X) || 
 3880:                         X <- qlc_SUITE:table_bad_parent_fun(L, [2]),
 3881:                         (element(2, X) =:= a)
 3882:                             or (b =:= element(2, X))]),
 3883:           {'EXIT', {badarg,_}} = (catch qlc:cursor(QH)),
 3884:           {'EXIT', {badarg,_}} = (catch qlc:eval(QH))">>,
 3885: 
 3886:        <<"%% Very simple test of stop_fun.
 3887:           Ets = ets:new(apa, [public]),
 3888:           L = [{1,a},{2,b},{3,c}],
 3889:           H = qlc:q([X || {X,_} <- qlc_SUITE:stop_list(L, Ets)]),
 3890:           C = qlc:cursor(H),
 3891:           [{stop_fun,StopFun}] = ets:lookup(Ets, stop_fun),
 3892:           StopFun(),
 3893:           {'EXIT', {{qlc_cursor_pid_no_longer_exists, _}, _}} =
 3894:                   (catch qlc:next_answers(C, all_remaining)),
 3895:           ets:delete(Ets)">>
 3896: 
 3897:        ],
 3898:     
 3899:     ?line run(Config, Ts),
 3900:     ok.
 3901: 
 3902: skip_filters(doc) ->
 3903:     "Lookup keys. With records.";
 3904: skip_filters(suite) -> [];
 3905: skip_filters(Config) when is_list(Config) ->
 3906:     %% Skipped filters
 3907:     TsS = [
 3908:        %% Cannot skip the filter.
 3909:        <<"etsc(fun(E) ->
 3910:                 H = qlc:q([X || X <- ets:table(E), 
 3911:                           (element(1, X) =:= 1) xor (element(1, X) =:= 1)]),
 3912:                 [] = qlc:eval(H),
 3913:                 [1] = lookup_keys(H)
 3914:                end, [{keypos,1}], [{1},{2}])">>,
 3915: 
 3916:        %% The filter can be skipped. Just a lookup remains.
 3917:        <<"etsc(fun(E) ->
 3918:                 H = qlc:q([X || X <- ets:table(E), 
 3919:                           (element(1, X) =:= 1) or (element(1, X) =:= 1)]),
 3920:                 [{1}] = qlc:eval(H),
 3921:                 {table, _} = i(H),
 3922:                 [1] = lookup_keys(H)
 3923:                end, [{keypos,1}], [{1},{2}])">>,
 3924: 
 3925:        %% safe_unify fails on 3 and <<X:32>>
 3926:        <<"etsc(fun(E) ->
 3927:                 H = qlc:q([X || X <- ets:table(E), 
 3928:                      (element(1, X) =:= 1) and (3 =:= <<X:32>>)]),
 3929:                 [] = qlc:eval(H),
 3930:                 [1] = lookup_keys(H)
 3931:                end, [{keypos,1}], [{1},{2}])">>,
 3932: 
 3933:        %% Two filters are skipped.
 3934:        <<"etsc(fun(E) ->
 3935:                 Q = qlc:q([{B,C,D} || {A={C},B} <- ets:table(E), 
 3936:                                       (A =:= {1}) or (A =:= {2}),
 3937:                                       (C =:= 1) or (C =:= 2),
 3938:                                       D <- [1,2]]),
 3939:                 {qlc,_,[{generate,_,{table,_}},{generate,_,{list,[1,2]}}],[]}
 3940:                   = i(Q),
 3941:                 [{1,1,1},{1,1,2},{2,2,1},{2,2,2}] = lists:sort(qlc:eval(Q)),
 3942:                 [{1},{2}] = lookup_keys(Q)
 3943:          end, [{{1},1},{{2},2},{{3},3}])">>,
 3944: 
 3945:        <<"etsc(fun(E) ->
 3946:                 Q = qlc:q([{B,C} || {A={C},B} <- ets:table(E), 
 3947:                                     (A =:= {1}) or (A =:= {2}),
 3948:                                     (C =:= 1) or (C =:= 2)]),
 3949:                 {qlc,_,[{generate,_,{table,_}}],[]} = i(Q),
 3950:                 [{1,1},{2,2}] = lists:sort(qlc:eval(Q)),
 3951:                 [{1},{2}] = lookup_keys(Q)
 3952:          end, [{{1},1},{{2},2},{{3},3}])">>,
 3953: 
 3954:        %% Lookup. No match spec, no filter.
 3955:        <<"etsc(fun(E) ->
 3956:                 Q = qlc:q([X || X <- ets:table(E), 
 3957:                                element(1, X) =:= 1]),
 3958:                 {table, _} = i(Q),
 3959:                 [{1}] = qlc:e(Q),
 3960:                 [1] = lookup_keys(Q)
 3961:          end, [{1},{2}])">>,
 3962: 
 3963:        <<"etsc(fun(E) ->
 3964:                  Q = qlc:q([{X,Y} || X <- ets:table(E), 
 3965:                                      element(1, X) =:= 1,
 3966:                                      Y <- [1,2]]),
 3967:                  {qlc,_,[{generate,_,{table,_}},{generate,_,{list,_}}],[]}
 3968:                       = i(Q),
 3969:                  [{{1},1},{{1},2}] = lists:sort(qlc:e(Q)),
 3970:                  [1] = lookup_keys(Q)
 3971:          end, [{1},{2}])">>,
 3972: 
 3973:        <<"etsc(fun(E) ->
 3974:                  Q = qlc:q([X || {X,Y} <- ets:table(E), 
 3975:                                  X =:= a, 
 3976:                                  X =:= Y]),
 3977:                  {list,{table,_},_} = i(Q),
 3978:                  [a] = qlc:e(Q),
 3979:                  [a] = lookup_keys(Q)
 3980:           end, [{a,a},{b,c},{c,a}])">>,
 3981: 
 3982:        %% The imported variable (A) is never looked up in the current
 3983:        %% implementation. This means that the first filter cannot be skipped;
 3984:        %% the constant 'a' is looked up, and then the first filter evaluates
 3985:        %% to false.
 3986:        <<"etsc(fun(E) ->
 3987:                  A = 3,
 3988:                  Q = qlc:q([X || X <- ets:table(E), 
 3989:                                  A == element(1,X),
 3990:                                  element(1,X) =:= a]),
 3991:                  [] = qlc:e(Q),
 3992:                  [a] = lookup_keys(Q)
 3993:           end, [{a},{b},{c}])">>,
 3994: 
 3995:        %% No lookup.
 3996:        {cres, 
 3997:         <<"etsc(fun(E) ->
 3998:                   Q = qlc:q([X || {X} <- ets:table(E), 
 3999:                                   X =:= 1, 
 4000:                                   X =:= 2]),
 4001:                   {table, _} = i(Q),
 4002:                   [] = qlc:e(Q),
 4003:                   false = lookup_keys(Q)
 4004:           end, [{1,1},{2,0}])">>,
 4005:         {warnings,[{{4,37},qlc,nomatch_filter}]}},
 4006: 
 4007:        <<"etsc(fun(E) ->
 4008:                  Q = qlc:q([{A,B,C} ||
 4009:                                {A} <- ets:table(E),
 4010:                                A =:= 1,
 4011:                                {B} <- ets:table(E),
 4012:                                B =:= 2,
 4013:                                {C} <- ets:table(E),
 4014:                                C =:= 3]),
 4015:                  {qlc,_,[{generate,_,{list,{table,_},_}},
 4016:                          {generate,_,{list,{table,_},_}},
 4017:                          {generate,_,{list,{table,_},_}}],[]} = i(Q),
 4018:                  [{1,2,3}] = qlc:e(Q),
 4019:                  [1,2,3] = lookup_keys(Q)
 4020:           end, [{0},{1},{2},{3},{4}])">>
 4021: 
 4022:            ],
 4023:     ?line run(Config, TsS),
 4024: 
 4025:     Ts = [
 4026:        <<"etsc(fun(E) ->
 4027:                  H = qlc:q([X || {X,_} <- ets:table(E),
 4028:                                  X =:= 2]),
 4029:                  {list,{table,_},_} = i(H),
 4030:                  [2] = qlc:e(H)
 4031:          end, [{1,a},{2,b}])">>,
 4032: 
 4033:        <<"etsc(fun(E) ->
 4034:                  H = qlc:q([X || {X,_} <- ets:table(E),
 4035:                                  ((X =:= 2) or (X =:= 1)) and (X > 1)]),
 4036:                  {list,{table,_},_} = i(H),
 4037:                  [2] = qlc:e(H)
 4038:          end, [{1,a},{2,b}])">>,
 4039: 
 4040:        <<"etsc(fun(E) ->
 4041:                  H = qlc:q([X || {X,Y} <- ets:table(E),
 4042:                                  (X =:= 2) and (Y =:= b)]),
 4043:                  {list,{table,_},_} = i(H),
 4044:                  [2] = qlc:e(H)
 4045:          end, [{1,a},{2,b}])">>,
 4046: 
 4047:        <<"etsc(fun(E) ->
 4048:                  H = qlc:q([X || X <- ets:table(E),
 4049:                                  (element(1,X) =:= 2) and (X =:= {2,b})]),
 4050:                  {list,{table,_},_} = i(H),
 4051:                  [{2,b}] = qlc:e(H)
 4052:          end, [{1,a},{2,b}])">>,
 4053: 
 4054:        <<"etsc(fun(E) ->
 4055:                  H = qlc:q([{X,Y,Z,W} || 
 4056:                                {X,Y} <- ets:table(E),
 4057:                                {Z,W} <- ets:table(E),
 4058:                                (Y =:= 3) or (Y =:= 4)]),
 4059:                  {qlc,_,[{generate,_,{table,{ets,table,_}}},
 4060:                          {generate,_,{table,{ets,table,_}}}],[]} = i(H),
 4061:                  [{a,3,a,3},{a,3,b,5}] = lists:sort(qlc:e(H))
 4062:          end, [{a,3},{b,5}])">>,
 4063: 
 4064:        <<"etsc(fun(E) ->
 4065:                  H = qlc:q([{X,Y} || 
 4066:                                {X,Y=3} <- ets:table(E), % no matchspec
 4067:                                %% Two columns restricted, but lookup anyway
 4068:                                (X =:= a)]),
 4069:                  {qlc,_,[{generate,_,{table,_}}],[]} = i(H),
 4070:                  [{a,3}] = qlc:e(H)
 4071:          end, [{a,3},{b,4}])">>,
 4072: 
 4073:        <<"etsc(fun(E) ->
 4074:                  V = 3,
 4075:                  H = qlc:q([{X,Y} || 
 4076:                                {X,Y} <- ets:table(E),
 4077:                                (Y =:= V)]), % imported variable, no lookup
 4078:                  {table,{ets,table,_}} = i(H),
 4079:                  [{a,3}] = qlc:e(H)
 4080:          end, [{a,3},{b,4}])">>,
 4081: 
 4082:        <<"etsc(fun(E) ->
 4083:                  V = b,
 4084:                  H = qlc:q([{X,Y} || 
 4085:                                {X,Y} <- ets:table(E),
 4086:                                (X =:= V)]), % imported variable, lookup
 4087:                  {list,{table,_},_} = i(H),
 4088:                  [{b,4}] = qlc:e(H)
 4089:          end, [{a,3},{b,4}])">>,
 4090: 
 4091:        <<"H = qlc:q([{A,B} || {{A,B}} <- [{{1,a}},{{2,b}}],
 4092:                               A =:= 1,
 4093:                               B =:= a]),
 4094:               {list,{list,[_,_]},_} = i(H),
 4095:               [{1,a}] = qlc:e(H)">>,
 4096: 
 4097:        <<"etsc(fun(E) ->
 4098:                  H = qlc:q([{A,B} || {{A,B}} <- ets:table(E),
 4099:                                      A =:= 1,
 4100:                                      B =:= a]),
 4101:                  {list,{table,_},_} = i(H),
 4102:                  [{1,a}] = qlc:e(H)
 4103:          end, [{{1,a}},{{2,b}}])">>,
 4104: 
 4105:        %% The filters are skipped, and the guards of the match specifications
 4106:        %% are skipped as well. Only the transformations of the matchspecs
 4107:        %% are kept.
 4108:        <<"etsc(fun(E1) ->
 4109:                  etsc(fun(E2) ->
 4110:                               H = qlc:q([{X,Y,Z,W} ||
 4111:                                              {X,_}=Z <- ets:table(E1),
 4112:                                              W={Y} <- ets:table(E2),
 4113:                                              (X =:= 1) or (X =:= 2),
 4114:                                              (Y =:= a) or (Y =:= b)]
 4115:                                          ,{lookup,true}
 4116:                                         ),
 4117:                               {qlc,_,[{generate,_,{list,{table,_},
 4118:                                                    [{{'$1','_'},[],['$_']}]}},
 4119:                                       {generate,_,{list,{table,_},
 4120:                                                    [{{'$1'},[],['$_']}]}}],[]}
 4121:                               = i(H),
 4122:                               [{1,a,{1,a},{a}},
 4123:                                {1,b,{1,a},{b}},
 4124:                                {2,a,{2,b},{a}},
 4125:                                {2,b,{2,b},{b}}] = qlc:e(H)
 4126:                       end, [{a},{b}])
 4127:          end, [{1,a},{2,b}])">>,
 4128: 
 4129:        %% The same example again, but this time no match specs are run.
 4130:        <<"fun(Z) -> 
 4131:               etsc(fun(E1) ->
 4132:                      etsc(fun(E2) ->
 4133:                                   H = qlc:q([{X,Y} ||
 4134:                                                  Z > 2,
 4135:                                                  X <- ets:table(E1),
 4136:                                                  Y <- ets:table(E2),
 4137:                                                  (element(1, X) =:= 1) or
 4138:                                                  (element(1, X) =:= 2),
 4139:                                                  (element(1, Y) =:= a) or
 4140:                                                  (element(1, Y) =:= b)]
 4141:                                              ,{lookup,true}
 4142:                                             ),
 4143:                                   {qlc,_,[_,{generate,_,{table,_}},
 4144:                                           {generate,_,{table,_}}],[]} = i(H),
 4145:                                   [{{1,a},{a}},
 4146:                                    {{1,a},{b}},
 4147:                                    {{2,b},{a}},
 4148:                                    {{2,b},{b}}] = qlc:e(H)
 4149:                           end, [{a},{b}])
 4150:              end, [{1,a},{2,b}])
 4151:          end(4)">>,
 4152: 
 4153:        %% Once again, this time with a join.
 4154:        <<"etsc(fun(E1) ->
 4155:                  etsc(fun(E2) ->
 4156:                               H = qlc:q([{X,Y,Z,W} ||
 4157:                                              {X,V}=Z <- ets:table(E1),
 4158:                                              W={Y} <- ets:table(E2),
 4159:                                              (X =:= 1) or (X =:= 2),
 4160:                                              (Y =:= a) or (Y =:= b),
 4161:                                              Y =:= V]
 4162:                                          ,[{lookup,true},{join,merge}]
 4163:                                         ),
 4164:                               {qlc,_,[{generate,_,{qlc,_,
 4165:                                 [{generate,_,{qlc,_,[{generate,_,
 4166:                                     {keysort,{list,{table,_},_},2,[]}},
 4167:                                  _C1,_C2],[]}},
 4168:                                   {generate,_,
 4169:                                       {qlc,_,[{generate, _,
 4170:                                          {keysort,{list,{table,_},_},1,[]}},
 4171:                                               _C3],
 4172:                                        []}},
 4173:                                  _],
 4174:                                 [{join,merge}]}},_],[]} = i(H),
 4175:                               [{1,a,{1,a},{a}},{2,b,{2,b},{b}}] = 
 4176:                                   lists:sort(qlc:e(H))
 4177:                       end, [{a},{b}])
 4178:          end, [{1,a},{2,b}])">>,
 4179: 
 4180:        %% Filters 2 and 3 are not skipped. 
 4181:        %% (Only one filter at a time is tried by the parse transform.)
 4182:        <<"etsc(fun(E) ->
 4183:                  H = qlc:q([X || {{A,B}=X,Y} <- ets:table(E), % no matchspec
 4184:                                      Y =:= 3,
 4185:                                      A =:= 1,
 4186:                                      B =:= a]),
 4187: 
 4188:                  {qlc,_,[{generate,_,{table,_}},_,_,_],[]}= i(H),
 4189:                  [{1,a}] = qlc:e(H)
 4190:          end, [{{1,a},3},{{2,b},4}])">>,
 4191: 
 4192:        <<"etsc(fun(E) ->
 4193:                  H = qlc:q([X || {X=_,_} <- ets:table(E), % no matchspec
 4194:                                   (X =:= 3) and (X > 3)]),
 4195:                  {qlc,_,[{generate,_,{table,_}},_],[]} = i(H),
 4196:                  [] = qlc:e(H)
 4197:          end, [{3,a},{4,b}])">>,
 4198: 
 4199:        <<"etsc(fun(E) ->
 4200:                  H = qlc:q([X || {X=_,_} <- ets:table(E), % no matchspec
 4201:                                  (X =:= 3) or true]),
 4202:                  {qlc,_,[{generate,_,{table,{ets,table,_}}},_],[]} = i(H),
 4203:                  [3,4] = lists:sort(qlc:e(H))
 4204:          end, [{3,a},{4,b}])">>,
 4205: 
 4206:        <<"etsc(fun(E) ->
 4207:                  H = qlc:q([X || {X=_,_} <- ets:table(E), % no matchspec
 4208:                                  (X =:= 3) or false]),
 4209:                  {qlc,_,[{generate,_,{table,_}}],[]} = i(H),
 4210:                  [3] = lists:sort(qlc:e(H))
 4211:          end, [{3,a},{4,b}])">>,
 4212: 
 4213:        <<"etsc(fun(E) ->
 4214:                  H = qlc:q([X || {X=_,_} <- ets:table(E), % no matchspec
 4215:                                  (X =:= X) and (X =:= 3)]),
 4216:                  {qlc,_,[{generate,_,{table,_}}],[]} = i(H),
 4217:                  [3] = lists:sort(qlc:e(H))
 4218:          end, [{3,a},{4,b}])">>,
 4219: 
 4220:        %% The order of filters matters. A guard filter cannot be used
 4221:        %% unless there are no non-guard filter placed before the guard
 4222:        %% filter that uses the guard filter's generator. There is
 4223:        %% more examples in join_filter().
 4224:        <<"etsc(fun(E) ->
 4225:                  %% Lookup. 
 4226:                  Q = qlc:q([{A,B,A} ||
 4227:                                {A=_,B} <- ets:table(E), % no match spec
 4228:                                A =:= 1,
 4229:                                begin 1/B > 0 end]),
 4230:                  [{1,1,1}] = lists:sort(qlc:e(Q))
 4231:          end, [{1,1},{2,0}])">>,
 4232:        <<"etsc(fun(E) ->
 4233:                  %% No lookup. 
 4234:                  Q = qlc:q([{A,B,A} ||
 4235:                                {A=_,B} <- ets:table(E), % no match spec
 4236:                                begin 1/B > 0 end,
 4237:                                A =:= 1]),
 4238:                  {'EXIT', _} = (catch qlc:e(Q))
 4239:          end, [{1,1},{2,0}])">>,
 4240:        %% The same thing, with a match specification.
 4241:        <<"etsc(fun(E) ->
 4242:                  Q = qlc:q([{A,B,A} ||
 4243:                                {A,B} <- ets:table(E), % match spec
 4244:                                A < 2,
 4245:                                begin 1/B > 0 end]),
 4246:                  [{1,1,1}] = lists:sort(qlc:e(Q))
 4247:          end, [{1,1},{2,0}])">>,
 4248:        <<"etsc(fun(E) ->
 4249:                  Q = qlc:q([{A,B,A} ||
 4250:                                {A,B} <- ets:table(E), % match spec
 4251:                                begin 1/B > 0 end,
 4252:                                A < 2]),
 4253:                  {'EXIT', _} = (catch qlc:e(Q))
 4254:          end, [{1,1},{2,0}])">>,
 4255:        %% More examples, this time two tables.
 4256:        <<"etsc(fun(E) ->
 4257:                  Q = qlc:q([{A,B,C,D} ||
 4258:                                {A,B} <- ets:table(E), % match spec
 4259:                                A < 2,
 4260:                                {C,D} <- ets:table(E),
 4261:                                begin 1/B > 0 end, %\"invalidates\" next filter
 4262:                                C =:= 1,
 4263:                                begin 1/D > 0 end]),
 4264:                  {qlc,_,[{generate,_,{table,{ets,table,_}}},
 4265:                          {generate,_,{table,{ets,table,_}}},
 4266:                          _,_,_],[]} = i(Q),
 4267:                  [{1,1,1,1}] = lists:sort(qlc:e(Q))
 4268:          end, [{1,1},{2,0}])">>,
 4269:        <<"etsc(fun(E) ->
 4270:               Q = qlc:q([{A,B,C,D} ||
 4271:                             {A,B} <- ets:table(E),
 4272:                             {C,D} <- ets:table(E),
 4273:                             begin 1/B > 0 end, % \"invalidates\" two filters
 4274:                             A < 2,
 4275:                             C =:= 1,
 4276:                             begin 1/D > 0 end]),
 4277:               {qlc,_,[{generate,_,{table,{ets,table,_}}},
 4278:                       {generate,_,{table,{ets,table,_}}},_,_,_,_],[]} = i(Q),
 4279:               {'EXIT', _} = (catch qlc:e(Q))
 4280:          end, [{1,1},{2,0}])">>,
 4281:       <<"%% There are objects in the ETS table, but none passes the filter.
 4282:          %% F() would not be run if it did not \"invalidate\" the following
 4283:          %% guards. 
 4284:          etsc(fun(E) ->
 4285:                       F = fun() -> [foo || A <- [0], 1/A] end,
 4286:                       Q1 = qlc:q([X || {X} <- ets:table(E),
 4287:                                        F(), % \"invalidates\" next guard
 4288:                                        X =:= 17]),
 4289:                       {'EXIT', _} = (catch qlc:e(Q1))
 4290:               end, [{1},{2},{3}])">>,
 4291:        <<"%% The last example works just like this one:
 4292:           etsc(fun(E) ->
 4293:                       F = fun() -> [foo || A <- [0], 1/A] end,
 4294:                       Q1 = qlc:q([X || {X} <- ets:table(E),
 4295:                                        F(),
 4296:                                        begin X =:= 17 end]),
 4297:                       {'EXIT', _} = (catch qlc:e(Q1))
 4298:               end, [{1},{2},{3}])">>
 4299: 
 4300:           ],
 4301:     ?line run(Config, Ts),
 4302: 
 4303:     ok.
 4304: 
 4305: 
 4306: ets(doc) ->
 4307:     "ets:table/1,2.";
 4308: ets(suite) -> [];
 4309: ets(Config) when is_list(Config) ->
 4310:     Ts = [
 4311:        <<"E = ets:new(t, [ordered_set]),
 4312:           true = ets:insert(E, [{1},{2}]),
 4313:           {'EXIT', _} = 
 4314:               (catch qlc:e(qlc:q([X || {X} <- ets:table(E, bad_option)]))),
 4315:           {'EXIT', _} = 
 4316:               (catch qlc:e(qlc:q([X || {X} <- ets:table(E,{traverse,bad})]))),
 4317:           All = [{'$1',[],['$1']}],
 4318:           TravAll = {traverse,{select,All}},
 4319:           [_, _] = qlc:e(qlc:q([X || {X} <- ets:table(E, TravAll)])),
 4320:           [_, _] = qlc:e(qlc:q([X || {X} <- ets:table(E,{traverse,select})])),
 4321:           [1,2] = 
 4322:              qlc:e(qlc:q([X || {X} <- ets:table(E, {traverse, first_next})])),
 4323:           [2,1] = 
 4324:              qlc:e(qlc:q([X || {X} <- ets:table(E, {traverse, last_prev})])),
 4325:           {table,{ets,table,[_,[{traverse,{select,_}},{n_objects,1}]]}} = 
 4326:               i(qlc:q([X || {X} <- ets:table(E, {n_objects,1})])),
 4327:           {qlc,_,[{generate,_,{table,{ets,table,[_,{n_objects,1}]}}},_],[]} =
 4328:               i(qlc:q([X || {X} <- ets:table(E,{n_objects,1}), 
 4329:                                    begin (X >= 1) or (X < 1) end])),
 4330:           {qlc,_,[{generate,_,{table,{ets,table,[_]}}},_],[]} = 
 4331:               i(qlc:q([X || {X} <- ets:table(E), 
 4332:                                    begin (X >= 1) or (X < 1) end])),
 4333:           ets:delete(E)">>,
 4334: 
 4335:        begin
 4336:        MS = ets:fun2ms(fun({X,Y}) when X > 1 -> {X,Y} end),
 4337:        [<<"E = ets:new(apa,[]),
 4338:            true = ets:insert(E, [{1,a},{2,b},{3,c}]),
 4339:            MS =  ">>, io_lib:format("~w", [MS]), <<",
 4340:            Q = qlc:q([X || {X,_} <- ets:table(E, {traverse, {select, MS}}), 
 4341:                            X =:= 1]),
 4342:            R = qlc:e(Q),
 4343:            ets:delete(E),
 4344:            [] = R">>]
 4345:        end
 4346: 
 4347:        ],
 4348:     
 4349:     ?line run(Config, Ts),
 4350:     ok.
 4351: 
 4352: dets(doc) ->
 4353:     "dets:table/1,2.";
 4354: dets(suite) -> [];
 4355: dets(Config) when is_list(Config) ->
 4356:     dets:start(),
 4357:     T = t,
 4358:     Fname = filename(T, Config),
 4359:     Ts = [
 4360:        [<<"T = t, Fname = \"">>, Fname, <<"\",
 4361:            file:delete(Fname),
 4362:            {ok, _} = dets:open_file(T, [{file,Fname}]),
 4363:            ok = dets:insert(T, [{1},{2}]),
 4364:            {'EXIT', _} = 
 4365:               (catch qlc:e(qlc:q([X || {X} <- dets:table(T, bad_option)]))),
 4366:            {'EXIT', _} = 
 4367:               (catch qlc:e(qlc:q([X || {X} <- dets:table(T,{traverse,bad})]))),
 4368:            {'EXIT', _} = 
 4369:               (catch 
 4370:                qlc:e(qlc:q([X || {X} <- dets:table(T,{traverse,last_prev})]))),
 4371:            All = [{'$1',[],['$1']}],
 4372:            TravAll = {traverse,{select,All}},
 4373:            [_,_] = qlc:e(qlc:q([X || {X} <- dets:table(T, TravAll)])),
 4374:            [_,_] = qlc:e(qlc:q([X || {X} <- dets:table(T,{traverse,select})])),
 4375:            [_,_] = 
 4376:              qlc:e(qlc:q([X || {X} <- dets:table(T, {traverse, first_next})])),
 4377:            {table,{dets,table,[T,[{traverse,{select,_}},{n_objects,1}]]}} =
 4378:                i(qlc:q([X || {X} <- dets:table(T, {n_objects,1})])),
 4379:            {qlc,_,[{generate,_,{table,{dets,table,[t,{n_objects,1}]}}},_],[]}=
 4380:                i(qlc:q([X || {X} <- dets:table(T,{n_objects,1}), 
 4381:                              begin (X >= 1) or (X < 1) end])),
 4382:            {qlc,_,[{generate,_,{table,{dets,table,[_]}}},_],[]} = 
 4383:                i(qlc:q([X || {X} <- dets:table(T), 
 4384:                              begin (X >= 1) or (X < 1) end])),
 4385:            H = qlc:q([X || {X} <- dets:table(T, {n_objects, default}),
 4386:                            begin (X =:= 1) or (X =:= 2) or (X =:= 3) end]),
 4387:            [1,2] = lists:sort(qlc:e(H)),
 4388:            {qlc,_,[{generate,_,{table,_}},_],[]} = i(H),
 4389: 
 4390:            H2 = qlc:q([X || {X} <- dets:table(T), (X =:= 1) or (X =:= 2)]),
 4391:            [1,2] = lists:sort(qlc:e(H2)),
 4392:            {list,{table,_},_} = i(H2),
 4393:            true = binary_to_list(<<
 4394:             \"ets:match_spec_run(lists:flatmap(fun(V)->dets:lookup(t,V)end,\"
 4395:             \"[1,2]),ets:match_spec_compile([{{'$1'},[],['$1']}]))\">>)
 4396:                    == format_info(H2, true),
 4397: 
 4398:            H3 = qlc:q([X || {X} <- dets:table(T), (X =:= 1)]),
 4399:            [1] = qlc:e(H3),
 4400:            {list,{table,_},_} = i(H3),
 4401: 
 4402:            ok = dets:close(T),
 4403:            file:delete(\"">>, Fname, <<"\"),
 4404:            ok">>],
 4405: 
 4406:        begin
 4407:        MS = ets:fun2ms(fun({X,Y}) when X > 1 -> {X,Y} end),
 4408:        [<<"T = t, Fname = \"">>, Fname, <<"\",
 4409:            {ok, _} = dets:open_file(T, [{file,Fname}]),
 4410:            MS =  ">>, io_lib:format("~w", [MS]), <<",
 4411:            ok = dets:insert(T, [{1,a},{2,b},{3,c}]),
 4412:            Q = qlc:q([X || {X,_} <- dets:table(T, {traverse, {select, MS}}), 
 4413:                            X =:= 1]),
 4414:            R = qlc:e(Q),
 4415:            ok = dets:close(T),
 4416:            file:delete(\"">>, Fname, <<"\"),
 4417:            [] = R">>]
 4418:        end,
 4419: 
 4420:        [<<"T = t, Fname = \"">>, Fname, <<"\",
 4421:            {ok, _} = dets:open_file(T, [{file,Fname}]),
 4422:            Objs = [{X} || X <- lists:seq(1,10)],
 4423:            ok = dets:insert(T, Objs),
 4424:            {ok, Where} = dets:where(T, {2}),
 4425:            ok = dets:close(T),
 4426:            qlc_SUITE:crash(Fname, Where),
 4427: 
 4428:            {ok, _} = dets:open_file(T, [{file,Fname}]),
 4429:            HT = qlc:q([X || {X} <- dets:table(T, {traverse, first_next})]),
 4430:            {'EXIT',{error,{{bad_object,_},_}}} = (catch qlc:e(HT)),
 4431:            _ = dets:close(T),
 4432: 
 4433:            {ok, _} = dets:open_file(T, [{file,Fname}]),
 4434:            HMS = qlc:q([X || {X} <- dets:table(T, {traverse, select})]),
 4435:            {error,{{bad_object,_},_}} = qlc:e(HMS),
 4436:            _ = dets:close(T),
 4437: 
 4438:            {ok, _} = dets:open_file(T, [{file,Fname}]),
 4439:            HLU = qlc:q([X || {X} <- dets:table(T), X =:= 2]),
 4440:            {error,{{bad_object,_},_}} = qlc:e(HLU),
 4441:            _ = dets:close(T),
 4442: 
 4443:            file:delete(Fname)">>]
 4444: 
 4445:        ],
 4446:     
 4447:     ?line run(Config, Ts),
 4448:     _ = file:delete(Fname),
 4449:     ok.
 4450: 
 4451: 
 4452: join_option(doc) ->
 4453:     "The 'join' option (any, lookup, merge, nested_loop). Also cache/unique.";
 4454: join_option(suite) -> [];
 4455: join_option(Config) when is_list(Config) ->
 4456:     Ts = [
 4457:        <<"Q1 = qlc:q([X || X <- [1,2,3]],{join,merge}),
 4458:           {'EXIT', {no_join_to_carry_out,_}} = (catch {foo, qlc:info(Q1)}),
 4459:           {'EXIT', {no_join_to_carry_out,_}} = (catch {foo, qlc:e(Q1)}),
 4460: 
 4461:           Q2 = qlc:q([X || X <- [1,2,3], X > 1],{join,merge}),
 4462:           {'EXIT', {no_join_to_carry_out,_}} = (catch {foo, qlc:info(Q2)}),
 4463:           {'EXIT', {no_join_to_carry_out,_}} = (catch {foo, qlc:e(Q2)}),
 4464: 
 4465:           Q3 = qlc:q([{X,Y} ||
 4466:                          {X} <- [{1},{2},{3}],
 4467:                          {Y} <- [{a},{b},{c}],
 4468:                          X =:= Y],
 4469:                      {join, merge}),
 4470: 
 4471:           {1,0,0,2} = join_info(Q3),
 4472:           [] = qlc:e(Q3),
 4473: 
 4474:           Q4 = qlc:q([{X,Y} ||
 4475:                          {X} <- [{1},{2},{3}],
 4476:                          {Y} <- [{a},{b},{c}],
 4477:                          X > Y],
 4478:                      {join, lookup}),
 4479:           {'EXIT', {no_join_to_carry_out, _}} = (catch {foo, qlc:info(Q4)}),
 4480:           {'EXIT', {no_join_to_carry_out, _}} = (catch {foo, qlc:e(Q4)}),
 4481: 
 4482:           Q5 = qlc:q([{X,Y} ||
 4483:                          {X} <- [{1},{2},{3}],
 4484:                          {Y} <- [{3},{4},{5}],
 4485:                          X == Y],
 4486:                      {join, merge}),
 4487:           [{3,3}] = qlc:e(Q5),
 4488: 
 4489:           Q6 = qlc:q([{X,Y} ||
 4490:                          {X} <- [{1},{2},{3}],
 4491:                          {Y} <- [{3},{4},{5}],
 4492:                          X == Y],
 4493:                      {join, lookup}),
 4494:           {'EXIT', {cannot_carry_out_join, _}} = (catch {foo, qlc:info(Q6)}),
 4495:           {'EXIT', {cannot_carry_out_join, _}} = (catch {foo, qlc:e(Q6)}),
 4496: 
 4497:           Q7 = qlc:q([{X,Y} ||
 4498:                          {X} <- [{1},{2},{3}],
 4499:                          {Y} <- [{3},{4},{5}],
 4500:                          X == Y],
 4501:                      {join, nested_loop}),
 4502:           {0,0,1,0} = join_info(Q7),
 4503:           [{3,3}] = qlc:e(Q7),
 4504: 
 4505:           Q8 = qlc:q([{X,Y} ||
 4506:                          {X} <- [{1},{2},{3}],
 4507:                          {Y} <- [{3},{4},{5}],
 4508:                          X =:= Y],
 4509:                      {join, nested_loop}),
 4510:           {0,0,1,0} = join_info(Q8),
 4511:           [{3,3}] = qlc:e(Q8),
 4512: 
 4513:           %% Only guards are inspected...
 4514:           Q9 = qlc:q([{X,Y} ||
 4515:                          {X} <- [{1},{2},{3}],
 4516:                          {Y} <- [{3},{4},{5}],
 4517:                          begin X =:= Y end],
 4518:                      {join, nested_loop}),
 4519:           {'EXIT', {no_join_to_carry_out, _}} = (catch {foo, qlc:info(Q9)}),
 4520:           {'EXIT', {no_join_to_carry_out, _}} = (catch {foo, qlc:e(Q9)}),
 4521: 
 4522:           Q10 = qlc:q([{X,Y} ||
 4523:                          {X} <- [{1},{2},{3}],
 4524:                          {Y} <- [{3},{4},{5}],
 4525:                          X < Y],
 4526:                      {join, nested_loop}),
 4527:           {'EXIT', {no_join_to_carry_out, _}} = (catch {foo, qlc:info(Q10)}),
 4528:           {'EXIT', {no_join_to_carry_out, _}} = (catch {foo, qlc:e(Q10)}),
 4529: 
 4530:           F = fun(J) -> qlc:q([X || X <- [1,2]], {join,J}) end,
 4531:           {'EXIT', {no_join_to_carry_out, _}} = 
 4532:                 (catch {foo, qlc:e(F(merge))}),
 4533:           {'EXIT', {no_join_to_carry_out, _}} = 
 4534:                 (catch {foo, qlc:e(F(lookup))}),
 4535:           {'EXIT', {no_join_to_carry_out, _}} = 
 4536:                 (catch {foo, qlc:e(F(nested_loop))}),
 4537:           [1,2] = qlc:e(F(any)),
 4538: 
 4539:           %% No join of columns in the same table.
 4540:           Q11 = qlc:q([{X,Y} || {a = X, X = Y} <- [{a,1},{a,a},{a,3},{a,a}]],
 4541:                       {join,merge}),
 4542:           {'EXIT', {no_join_to_carry_out, _}} = (catch qlc:e(Q11)),
 4543:           Q12 = qlc:q([{X,Y} || {X = a, X = Y} <- [{a,1},{a,a},{a,3},{a,a}]],
 4544:                       {join,merge}),
 4545:           {'EXIT', {no_join_to_carry_out, _}} = (catch qlc:e(Q12)),
 4546:           %% X and Y are \"equal\" (same constants), but must not be joined.
 4547:           Q13 = qlc:q([{X,Y} || {X,_Z} <- [{a,1},{a,2},{b,1},{b,2}],
 4548:                                 {Y} <- [{a}],
 4549:                                 (X =:= a) and (Y =:= b) or 
 4550:                                 (X =:= b) and (Y =:= a)],
 4551:                      {join,merge}),
 4552:           {'EXIT', {no_join_to_carry_out, _}} = (catch qlc:e(Q13))
 4553: 
 4554: ">>,
 4555: 
 4556:        <<"Q1 = qlc:q([X || X <- [1,2,3]], {lookup,true}),
 4557:           {'EXIT', {no_lookup_to_carry_out, _}} = (catch {foo, qlc:info(Q1)}),
 4558:           {'EXIT', {no_lookup_to_carry_out, _}} = (catch {foo, qlc:e(Q1)}),
 4559:           Q2 = qlc:q([{X,Y} || X <- [1,2,3], Y <- [x,y,z]], lookup),
 4560:           {'EXIT', {no_lookup_to_carry_out, _}} = (catch {foo, qlc:info(Q2)}),
 4561:           {'EXIT', {no_lookup_to_carry_out, _}} = (catch {foo, qlc:e(Q2)}),
 4562:           Q3 = qlc:q([X || {X} <- [{1},{2},{3}]], {lookup,true}),
 4563:           {'EXIT', {no_lookup_to_carry_out, _}} = (catch {foo, qlc:e(Q3)}),
 4564:           {'EXIT', {no_lookup_to_carry_out, _}} = (catch {foo, qlc:info(Q3)}),
 4565: 
 4566:           E1 = create_ets(1, 10),
 4567:           Q4 = qlc:q([{X,Y} || {X,Y} <- ets:table(E1), X =:= 3], lookup),
 4568:           {match_spec, _} = strip_qlc_call(Q4),
 4569:           [{3,3}] = qlc:e(Q4),
 4570:           Q5 = qlc:q([{X,Y} || {X,Y} <- ets:table(E1), X =:= 3], {lookup,false}),
 4571:           {table, ets, _} = strip_qlc_call(Q5),
 4572:           [{3,3}] = qlc:e(Q5),
 4573:           Q6 = qlc:q([{X,Y} || {X,Y} <- ets:table(E1), X =:= 3], {lookup,any}),
 4574:           {match_spec, _} = strip_qlc_call(Q6),
 4575:           [{3,3}] = qlc:e(Q6),
 4576:           ets:delete(E1)">>
 4577: 
 4578:        ],
 4579:     ?line run(Config, Ts),
 4580: 
 4581:     %% The 'cache' and 'unique' options of qlc/2 affects join.
 4582:     CUTs = [
 4583:        <<"L1 = [1,2],
 4584:           L2 = [{1,a},{2,b}],
 4585:           L3 = [{a,1},{b,2}],
 4586:           Q = qlc:q([{X,Y,Z} ||
 4587:                         Z <- L1,
 4588:                         {X,_} <- L2,
 4589:                         {_,Y} <- L3,
 4590:                         X =:= Y],
 4591:                     [cache, unique]),
 4592:           {qlc,_,
 4593:               [{generate,_,{list,L1}},
 4594:                {generate,_,{qlc,_,[{generate,_,
 4595:                       {qlc,_,[{generate,_,{keysort,{list,L2},1,[]}}],[]}},
 4596:                                 {generate,_,{qlc,_,
 4597:                               [{generate,_,{keysort,{list,L3},2,[]}}],[]}},_],
 4598:                             [{join,merge},{cache,ets},{unique,true}]}},_],
 4599:               [{unique,true}]} = i(Q),
 4600:           [{1,1,1},{2,2,1},{1,1,2},{2,2,2}] = qlc:e(Q)">>,
 4601:        <<"L1 = [1,2],
 4602:           L2 = [{1,a},{2,b}],
 4603:           L3 = [{a,1},{b,2}],
 4604:           Q = qlc:q([{X,Y,Z} ||
 4605:                         Z <- L1,
 4606:                         {X,_} <- L2,
 4607:                         {_,Y} <- L3,
 4608:                         X =:= Y],
 4609:                     []),
 4610:           Options = [{cache_all,ets}, unique_all],
 4611:           {qlc,_,[{generate,_,{qlc,_,[{generate,_,{list,L1}}],
 4612:                                [{unique,true}]}},
 4613:                   {generate,_,{qlc,_,
 4614:                               [{generate,_,{qlc,_,[{generate,_,
 4615:                                  {keysort,{qlc,_,[{generate,_,{list,L2}}],
 4616:                                            [{cache,ets},{unique,true}]},
 4617:                                           1,[]}}],[]}},
 4618:                                {generate,_,{qlc,_,
 4619:                                     [{generate,_,{keysort,
 4620:                                       {qlc,_,[{generate,_,{list,L3}}],
 4621:                                        [{cache,ets},{unique,true}]},
 4622:                                                   2,[]}}],[]}},_],
 4623:                               [{join,merge},{cache,ets},{unique,true}]}},
 4624:                   _],[{unique,true}]} = i(Q, Options),
 4625:           [{1,1,1},{2,2,1},{1,1,2},{2,2,2}] = qlc:e(Q, Options)">>
 4626:        ],
 4627:     ?line run(Config, CUTs),
 4628: 
 4629:     ok.
 4630: 
 4631: join_filter(doc) ->
 4632:     "Various aspects of filters and join.";
 4633: join_filter(suite) -> [];
 4634: join_filter(Config) when is_list(Config) ->
 4635:     Ts = [
 4636:       <<"E1 = create_ets(1, 10),
 4637:           Q = qlc:q([X || {X,_} <- ets:table(E1),
 4638:                           begin A = X * X end, % ej true (?)
 4639:                           X >= A]),
 4640:           {'EXIT', _} = (catch qlc:e(Q)),
 4641:           ets:delete(E1)">>,
 4642: 
 4643:       %% The order of filters matters. See also skip_filters().
 4644:       <<"Q = qlc:q([{X,Y} || {X,Y} <- [{a,1},{b,2}], 
 4645:          {Z,W} <- [{a,1},{c,0}], 
 4646:          X =:= Z,
 4647:          begin Y/W > 0 end]),
 4648:          [{a,1}] = qlc:e(Q)">>,
 4649:       <<"Q = qlc:q([{X,Y} || {X,Y} <- [{a,1},{b,2}], 
 4650:          {Z,W} <- [{a,1},{c,0}], 
 4651:          begin Y/W > 0 end,
 4652:          X =:= Z]),
 4653:          {'EXIT', _} = (catch qlc:e(Q))">>,
 4654: 
 4655:       <<"etsc(fun(E1) ->
 4656:                    etsc(fun(E2) ->
 4657:                              F = fun() -> [foo || A <- [0], 1/A] end,
 4658:                              Q1 = qlc:q([X || {X} <- ets:table(E1),
 4659:                                               {Y} <- ets:table(E2),
 4660:                                               F(), % invalidates next filter
 4661:                                               X =:= Y]),
 4662:                               {qlc,_,[{generate,_,{table,{ets,table,_}}},
 4663:                                       {generate,_,{table,{ets,table,_}}},_,_],
 4664:                               []} = i(Q1),
 4665:                              {'EXIT', _} = (catch qlc:e(Q1))
 4666:                         end, [{1},{2},{3}])
 4667:               end, [{a},{b},{c}])">>
 4668: 
 4669:     ],
 4670:     ?line run(Config, Ts),
 4671:     ok.
 4672: 
 4673: join_lookup(doc) ->
 4674:     "Lookup join.";
 4675: join_lookup(suite) -> [];
 4676: join_lookup(Config) when is_list(Config) ->
 4677:     Ts = [
 4678:        <<"E1 = create_ets(1, 10),
 4679:           E2 = create_ets(5, 15),
 4680:           Q = qlc:q([{X,Y} || {_,Y} <- ets:table(E2),
 4681:                               {X,_} <- ets:table(E1),
 4682:                               X =:= Y], [{join,lookup}]),
 4683:           {0,1,0,0} = join_info_count(Q),
 4684:           R = qlc:e(Q),
 4685:           ets:delete(E1),
 4686:           ets:delete(E2),
 4687:           [{5,5},{6,6},{7,7},{8,8},{9,9},{10,10}] = lists:sort(R)">>,
 4688: 
 4689:        <<"E1 = create_ets(1, 10),
 4690:           E2 = create_ets(5, 15),
 4691:           F = fun(J) -> qlc:q([{X,Y} || {X,_} <- ets:table(E1),
 4692:                                         {_,Y} <- ets:table(E2),
 4693:                                         X =:= Y], {join, J})
 4694:               end,
 4695:           Q = F(lookup),
 4696:           {0,1,0,0} = join_info_count(Q),
 4697:           R = qlc:e(Q),
 4698:           ets:delete(E1),
 4699:           ets:delete(E2),
 4700:           [{5,5},{6,6},{7,7},{8,8},{9,9},{10,10}] = lists:sort(R)">>,
 4701: 
 4702:        <<"etsc(fun(E1) ->
 4703:                   E2 = qlc_SUITE:table([{1,a},{a},{1,b},{b}], 2, []),
 4704:                   Q = qlc:q([{X,Y} || {X,Y} <- ets:table(E1), % (1)
 4705:                                       {_,Z} <- E2,   % (2)
 4706:                                       (Z =:= Y) and (X =:= a) 
 4707:                                       or
 4708:                                       (Z =:= Y) and (X =:= b)]),
 4709:                   %% Cannot look up in (1) (X is keypos). Can look up (2).
 4710:                   %% Lookup-join: traverse (1), look up in (2).
 4711:                   {0,1,0,0} = join_info_count(Q),
 4712:                   [{a,a},{b,a}] = qlc:e(Q)
 4713:                end, [{a,a},{b,a},{c,3},{d,4}])">>,
 4714: 
 4715:        <<"%% The pattern {X,_} is used to filter out looked up objects.
 4716:           etsc(fun(E) ->
 4717:                        Q = qlc:q([X || {X,_} <- ets:table(E), 
 4718:                                        Y <- [{a,b},{c,d},{1,2},{3,4}], 
 4719:                                        X =:= element(1, Y)]),
 4720:                        {0,1,0,0} = join_info_count(Q),
 4721:                        [1] = qlc:e(Q)
 4722:                end, [{1,2},{3}])">>,
 4723: 
 4724:        <<"E = ets:new(e, [bag,{keypos,2}]),
 4725:           L = lists:sort([{a,1},{b,1},{c,1},{d,1},
 4726:                           {aa,2},{bb,2},{cc,2},{dd,2}]),
 4727:           true = ets:insert(E, L ++ [{aaa,1,1},{bbb,2,2},{ccc,3,3}]),
 4728:           Q = qlc:q([Z || {_,Y}=Z <- ets:table(E),
 4729:                           {X} <- [{X} || X <- lists:seq(0, 10)],
 4730:                           X =:= Y]),
 4731:           {0,1,0,0} = join_info_count(Q),
 4732:           R = qlc:e(Q),
 4733:           ets:delete(E),
 4734:           L = lists:sort(R)">>,
 4735: 
 4736:        <<"E = ets:new(e, [bag,{keypos,2}]),
 4737:           L = lists:sort([{a,1},{b,1},{c,1},{d,1},
 4738:                           {aa,2},{bb,2},{cc,2},{dd,2}]),
 4739:           true = ets:insert(E, L ++ [{aaa,1,1},{bbb,2,2},{ccc,3,3}]),
 4740:           Q = qlc:q([Z || {X} <- [{X} || X <- lists:seq(0, 10)],
 4741:                           {_,Y}=Z <- ets:table(E),
 4742:                           X =:= Y]),
 4743:           {0,1,0,0} = join_info_count(Q),
 4744:           R = qlc:e(Q),
 4745:           ets:delete(E),
 4746:           L = lists:sort(R)">>,
 4747: 
 4748:        <<"Q = qlc:q([{XX,YY} ||
 4749:                             {XX,X} <- [{b,1},{c,3}],
 4750:                             {Y,YY} <- qlc_SUITE:table_lookup_error([{1,a}]),
 4751:                             X =:= Y],
 4752:                         {join,lookup}),
 4753:           {error, lookup, failed} = qlc:e(Q)">>,
 4754: 
 4755:        <<"E = create_ets(1, 10),
 4756:           Q = qlc:q([{X,Y} ||
 4757:                         {X,_} <- ets:table(E),
 4758:                         {_,Y} <- qlc_SUITE:table_error([{a,1}], 1, err),
 4759:                         X =:= Y]),
 4760:           {0,1,0,0} = join_info_count(Q),
 4761:           err = qlc:e(Q),
 4762:           ets:delete(E)">>
 4763: 
 4764:           ],
 4765:     ?line run(Config, Ts),
 4766:     ok.
 4767: 
 4768: join_merge(doc) ->
 4769:     "Merge join.";
 4770: join_merge(suite) -> [];
 4771: join_merge(Config) when is_list(Config) ->
 4772:     Ts = [
 4773:        <<"Q = qlc:q([{X,Y} || {X} <- [], {Y} <- [{1}], X =:= Y], 
 4774:                     {join,merge}),
 4775:           [] = qlc:e(Q)
 4776:        ">>,
 4777: 
 4778:        <<"Q = qlc:q([{X,Y} || {X} <- [{1}], {Y} <- [], X =:= Y], 
 4779:                     {join,merge}),
 4780:           [] = qlc:e(Q)
 4781:        ">>,
 4782: 
 4783:        <<"Q = qlc:q([{X,Y} || {X} <- [{1},{1},{1}], 
 4784:                               {Y} <- [{1},{1},{1}], X =:= Y], 
 4785:                     {join,merge}),
 4786:           9 = length(qlc:e(Q))
 4787:        ">>,
 4788: 
 4789:        <<"%% Two merge joins possible.
 4790:           Q = qlc:q([{X,Y,Z,W} || {X,Y} <- [{1,a},{1,b},{1,c}], 
 4791:                                   {Z,W} <- [{1,a},{1,b},{1,c}], 
 4792:                                   X =:= Z, 
 4793:                                   Y =:= W]),
 4794:           {qlc,_,[{generate,_,
 4795:                    {qlc,_,
 4796:                     [{generate,_,
 4797:                       {qlc,_,[{generate,_,{keysort,{list,_},C,[]}}],[]}},
 4798:                      {generate,_,
 4799:                       {qlc,_,[{generate,_,{keysort,{list,_},C,[]}}],[]}},
 4800:                      _],
 4801:                     [{join,merge}]}},
 4802:                   _,_],[]} = qlc:info(Q, {format,debug}),
 4803:           [{1,a,1,a},{1,b,1,b},{1,c,1,c}] = qlc:e(Q)">>,
 4804: 
 4805:        <<"%% As the last one, but comparison.
 4806:           Q = qlc:q([{X,Y,Z,W} || {X,Y} <- [{1,a},{1,b},{1,c}], 
 4807:                                   {Z,W} <- [{1,a},{1,b},{1,c}], 
 4808:                                   X == Z, % skipped
 4809:                                   Y =:= W]),
 4810:           {qlc,_,[{generate,_,
 4811:                    {qlc,_,
 4812:                     [{generate,_,
 4813:                       {qlc,_,[{generate,_,{keysort,{list,_},1,[]}}],[]}},
 4814:                      {generate,_,
 4815:                       {qlc,_,[{generate,_,{keysort,{list,_},1,[]}}],[]}},
 4816:                      _],
 4817:                     [{join,merge}]}},
 4818:                   _],[]} = qlc:info(Q, {format,debug}),
 4819:           [{1,a,1,a},{1,b,1,b},{1,c,1,c}] = qlc:e(Q)">>,
 4820: 
 4821:        <<"%% This is no join.
 4822:           Q = qlc:q([{X,Y,Z,W} || {X,Y} <- [], {Z,W} <- [], 
 4823:                                   X =:= Y, Z =:= W]),
 4824:           {0,0,0,0} = join_info_count(Q)">>,
 4825: 
 4826:        <<"%% Used to replace empty ETS tables with [], but that won't work.
 4827:           E1 = ets:new(e1, []),
 4828:           E2 = ets:new(e2, []),
 4829:           Q = qlc:q([{X,Z,W} ||
 4830:                         {X, Z} <- ets:table(E1),
 4831:                         {W, Y} <- ets:table(E2),
 4832:                         X =:= Y],
 4833:                     {join, lookup}),
 4834:           [] = qlc:e(Q),
 4835:           ets:delete(E1),
 4836:           ets:delete(E2)">>,
 4837: 
 4838:        <<"Q = qlc:q([{X,Y} || {X} <- [{3},{1},{0}], 
 4839:                               {Y} <- [{1},{2},{3}], 
 4840:                               X =:= Y]),
 4841:           {1,0,0,2} = join_info_count(Q),
 4842:           [{1,1},{3,3}] = qlc:e(Q)">>,
 4843: 
 4844:        <<"QH = qlc:q([{X,Y,Z,W} || {X,Y} <- [{3,c},{2,b},{1,a}],
 4845:                                    {Z,W} <- [{2,b},{4,d},{5,e},{3,c}], 
 4846:                                    X =:= Z, 
 4847:                                    Y =:= W]),
 4848:           {1,0,0,2} = join_info_count(QH),
 4849:           [{2,b,2,b},{3,c,3,c}] = qlc:e(QH)">>,
 4850: 
 4851:        <<"%% QLC finds no join column at run time...
 4852:           QH = qlc:q([1 || X <- [{1,2,3},{4,5,6}], 
 4853:                            Y <- [{1,2},{3,4}], 
 4854:                            X =:= Y]),
 4855:           {0,0,0,0} = join_info_count(QH),
 4856:           [] = qlc:e(QH)">>,
 4857: 
 4858:        <<"QH = qlc:q([X || X <- [{1,2,3},{4,5,6}], 
 4859:                            Y <- [{1,2},{3,4}], 
 4860:                            element(1, X) =:= element(2, Y)]),
 4861:           {1,0,0,2} = join_info_count(QH),
 4862:           [{4,5,6}] = qlc:e(QH)">>,
 4863: 
 4864:        <<"Q = qlc:q([{A,X,Z,W} ||
 4865:                         A <- [a,b,c],
 4866:                         {X,Z} <- [{a,1},{b,4},{c,6}],
 4867:                         {W,Y} <- [{2,a},{3,b},{4,c}],
 4868:                         X =:= Y],
 4869:                    {cache, list}),
 4870:           _ = qlc:info(Q),
 4871:          [{a,a,1,2},{a,b,4,3},{a,c,6,4},{b,a,1,2},{b,b,4,3},
 4872:           {b,c,6,4},{c,a,1,2},{c,b,4,3},{c,c,6,4}] = qlc:e(Q)">>,
 4873: 
 4874:        <<"Q = qlc:q([{X,Y} || 
 4875:                         {X,Z} <- [{a,1},{b,4},{c,6}],
 4876:                         {W,Y} <- [{2,a},{3,b},{4,c}],
 4877:                         Z > W,
 4878:                         X =:= Y],
 4879:                     {join,merge}),
 4880:           {qlc,_,[{generate,_,{qlc,_,
 4881:                               [{generate,_,
 4882:                                 {qlc,_,[{generate,_,{keysort,_,1,[]}}],[]}},
 4883:                                {generate,_,
 4884:                                 {qlc,_,[{generate,_,{keysort,_,2,[]}}],
 4885:                                  []}},_],[{join,merge}]}},
 4886:                   _,_],[]} = i(Q),
 4887:           [{b,b},{c,c}] = qlc:e(Q)">>,
 4888: 
 4889:        <<"E1 = create_ets(1, 10),
 4890:           E2 = create_ets(5, 15),
 4891:           %% A match spec.; Q does not see Q1 and Q2 as lookup-tables.
 4892:           Q1 = qlc:q([X || X <- ets:table(E1)]),
 4893:           Q2 = qlc:q([X || X <- ets:table(E2)]),
 4894:           F = fun(J) -> qlc:q([{X,Y} || X <- Q1,
 4895:                                         Y <- Q2,
 4896:                                         element(1,X) =:= element(1,Y)], 
 4897:                               [{join,J}])
 4898:               end,
 4899:           {'EXIT',{cannot_carry_out_join,_}} = (catch qlc:e(F(lookup))),
 4900:           Q = F(merge),
 4901:           {1,0,0,2} = join_info(Q),
 4902:           R = lists:sort(qlc:e(Q)),
 4903:           ets:delete(E1),
 4904:           ets:delete(E2),
 4905:           true = [{Y,Y} || X <- lists:seq(5, 10), {} =/= (Y = {X,X})] =:= R
 4906:        ">>,
 4907: 
 4908:        <<"E1 = create_ets(1, 10),
 4909:           E2 = create_ets(5, 15),
 4910:           Q = qlc:q([{X,Y} || X <- ets:table(E1),
 4911:                               Y <- ets:table(E2),
 4912:                               element(1,X) =:= element(1,Y)], 
 4913:                     [{join,merge}]),
 4914:           {1,0,0,2} = join_info(Q),
 4915:           R = lists:sort(qlc:e(Q)),
 4916:           ets:delete(E1),
 4917:           ets:delete(E2),
 4918:           true = [{Y,Y} || X <- lists:seq(5, 10), {} =/= (Y = {X,X})] =:= R
 4919:        ">>,
 4920: 
 4921:        <<"E1 = create_ets(1, 10),
 4922:           E2 = create_ets(5, 15),
 4923:           Q1 = qlc:q([Y || X <- ets:table(E1), begin Y = {X}, true end]),
 4924:           %% A match spec.; Q does not see Q2 as a lookup-table.
 4925:           %%
 4926:           %% OTP-6673: lookup join is considered but since there is no
 4927:           %% filter that can do the job of Q2, lookup join is not an option..
 4928:           Q2 = qlc:q([{X} || X <- ets:table(E2)]),
 4929:           F = fun(J) ->
 4930:                       qlc:q([{X,Y} || X <- Q1,
 4931:                                       Y <- Q2,
 4932:                                       element(1,X) =:= element(1,Y)],
 4933:                             [{join,J}])
 4934:               end,
 4935:           {'EXIT',{cannot_carry_out_join,_}} = (catch qlc:e(F(lookup))),
 4936:           Q = F(any),
 4937:           {1,0,0,2} = join_info(Q),
 4938:           R = lists:sort(qlc:e(Q)),
 4939:           ets:delete(E1),
 4940:           ets:delete(E2),
 4941:           true = [{Y,Y} || X <- lists:seq(5, 10), {} =/= (Y = {{X,X}})] =:= R
 4942:        ">>,
 4943: 
 4944:        <<"L1 = [{1,a},{2,a},{1,b},{2,b},{1,c},{2,c}],
 4945:           L2 = [{b,Y} || Y <- lists:seq(1, 10000)],
 4946:           F = fun(J) ->
 4947:                       Q = qlc:q([{XX,YY} ||
 4948:                                     {X,XX} <- L1,
 4949:                                     {YY,Y} <- L2,
 4950:                                     X == Y],
 4951:                                 {join,J}),
 4952:                       qlc:q([{XX1,YY1,XX2,YY2} ||
 4953:                                 {XX1,YY1} <- Q,
 4954:                                 {XX2,YY2} <- Q])
 4955:               end,
 4956:           Qm = F(merge),
 4957:           Qn = F(nested_loop),
 4958:           true = lists:sort(qlc:e(Qm)) =:= lists:sort(qlc:e(Qn))">>,
 4959: 
 4960:        <<"L1 = [{{1,a},2},{{3,c},4}],
 4961:           L2 = [{a,{1,a}},{c,{4,d}}],
 4962:           Q = qlc:q([{X,Y} || {X,_} <- L1,
 4963:                               {_,{Y,Z}} <- L2,
 4964:                               X == {Y,Z}
 4965:                            ]),
 4966:           {qlc,_,[{generate,_,{qlc,_,
 4967:                    [{generate,_,
 4968:                      {qlc,_,[{generate,_,{keysort,{list,L1},1,[]}}],[]}},
 4969:                     {generate,_,
 4970:                      {qlc,_,[{generate,_,{keysort,{list,L2},2,[]}}],[]}},
 4971:                     _],
 4972:                    [{join,merge}]}}],[]}  = i(Q),
 4973:           [{{1,a},1}] = qlc:e(Q)">>,
 4974: 
 4975:        <<"etsc(fun(E1) ->
 4976:                    etsc(fun(E2) ->
 4977:                       Q = qlc:q([{X,Y} || {X,Y} <- ets:table(E1), % (1)
 4978:                                           {Z} <- ets:table(E2),   % (2)
 4979:                                             (Z =:= X) and 
 4980:                                             (Y =:= a) and 
 4981:                                             (X =:= Y) or 
 4982:                                           (Y =:= b) and 
 4983:                                           (Z =:= Y)]),
 4984:                       %% Cannot look up in (1) (X is keypos). Can look up (2).
 4985:                       %% Lookup join not possible (cannot look up in (1)).
 4986:                       %% Merge join is possible (after lookup in (2)).
 4987:                       {1,0,0,2} = join_info_count(Q),
 4988:                       {qlc,_,
 4989:                        [{generate,_,
 4990:                          {qlc,_,[{generate,_,
 4991:                                   {qlc,_,[{generate,_,
 4992:                                            {keysort,
 4993:                                             {table,{ets,table,_}},
 4994:                                                   2,[]}},_C1],[]}},
 4995:                                  {generate,_,
 4996:                                   {qlc,_,[{generate,_,
 4997:                                            {keysort,{table,_},1,[]}},_C2],
 4998:                                    []}},
 4999:                                  _],[{join,merge}]}},_],[]} = i(Q),
 5000:                       [{a,a}] = qlc:e(Q)
 5001:                    end, [{a}])
 5002:                 end, [{a,1},{a,a},{b,1},{b,2}])">>,
 5003: 
 5004:        <<"Q = qlc:q([{G1,G2} || 
 5005:                         G1<- [{1}],
 5006:                         G2 <- [{1}],
 5007:                         element(1, G1) =:= element(1, G2)]),
 5008:           {1,0,0,2} = join_info(Q),
 5009:           [{{1},{1}}] = qlc:e(Q)">>,
 5010: 
 5011:        <<"Q = qlc:q([{X,Y} || 
 5012:                          X <- [{1}], 
 5013:                          Y <- [{1}], 
 5014:                          element(1, X) =:= element(1, Y)], 
 5015:                      {join,merge}),
 5016:           {1,0,0,2} = join_info(Q),
 5017:           [{{1},{1}}] = qlc:e(Q)">>,
 5018: 
 5019:        <<"%% Generator after the join-filter.
 5020:           Q = qlc:q([Z || 
 5021:                         {X} <- [{1},{2},{3}], 
 5022:                         {Y} <- [{2},{3},{4}], 
 5023:                         X =:= Y, 
 5024:                         Z <- [1,2]]),
 5025:           {qlc,_,
 5026:            [{generate,_,{qlc,_,
 5027:                 [{generate,_,{qlc,_,
 5028:                     [{generate,_,{keysort,{list,[{1},{2},{3}]},1,[]}}],[]}},
 5029:                 {generate,_,{qlc,_,
 5030:                     [{generate,_,{keysort,{list,_},1,[]}}],[]}},_],
 5031:                 [{join,merge}]}}, _,{generate,_,{list,_}}],[]} = i(Q),
 5032:           [1,2,1,2] = qlc:e(Q)">>,
 5033: 
 5034:        <<"%% X and W occur twice in the pattern of the extra join handle.
 5035:           Q = qlc:q([{Z,W} ||
 5036:                         {X,Z,X} <- [{1,2,1},{1,2,2}],
 5037:                         {W,Y,W} <- [{a,1,a}],
 5038:                         X =:= Y]),
 5039:           [{2,a}] = qlc:e(Q)">>
 5040: 
 5041:           ],
 5042:     ?line run(Config, Ts),
 5043: 
 5044:     %% Small examples. Returning an error term.
 5045:     ETs = [
 5046:        <<"F = fun(M) ->
 5047:                   qlc:q([{XX,YY} ||
 5048:                          {XX,X} <- [{a,1},{b,2},{bb,2},{c,3},{cc,3}],
 5049:                          {Y,YY} <- [{0,a},{1,a},{1,aa},{2,b},{2,bb},{2,bbb},
 5050:                                     {3,c},{3,cc}],
 5051:                           X =:= Y],
 5052:                         {join,M})
 5053:               end,
 5054:           R = qlc:e(F(nested_loop)),
 5055:           R = qlc:e(F(merge))">>,
 5056: 
 5057:        <<"F = fun(M) ->
 5058:                 qlc:q([{XX,YY} ||
 5059:                        {XX,X} <- [{a,1},{b,2},{bb,2},{c,3},{cc,3}],
 5060:                        {Y,YY} <- [{0,a},{1,a},{1,aa},{2,b},{2,bb},{2,bbb},
 5061:                                   {4,d}],
 5062:                         X =:= Y],
 5063:                       {join,M})
 5064:               end,
 5065:           R = qlc:e(F(nested_loop)),
 5066:           R = qlc:e(F(merge))">>,
 5067: 
 5068:        <<"Q = qlc:q([{XX,YY} ||
 5069:                         {XX,X} <- [{b,1},{c,3}],
 5070:                         {Y,YY} <- [{1,a}],
 5071:                         X =:= Y],
 5072:                     {join,merge}),
 5073:           [{b,a}] = qlc:e(Q)">>,
 5074: 
 5075:        <<"Q = qlc:q([{XX,YY} ||
 5076:                             {XX,X} <- [{b,1},{c,3}],
 5077:                             {Y,YY} <- qlc_SUITE:table_error([{1,a}], 1, err),
 5078:                             X =:= Y],
 5079:                         {join,merge}),
 5080:               err = qlc:e(Q)">>,
 5081:            
 5082:        <<"Q = qlc:q([{XX,YY} ||
 5083:                             {XX,X} <- [{a,1},{aa,1}],
 5084:                             {Y,YY} <- [{1,a}],
 5085:                             X =:= Y],
 5086:                         {join,merge}),
 5087:               [{a,a},{aa,a}] = qlc:e(Q)">>,
 5088: 
 5089:        <<"Q = qlc:q([{XX,YY} ||
 5090:                             {XX,X} <- qlc_SUITE:table_error([{a,1},{aa,1}], 
 5091:                                                              2, err),
 5092:                             {Y,YY} <- [{1,a}],
 5093:                             X =:= Y],
 5094:                         {join,merge}),
 5095:               err = qlc:e(Q)">>,
 5096:            
 5097:        <<"Q = qlc:q([{XX,YY} ||
 5098:                             {XX,X} <- [{a,1}],
 5099:                             {Y,YY} <- [{1,a},{1,aa}],
 5100:                             X =:= Y],
 5101:                         {join,merge}),
 5102:               [{a,a},{a,aa}]= qlc:e(Q)">>,
 5103:            
 5104:        <<"Q = qlc:q([{XX,YY} ||
 5105:                             {XX,X} <- qlc_SUITE:table_error([{a,1}], 2, err),
 5106:                             {Y,YY} <- [{1,a},{1,aa}],
 5107:                             X =:= Y],
 5108:                         {join,merge}),
 5109:           C = qlc:cursor(Q),
 5110:           [{a,a}] = qlc:next_answers(C, 1),
 5111:           qlc:delete_cursor(C),
 5112:           err = qlc:e(Q)">>,
 5113: 
 5114:        <<"F = fun(M) ->
 5115:                     qlc:q([{XX,YY} ||
 5116:                                {XX,X} <- [{a,1},{b,2},{bb,2},{c,3},{cc,3}],
 5117:                                {Y,YY} <- [{0,a},{1,a},{1,aa},{2,b},
 5118:                                           {2,bb},{2,bbb}],
 5119:                             X =:= Y],
 5120:                           {join,M})
 5121:               end,
 5122:               %% [{a,a},{a,aa},{b,b},{b,bb},{b,bbb},{bb,b},{bb,bb},{bb,bbb}]
 5123:               R = qlc:e(F(nested_loop)),
 5124:               R = qlc:e(F(merge))">>,
 5125: 
 5126: 
 5127:        <<"F = fun(M) ->
 5128:                    qlc:q([{XX,YY} ||
 5129:                           {XX,X} <- [{a,1},{b,2},{bb,2},{c,3},{cc,3}],
 5130:                           {Y,YY} <- qlc_SUITE:table_error([{0,a},{1,a},{1,aa},
 5131:                                                            {2,b},{2,bb},
 5132:                                                            {2,bbb}], 
 5133:                                                           1, err),
 5134:                            X =:= Y],
 5135:                          {join,M})
 5136:               end,
 5137:               %% [{a,a},{a,aa},{b,b},{b,bb},{b,bbb},{bb,b},{bb,bb},{bb,bbb}]
 5138:               err = qlc:e(F(nested_loop)),
 5139:               err = qlc:e(F(merge))">>,
 5140: 
 5141:        <<"Q = qlc:q([{XX,YY} ||
 5142:                             {XX,X} <- qlc_SUITE:table_error([], 2, err),
 5143:                             {Y,YY} <- [{2,b},{3,c}],
 5144:                             X =:= Y],
 5145:                         {join,merge}),
 5146:               err = qlc:e(Q)">>,
 5147: 
 5148:        <<"Q = qlc:q([{XX,YY} ||
 5149:                             {XX,X} <- [{a,1},{c,3}],
 5150:                             {Y,YY} <- [{2,b},{3,c}],
 5151:                             X =:= Y],
 5152:                         {join,merge}),
 5153:               [{c,c}] = qlc:e(Q)">>,
 5154: 
 5155:        <<"Q = qlc:q([{XX,YY} ||
 5156:                             {XX,X} <- [{a,1},{aa,1}],
 5157:                             {Y,YY} <- [{1,a},{1,aa}],
 5158:                             X =:= Y],
 5159:                         {join,merge}),
 5160:               [{a,a},{a,aa},{aa,a},{aa,aa}] = qlc:e(Q)">>,
 5161: 
 5162:        <<"Q = qlc:q([{XX,YY} ||
 5163:                             {XX,X} <- [{a,1},{b,2}],
 5164:                             {Y,YY} <- [{1,a},{1,aa}],
 5165:                             X =:= Y],
 5166:                         {join,merge}),
 5167:               [{a,a},{a,aa}] = qlc:e(Q)">>,
 5168: 
 5169:        <<"Q = qlc:q([{XX,YY} ||
 5170:                             {XX,X} <- [{a,1},{b,2}],
 5171:                             {Y,YY} <- qlc_SUITE:table_error([{1,a},{1,aa}], 
 5172:                                                             1, err),
 5173:                             X =:= Y],
 5174:                         {join,merge}),
 5175:               err = qlc:e(Q)">>,
 5176: 
 5177:        <<"Q = qlc:q([{XX,YY} ||
 5178:                             {XX,X} <- [{a,1},{b,2}],
 5179:                             {Y,YY} <- [{1,a},{1,aa},{1,aaa},{1,aaaa}],
 5180:                             X =:= Y],
 5181:                         {join,merge}),
 5182:               [{a,a},{a,aa},{a,aaa},{a,aaaa}]= qlc:e(Q)">>,
 5183: 
 5184:        <<"Q = qlc:q([{element(1, X), element(2, Y)} ||
 5185:                             X <- [{a,1},{aa,1}],
 5186:                             Y <- [{1,a},{1,aa}],
 5187:                             element(2, X) =:= element(1, Y)],
 5188:                         {join,merge}),
 5189:               [{a,a},{a,aa},{aa,a},{aa,aa}] = qlc:e(Q)">>,
 5190: 
 5191:        <<"Q = qlc:q([{element(1, X), element(2, Y)} ||
 5192:                             X <- [{a,1},{aa,1}],
 5193:                             Y <- qlc_SUITE:table_error([], 1, err),
 5194:                             element(2, X) =:= element(1, Y)],
 5195:                         {join,merge}),
 5196:               err = qlc:e(Q)">>,
 5197: 
 5198:        <<"Q = qlc:q([{element(1, X), element(2, Y)} ||
 5199:                             X <- qlc_SUITE:table_error([{a,1}], 2, err),
 5200:                             Y <- [{2,b}],
 5201:                             element(2, X) =:= element(1, Y)],
 5202:                         {join,merge}),
 5203:               err = qlc:e(Q)">>,
 5204: 
 5205:        <<"Q = qlc:q([{XX,YY} ||
 5206:                   {XX,X} <- [{1,a},{'1b',b},{2,b}],
 5207:                   {Y,YY} <- [{a,1},{b,'1b'},{c,1}],
 5208:                   X == Y],
 5209:               {join,merge}),
 5210:           [{1,1},{'1b','1b'},{2,'1b'}] = qlc:e(Q)">>,
 5211: 
 5212:        <<"Q = qlc:q([{XX,YY} ||
 5213:                   {XX,X} <- qlc_SUITE:table_error([{1,a},{'1b',b},{2,b}], 
 5214:                                                   2, err),
 5215:                   {Y,YY} <- [{a,1},{b,'1b'},{c,1}],
 5216:                   X == Y],
 5217:               {join,merge}),
 5218:           err = qlc:e(Q)">>
 5219: 
 5220:           ],
 5221:     ?line run(Config, ETs),
 5222: 
 5223:     %% Mostly examples where temporary files are needed while merging.
 5224:     FTs = [
 5225:        <<"L1 = [{Y,a} || Y <- lists:seq(1, 2)],
 5226:           L2 = [{a,Y} || Y <- lists:seq(1, 10000)],
 5227:           F = fun(J) ->
 5228:                       qlc:q([{XX,YY} ||
 5229:                                 {XX,X} <- L1,
 5230:                                 {Y,YY} <- L2,
 5231:                                 X == Y],
 5232:                             {join,J})
 5233:               end,
 5234:           Qm = F(merge),
 5235:           Qn = F(nested_loop),
 5236:           true = qlc:e(Qm,{max_list_size, 0}) =:= qlc:e(Qn)">>,
 5237: 
 5238:        <<"L1 = [{Y,a} || Y <- lists:seq(1, 2)],
 5239:           L2 = [{a,Y} || Y <- lists:seq(1, 10000)],
 5240:           Q = qlc:q([{XX,YY} ||
 5241:                         {XX,X} <- L1,
 5242:                         {Y,YY} <- L2,
 5243:                         X == Y],
 5244:                     {join,merge}),
 5245:           {error,_,{file_error,_,_}} = 
 5246:                qlc:e(Q, [{max_list_size,64*1024},{tmpdir,\"/a/b/c\"}])">>,
 5247: 
 5248:        <<"L1 = qlc_SUITE:table_error([{1,a},{2,a}], 2, err),
 5249:           L2 = [{a,Y} || Y <- lists:seq(1, 10000)],
 5250:           F = fun(J) ->
 5251:                       qlc:q([{XX,YY} ||
 5252:                                 {XX,X} <- L1,
 5253:                                 {Y,YY} <- L2,
 5254:                                 X == Y],
 5255:                             {join,J})
 5256:               end,
 5257:           Qm = F(merge),
 5258:           Qn = F(nested_loop),
 5259:           err = qlc:e(Qm, {max_list_size,64*1024}),
 5260:           err = qlc:e(Qn)">>,
 5261: 
 5262:        <<"L1 = [{Y,a} || Y <- lists:seq(1, 2)],
 5263:           L2 = qlc_SUITE:table_error([{a,Y} || Y <- lists:seq(1, 10000)], 
 5264:                                      1, err),
 5265:           F = fun(J) ->
 5266:                       qlc:q([{XX,YY} ||
 5267:                                 {XX,X} <- L1,
 5268:                                 {Y,YY} <- L2,
 5269:                                 X == Y],
 5270:                             {join,J})
 5271:               end,
 5272:           Qm = F(merge),
 5273:           Qn = F(nested_loop),
 5274:           err = qlc:e(Qm, {max_list_size,64*1024}),
 5275:           err = qlc:e(Qn)">>,
 5276: 
 5277:        <<"L1 = [{Y,a} || Y <- lists:seq(1, 2)] ++ 
 5278:                [{'1b',b},{2,b}] ++ [{Y,d} || Y <- lists:seq(1, 2)],
 5279:           L2 = [{a,Y} || Y <- lists:seq(1, 10000)] ++ 
 5280:                [{b,'1b'}] ++ [{c,1}] ++ [{d,Y} || Y <- lists:seq(1, 10000)],
 5281:           F = fun(J) ->
 5282:                       qlc:q([{XX,YY} ||
 5283:                                 {XX,X} <- L1,
 5284:                                 {Y,YY} <- L2,
 5285:                                 X == Y],
 5286:                             {join,J})
 5287:               end,
 5288:           Qm = F(merge),
 5289:           Qn = F(nested_loop),
 5290:           true = lists:sort(qlc:e(Qm, {max_list_size,64*1024})) =:= 
 5291:                  lists:sort(qlc:e(Qn))">>,
 5292: 
 5293:        <<"F = fun(J) ->
 5294:                       qlc:q([{XX,YY} ||
 5295:                                 {XX,X} <- [{Y,a} || Y <- lists:seq(1, 2)],
 5296:                                 {Y,YY} <- [{a,Y} || Y <- lists:seq(1,100000)],
 5297:                                 X == Y],
 5298:                             {join,J})
 5299:               end,
 5300:           Qm = F(merge),
 5301:           Qn = F(nested_loop),
 5302:           true = qlc:e(Qm, {max_list_size,64*1024}) =:= qlc:e(Qn)">>,
 5303: 
 5304:        %% More than one join in one QLC expression.
 5305:        <<"L1 = [{Y,a} || Y <- lists:seq(1, 2)],
 5306:           L2 = [{a,Y} || Y <- lists:seq(1, 10000)],
 5307:           F = fun(J) ->
 5308:                       Q = qlc:q([{XX,YY} ||
 5309:                                     {XX,X} <- L1,
 5310:                                     {Y,YY} <- L2,
 5311:                                     X == Y,
 5312:                                     begin XX > 1 end,
 5313:                                     begin YY > 9999 end],
 5314:                                 {join,J}),
 5315:                       qlc:q([{XX1,YY1,XX2,YY2} ||
 5316:                                 {XX1,YY1} <- Q,
 5317:                                 {XX2,YY2} <- Q])
 5318:               end,
 5319:           Qm = F(merge),
 5320:           Qn = F(nested_loop),
 5321:           R1 = lists:sort(qlc:e(Qm, {max_list_size,64*1024})),
 5322:           R2 = lists:sort(qlc:e(Qm, {max_list_size,1 bsl 31})),
 5323:           true = R1 =:= lists:sort(qlc:e(Qn)),
 5324:           true = R1 =:= R2">>,
 5325: 
 5326:        <<"L1 = [{Y,a} || Y <- lists:seq(1, 2)],
 5327:           L2 = [{a,Y} || Y <- lists:seq(1, 10000)],
 5328:           F = fun(J) ->
 5329:                       Q = qlc:q([{XX,YY} ||
 5330:                                     {XX,X} <- L1,
 5331:                                     {Y,YY} <- L2,
 5332:                                     X == Y,
 5333:                                     begin XX > 1 end,
 5334:                                     begin YY > 9999 end],
 5335:                                 {join,J}),
 5336:                       qlc:q([{XX1,YY1,XX2,YY2} ||
 5337:                                 {XX1,YY1} <- Q,
 5338:                                 {XX2,YY2} <- Q,
 5339:                                 throw(thrown)])
 5340:               end,
 5341:           Qm = F(merge),
 5342:           thrown = (catch {any_term, qlc:e(Qm, {max_list_size,64*1024})})">>,
 5343: 
 5344:        <<"%% Bigger than 64*1024.
 5345:           T1 = {1, lists:seq(1, 20000)},
 5346:           L1 = [{a,T1},{b,T1}],
 5347:           L2 = [{T1,a},{T1,b}],
 5348:           F = fun(J) ->
 5349:                       qlc:q([{XX,YY} ||
 5350:                                 {XX,X} <- L1,
 5351:                                 {Y,YY} <- L2,
 5352:                                 X == Y],
 5353:                             {join,J})
 5354:               end,
 5355:           Qm = F(merge),
 5356:           Qn = F(nested_loop),
 5357:           R = [{a,a},{a,b},{b,a},{b,b}],
 5358:           R = qlc:e(Qm, {max_list_size,64*1024}),
 5359:           R = qlc:e(Qn)">>,
 5360: 
 5361:        <<"%% Bigger than 64*1024. No temporary files.
 5362:           T1 = {1, lists:seq(1, 20000)},
 5363:           L1 = [{a,T1},{b,T1}],
 5364:           L2 = [{T1,a},{T1,b}],
 5365:           F = fun(J) ->
 5366:                       qlc:q([{XX,YY} ||
 5367:                                 {XX,X} <- L1,
 5368:                                 {Y,YY} <- L2,
 5369:                                 X == Y],
 5370:                             {join,J})
 5371:               end,
 5372:           Qm = F(merge),
 5373:           Qn = F(nested_loop),
 5374:           R = [{a,a},{a,b},{b,a},{b,b}],
 5375:           R = qlc:e(Qm, {max_list_size,1 bsl 31}),
 5376:           R = qlc:e(Qn)">>
 5377: 
 5378: 
 5379:           ],
 5380:     ?line run(Config, FTs),
 5381:     
 5382:     ok.
 5383: 
 5384: join_sort(doc) ->
 5385:     "Merge join optimizations (avoid unnecessary sorting).";
 5386: join_sort(suite) -> [];
 5387: join_sort(Config) when is_list(Config) ->
 5388:     Ts = [
 5389:        <<"H1_1 = qlc:keysort(1, [{1,2,3},{4,5,6}]),
 5390:           H1 = qlc:q([X || X <- H1_1], unique),
 5391:           H2 = qlc:keysort(2, [{1,2},{3,4}]),
 5392:           H3 = qlc:q([{X,Y} || {X,_,_} <- H1, 
 5393:                                {_,Y} <- H2, 
 5394:                                X =:= Y]),
 5395:           {1,0,0,2} = join_info(H3),
 5396:           [{4,4}] = qlc:e(H3)">>,
 5397: 
 5398:        <<"H1_1 = qlc:keysort(1, [{1,2,3},{4,5,6}]),
 5399:           H1 = qlc:q([X || X <- H1_1], unique), % keeps the order
 5400:           H2 = qlc:keysort(2, [{1,2},{3,4}]),
 5401:           H3 = qlc:q([{X,Y} || {X,_,_} <- H1, % no extra keysort
 5402:                                {Y,_} <- H2,   % an extra keysort
 5403:                                X =:= Y]),
 5404:           {1,0,0,3} = join_info(H3),
 5405:           [{1,1}] = qlc:e(H3)">>,
 5406: 
 5407:        <<"H1_1 = qlc:keysort(1, [{1,2,3},{4,5,6}], {tmpdir,\"\"}),
 5408:           H1 = qlc:q([X || X <- H1_1], unique),
 5409:           H2 = qlc:keysort(2, [{1,2},{3,4}]),
 5410:           H3 = qlc:q([{X,Y} || {_,X,_} <- H1, 
 5411:                                {_,Y} <- H2, 
 5412:                                X =:= Y]),
 5413:           {1,0,0,3} = join_info(H3),
 5414:           [{2,2}] = qlc:e(H3)">>,
 5415: 
 5416:        <<"H1_1 = qlc:keysort(1, [{1,2,3},{4,5,6}], {tmpdir,\"\"}),
 5417:           H1 = qlc:q([X || X <- H1_1], unique),
 5418:           H2 = qlc:keysort(2, [{1,2},{3,4}]),
 5419:           H3 = qlc:q([{X,Y} || {_,X,_} <- H1, 
 5420:                                {_,Y} <- H2, 
 5421:                                X =:= Y]),
 5422:           {1,0,0,3} = join_info(H3),
 5423:           [{2,2}] = qlc:e(H3)">>,
 5424: 
 5425:        <<"H1 = qlc:sort([{1,a},{2,b},{3,c}]),
 5426:           %% Since H1 is sorted it is also keysorted on the first column.
 5427:           Q = qlc:q([{X, Y} || {X,_} <- H1,
 5428:                                {Y} <- [{0},{1},{2}],
 5429:                                X == Y]),
 5430:           {1,0,0,1} = join_info(Q),
 5431:           [{1,1},{2,2}] = qlc:e(Q)">>,
 5432: 
 5433:        <<"H1 = qlc:sort([{r,a,1},{r,b,2},{r,c,3}]),
 5434:           Q = qlc:q([{X, Y} || {r,_,X} <- H1, % needs keysort(3)
 5435:                                {Y} <- [{0},{1},{2}],
 5436:                                X == Y]),
 5437:           {1,0,0,2} = join_info(Q),
 5438:           [{1,1},{2,2}] = qlc:e(Q)">>,
 5439: 
 5440:        <<"QH = qlc:q([X || X <- [{1,2,3},{4,5,6}], 
 5441:                            Y <- qlc:sort([{1,2},{3,4}]), 
 5442:                            element(1, X) =:= element(2, Y)]),
 5443:           {1,0,0,2} = join_info_count(QH),
 5444:           [{4,5,6}] = qlc:e(QH)">>,
 5445: 
 5446:        <<"H1_1 = qlc:keysort(1, [{1,2,3},{4,5,6},{1,2,3}]),
 5447:           H1 = qlc:q([X || X <- H1_1], unique),
 5448:           H2 = qlc:keysort(2, [{2,1},{3,4}]),
 5449:           H3 = qlc:q([{X,Y} || {X,_,_} <- H1, 
 5450:                                {_,Y} <- H2, 
 5451:                                X =:= Y]),
 5452:           H4 = qlc:keysort(1, [{1,2},{3,4},{4,a}]),
 5453:           H5 = qlc:q([{X,Y} || {X,_} <- H4,
 5454:                                {_,Y} <- H3,
 5455:                                X =:= Y]),
 5456:           {2,0,0,3} = join_info_count(H5),
 5457:           [{1,1},{4,4}]= qlc:e(H5)">>,
 5458: 
 5459:        <<"
 5460:           H1 = qlc:keysort(2, [{1,a,u},{2,b,k},{3,c,l}]),
 5461:           H2 = qlc:q([{a,X,Y,a} || {1,X,u} <- H1,
 5462:                                    {2,Y,k} <- H1]),
 5463:           %% Neither H1 nor H2 need to be key-sorted 
 5464:           %% (the columns are constant).
 5465:           H3 = qlc:q([{A,B,C,D,E,F,G,H} ||
 5466:                          {A,B,C,D} <- H2,
 5467:                          {E,F,G,H} <- H2,
 5468:                          A =:= H],
 5469:                      {join,merge}),
 5470:           {1,0,0,4} = join_info_count(H3),
 5471:           [{a,a,b,a,a,a,b,a}] = qlc:e(H3)">>,
 5472: 
 5473:        <<"%% Q1 is sorted on X or Y.
 5474:           Q1 = qlc:q([{X,Y} ||
 5475:                          {X,_} <- qlc:keysort(1, [{1,a},{2,b}]),
 5476:                          {_,Y} <- qlc:keysort(2, [{aa,11},{bb,22}]),
 5477:                          X < Y]),
 5478:           [{1,11},{1,22},{2,11},{2,22}] = qlc:e(Q1),
 5479:           Q = qlc:q([{X,Y} ||
 5480:                         {X,_} <- Q1, % no need to sort Q1
 5481:                         {Y} <- [{0},{1},{2},{3}],
 5482:                         X =:= Y]),
 5483:           {1,0,0,3} = join_info_count(Q),
 5484:           [{1,1},{1,1},{2,2},{2,2}] = qlc:e(Q)">>,
 5485: 
 5486:        <<"H1 = qlc:keysort([2], [{r,1},{r,2},{r,3}]),
 5487:           %% H1 is actually sorted, but this info is not captured.
 5488:           Q = qlc:q([{X, Y} || {r,X} <- H1,
 5489:                                {Y} <- [{0},{1},{2}],
 5490:                                X == Y]),
 5491:           {1,0,0,2} = join_info_count(Q),
 5492:           [{1,1},{2,2}] = qlc:e(Q)">>,
 5493: 
 5494:        <<"%% Two leading constants columns and sorted objects
 5495:           %% implies keysorted on column 3.
 5496:           H1 = qlc:sort(qlc:q([{a,X,Y} || {X,Y} <- [{1,2},{2,3},{3,3}]])),
 5497:           H2 = qlc:q([{X,Y} || 
 5498:                          {a,3,X} <- H1,
 5499:                          {a,2,Y} <- H1,
 5500:                          X =:= Y]),
 5501:           {1,0,0,0} = join_info_count(H2),
 5502:           [{3,3}] = qlc:e(H2)">>,
 5503: 
 5504:        <<"QH = qlc:q([{X,Y} || {X,Y} <- [{1,4},{1,3}],
 5505:                                {Z} <- [{1}],
 5506:                                X =:= Z, (Y =:= 3) or (Y =:= 4)]),
 5507:           {1,0,0,1} = join_info_count(QH),
 5508:           [{1,4},{1,3}] = qlc:e(QH)">>,
 5509: 
 5510:        <<"E = ets:new(join, [ordered_set]),
 5511:           true = ets:insert(E, [{1,a},{2,b},{3,c}]),
 5512:           Q = qlc:q([{X, Y} || {X,_} <- ets:table(E), % no need to sort
 5513:                                {Y} <- [{0},{1},{2}],
 5514:                                X == Y], {join,merge}),
 5515:           {1,0,0,1} = join_info(Q),
 5516:           [{1,1},{2,2}] = qlc:e(Q),
 5517:           ets:delete(E)">>,
 5518: 
 5519:        <<"H1 = qlc:sort([{r,1,a},{r,2,b},{r,3,c}]),
 5520:           Q = qlc:q([{X, Y} || {r,X,_} <- H1, % does not need keysort(3)
 5521:                                {Y} <- [{0},{1},{2}],
 5522:                                X == Y]),
 5523:           {1,0,0,1} = join_info(Q),
 5524:           [{1,1},{2,2}] = qlc:e(Q)">>,
 5525: 
 5526:        <<"H1 = qlc:keysort(2,[{r,1},{r,2},{r,3}]),
 5527:           H2 = [{a},{b}],
 5528:           %% Several columns in different qualifiers have initial 
 5529:           %% constant columns.
 5530:           H3 = qlc:keysort(1,[{c1,c2,1},{foo,bar,2},{c1,c2,3},{c1,c2,2}]),
 5531:           Q = qlc:q([{r,X,Y,Z} || {r,X} <- H1,
 5532:                                   {Y} <- H2,
 5533:                                   {c1,c2,Z} <- H3,
 5534:                                   X =:= Z], {join,merge}),
 5535:           {1,0,0,3} = join_info(Q),
 5536:           [{r,1,a,1},{r,1,b,1},{r,2,a,2},{r,2,b,2},{r,3,a,3},{r,3,b,3}] =
 5537:               qlc:e(Q)">>,
 5538: 
 5539:        <<"H1 = qlc:keysort(2,[{r,1},{r,2},{r,3}]),
 5540:           H2 = [{a},{b}],
 5541:           %% As the last one, but one keysort less.
 5542:           H3 = qlc:keysort(3,[{c1,c2,1},{foo,bar,2},{c1,c2,3},{c1,c2,2}]),
 5543:           Q = qlc:q([{r,X,Y,Z} || {r,X} <- H1,
 5544:                                   {Y} <- H2,
 5545:                                   {c1,c2,Z} <- H3,
 5546:                                   X =:= Z], {join,merge}),
 5547:           {1,0,0,2} = join_info(Q),
 5548:           [{r,1,a,1},{r,1,b,1},{r,2,a,2},{r,2,b,2},{r,3,a,3},{r,3,b,3}] =
 5549:               qlc:e(Q)">>,
 5550: 
 5551:        <<"H1 = qlc:keysort(2,[{r,1},{r,2},{r,3}]),
 5552:           H2 = [{a},{b}],
 5553:           H3 = qlc:keysort(1,[{c1,c2,1},{foo,bar,2},{c1,c2,3},{c1,c2,2}]),
 5554:           %% One generator before the joined generators.
 5555:           Q = qlc:q([{r,X,Y,Z} || {Y} <- H2,
 5556:                                   {r,X} <- H1,
 5557:                                   {c1,c2,Z} <- H3,
 5558:                                   X =:= Z], {join,merge}),
 5559:           {1,0,0,3} = join_info(Q),
 5560:           [{r,1,a,1},{r,2,a,2},{r,3,a,3},{r,1,b,1},{r,2,b,2},{r,3,b,3}] = 
 5561:               qlc:e(Q)">>,
 5562: 
 5563:        <<"H1 = [{a,1},{b,2},{c,3},{d,4}],
 5564:           H2 = [{a},{b}],
 5565:           H3 = [{c1,c2,a},{foo,bar,b},{c1,c2,c},{c1,c2,d}],
 5566:           %% A couple of \"extra\" filters and generators.
 5567:           Q = qlc:q([{X,Y,Z} || {X,_} <- H1,
 5568:                                 {Y} <- H2,
 5569:                                 X > Y,
 5570:                                 {c1,c2,Z} <- H3,
 5571:                                 {W} <- [{a},{b}],
 5572:                                 W > a,
 5573:                                 X =:= Z]),
 5574:           {1,0,0,2} = join_info(Q),
 5575:           [{c,a,c},{c,b,c},{d,a,d},{d,b,d}] = qlc:e(Q)">>,
 5576: 
 5577:        <<"H1 = qlc:keysort(2,[{r,1},{r,2},{r,3}]),
 5578:           H2 = qlc:sort([{c1,c2,1},{foo,bar,2},{c1,c2,3},{c1,c2,2}]),
 5579:           %% H2 is sorted, no keysort necessary.
 5580:           %% This example shows that the 'filter-part' of the pattern
 5581:           %% ({c1,c2,Z}) should be evaluated _before_ the join.
 5582:           %% Otherwise the objects cannot be assumed to be keysort:ed on the
 5583:           %% third column (if merge join), and lookup-join would lookup
 5584:           %% more keys than necessary.
 5585:           Q = qlc:q([{r,X,Z} || {r,X} <- H1,
 5586:                                 {c1,c2,Z} <- H2,
 5587:                                 X =:= Z] ,{join,merge}),
 5588:           {1,0,0,1} = join_info(Q),
 5589:           [{r,1,1},{r,2,2},{r,3,3}] = qlc:e(Q)">>,
 5590: 
 5591:        <<"H1 = [{1,a},{2,b},{3,c}],
 5592:           H2 = [{0,0},{1,1},{2,2}],
 5593:           H3 = qlc:q([{A,C,D} ||
 5594:                          {A,_B} <- H1,
 5595:                          {C,D} <- H2,
 5596:                          A == D, C == D]),
 5597:           H4 = [{1,1},{2,2},{3,3}],
 5598:           H5 = qlc:q([{X,Y} ||
 5599:                          {X,_,_} <- H3, % no need to sort this one (merge join)
 5600:                          {_,Y} <- H4,
 5601:                          X == Y]),
 5602:           Q = qlc:q([{X,Y} ||
 5603:                         {X,_} <- H5, % no need to sort this one
 5604:                         {Y,_} <- H4,
 5605:                         X == Y]),
 5606:           {{3,0,0,4},{3,0,0,6}} = join_info(Q),
 5607:           [{1,1},{2,2}] = qlc:e(Q)">>,
 5608: 
 5609:        <<"%% There is an extra test (_C1, element(1, X) =:= 1) that is not
 5610:           %% necessary since the match spec does the same check. This can be
 5611:           %% improved upon.
 5612:           Q = qlc:q([{X,Y} ||
 5613:                         X <- [{2},{1}],
 5614:                         element(1, X) =:= 1,
 5615:                         Y=_ <- [{2},{1}],
 5616:                         element(1, X) =:= element(1, Y)]),
 5617:           {qlc,_,
 5618:               [{generate,_,{qlc,_,
 5619:                               [{generate,_,{qlc,_,
 5620:                                              [{generate,_,{list,{list,_},_}},
 5621:                                               _C1],[]}},
 5622:                                {generate,_,{qlc,_,
 5623:                                              [{generate,_,{list,[{2},{1}]}},
 5624:                                               _C2],[]}},_],
 5625:                               [{join,merge}]}},_],[]} = i(Q),
 5626:           {1,0,0,0} = join_info_count(Q),
 5627:           [{{1},{1}}] = qlc:e(Q)">>,
 5628: 
 5629:        <<"etsc(fun(E) ->
 5630:                        L = [{a,b,a},{c,d,b},{1,2,a},{3,4,b}],
 5631:                        Q = qlc:q([P1 || {X,2,Z}=P1 <- ets:table(E), 
 5632:                                         Y <- L,
 5633:                                         X =:= 1,
 5634:                                         Z =:= a,
 5635:                                         P1 =:= Y, 
 5636:                                         X =:= element(1, Y)]),
 5637:                        {1,0,0,0} = join_info_count(Q),
 5638:                        [{1,2,a}] = qlc:e(Q)
 5639:                end, [{1,2,a},{3,4,b}])">>,
 5640: 
 5641:        %% Merge join on Z and element(3, Y). No need to sort!
 5642:        <<"etsc(fun(E) ->
 5643:                        L = [{a,b,a},{c,d,b},{1,2,a},{3,4,b}],
 5644:                        Q = qlc:q([P1 || {X,2,Z}=P1 <- ets:table(E), 
 5645:                                         Y <- L,
 5646:                                         (X =:= 1) or (X =:= 2),
 5647:                                         Z =:= a,
 5648:                                         P1 =:= Y, 
 5649:                                         X =:= element(1, Y)]),
 5650:                        {1,0,0,0} = join_info_count(Q),
 5651:                        [{1,2,a}] = qlc:e(Q)
 5652:                end, [{1,2,a},{3,4,b}])">>,
 5653: 
 5654:        <<"%% Y is constant as well as X. No keysort, which means that
 5655:           %% Y must be filtered before merge join.
 5656:           etsc(fun(E) ->
 5657:                        Q = qlc:q([X || {1,2}=X <- ets:table(E), 
 5658:                                        Y <- [{a,b},{c,d},{1,2},{3,4}], 
 5659:                                        X =:= Y, 
 5660:                                        element(1, X) =:= element(1, Y)]),
 5661:                        {1,0,0,0} = join_info_count(Q),
 5662:                        [{1,2}] = qlc:e(Q)
 5663:                end, [{1,2},{3,4}])">>
 5664: 
 5665:          ],
 5666:     ?line run(Config, Ts),
 5667:     ok.
 5668: 
 5669: join_complex(doc) ->
 5670:     "Join of more than two columns.";
 5671: join_complex(suite) -> [];
 5672: join_complex(Config) when is_list(Config) ->
 5673:     Ts = [{three,
 5674:            <<"three() ->
 5675:                   L = [],
 5676:                   Q = qlc:q([{X,Y,Z} || {X,_} <- L,
 5677:                                         {_,Y} <- L,
 5678:                                         {Z,_} <- L,
 5679:                                         X =:= Y, Y == Z
 5680:                                      ]),
 5681:                   qlc:e(Q).">>,
 5682:            [],
 5683:            {warnings,[{3,qlc,too_complex_join}]}},
 5684: 
 5685:           {two,
 5686:            <<"two() ->
 5687:                   Q = qlc:q([{X,Y,Z,W} || 
 5688:                       {X} <- [], 
 5689:                       {Y} <- [], 
 5690:                       {Z} <- [], 
 5691:                       {W} <- [], 
 5692:                       X =:= Y, 
 5693:                       Z =:= W],{join,merge}),
 5694:                   qlc:e(Q).">>,
 5695:            [],
 5696:            {warnings,[{2,qlc,too_many_joins}]}}
 5697:        ],
 5698: 
 5699:     ?line compile(Config, Ts),
 5700: 
 5701:     Ts2 = [{three,
 5702:             <<"three() ->
 5703:                   L = [],
 5704:                   Q = qlc:q([{X,Y,Z} || {X,_} <- L,
 5705:                                         {_,Y} <- L,
 5706:                                         {Z,_} <- L,
 5707:                                         X =:= Y, Y == Z
 5708:                                      ]),
 5709:                   qlc:e(Q).">>,
 5710:             [],
 5711:             {[],
 5712:              ["cannot handle join of three or more generators efficiently"]}},
 5713: 
 5714:           {two,
 5715:            <<"two() ->
 5716:                   Q = qlc:q([{X,Y,Z,W} || 
 5717:                       {X} <- [], 
 5718:                       {Y} <- [], 
 5719:                       {Z} <- [], 
 5720:                       {W} <- [], 
 5721:                       X =:= Y, 
 5722:                       Z =:= W],{join,merge}),
 5723:                   qlc:e(Q).">>,
 5724:            [],
 5725:            {[],["cannot handle more than one join efficiently"]}}
 5726:        ],
 5727: 
 5728:     ?line compile_format(Config, Ts2),
 5729: 
 5730:     ok.
 5731: 
 5732: 
 5733: otp_5644(doc) ->
 5734:     "OTP-5644. Handle the new language element M:F/A.";
 5735: otp_5644(suite) -> [];
 5736: otp_5644(Config) when is_list(Config) ->
 5737:     Ts = [
 5738:        <<"Q = qlc:q([fun modul:mfa/0 || _ <- [1,2], 
 5739:                                         is_function(fun modul:mfa/0, 0)]),
 5740:           [_,_] = qlc:eval(Q)">>
 5741:        ],
 5742:     
 5743:     ?line run(Config, Ts),
 5744:     ok.
 5745: 
 5746: otp_5195(doc) ->
 5747:     "OTP-5195. Allow traverse functions returning terms.";
 5748: otp_5195(suite) -> [];
 5749: otp_5195(Config) when is_list(Config) ->
 5750:     %% Several minor improvements have been implemented in OTP-5195.
 5751:     %% The test cases are spread all over... except these.
 5752:     %%
 5753:     %% Traverse functions returning terms.
 5754: 
 5755:     Ts = [<<"L = [1,2,3],
 5756:              Err = {error,modul,err},
 5757:              H = qlc:q([X || X <- qlc_SUITE:table_error(L, Err)]),
 5758:              Err = qlc:e(H)">>,
 5759: 
 5760:           <<"Err = {error,modul,err},
 5761:              TravFun = fun() -> Err end,
 5762:              H1 = qlc:sort(qlc:q([X || X <- qlc:table(TravFun, [])])),
 5763:              H = qlc:q([{X} || X <- H1]),
 5764:              Err = qlc:e(H)">>,
 5765: 
 5766:           <<"L = [1,2,3],
 5767:              Err = {error,modul,err},
 5768:              H = qlc:q([X || X <- qlc_SUITE:table_error(L, Err)]),
 5769:              C = qlc:cursor(H),
 5770:              R = qlc:next_answers(C, all_remaining),
 5771:              qlc:delete_cursor(C),
 5772:              Err = R">>,
 5773: 
 5774:           <<"L = [1,2,3],
 5775:              Err = {error,modul,err},
 5776:              H = qlc:q([X || X <- qlc_SUITE:table_error(L, Err)]),
 5777:              F = fun(Obj, A) -> A++[Obj] end,
 5778:              Err = qlc:fold(F, [], H)">>,
 5779: 
 5780:           <<"Err = {error,modul,err},
 5781:              TravFun = fun() -> Err end,
 5782:              H1 = qlc:sort(qlc:q([X || X <- qlc:table(TravFun, [])])),
 5783:              H = qlc:q([{X} || X <- H1]),
 5784:              F = fun(Obj, A) -> A++[Obj] end,
 5785:              Err = qlc:fold(F, [], H)">>,
 5786: 
 5787:           <<"Q1 = qlc:append([qlc:append([ugly()]),[3]]),
 5788:              Q = qlc:q([X || X <- Q1]),
 5789:              42 = qlc:e(Q),
 5790:              ok.
 5791: 
 5792:              ugly() ->
 5793:                  [apa | fun() -> 42 end].
 5794:              foo() -> bar">>,
 5795: 
 5796:           <<"L = [1,2,3],
 5797:              Err = {error,modul,err},
 5798:              H = qlc:q([X || X <- qlc_SUITE:table_error(L, Err)]),
 5799:              H1 = qlc:q([X || X <- H], unique),
 5800:              Err = qlc:e(H1)">>,
 5801: 
 5802:           <<"Err = {error, module, err},
 5803:              L = [1,2,3],
 5804:              H1 = qlc:q([{X} || X <- qlc_SUITE:table_error(L, Err)]),
 5805:              H = qlc:q([{X,Y,Z} || X <- H1, Y <- H1, Z <- L], cache),
 5806:              qlc:e(H, cache_all)">>,
 5807: 
 5808:           <<"Err = {error, module, err},
 5809:              L = [1,2,3],
 5810:              H1 = qlc:q([X || X <- qlc_SUITE:table_error(L, Err)]),
 5811:              H = qlc:q([{X,Y,Z} || X <- H1, Y <- H1, Z <- L], cache),
 5812:              qlc:e(H, [cache_all,unique_all])">>,
 5813: 
 5814:           <<"L = [{1},{2},{3}],
 5815:              H = qlc:q([X || {X} <- qlc_SUITE:table_lookup_error(L), 
 5816:                              X =:= 2]),
 5817:              {error, lookup, failed} = qlc:e(H)">>,
 5818: 
 5819:           %% The traverse function can return any value, but it must not
 5820:           %% return an improper list. Improper lists must not be given anyway.
 5821:           <<"{'EXIT', {{badfun,a},_}} =
 5822:              (catch qlc:e(qlc:q([{X} || X <- [1 | a], begin true end])))">>
 5823: 
 5824:        ],
 5825:     
 5826:     ?line run(Config, Ts),
 5827: 
 5828:     Ts2 = [<<"Q = qlc:q([{X,Y} || {X} <- [{1},{2},{3}],
 5829:                                   begin
 5830:                                       %% Used to generate a badly formed file
 5831:                                       Y = 3, true
 5832:                                   end,
 5833:                                   X =:= Y]),
 5834:               [{3,3}] = qlc:e(Q)">>],
 5835:     ?line run(Config, Ts2),
 5836: 
 5837:     ok.
 5838: 
 5839: otp_6038_bug(doc) ->
 5840:     "OTP-6038. Bug fixes: unique and keysort; cache.";
 5841: otp_6038_bug(suite) -> [];
 5842: otp_6038_bug(Config) when is_list(Config) ->
 5843:     %% The 'unique' option can no longer be merged with the keysort options.
 5844:     %% This used to return [{1,a},{1,c},{2,b},{2,d}], but since 
 5845:     %% file_sorter:keysort now removes duplicates based on keys, the
 5846:     %% correct return value is [{1,a},{2,b}].
 5847:     Ts = [<<"H1 = qlc:q([X || X <- [{1,a},{2,b},{1,c},{2,d}]], unique),
 5848:              H2 = qlc:keysort(1, H1, [{unique,true}]),
 5849:              [{1,a},{2,b}] = qlc:e(H2)">>],
 5850: 
 5851:     ?line run(Config, Ts),
 5852:     
 5853:     %% Sometimes the cache options did not empty the correct tables.
 5854:     CTs = [
 5855:        <<"Options = [cache,unique],
 5856:           V1 = qlc:q([{X,Y} || X <- [1,2], Y <- [3]], Options),
 5857:           V2 = qlc:q([{X,Y} || X <- [a,b], Y <- V1]),
 5858:           V3 = qlc:q([{X,Y} || X <- [5,6], Y <- [7]], Options),
 5859:           Q = qlc:q([{X,Y} || X <- V2, Y <- V3]),
 5860:           R = qlc:e(Q),
 5861:           L1 = [{X,Y} || X <- [1,2], Y <- [3]],
 5862:           L2 = [{X,Y} || X <- [a,b], Y <- L1],
 5863:           L3 = [{X,Y} || X <- [5,6], Y <- [7]],
 5864:           L = [{X,Y} || X <- L2, Y <- L3],
 5865:           true = R =:= L">>,
 5866:        <<"Options = [cache,unique],
 5867:           V1 = qlc:q([{X,Y} || X <- [1,2], Y <- [3]], Options),
 5868:           V2 = qlc:q([{X,Y} || X <- [a,b], Y <- V1]),
 5869:           V3 = qlc:q([{X,Y} || X <- [5,6], Y <- [7]], Options),
 5870:           V4 = qlc:q([{X,Y} || X <- V2, Y <- V3], Options),
 5871:           Q = qlc:q([{X,Y} || X <- [1,2], Y <- V4]),
 5872:           R = qlc:e(Q),
 5873:           L1 = [{X,Y} || X <- [1,2], Y <- [3]],
 5874:           L2 = [{X,Y} || X <- [a,b], Y <- L1],
 5875:           L3 = [{X,Y} || X <- [5,6], Y <- [7]],
 5876:           L4 = [{X,Y} || X <- L2, Y <- L3],
 5877:           L = [{X,Y} || X <- [1,2], Y <- L4],
 5878:           true = R =:= L">>
 5879:        ],
 5880:     ?line run(Config, CTs),    
 5881: 
 5882:     ok.
 5883: 
 5884: otp_6359(doc) ->
 5885:     "OTP-6359. dets:select() never returns the empty list.";
 5886: otp_6359(suite) -> [];
 5887: otp_6359(Config) when is_list(Config) ->
 5888:     dets:start(),
 5889:     T = luna,
 5890:     Fname = filename(T, Config),
 5891: 
 5892:     Ts = [
 5893:        [<<"T = luna, Fname = \"">>, Fname, <<"\",
 5894:            {ok, _} = dets:open_file(T, [{file,Fname}]),
 5895:            Q = qlc:q([F || 
 5896:                          F <- dets:table(T), 
 5897:                          (F band ((1 bsl 0)) =/= 0), 
 5898:                          true]),
 5899:            [] = qlc:eval(Q),
 5900:            ok = dets:close(T),
 5901:            file:delete(\"">>, Fname, <<"\"),
 5902:            ok">>]
 5903:     ],
 5904: 
 5905:     ?line run(Config, Ts),
 5906:     ok.
 5907: 
 5908: otp_6562(doc) ->
 5909:     "OTP-6562. compressed = false (should be []) when sorting before join.";
 5910: otp_6562(suite) -> [];
 5911: otp_6562(Config) when is_list(Config) ->
 5912:     Bug = [
 5913:       %% This example uses a file to sort E2 on the second column. It is
 5914:       %% not easy to verify that this happens; the file_sorter module's
 5915:       %% size option cannot be set in this case. But it is not likely
 5916:       %% that the default size (512 KiB) will ever change, so it should
 5917:       %% be future safe.
 5918:       <<"E1 = create_ets(1, 10),
 5919:          E2 = create_ets(5, 150000),
 5920:          Q = qlc:q([{XX,YY} ||
 5921:                        {X,XX} <- ets:table(E1),
 5922:                        {YY,Y} <- ets:table(E2),
 5923:                        X == Y],
 5924:                    {join,merge}),
 5925:          [{5,5},{6,6},{7,7},{8,8},{9,9},{10,10}] = qlc:e(Q),
 5926:          ets:delete(E1),
 5927:          ets:delete(E2)">>
 5928:     ],
 5929:     ?line run(Config, Bug),
 5930: 
 5931:     Bits = [
 5932:        {otp_6562_1,
 5933:         <<"otp_6562_1() ->
 5934:                Q = qlc:q([X || <<X:8>> <= <<\"hej\">>]),
 5935:                qlc:info(Q).
 5936:         ">>,
 5937:         [],
 5938:         {errors,[{2,qlc,binary_generator}],
 5939:          []}}
 5940:        ],
 5941:     ?line [] = compile(Config, Bits),
 5942: 
 5943:     ?line R1 = {error,qlc,{1,qlc,binary_generator}}
 5944:              = qlc:string_to_handle("[X || <<X:8>> <= <<\"hej\">>]."),
 5945:     ?line "1: cannot handle binary generators\n" = 
 5946:              lists:flatten(qlc:format_error(R1)),
 5947: 
 5948:     ok.
 5949: 
 5950: otp_6590(doc) ->
 5951:     "OTP-6590. Bug fix (join info).";
 5952: otp_6590(suite) -> [];
 5953: otp_6590(Config) when is_list(Config) ->
 5954:     Ts = [<<"fun(Tab1Value) -> 
 5955:                     Q = qlc:q([T1#tab1.id || T1 <- [#tab1{id = id1,
 5956:                                                           value = v, 
 5957:                                                           tab2_id = id}],
 5958:                                              T2 <- [#tab2{id = id}],
 5959:                                              T1#tab1.value =:= Tab1Value,
 5960:                                              T1#tab1.tab2_id =:= T2#tab2.id]),
 5961:                     [id1] = qlc:e(Q)
 5962:             end(v)">>],
 5963: 
 5964:     ?line run(Config, <<"-record(tab1, {id, tab2_id, value}).
 5965:                          -record(tab2, {id, value}).\n">>, Ts),
 5966:     ok.
 5967: 
 5968: otp_6673(doc) ->
 5969:     "OTP-6673. Optimizations and fixes.";
 5970: otp_6673(suite) -> [];
 5971: otp_6673(Config) when is_list(Config) ->
 5972:     Ts_PT = 
 5973:         [<<"etsc(fun(E1) ->
 5974:                 etsc(fun(E2) ->
 5975:                        Q = qlc:q([{A,B,C,D} || 
 5976:                                      {A,B} <- ets:table(E1),
 5977:                                      {C,D} <- ets:table(E2),
 5978:                                      A =:= 2, % lookup
 5979:                                      B =:= D, % join
 5980:                                      C =:= g]), % lookup invalidated by join
 5981:                        {qlc,_,[{generate,_,
 5982:                                 {qlc,_,
 5983:                                  [{generate,_,
 5984:                                    {qlc,_,[{generate,_,
 5985:                                             {keysort,
 5986:                                              {list,{table,_},
 5987:                                               [{{'$1','$2'},[],['$_']}]},
 5988:                                              2,[]}},_],[]}},
 5989:                                   {generate,_,{qlc,_,
 5990:                                     [{generate,_,
 5991:                                       {keysort,{table,_},2,[]}}],
 5992:                                     []}},_],
 5993:                                  [{join,merge}]}},_,_],[]} = i(Q),
 5994:                        [{2,y,g,y}] = qlc:e(Q)
 5995:                      end, [{f,x},{g,y},{h,z}])
 5996:                  end, 
 5997:                  [{1,x},{2,y},{3,z}])">>,
 5998:          <<"etsc(fun(E1) ->
 5999:                 etsc(fun(E2) ->
 6000:                        Q = qlc:q([{A,B,C,D} || 
 6001:                                      {A,B} <- ets:table(E1),
 6002:                                      {C,D} <- ets:table(E2),
 6003:                                      A =:= 2, % lookup
 6004:                                      C =:= g, % lookup
 6005:                                      B =:= D]), % join
 6006:                        {qlc,_,[{generate,_,
 6007:                                 {qlc,_,
 6008:                                  [{generate,_,
 6009:                                    {qlc,_,[{generate,_,
 6010:                                             {keysort,
 6011:                                              {list,{table,_},
 6012:                                               [{{'$1','$2'},[],['$_']}]},
 6013:                                              2,[]}},_],[]}},
 6014:                                   {generate,_,{qlc,_,
 6015:                                                [{generate,_,
 6016:                                                  {keysort,
 6017:                                                   {list,{table,_},
 6018:                                                    [{{'$1','$2'},[],['$_']}]},
 6019:                                                   2,[]}},_],[]}},_],
 6020:                                  [{join,merge}]}},_],[]} = i(Q),
 6021:                        [{2,y,g,y}] = qlc:e(Q)
 6022:                      end, [{f,x},{g,y},{h,z}])
 6023:                  end, 
 6024:                  [{1,x},{2,y},{3,z}])">>],
 6025: 
 6026:     ?line run(Config, Ts_PT),
 6027: 
 6028:     MS = ets:fun2ms(fun({X,_Y}=T) when X > 1 -> T end),
 6029:     Ts_RT = [
 6030:         [<<"%% Explicit match-spec. ets:table() ensures there is no lookup
 6031:             %% function, which means that lookup join will not be considered.
 6032:             MS = ">>, io_lib:format("~w", [MS]), <<",
 6033:             etsc(fun(E) ->
 6034:                          F = fun(J) ->
 6035:                                    qlc:q([{X,W} ||
 6036:                                              {X,_Y} <- 
 6037:                                                  ets:table(E,{traverse,
 6038:                                                               {select,MS}}),
 6039:                                              {Z,W} <- [{1,1},{2,2},{3,3}],
 6040:                                              X =:= Z], {join,J})
 6041:                              end,
 6042:                          Qm = F(any),
 6043:                          [{2,2},{3,3}] = qlc:e(Qm),
 6044:                          {'EXIT',{cannot_carry_out_join,_}} = 
 6045:                              (catch qlc:e(F(lookup)))
 6046:                  end, [{1,a},{2,b},{3,c}])">>],
 6047: 
 6048:          <<"%% The filter 'A =< y' can be evaluated by traversing E1 using a
 6049:             %% match specification, but then lookup join cannot use E1 for
 6050:             %% looking up keys. This example shows that the filter is kept if
 6051:             %% lookup join is employed (otherwise it is optimized away since
 6052:             %% the match spec is used).
 6053:             etsc(fun(E1) ->
 6054:                          Q = qlc:q([{A,B,C,D} || 
 6055:                                        {A,B} <- ets:table(E1),
 6056:                                        {C,D} <- [{x,f},{y,g},{z,h}],
 6057:                                        A =< y, % kept
 6058:                                        A =:= C], {join,lookup}),
 6059:                          [{x,1,x,f},{y,2,y,g}] = lists:sort(qlc:e(Q))
 6060:                  end, [{x,1},{y,2},{z,3}])">>
 6061: 
 6062:     ],
 6063:     ?line run(Config, Ts_RT),
 6064: 
 6065:     ok.
 6066: 
 6067: otp_6964(doc) ->
 6068:     "OTP-6964. New option 'tmpdir_usage'.";
 6069: otp_6964(suite) -> [];
 6070: otp_6964(Config) when is_list(Config) ->
 6071:     T1 = [
 6072:        <<"Q1 = qlc:q([{X} || X <- [1,2]]),
 6073:           {'EXIT', {badarg,_}} = (catch qlc:e(Q1, {tmpdir_usage,bad})),
 6074:           %% merge join
 6075:           F = fun(Use) ->
 6076:                       L1 = [{Y,a} || Y <- lists:seq(1, 2)],
 6077:                       L2 = [{a,Y} || Y <- lists:seq(1, 10000)],
 6078:                       Q = qlc:q([{XX,YY} ||
 6079:                                     {XX,X} <- L1,
 6080:                                     {Y,YY} <- L2,
 6081:                                     X == Y],
 6082:                                 {join,merge}),
 6083:                       qlc:e(Q, [{max_list_size,64*1024},{tmpdir_usage,Use}])
 6084:               end,
 6085:           D = erlang:system_flag(backtrace_depth, 0),
 6086:       try
 6087:           20000 = length(F(allowed)),
 6088:           ErrReply = F(not_allowed),
 6089:           {error, qlc, {tmpdir_usage,joining}} = ErrReply,
 6090:           \"temporary file was needed for joining\n\" = 
 6091:               lists:flatten(qlc:format_error(ErrReply)),
 6092:           qlc_SUITE:install_error_logger(),
 6093:           20000 = length(F(warning_msg)),
 6094:           {error, joining} = qlc_SUITE:read_error_logger(),
 6095:           20000 = length(F(info_msg)),
 6096:           {info, joining} = qlc_SUITE:read_error_logger(),
 6097:           20000 = length(F(error_msg)),
 6098:           {error, joining} = qlc_SUITE:read_error_logger()
 6099:       after
 6100:           _ = erlang:system_flag(backtrace_depth, D)
 6101:       end,
 6102:           qlc_SUITE:uninstall_error_logger()">>],
 6103:     ?line run(Config, T1),
 6104: 
 6105:     T2 = [
 6106:        <<"%% File sorter.
 6107:           T = lists:seq(1, 10000),
 6108:           Q0 = qlc:q([{X} || X <- [T,T,T], begin X > 0 end], 
 6109:                      [{cache,list},unique]),
 6110:           Q1 = qlc:q([{X,Y,Z} ||
 6111:                          X <- Q0,
 6112:                          Y <- Q0,
 6113:                          Z <- Q0],
 6114:                      [{cache,list},unique]),
 6115:           Q = qlc:q([{X, Y} || Y <- [1], X <- Q1]),
 6116:           F = fun(Use) ->
 6117:                       qlc:e(Q, [{max_list_size,10000},{tmpdir_usage,Use}])
 6118:               end,
 6119:           1 = length(F(allowed)),
 6120:           ErrReply = F(not_allowed),
 6121:           {error, qlc, {tmpdir_usage,caching}} = ErrReply,
 6122:           \"temporary file was needed for caching\n\" = 
 6123:               lists:flatten(qlc:format_error(ErrReply)),
 6124:           qlc_SUITE:install_error_logger(),
 6125:           1 = length(F(error_msg)),
 6126:           {error, caching} = qlc_SUITE:read_error_logger(),
 6127:           {error, caching} = qlc_SUITE:read_error_logger(),
 6128:           1 = length(F(warning_msg)),
 6129:           {error, caching} = qlc_SUITE:read_error_logger(),
 6130:           {error, caching} = qlc_SUITE:read_error_logger(),
 6131:           1 = length(F(info_msg)),
 6132:           {info, caching} = qlc_SUITE:read_error_logger(),
 6133:           {info, caching} = qlc_SUITE:read_error_logger(),
 6134:           qlc_SUITE:uninstall_error_logger()">>],
 6135: 
 6136:     ?line run(Config, T2),
 6137: 
 6138:     T3 = [
 6139:        <<"%% sort/keysort
 6140:           E1 = create_ets(1, 10),
 6141:           E2 = create_ets(5, 50000),
 6142:           Q = qlc:q([{XX,YY} ||
 6143:                         {X,XX} <- ets:table(E1),
 6144:                         {YY,Y} <- ets:table(E2),
 6145:                         X == Y],
 6146:                     {join,merge}),
 6147:           F = fun(Use) ->
 6148:                       qlc:e(Q, {tmpdir_usage,Use})
 6149:               end,
 6150:           ErrReply = F(not_allowed),
 6151:           {error,qlc,{tmpdir_usage,sorting}} = ErrReply,
 6152:           \"temporary file was needed for sorting\n\" = 
 6153:               lists:flatten(qlc:format_error(ErrReply)),
 6154:           qlc_SUITE:install_error_logger(),
 6155:           L = [{5,5},{6,6},{7,7},{8,8},{9,9},{10,10}],
 6156:           L = F(allowed),
 6157:           L = F(error_msg),
 6158:           {error, sorting} = qlc_SUITE:read_error_logger(),
 6159:           L = F(info_msg),
 6160:           {info, sorting} = qlc_SUITE:read_error_logger(),
 6161:           L = F(warning_msg),
 6162:           {error, sorting} = qlc_SUITE:read_error_logger(),
 6163:           qlc_SUITE:uninstall_error_logger(),
 6164:           ets:delete(E1),
 6165:           ets:delete(E2)">>],
 6166:     ?line run(Config, T3),
 6167: 
 6168:     T4 = [
 6169:        <<"%% cache list
 6170:           etsc(fun(E) ->
 6171:                        Q0 = qlc:q([X || X <- ets:table(E),
 6172:                                         begin element(1, X) > 5 end],
 6173:                                   {cache,list}),
 6174:                        Q = qlc:q([{X, element(1,Y)} || X <- lists:seq(1, 5),
 6175:                                                        Y <- Q0]),
 6176:                        R = [{X,Y} || X <- lists:seq(1, 5), 
 6177:                                      Y <- lists:seq(6, 10)],
 6178:                        F = fun(Use) ->
 6179:                                    qlc:e(Q, [{max_list_size, 100*1024},
 6180:                                              {tmpdir_usage, Use}])
 6181:                            end,
 6182:                        R = lists:sort(F(allowed)),
 6183:                        qlc_SUITE:install_error_logger(),
 6184:                        R = lists:sort(F(info_msg)),
 6185:                        {info, caching} = qlc_SUITE:read_error_logger(),
 6186:                        R = lists:sort(F(error_msg)),
 6187:                        {error, caching} = qlc_SUITE:read_error_logger(),
 6188:                        R = lists:sort(F(warning_msg)),
 6189:                        {error, caching} = qlc_SUITE:read_error_logger(),
 6190:                        qlc_SUITE:uninstall_error_logger(),
 6191:                        ErrReply = F(not_allowed),
 6192:                        {error,qlc,{tmpdir_usage,caching}} = ErrReply,
 6193:                        \"temporary file was needed for caching\n\" = 
 6194:                            lists:flatten(qlc:format_error(ErrReply))
 6195:                end, [{keypos,1}], [{I,a,lists:duplicate(100000,1)} || 
 6196:                                        I <- lists:seq(1, 10)])">>],
 6197:     ?line run(Config, T4),
 6198:     ok.
 6199: 
 6200: otp_7238(doc) ->
 6201:     "OTP-7238. info-option 'depth', &c.";
 6202: otp_7238(suite) -> [];
 6203: otp_7238(Config) when is_list(Config) ->
 6204:     dets:start(),
 6205:     T = otp_7238, 
 6206:     Fname = filename(T, Config),
 6207: 
 6208:     ?line ok = compile_gb_table(Config),
 6209: 
 6210:     %% A few more warnings.
 6211:     T1 = [
 6212:        %% The same error message string, but with different tags
 6213:        %% (the strings are not compared :-(
 6214:        {nomatch_1, 
 6215:         <<"nomatch_1() ->
 6216:                {qlc:q([X || X={X} <- []]), [t || \"a\"=\"b\" <- []]}.">>,
 6217:         [],
 6218:         {warnings,[{{2,30},qlc,nomatch_pattern},
 6219:                    {{2,44},v3_core,nomatch}]}},
 6220: 
 6221:        %% Not found by qlc...
 6222:        {nomatch_2,
 6223:         <<"nomatch_2() ->
 6224:                qlc:q([t || {\"a\"++\"b\"} = {\"ac\"} <- []]).">>,
 6225:         [],
 6226:         {warnings,[{{2,22},v3_core,nomatch}]}},
 6227: 
 6228:        {nomatch_3,
 6229:         <<"nomatch_3() ->
 6230:                qlc:q([t || [$a, $b] = \"ba\" <- []]).">>,
 6231:         [],
 6232:         {warnings,[{{2,37},qlc,nomatch_pattern}]}},
 6233: 
 6234:        %% Not found by qlc...
 6235:        {nomatch_4,
 6236:         <<"nomatch_4() ->
 6237:                qlc:q([t || \"a\"++_=\"b\" <- []]).">>,
 6238:         [],
 6239:         {warnings,[{{2,22},v3_core,nomatch}]}},
 6240: 
 6241:        %% Found neither by the compiler nor by qlc...
 6242:        {nomatch_5,
 6243:         <<"nomatch_5() ->
 6244:                qlc:q([X || X = <<X>> <- [3]]).">>,
 6245:         [],
 6246:         []},
 6247: 
 6248:        {nomatch_6,
 6249:         <<"nomatch_6() ->
 6250:                qlc:q([X || X <- [],
 6251:                            X =:= {X}]).">>,
 6252:         [],
 6253:         {warnings,[{{3,30},qlc,nomatch_filter}]}},
 6254: 
 6255:        {nomatch_7,
 6256:         <<"nomatch_7() ->
 6257:                qlc:q([X || {X=Y,{Y}=X} <- []]).">>,
 6258:         [],
 6259:         {warnings,[{{2,28},qlc,nomatch_pattern}]}},
 6260: 
 6261:        {nomatch_8,
 6262:         <<"nomatch_8() ->
 6263:                qlc:q([X || {X={},X=[]} <- []]).">>,
 6264:         [],
 6265:         {warnings,[{{2,28},qlc,nomatch_pattern}]}},
 6266: 
 6267:        {nomatch_9,
 6268:         <<"nomatch_9() ->
 6269:                qlc:q([X || X <- [], X =:= {}, X =:= []]).">>,
 6270:         [],
 6271:         {warnings,[{{2,49},qlc,nomatch_filter}]}},
 6272: 
 6273:        {nomatch_10,
 6274:         <<"nomatch_10() ->
 6275:                qlc:q([X || X <- [],
 6276:                            ((X =:= 1) or (X =:= 2)) and (X =:= 3)]).">>,
 6277:         [],
 6278:         {warnings,[{{3,53},qlc,nomatch_filter}]}},
 6279: 
 6280:        {nomatch_11,
 6281:         <<"nomatch_11() ->
 6282:                qlc:q([X || X <- [], x =:= []]).">>,
 6283:         [],
 6284:         {warnings,[{{2,39},qlc,nomatch_filter}]}},
 6285: 
 6286:        {nomatch_12,
 6287:         <<"nomatch_12() ->
 6288:                qlc:q([X || X={} <- [], X =:= []]).">>,
 6289:         [],
 6290:         {warnings,[{{2,42},qlc,nomatch_filter}]}},
 6291: 
 6292:        {nomatch_13,
 6293:         <<"nomatch_13() ->
 6294:                qlc:q([Z || Z <- [], 
 6295:                            X={X} <- [], 
 6296:                            Y={Y} <- []]).">>,
 6297:         [],
 6298:         {warnings,[{{3,29},qlc,nomatch_pattern},
 6299:                    {{4,29},qlc,nomatch_pattern}]}},
 6300: 
 6301:        {nomatch_14,
 6302:         <<"nomatch_14() ->
 6303:                qlc:q([X || X={X} <- [],
 6304:                            1 > 0,
 6305:                            1 > X]).">>,
 6306:         [],
 6307:         {warnings,[{{2,29},qlc,nomatch_pattern}]}},
 6308: 
 6309:        {nomatch_15,
 6310:         <<"nomatch_15() ->
 6311:               qlc:q([{X,Y} || X={X} <- [1],
 6312:                               Y <- [1],
 6313:                               1 > 0,
 6314:                               1 > X]).">>,
 6315:         [],
 6316:         {warnings,[{{2,32},qlc,nomatch_pattern}]}},
 6317: 
 6318:        %% Template warning.
 6319:        {nomatch_template1,
 6320:         <<"nomatch_template1() ->
 6321:                qlc:q([{X} = {} || X <- []]).">>,
 6322:         [],
 6323:         {warnings,[{2,sys_core_fold,no_clause_match}]}}
 6324:          ],
 6325:     ?line [] = compile(Config, T1),
 6326: 
 6327:     %% 'depth' is a new option used by info()
 6328:     T2 = [
 6329:        %% Firstly: lists
 6330:        <<"L = [[a,b,c],{a,b,c},[],<<\"foobar\">>],
 6331:           Q = qlc:q([{X} || X <- L]),
 6332:           {call, _,
 6333:            {remote,_,{atom,_,ets},{atom,_,match_spec_run}},
 6334:            [{cons,_,{atom,_,'...'},
 6335:              {cons,_,{atom,_,'...'},
 6336:               {cons,_,{nil,_},{cons,_,{atom,_,'...'},{nil,_}}}}},
 6337:             _]} = qlc:info(Q, [{format,abstract_code},{depth,0}]),
 6338: 
 6339:           {call,_,_,
 6340:            [{cons,_,{cons,_,{atom,_,'...'},{nil,_}},
 6341:              {cons,_,
 6342:               {tuple,_,[{atom,_,'...'}]},
 6343:               {cons,_,{nil,_},
 6344:                {cons,_,
 6345:                 {bin,_,
 6346:                  [{_,_,{_,_,$.},_,_},
 6347:                   {_,_,{_,_,$.},_,_},
 6348:                   {_,_,{_,_,$.},_,_}]},
 6349:                 {nil,_}}}}},
 6350:             _]} = qlc:info(Q, [{format,abstract_code},{depth,1}]),
 6351: 
 6352:           {call,_,
 6353:            _,
 6354:           [{cons,_,{cons,_,{atom,_,a},{atom,_,'...'}},
 6355:             {cons,_,
 6356:              {tuple,_,[{atom,_,a},{atom,_,'...'}]},
 6357:              {cons,_,{nil,_},
 6358:               {cons,_,
 6359:                {bin,_,
 6360:                 [{_,_,{_,_,$f},_,_},
 6361:                  {_,_,{_,_,$.},_,_},
 6362:                  {_,_,{_,_,$.},_,_},
 6363:                  {_,_,{_,_,$.},_,_}]},
 6364:                {nil,_}}}}},
 6365:           _]} = qlc:info(Q, [{format,abstract_code},{depth,2}]),
 6366: 
 6367:           {call,_,_,
 6368:            [{cons,_,
 6369:              {cons,_,{atom,_,a},{cons,_,{atom,_,b},{atom,_,'...'}}},
 6370:              {cons,_,
 6371:               {tuple,_,[{atom,_,a},{atom,_,b},{atom,_,'...'}]},
 6372:               {cons,_,{nil,_},
 6373:                {cons,_,
 6374:                 {bin,_,
 6375:                  [{_,_,{_,_,$f},_,_},
 6376:                   {_,_,{_,_,$o},_,_},_,_,_]},
 6377:                 {nil,_}}}}},
 6378:             _]} = qlc:info(Q, [{format,abstract_code},{depth,3}]),
 6379: 
 6380:           {call,_,_,
 6381:            [{cons,_,
 6382:              {cons,_,
 6383:               {atom,_,a},{cons,_,{atom,_,b},{cons,_,{atom,_,c},{nil,_}}}},
 6384:              {cons,_,
 6385:               {tuple,_,[{atom,_,a},{atom,_,b},{atom,_,c}]},
 6386:               {cons,_,{nil,_},
 6387:                {cons,_,
 6388:                 {bin,_,
 6389:                  [{_,_,{_,_,$f},_,_},
 6390:                   {_,_,{_,_,$o},_,_},
 6391:                   {_,_,{_,_,$o},_,_},
 6392:                   {_,_,{_,_,$b},_,_},
 6393:                   {_,_,{_,_,$a},_,_},
 6394:                   {_,_,{_,_,$r},_,_}]},
 6395:                 {nil,_}}}}},
 6396:             _]} = qlc:info(Q, [{format,abstract_code},{depth,10}]),
 6397: 
 6398:           {call,_,_,
 6399:            [{cons,_,
 6400:              {cons,_,
 6401:               {atom,_,a},{cons,_,{atom,_,b},{cons,_,{atom,_,c},{nil,_}}}},
 6402:              {cons,_,
 6403:               {tuple,_,[{atom,_,a},{atom,_,b},{atom,_,c}]},
 6404:               {cons,_,{nil,_},
 6405:                {cons,_,
 6406:                 {bin,_,
 6407:                  [{_,_,{_,_,$f},_,_},
 6408:                   {_,_,{_,_,$o},_,_},
 6409:                   {_,_,{_,_,$o},_,_},
 6410:                   {_,_,{_,_,$b},_,_},
 6411:                   {_,_,{_,_,$a},_,_},
 6412:                   {_,_,{_,_,$r},_,_}]},
 6413:                 {nil,_}}}}},
 6414:             _]} = qlc:info(Q, [{format,abstract_code},{depth,infinity}])">>,
 6415:        
 6416:        %% Secondly: looked up keys
 6417:        <<"F = fun(D) ->
 6418:                 etsc(fun(E) ->
 6419:                        Q = qlc:q([C || {N,C} <- ets:table(E), 
 6420:                                        (N =:= {2,2}) or (N =:= {3,3})]),
 6421:                        F = qlc:info(Q, [{format,abstract_code},{depth,D}]),
 6422:                        {call,_,_,[{call,_,_,[_Fun,Values]},_]} = F,
 6423:                        [b,c] = lists:sort(qlc:eval(Q)),
 6424:                        Values
 6425:                      end, [{{1,1},a},{{2,2},b},{{3,3},c},{{4,4},d}])
 6426:               end,
 6427: 
 6428:           [{cons,_,{atom,_,'...'},{cons,_,{atom,_,'...'},{nil,_}}},
 6429:            {cons,_,
 6430:             {tuple,_,[{atom,_,'...'}]},
 6431:             {cons,_,{tuple,_,[{atom,_,'...'}]},{nil,_}}},
 6432:            {cons,_,
 6433:             {tuple,_,[{integer,_,2},{atom,_,'...'}]},
 6434:             {cons,_,{tuple,_,[{integer,_,3},{atom,_,'...'}]},{nil,_}}},
 6435:            {cons,_,
 6436:             {tuple,_,[{integer,_,2},{integer,_,2}]},
 6437:             {cons,_,{tuple,_,[{integer,_,3},{integer,_,3}]},{nil,_}}},
 6438:            {cons,_,
 6439:             {tuple,_,[{integer,_,2},{integer,_,2}]},
 6440:             {cons,_,{tuple,_,[{integer,_,3},{integer,_,3}]},{nil,_}}}] =
 6441:               lists:map(F, [0,1,2,3,infinity])">>,
 6442:        [<<"T = otp_7238, Fname = \"">>, Fname, <<"\",
 6443:            {ok, _} = dets:open_file(T, [{file,Fname}]),
 6444:            ok = dets:insert(T, [{{1,1},a},{{2,2},b},{{3,3},c},{{4,4},d}]),
 6445:            Q = qlc:q([C || {N,C} <- dets:table(T), 
 6446:                            (N =:= {2,2}) or (N =:= {3,3})]),
 6447:            F = qlc:info(Q, [{format,abstract_code},{depth,1}]),
 6448:            [b,c] = lists:sort(qlc:eval(Q)),
 6449:            {call,_,_,
 6450:             [{call,_,_,
 6451:               [_,
 6452:                {cons,_,
 6453:                 {tuple,_,[{atom,_,'...'}]},
 6454:                 {cons,_,{tuple,_,[{atom,_,'...'}]},{nil,_}}}]},
 6455:              _]} = F,
 6456:            ok = dets:close(T),
 6457:            file:delete(\"">>, Fname, <<"\")">>],
 6458: 
 6459:        %% Thirdly: format_fun has been extended (in particular: gb_table)
 6460:        <<"T = gb_trees:from_orddict([{{1,a},w},{{2,b},v},{{3,c},u}]),
 6461:           QH = qlc:q([X || {{X,Y},_} <- gb_table:table(T),
 6462:                            ((X =:= 1) or (X =:= 2)),
 6463:                            ((Y =:= a) or (Y =:= b) or (Y =:= c))]),
 6464:           {call,_,_,
 6465:            [{call,_,_,
 6466:              [{'fun',_,
 6467:                {clauses,
 6468:                 [{clause,_,_,[],
 6469:                   [{'case',_,
 6470:                     {call,_,_,
 6471:                      [_,
 6472:                       {call,_,_,
 6473:                        [{cons,_,
 6474:                          {tuple,_,[{atom,_,'...'}]},
 6475:                          {cons,_,
 6476:                           {tuple,_,[{atom,_,'...'}]},
 6477:                           {cons,_,{tuple,_,[{atom,_,'...'}]},{nil,_}}}}]}]},
 6478:                     [_,_]}]}]}},
 6479:               {cons,_,
 6480:                {tuple,_,[{atom,_,'...'}]},
 6481:                {cons,_,
 6482:                 {tuple,_,[{atom,_,'...'}]},
 6483:                 {cons,_,
 6484:                  {tuple,_,[{atom,_,'...'}]},
 6485:                  {cons,_,
 6486:                   {tuple,_,[{atom,_,'...'}]},
 6487:                   {cons,_,
 6488:                    {tuple,_,[{atom,_,'...'}]},
 6489:                    {cons,_,{tuple,_,[{atom,_,'...'}]},{nil,_}}}}}}}]},
 6490:             {call,_,_,
 6491:              [{cons,_,{tuple,_,[{atom,_,'...'}]},{nil,_}}]}]} = 
 6492:             qlc:info(QH, [{format,abstract_code},{depth,1}])">>,
 6493:        <<"T1 = [{1,1,a},{2,2,b},{3,3,c},{4,4,d}],
 6494:           T2 = [{x,1},{y,1},{z,2}],
 6495:           QH1 = T1,
 6496:           T = gb_trees:from_orddict(T2),
 6497:           QH2 = qlc:q([X || {_,X} <- gb_table:table(T)], cache),
 6498:           Q = qlc:q([{X1,X2,X3} || {X1,X2,X3} <- QH1, 
 6499:                                    Y2 <- QH2, 
 6500:                                    X2 =:= Y2]),
 6501:           {block,_,
 6502:            [{match,_,_,
 6503:              {call,_,_,
 6504:               [{lc,_,_,
 6505:                 [{generate,_,_,
 6506:                   {call,_,_,
 6507:                    [{call,_,_,
 6508:                      [{cons,_,
 6509:                        {tuple,_,[{atom,_,'...'}]},
 6510:                        {atom,_,'...'}}]}]}}]},
 6511:                _]}},
 6512:             {call,_,_,
 6513:              [{lc,_,_,
 6514:                [{generate,_,_,
 6515:                  {cons,_,{tuple,_,[{atom,_,'...'}]},{atom,_,'...'}}},
 6516:                 _,_]}]}]} = 
 6517:               qlc:info(Q, [{format,abstract_code},{depth, 1},
 6518:                            {n_elements,1}])">>,
 6519:        <<"L = [{{key,1},a},{{key,2},b},{{key,3},c}],
 6520:           T = gb_trees:from_orddict(orddict:from_list(L)),
 6521:           Q = qlc:q([K || {K,_} <- gb_table:table(T), 
 6522:                                    (K =:= {key,1}) or (K =:= {key,2})]),
 6523: {call,_,_,
 6524:  [{call,_,_,
 6525:    [{'fun',_,
 6526:      {clauses,
 6527:       [{clause,_,_,[],
 6528:         [{'case',_,
 6529:           {call,_,_,
 6530:            [_,
 6531:             {call,_,_,
 6532:              [{cons,_,
 6533:                {tuple,_,[{tuple,_,[{atom,_,'...'}]},{atom,_,'...'}]},
 6534:                {cons,_,
 6535:                 {tuple,_,[{tuple,_,[{atom,_,'...'}]},{atom,_,'...'}]},
 6536:                 {cons,_,
 6537:                  {tuple,_,[{tuple,_,[{atom,_,'...'}]},{atom,_,'...'}]},
 6538:                  {nil,_}}}}]}]},
 6539:           _}]}]}},
 6540:     {cons,_,
 6541:      {tuple,_,[{atom,_,key},{atom,_,'...'}]},
 6542:      {cons,_,{tuple,_,[{atom,_,key},{atom,_,'...'}]},{nil,_}}}]},
 6543:   {call,_,
 6544:    {remote,_,{atom,_,ets},{atom,_,match_spec_compile}},
 6545:    [{cons,_,
 6546:      {tuple,_,[{tuple,_,[{atom,_,'...'}]},{atom,_,'...'}]},
 6547:      {nil,_}}]}]} = 
 6548:           qlc:info(Q, [{format,abstract_code},{depth, 2}])">>
 6549: 
 6550:          ],
 6551:     ?line run(Config, T2),
 6552: 
 6553:     T3 = [
 6554:        {nomatch_6,
 6555:         <<"nomatch_6() ->
 6556:                qlc:q([X || X <- [],
 6557:                            X =:= {X}]).">>,
 6558:         [],
 6559:         {[],["filter evaluates to 'false'"]}},
 6560: 
 6561:        {nomatch_7,
 6562:         <<"nomatch_7() ->
 6563:                qlc:q([X || {X=Y,{Y}=X} <- []]).">>,
 6564:         [],
 6565:         {[],["pattern cannot possibly match"]}}],
 6566:     ?line compile_format(Config, T3),
 6567: 
 6568:     %% *Very* simple test - just check that it doesn't crash.
 6569:     Type = [{cres,
 6570:              <<"Q = qlc:q([X || {X} <- []]),
 6571:                 {'EXIT',{{badfun,_},_}} = (catch qlc:e(Q))">>,
 6572:              [type_checker],
 6573:              []}],
 6574:     ?line run(Config, Type),
 6575: 
 6576:     ok.
 6577:     
 6578: otp_7114(doc) ->
 6579:     "OTP-7114. Match spec, table and duplicated objects..";
 6580: otp_7114(suite) -> [];
 6581: otp_7114(Config) when is_list(Config) ->
 6582:     Ts = [<<"T = ets:new(t, [bag]),
 6583:              [ets:insert(T, {t, I, I div 2}) || I <- lists:seq(1,10)],
 6584:              Q1 = qlc:q([element(3, E) || E <- ets:table(T)]),
 6585:              [0,1,1,2,2,3,3,4,4,5] = lists:sort(qlc:e(Q1)),
 6586:              [0,1,2,3,4,5] = qlc:e(Q1, unique_all),
 6587:              [0,1,2,3,4,5] = qlc:e(qlc:sort(Q1), unique_all),
 6588:              [0,1,2,3,4,5] = qlc:e(qlc:sort(qlc:e(Q1)), unique_all),
 6589:              ets:delete(T),
 6590:              ok">>],
 6591:     ?line run(Config, Ts).
 6592: 
 6593: otp_7232(doc) ->
 6594:     "OTP-7232. qlc:info() bug (pids, ports, refs, funs).";
 6595: otp_7232(suite) -> [];
 6596: otp_7232(Config) when is_list(Config) ->
 6597:     Ts = [<<"L = [fun math:sqrt/1, list_to_pid(\"<0.4.1>\"),
 6598:                   erlang:make_ref()],
 6599:              \"[fun math:sqrt/1,<0.4.1>,#Ref<\" ++ _  = qlc:info(L),
 6600:              {call,_,
 6601:                {remote,_,{atom,_,qlc},{atom,_,sort}},
 6602:                [{cons,_,
 6603:                       {'fun',_,{function,{atom,_,math},{atom,_,sqrt},_}},
 6604:                       {cons,_,
 6605:                             {string,_,\"<0.4.1>\"}, % could use list_to_pid..
 6606:                             {cons,_,{string,_,\"#Ref<\"++_},{nil,_}}}},
 6607:                 {nil,_}]} = 
 6608:               qlc:info(qlc:sort(L),{format,abstract_code})">>,
 6609: 
 6610:           <<"Q1 = qlc:q([X || X <- [1000,2000]]),
 6611:              Q = qlc:sort(Q1, {order, fun(A,B)-> A>B end}),
 6612:              \"qlc:sort([1000,2000],[{order,fun'-function/0-fun-2-'/2}])\" = 
 6613:                 format_info(Q, true),
 6614:              AC = qlc:info(Q, {format, abstract_code}),
 6615:              \"qlc:sort([1000,2000], [{order,fun '-function/0-fun-2-'/2}])\" = 
 6616:                 binary_to_list(iolist_to_binary(erl_pp:expr(AC)))">>,
 6617: 
 6618:          %% OTP-7234. erl_parse:abstract() handles bit strings
 6619:           <<"Q = qlc:sort([<<17:9>>]),
 6620:              \"[<<8,1:1>>]\" = qlc:info(Q)">>
 6621: 
 6622:          ],
 6623:     ?line run(Config, Ts).
 6624: 
 6625: otp_7552(doc) ->
 6626:     "OTP-7552. Merge join bug.";
 6627: otp_7552(suite) -> [];
 6628: otp_7552(Config) when is_list(Config) ->
 6629:     %% The poor performance cannot be observed unless the 
 6630:     %% (redundant) join filter is skipped. 
 6631:     Ts = [<<"Few = lists:seq(1, 2),
 6632:              Many = lists:seq(1, 10),
 6633:              S = [d,e],
 6634:              L1 = [{Y,a} || Y <- Few] ++ [{'1b',b},{2,b}] ++ 
 6635:                     [{Y,X} || X <- S, Y <- Few],
 6636:              L2 = [{a,Y} || Y <- Many] ++ 
 6637:                     [{b,'1b'}] ++ [{c,1}] ++ 
 6638:                     [{X,Y} || X <- S, Y <- Many],
 6639:                    F = fun(J) ->
 6640:                                qlc:q([{XX,YY} ||
 6641:                                          {XX,X} <- L1,
 6642:                                          {Y,YY} <- L2,
 6643:                                          X == Y],
 6644:                                      {join,J})
 6645:                        end,
 6646:                    Qm = F(merge),
 6647:                    Qn = F(nested_loop),
 6648:                    true = lists:sort(qlc:e(Qm, {max_list_size,20})) =:= 
 6649:                           lists:sort(qlc:e(Qn))">>],
 6650:     ?line run(Config, Ts).
 6651: 
 6652: otp_7714(doc) ->
 6653:     "OTP-7714. Merge join bug.";
 6654: otp_7714(suite) -> [];
 6655: otp_7714(Config) when is_list(Config) ->
 6656:     %% The original example uses Mnesia. This one does not.
 6657:     Ts = [<<"E1 = ets:new(set,[]),
 6658:              true = ets:insert(E1, {a,1}),
 6659:              E2 = ets:new(set,[]),
 6660:              _ = [true = ets:insert(E2, {I, 1}) ||
 6661:                      I <- lists:seq(1, 3)],
 6662:              Q = qlc:q([{A,B} || 
 6663:                            {A,I1} <- ets:table(E1),
 6664:                            {B,I2} <- ets:table(E2),
 6665:                            I1 =:= I2],{join,merge}),
 6666:              [{a,1},{a,2},{a,3}] = lists:sort(qlc:e(Q)),
 6667:              ets:delete(E1),
 6668:              ets:delete(E2)">>],
 6669:     ?line run(Config, Ts).
 6670: 
 6671: otp_6674(doc) ->
 6672:     "OTP-6674. match/comparison.";
 6673: otp_6674(suite) -> [];
 6674: otp_6674(Config) when is_list(Config) ->
 6675: 
 6676:     ?line ok = compile_gb_table(Config),
 6677: 
 6678:     Ts = [%% lookup join
 6679:           <<"E = ets:new(join, [ordered_set]),
 6680:              true = ets:insert(E, [{1,a},{2,b},{3,c}]),
 6681:              Q = qlc:q([{X, Y} || {X,_} <- ets:table(E),
 6682:                                   {Y} <- [{0},{1},{2}],
 6683:                                   X == Y]),
 6684:              {0,1,0,0} = join_info(Q),
 6685:              [{1,1},{2,2}] = qlc:e(Q),
 6686:              ets:delete(E)">>,
 6687: 
 6688:           <<"E = ets:new(join, [ordered_set]),
 6689:              true = ets:insert(E, [{1,a},{2,b},{3,c}]),
 6690:              Q = qlc:q([{X, Y} || {X,_} <- ets:table(E),
 6691:                                   {Y} <- [{0},{1},{2}],
 6692:                                   X =:= Y]),
 6693:              {0,1,0,0} = join_info(Q),
 6694:              {block,_,
 6695:               [_,
 6696:                {match,_,_,
 6697:                  {call,_,_,
 6698:                   [{lc,_,_,
 6699:                     [_,_,{op,_,'==',_,_}]},
 6700:                    {cons,_,
 6701:                     {tuple,_,[{atom,_,join},{atom,_,lookup}]},_}]}},
 6702:                _]} = qlc:info(Q, {format, abstract_code}),
 6703:              [{1,1},{2,2}] = qlc:e(Q),
 6704:              ets:delete(E)">>,
 6705: 
 6706:        <<"E = ets:new(join, [set]),
 6707:           Q = qlc:q([{X, Y} || {X,_} <- ets:table(E),
 6708:                                {Y} <- [{0},{1},{2}],
 6709:                                X == Y], {join, lookup}),
 6710:           {'EXIT',{cannot_carry_out_join,_}} = (catch qlc:e(Q)),
 6711:           ets:delete(E)">>,
 6712: 
 6713:        %% Lookup join possible in both directions.
 6714:        <<"E1 = ets:new(join, [ordered_set]),
 6715:           E2 = ets:new(join, [set]),
 6716:           true = ets:insert(E1, [{1.0,a},{2,b},{3,c}]),
 6717:           true = ets:insert(E2, [{0},{1},{2}]),
 6718:           Q = qlc:q([{X, Y} || {X,_} <- ets:table(E1),
 6719:                                {Y} <- ets:table(E2),
 6720:                                X == Y],{join,lookup}), % skipped
 6721:           {qlc,_,
 6722:             [{generate,_,
 6723:                  {qlc,_,
 6724:                      [{generate,_,
 6725:                           {qlc,_,[{generate,_,{table,{ets,table,[_]}}}],[]}},
 6726:                       {generate,_,{table,{ets,table,[_]}}},
 6727:                       _],
 6728:                      [{join,lookup}]}}],
 6729:             []} = qlc:info(Q, {format,debug}),
 6730:           {0,1,0,0} = join_info(Q),
 6731:           [{1.0,1},{2,2}] = lists:sort(qlc:e(Q)),
 6732:           ets:delete(E1), 
 6733:           ets:delete(E2)">>,
 6734:        <<"E1 = ets:new(join, [ordered_set]),
 6735:           E2 = ets:new(join, [set]),
 6736:           true = ets:insert(E1, [{1.0,a},{2,b},{3,c}]),
 6737:           true = ets:insert(E2, [{0},{1},{2}]),
 6738:           Q = qlc:q([{X, Y} || {X,_} <- ets:table(E1),
 6739:                                {Y} <- ets:table(E2),
 6740:                                X =:= Y],{join,merge}), % not skipped
 6741:           {1,0,0,1} = join_info(Q),
 6742:           [{2,2}] = qlc:e(Q),
 6743:           ets:delete(E1), 
 6744:           ets:delete(E2)">>,
 6745:        <<"E1 = ets:new(join, [ordered_set]),
 6746:           E2 = ets:new(join, [set]),
 6747:           true = ets:insert(E1, [{1.0,a},{2,b},{3,c}]),
 6748:           true = ets:insert(E2, [{0},{1},{2}]),
 6749:           Q = qlc:q([{X, Y} || {X,_} <- ets:table(E1),
 6750:                                {Y} <- ets:table(E2),
 6751:                                X =:= Y],{join,lookup}), % skipped
 6752:           {qlc,_,
 6753:            [{generate,_,
 6754:              {qlc,_,
 6755:               [{generate,_,
 6756:                 {qlc,_,
 6757:                  [{generate,_,{table,{ets,table,[_]}}}],
 6758:                  []}},
 6759:                {generate,_,{table,{ets,table,[_]}}},
 6760:                _],
 6761:               [{join,lookup}]}}],
 6762:             []} = qlc:info(Q, {format,debug}),
 6763:           {0,1,0,0} = join_info(Q),
 6764:           [{2,2}] = qlc:e(Q),
 6765:           ets:delete(E1), 
 6766:           ets:delete(E2)">>,
 6767:        <<"E1 = ets:new(join, [ordered_set]),
 6768:           E2 = ets:new(join, [set]),
 6769:           true = ets:insert(E1, [{1.0,a},{2,b},{3,c}]),
 6770:           true = ets:insert(E2, [{0},{1},{2}]),
 6771:           Q = qlc:q([{X, Y} || {X,_} <- ets:table(E1),
 6772:                                {Y} <- ets:table(E2),
 6773:                                %% Independent of term comparison:
 6774:                                X =:= Y, X == Y]),
 6775:           {0,1,0,0} = join_info(Q),
 6776:           [{2,2}] = qlc:e(Q),
 6777:           ets:delete(E1), 
 6778:           ets:delete(E2)">>,
 6779: 
 6780:        <<"E = ets:new(join, [ordered_set]),
 6781:           true = ets:insert(E, [{1,1},{2,2},{3,c}]),
 6782:           Q = qlc:q([{X, Y} || {X,Z} <- ets:table(E),
 6783:                                {Y} <- [{0},{1},{2}],
 6784:                                X == Z, Y == Z]), % cannot skip (yet)
 6785:           {qlc,_,
 6786:             [{generate,_,
 6787:                  {qlc,_,[_,_,_],[{join,lookup}]}},
 6788:              _,_],[]} = qlc:info(Q,{format,debug}),
 6789:           {0,1,0,0} = join_info(Q),
 6790:           [{1,1},{2,2}] = qlc:e(Q),
 6791:           ets:delete(E)">>,
 6792: 
 6793:        %% The following moved here from skip_filters. It was buggy!
 6794:        <<"etsc(fun(E) ->
 6795:                  A = 3,
 6796:                  Q = qlc:q([X || X <- ets:table(E),
 6797:                                  A == element(1,X)]),
 6798:                  {table, _} = i(Q),
 6799:                  case qlc:e(Q) of
 6800:                        [{3},{3.0}] -> ok;
 6801:                        [{3.0},{3}] -> ok
 6802:                  end,
 6803:                  false = lookup_keys(Q)
 6804:          end, [{3},{3.0},{c}])">>,
 6805:     <<"H1 = qlc:sort([{{192,192.0},1,a},{{192.0,192.0},2,b},{{192,192.0},3,c}]),
 6806:        Q = qlc:q([{X, Y} || {{A,B},X,_} <- H1, % does not need keysort(3)
 6807:                             A == 192, B =:= 192.0,
 6808:                             {Y} <- [{0},{1},{2}],
 6809:                             X == Y]),
 6810:        {block,0,
 6811:          [{match,_,_,
 6812:            {call,_,_,
 6813:             [{lc,_,_,
 6814:               [_,
 6815:                %% Has to compare extra constant:
 6816:                {op,_,'==',
 6817:                 {tuple,_,[{integer,_,192},{float,_,192.0}]},
 6818:                 {call,_,{atom,_,element},[{integer,_,1},{var,_,'P0'}]}}]}]}},
 6819:           _,_,
 6820:           {call,_,_,
 6821:            [{lc,_,_,
 6822:              [_,
 6823:               %% The join filter has been skipped.
 6824:               {op,_,'==',{var,_,'A'},{integer,_,192}},
 6825:               {op,_,'=:=',{var,_,'B'},{float,_,192.0}}]}]}]}
 6826:       = qlc:info(Q, {format,abstract_code}),
 6827:        {1,0,0,1} = join_info(Q),
 6828:        [{1,1},{2,2}] = qlc:e(Q)">>,
 6829: 
 6830:     %% Does not handle more than one lookup value (conjunctive).
 6831:     <<"T = gb_trees:from_orddict([{1,a},{2,b}]),
 6832:        H = qlc:q([X || {X,_} <- gb_table:table(T),
 6833:                                 X =:= 1 andalso X == 1.0]),
 6834:        false = lookup_keys(H),
 6835:        [1] = qlc:e(H)">>,
 6836: 
 6837:     %% EqualConstants...
 6838:     <<"etsc(fun(E) ->
 6839:                 Q = qlc:q([{X,Y} || {X} <- ets:table(E), 
 6840:                                 {Y} <- [{{1}},{{2}},{{1.0}},{{2.0}}],
 6841:                                 X =:= {1}, X == {1.0},
 6842:                                 X == Y], {join, merge}),
 6843:                 [{{1},{1}},{{1},{1.0}}] = lists:sort(qlc:e(Q)),
 6844:                 false = lookup_keys(Q)
 6845:          end, [{{1}}, {{2}}])">>,
 6846: 
 6847:     <<"T = gb_trees:from_orddict([{foo,{1}}, {bar,{2}}]),
 6848:        Q = qlc:q([{X,Y} || {_,X} <- gb_table:table(T), 
 6849:                        {Y} <- [{{1}},{{2}},{{1.0}},{{2.0}}],
 6850:                          (X =:= {1}) or (X == {2}), 
 6851:                          (X == {1.0}) or (X =:= {2.0}),
 6852:                        X == Y], {join, merge}),
 6853:        [{{1},{1}},{{1},{1.0}}] = qlc:e(Q)">>,
 6854: 
 6855:     %% Compare key
 6856:     <<"T = gb_trees:from_orddict([{1,a},{2,b}]),
 6857:        H = qlc:q([X || {X,_} <- gb_table:table(T),
 6858:                        X == 1]),
 6859:        [1] = lookup_keys(H),
 6860:        [1] = qlc:e(H)">>,
 6861:     <<"T = gb_trees:from_orddict([{1,a},{2,b}]),
 6862:        H = qlc:q([X || {X,_} <- gb_table:table(T),
 6863:                        X == 1.0]),
 6864:        [1.0] = lookup_keys(H), % this is how gb_table works...
 6865:        [1.0] = qlc:e(H)">>,
 6866:     <<"etsc(fun(E) ->
 6867:                    H = qlc:q([X || {X,_} <- ets:table(E), 
 6868:                                    X == 1.0]),
 6869:                    [1] = qlc:e(H), % and this is how ETS works.
 6870:                    [1.0] = lookup_keys(H)
 6871:            end, [ordered_set], [{1,a},{2,b}])">>,
 6872: 
 6873:     <<"T = gb_trees:from_orddict([{1,a},{2,b}]),
 6874:        H = qlc:q([X || {X,_} <- gb_table:table(T),
 6875:                        X =:= 2]),
 6876:        [2] = lookup_keys(H),
 6877:        %% Cannot (generally) remove the matching filter (the table
 6878:        %% compares the key). But note that gb_table returns the given
 6879:        %% term as key, so in this case the filter _could_ have been removed.
 6880:        %% However, there is no callback to inform qlc about that.
 6881:        {call,_,_,
 6882:              [_,{call,_,_,
 6883:                [{cons,_,{tuple,_,
 6884:                   [_,{cons,_,
 6885:                     {tuple,_,[{atom,_,'=:='},{atom,_,'$1'},{integer,_,2}]},
 6886:                     _},_]},_}]}]} =  qlc:info(H, {format,abstract_code}),
 6887:        [2] = qlc:e(H)">>,
 6888:     <<"T = gb_trees:from_orddict([{1,a},{2,b}]),
 6889:        H = qlc:q([X || {X,_} <- gb_table:table(T),
 6890:                        X =:= 2.0]),
 6891:        %% Just shows that the term (not the key) is returned.
 6892:        [2.0] = lookup_keys(H),
 6893:        [2.0] = qlc:e(H)">>,
 6894: 
 6895:     <<"I = 1,
 6896:        T = gb_trees:from_orddict([{1,a},{2,b}]),
 6897:        H = qlc:q([X || {X,_} <- gb_table:table(T),
 6898:                        X == I]), % imported variable
 6899:        [1] = lookup_keys(H),
 6900:        {call,_,_,
 6901:              [_,{call,_,_,
 6902:                [{cons,_,
 6903:                  {tuple,_,
 6904:                   [{tuple,_,[{atom,_,'$1'},{atom,_,'_'}]},
 6905:                    {nil,_}, % the filter has been skipped
 6906:                    {cons,_,{atom,_,'$1'},_}]},
 6907:                  _}]}]} = qlc:info(H, {format, abstract_code}),
 6908:        [1] = qlc:e(H)">>,
 6909:     <<"I = 2,
 6910:        T = gb_trees:from_orddict([{1,a},{2,b}]),
 6911:        H = qlc:q([X || {X,_} <- gb_table:table(T),
 6912:                        X =:= I]),
 6913:        [2] = lookup_keys(H),
 6914:        {call,_,_,
 6915:             [_,{call,_,_,
 6916:               [{cons,_,{tuple,_,
 6917:                  [_,{cons,_,
 6918:                    {tuple,_,
 6919:                     [{atom,_,'=:='},
 6920:                      {atom,_,'$1'},
 6921:                      {tuple,_,[{atom,_,const},{integer,_,2}]}]},
 6922:                    _},_]},
 6923:                 _}]}]} = qlc:info(H, {format, abstract_code}),
 6924:           [2] = qlc:e(H)">>,
 6925: 
 6926:     <<"etsc(fun(E) ->
 6927:                  Q = qlc:q([X || {X,_} <- ets:table(E),
 6928:                                  X =:= a]), % skipped
 6929:                  [a] = qlc:e(Q),
 6930:                  {list,{table,_},_} = i(Q),
 6931:                  [a] = lookup_keys(Q)
 6932:             end, [ordered_set], [{a,1},{b,2},{3,c}])">>,
 6933: 
 6934:     %% Does not find that if for instance X =:= {1} then the filter
 6935:     %% X == {1} can be removed.
 6936:     <<"etsc(fun(E) ->
 6937:                 Q = qlc:q([X || {X} <- ets:table(E), 
 6938:                                 X =:= {1}, X == {1.0}]),
 6939:                 [{1}] = qlc:e(Q),
 6940:                 [{1}] = lookup_keys(Q)
 6941:          end, [{{1}}, {{2}}])">>,
 6942:     <<"etsc(fun(E) ->
 6943:                 Q = qlc:q([X || {X} <- ets:table(E), 
 6944:                                 X =:= {1}, X == {1.0}]),
 6945:                 [{1}] = qlc:e(Q),
 6946:                 false = lookup_keys(Q)
 6947:          end, [ordered_set], [{{1}}, {{2}}])">>,
 6948:     <<"etsc(fun(E) ->
 6949:                 Q = qlc:q([X || {X} <- ets:table(E), 
 6950:                                 X == {1.0}, X =:= {1}]),
 6951:                 [{1}] = qlc:e(Q),
 6952:                 [{1}] = lookup_keys(Q)
 6953:          end, [{{1}}, {{2}}])">>,
 6954:     <<"etsc(fun(E) ->
 6955:                 Q = qlc:q([X || {X} <- ets:table(E), 
 6956:                                 X == {1.0}, X =:= {1}]),
 6957:                 [{1}] = qlc:e(Q),
 6958:                 false = lookup_keys(Q)
 6959:          end, [ordered_set], [{{1}}, {{2}}])">>,
 6960: 
 6961:     <<"E = ets:new(apa, []),
 6962:        true = ets:insert(E, [{1,a},{2,b}]),
 6963:        {'EXIT', {badarg, _}} = 
 6964:               (catch qlc_SUITE:bad_table_key_equality(E)),
 6965:        ets:delete(E)">>,
 6966: 
 6967:     <<"etsc(fun(E) ->
 6968:            Q = qlc:q([X || {X} <- ets:table(E), 
 6969:                                X =:= 1, X =:= is_integer(X)]),
 6970:            [] = qlc:e(Q),
 6971:            [1] = lookup_keys(Q)
 6972:        end, [{1}, {2}])">>,
 6973: 
 6974:     <<"etsc(fun(E) ->
 6975:                  Q = qlc:q([X || {X=1} <- ets:table(E), 
 6976:                                  X =:= is_integer(X)]),
 6977:                  {call,_,_,
 6978:                   [{lc,_,_,
 6979:                     [_,
 6980:                      {op,_,'=:=',
 6981:                       {var,_,'X'},
 6982:                       {call,_,
 6983:                        {atom,_,is_integer},
 6984:                        [{var,_,'X'}]}}]}]} = 
 6985:              qlc:info(Q, {format, abstract_code}),
 6986:              [] = qlc:e(Q),
 6987:              [1] = lookup_keys(Q)
 6988:          end, [{1}, {2}])">>,
 6989: 
 6990:     <<"T = gb_trees:from_orddict([{1,a},{2,b}]),
 6991:        H = qlc:q([X || {X,Y} <- gb_table:table(T),
 6992:                                 Y =:= a, true, X =:= 1]),
 6993:        [1] = lookup_keys(H),
 6994:        [1] = qlc:e(H)">>,
 6995: 
 6996:     <<"T = gb_trees:from_orddict([{{1.0,1},a},{{2.0,2},b}]),
 6997:        H = qlc:q([X || {{1.0,B}=X,_} <- gb_table:table(T),
 6998:                        B == 1]), % skipped
 6999:        [{1.0, 1}] = qlc:e(H),
 7000:        {qlc,_,[{generate,_,{table,_}}], []} = qlc:info(H, {format,debug})">>,
 7001:     <<"T = gb_trees:from_orddict([{{1.0,1},a},{{2.0,2},b}]),
 7002:        H = qlc:q([X || {{1.0,B}=X,_} <- gb_table:table(T),
 7003:                     B == 1.0]), % skipped
 7004:        [{1.0, 1.0}] = qlc:e(H), % this is how gb_table works...
 7005:        {qlc,_,[{generate,_,{table,_}}], []} = qlc:info(H, {format,debug})">>,
 7006:     <<"T = gb_trees:from_orddict([{{1.0,1},a},{{2.0,2},b}]),
 7007:        H = qlc:q([X || {{1.0,B}=X,_} <- gb_table:table(T),
 7008:                        B =:= 1.0]), % not skipped
 7009:        [{1.0, 1.0}] = qlc:e(H),
 7010:        {qlc,_,[{generate,_,{table,_}},_], []} = qlc:info(H,{format,debug})">>,
 7011:     <<"T = gb_trees:from_orddict([{{1.0,1},a},{{2.0,2},b}]),
 7012:        H = qlc:q([X || {{1.0,B}=X,_} <- gb_table:table(T),
 7013:                        B =:= 1]), % not skipped
 7014:        [{1.0, 1}] = qlc:e(H),
 7015:        {qlc,_,[{generate,_,{table,_}},_], []} = qlc:info(H,{format,debug})">>,
 7016: 
 7017:     <<"%% The imported variables do not interfere with join.
 7018:        E = ets:new(join, [ordered_set]),
 7019:        {A, B} = {1,1},
 7020:        true = ets:insert(E, [{1,a},{2,b},{3,c}]),
 7021:        Q = qlc:q([{X, Y} || {X,_Z} <- ets:table(E),
 7022:                             {Y} <- [{0},{1},{2}],
 7023:                             X =:= A, Y =:= B, 
 7024:                             Y == X], % skipped
 7025:                 {join, merge}),
 7026:        [{1,1}] = qlc:e(Q),
 7027:        {qlc,_,
 7028:            [{generate,_,
 7029:              {qlc,_,
 7030:               [{generate,_,
 7031:                 {qlc,_,[{generate,_,{list,{table,_},_}},_],[]}},
 7032:                {generate,_,
 7033:                 {qlc,_,[{generate,_,{list,_,_}},_],[]}},
 7034:                _],
 7035:               [{join,merge}]}}],
 7036:            []} = qlc:info(Q, {format, debug}),
 7037:        ets:delete(E)">>,
 7038: 
 7039:     <<"% An old bug: usort() should not be used when matching values
 7040:        etsc(fun(E) ->
 7041:                    I = 1,
 7042:                    H = qlc:q([X || {X,_} <- ets:table(E), 
 7043:                                    X =:= 1.0 orelse X =:= I]),
 7044:                    [1] = qlc:e(H),
 7045:                    [1.0] = lookup_keys(H) % do not look up twice
 7046:             end, [set], [{1,a},{2,b}])">>,
 7047:     <<"etsc(fun(E) ->
 7048:                    H = qlc:q([X || {X,_} <- ets:table(E), 
 7049:                                     X =:= 1.0 orelse X == 1]),
 7050:                    [1] = qlc:e(H),
 7051:                    false = lookup_keys(H) % doesn't handle this case
 7052:          end, [ordered_set], [{1,a},{2,b}])">>,
 7053: 
 7054:     <<"etsc(fun(E) ->
 7055:                  I1 = 1, I2 = 1,
 7056:                  H = qlc:q([X || {X,_} <- ets:table(E), 
 7057:                                  X =:= I1 orelse X == I2]),
 7058:                  [1] = qlc:e(H), % do not look up twice
 7059:                  [1] = lookup_keys(H)
 7060:          end, [ordered_set], [{1,a},{2,b}])">>,
 7061: 
 7062:     <<"etsc(fun(E) ->
 7063:                  I1 = 1, I2 = 1, I3 = 1,
 7064:                  H = qlc:q([X || {X,_} <- ets:table(E), 
 7065:                                  I1 == I2, I1 =:= I3, I3 == I2, I2 =:= I3,
 7066:                                  X =:= I1 orelse X == I2
 7067:                                  ]),
 7068:                  [1] = qlc:e(H),
 7069:                  [1] = lookup_keys(H)
 7070:          end, [ordered_set], [{1,a},{2,b}])">>,
 7071: 
 7072:     <<"E = ets:new(join, [ordered_set]),
 7073:        true = ets:insert(E, [{1,a},{2,b,x},{3,c}]),
 7074:        Q = qlc:q([P || P <- ets:table(E),
 7075:                        P =:= {1,a} orelse P =:= {2,b,x}]),
 7076:        [{1,a},{2,b,x}] = qlc:e(Q),
 7077:        ets:delete(E)">>,
 7078: 
 7079:     <<"etsc(fun(E) ->
 7080:                    Q = qlc:q([X || {X,Y} <- ets:table(E), 
 7081:                                    ((X =:= 3) or (Y =:= 4))  and (X == a)]),
 7082:                    {list,{table,_},_} = i(Q),
 7083:                    [] = qlc:e(Q), % a is not an answer
 7084:                    [a] = lookup_keys(Q)
 7085:           end, [{keypos,1},ordered_set], [{a,3},{b,4}])">>,
 7086: 
 7087:     <<"Q = qlc:q([{X,Y} ||
 7088:                   {X} <- [{<<3:4>>}],
 7089:                   {Y} <- [{<<3:4>>}],
 7090:                   X =:= <<1:3,1:1>>,        % <<3:4>>
 7091:                   Y =:= <<0:2,1:1,1:1>>,    % <<3:4>>
 7092:                   X =:= Y]),
 7093:                   [{<<3:4>>,<<3:4>>}] = qlc:e(Q)">>
 7094: 
 7095: 
 7096:     ],
 7097: 
 7098:     ?line run(Config, Ts).
 7099: 
 7100: manpage(doc) ->
 7101:     "Examples from qlc(3).";
 7102: manpage(suite) -> [];
 7103: manpage(Config) when is_list(Config) ->
 7104: 
 7105:     ?line ok = compile_gb_table(Config),
 7106: 
 7107:     Ts = [
 7108:        <<"QH = qlc:q([{X,Y} || X <- [a,b], Y <- [1,2]]),
 7109:           QC = qlc:cursor(QH),
 7110:           [{a,1}] = qlc:next_answers(QC, 1),
 7111:           [{a,2}] = qlc:next_answers(QC, 1),
 7112:           [{b,1},{b,2}] = qlc:next_answers(QC, all_remaining),
 7113:           ok = qlc:delete_cursor(QC)">>,
 7114: 
 7115:        <<"QH = qlc:q([{X,Y} || X <- [a,b], Y <- [1,2]]),
 7116:           [{a,1},{a,2},{b,1},{b,2}] = qlc:eval(QH)">>,
 7117: 
 7118:        <<"QH = [1,2,3,4,5,6],
 7119:           21 = qlc:fold(fun(X, Sum) -> X + Sum end, 0, QH)">>,
 7120: 
 7121:        <<"QH = qlc:q([{X,Y} || X <- [x,y], Y <- [a,b]]),
 7122:           B = \"begin\n\"
 7123:               \"    V1 =\n\"
 7124:               \"        qlc:q([ \n\"
 7125:               \"               SQV ||\n\"
 7126:               \"                   SQV <- [x,y]\n\"
 7127:               \"              ],\n\"
 7128:               \"              [{unique,true}]),\n\"
 7129:               \"    V2 =\n\"
 7130:               \"        qlc:q([ \n\"
 7131:               \"               SQV ||\n\"
 7132:               \"                   SQV <- [a,b]\n\"
 7133:               \"              ],\n\"
 7134:               \"              [{unique,true}]),\n\"
 7135:               \"    qlc:q([ \n\"
 7136:               \"           {X,Y} ||\n\"
 7137:               \"               X <- V1,\n\"
 7138:               \"               Y <- V2\n\"
 7139:               \"          ],\n\"
 7140:               \"          [{unique,true}])\n\"
 7141:               \"end\",
 7142:           true = B =:= qlc:info(QH, unique_all)">>,
 7143: 
 7144:        <<"E1 = ets:new(e1, []),
 7145:           E2 = ets:new(e2, []),
 7146:           true = ets:insert(E1, [{1,a},{2,b}]),
 7147:           true = ets:insert(E2, [{a,1},{b,2}]),
 7148:           Q = qlc:q([{X,Z,W} ||
 7149:                         {X, Z} <- ets:table(E1),
 7150:                         {W, Y} <- ets:table(E2),
 7151:                         X =:= Y]),
 7152:           L = \"begin\n\"
 7153:               \"    V1 =\n\"
 7154:               \"        qlc:q([ \n\"
 7155:               \"               P0 ||\n\"
 7156:               \"                   P0 = {W,Y} <- ets:table(_)\n\"
 7157:               \"              ]),\n\"
 7158:               \"    V2 =\n\"
 7159:               \"        qlc:q([ \n\"
 7160:               \"               [G1|G2] ||\n\"
 7161:               \"                   G2 <- V1,\n\"
 7162:               \"                   G1 <- ets:table(_),\n\"
 7163:               \"                   element(2, G1) =:= element(1, G2)\n\"
 7164:               \"              ],\n\"
 7165:               \"              [{join,lookup}]),\n\"
 7166:               \"    qlc:q([ \n\"
 7167:               \"           {X,Z,W} ||\n\"
 7168:               \"               [{X,Z}|{W,Y}] <- V2\n\"
 7169:               \"          ])\n\"
 7170:               \"end\",
 7171:           Info =
 7172:              re:replace(qlc:info(Q), 
 7173:                         \"table\\\\(-*[0-9]*\",
 7174:                         \"table(_\", [{return,list},global]),
 7175:           L = Info,
 7176:           ets:delete(E1),
 7177:           ets:delete(E2)">>,
 7178: 
 7179:        <<"Q = qlc:q([{A,X,Z,W} ||
 7180:                         A <- [a,b,c],
 7181:                         {X,Z} <- [{a,1},{b,4},{c,6}],
 7182:                         {W,Y} <- [{2,a},{3,b},{4,c}],
 7183:                         X =:= Y],
 7184:                     {cache, list}),
 7185:           L =
 7186:        \"begin\n\"
 7187:        \"    V1 =\n\"
 7188:        \"        qlc:q([ \n\"
 7189:        \"               P0 ||\n\"
 7190:        \"                   P0 = {X,Z} <- qlc:keysort(1, [{a,1},{b,4},{c,6}], [])\n\"
 7191:        \"              ]),\n\"
 7192:        \"    V2 =\n\"
 7193:        \"        qlc:q([ \n\"
 7194:        \"               P0 ||\n\"
 7195:        \"                   P0 = {W,Y} <- qlc:keysort(2, [{2,a},{3,b},{4,c}], [])\n\"
 7196:        \"              ]),\n\"
 7197:        \"    V3 =\n\"
 7198:        \"        qlc:q([ \n\"
 7199:        \"               [G1|G2] ||\n\"
 7200:        \"                   G1 <- V1,\n\"
 7201:        \"                   G2 <- V2,\n\"
 7202:        \"                   element(1, G1) == element(2, G2)\n\"
 7203:        \"              ],\n\"
 7204:        \"              [{join,merge},{cache,list}]),\n\"
 7205:        \"    qlc:q([ \n\"
 7206:        \"           {A,X,Z,W} ||\n\"
 7207:        \"               A <- [a,b,c],\n\"
 7208:        \"               [{X,Z}|{W,Y}] <- V3,\n\"
 7209:        \"               X =:= Y\n\"
 7210:        \"          ])\n\"
 7211:        \"end\",
 7212:           L = qlc:info(Q)">>,
 7213: 
 7214:        <<"E1 = ets:new(t, [set]), % uses =:=/2
 7215:           Q1 = qlc:q([K ||
 7216:           {K} <- ets:table(E1),
 7217:           K == 2.71 orelse K == a]),
 7218:           {list,{table,_}, [{{'$1'},[],['$1']}]} = i(Q1),
 7219:           true = ets:delete(E1)">>,
 7220: 
 7221:        <<"F = fun(E, I) ->
 7222:                     qlc:q([V || {K,V} <- ets:table(E), K == I])
 7223:               end,
 7224:           E2 = ets:new(t, [set]),
 7225:           true = ets:insert(E2, [{{2,2},a},{{2,2.0},b},{{2.0,2},c}]),
 7226:           Q2 = F(E2, {2,2}),
 7227:           {table,{ets,table,[_,
 7228:                 [{traverse,{select,[{{'$1','$2'},
 7229:                                      [{'==','$1',{const,{2,2}}}],
 7230:                                      ['$2']}]}}]]}} = i(Q2),
 7231:           [a,b,c] = lists:sort(qlc:e(Q2)),
 7232:           true = ets:delete(E2),
 7233: 
 7234:           E3 = ets:new(t, [ordered_set]), % uses ==/2
 7235:           true = ets:insert(E3, [{{2,2.0},b}]),
 7236:           Q3 = F(E3,{2,2}),
 7237:           {list,{table,_},[{{'$1','$2'},[],['$2']}]} = i(Q3),
 7238:           [b] = qlc:e(Q3),
 7239:           true = ets:delete(E3)">>,
 7240: 
 7241:        <<"T = gb_trees:empty(),
 7242:           QH = qlc:q([X || {{X,Y},_} <- gb_table:table(T),
 7243:                            ((X == 1) or (X == 2)) andalso
 7244:                            ((Y == a) or (Y == b) or (Y == c))]),
 7245:           L = \"ets:match_spec_run(lists:flatmap(fun(K) ->
 7246:                                         case
 7247:                                             gb_trees:lookup(K,
 7248:                                                             gb_trees:from_orddict([]))
 7249:                                         of
 7250:                                             {value,V} ->
 7251:                                                 [{K,V}];
 7252:                                             none ->
 7253:                                                 []
 7254:                                         end
 7255:                                  end,
 7256:                                  [{1,a},{1,b},{1,c},{2,a},{2,b},{2,c}]),
 7257:                    ets:match_spec_compile([{{{'$1','$2'},'_'},[],['$1']}]))\",
 7258:           L = qlc:info(QH)">>
 7259:       ],
 7260:     ?line run(Config, Ts),
 7261: 
 7262:     L = [1,2,3],
 7263:     Bs = erl_eval:add_binding('L', L, erl_eval:new_bindings()),
 7264:     QH = qlc:string_to_handle("[X+1 || X <- L].", [], Bs),
 7265:     [2,3,4] = qlc:eval(QH),
 7266: 
 7267:     %% ets(3)
 7268:     MS = ets:fun2ms(fun({X,Y}) when (X > 1) or (X < 5) -> {Y} end),
 7269:     ETs = [
 7270:         [<<"true = ets:insert(Tab = ets:new(t, []),[{1,a},{2,b},{3,c},{4,d}]),
 7271:             MS = ">>, io_lib:format("~w", [MS]), <<",
 7272:             QH1 = ets:table(Tab, [{traverse, {select, MS}}]),
 7273: 
 7274:             QH2 = qlc:q([{Y} || {X,Y} <- ets:table(Tab), (X > 1) or (X < 5)]),
 7275: 
 7276:             true = qlc:info(QH1) =:= qlc:info(QH2),
 7277:             true = ets:delete(Tab)">>]],
 7278:     ?line run(Config, ETs),
 7279: 
 7280:     %% dets(3)
 7281:     DTs = [
 7282:         [<<"{ok, T} = dets:open_file(t, []),
 7283:             ok = dets:insert(T, [{1,a},{2,b},{3,c},{4,d}]),
 7284:             MS = ">>, io_lib:format("~w", [MS]), <<",
 7285:             QH1 = dets:table(T, [{traverse, {select, MS}}]),
 7286: 
 7287:             QH2 = qlc:q([{Y} || {X,Y} <- dets:table(t), (X > 1) or (X < 5)]),
 7288: 
 7289:             true = qlc:info(QH1) =:= qlc:info(QH2),
 7290:             ok = dets:close(T)">>]],
 7291:     ?line run(Config, DTs),
 7292: 
 7293:     ok.
 7294: 
 7295: compile_gb_table(Config) ->
 7296:     GB_table_file = filename("gb_table.erl", Config),
 7297:     ?line ok = file:write_file(GB_table_file, gb_table()),
 7298:     ?line {ok, gb_table} = compile:file(GB_table_file, [{outdir,?privdir}]),
 7299:     ?line code:purge(gb_table),
 7300:     ?line {module, gb_table} = 
 7301:         code:load_abs(filename:rootname(GB_table_file)),
 7302:     ok.
 7303: 
 7304: gb_table() ->
 7305:     <<"
 7306: -module(gb_table).
 7307: 
 7308: -export([table/1]).
 7309: 
 7310: table(T) ->
 7311:     TF = fun() -> qlc_next(gb_trees:next(gb_trees:iterator(T))) end,
 7312:     InfoFun = fun(num_of_objects) -> gb_trees:size(T);
 7313:                  (keypos) -> 1;
 7314:                  (is_sorted_key) -> true;
 7315:                  (is_unique_objects) -> true;
 7316:                  (_) -> undefined
 7317:               end,
 7318:     LookupFun =
 7319:         fun(1, Ks) ->
 7320:                 lists:flatmap(fun(K) ->
 7321:                                       case gb_trees:lookup(K, T) of
 7322:                                           {value, V} -> [{K,V}];
 7323:                                           none -> []
 7324:                                       end
 7325:                               end, Ks)
 7326:         end,
 7327:     FormatFun =
 7328:         fun({all, NElements, ElementFun}) ->
 7329:                 ValsS = io_lib:format(\"gb_trees:from_orddict(~w)\",
 7330:                                       [gb_nodes(T, NElements, ElementFun)]),
 7331:                 io_lib:format(\"gb_table:table(~s)\", [ValsS]);
 7332:            ({lookup, 1, KeyValues, _NElements, ElementFun}) ->
 7333:                 ValsS = io_lib:format(\"gb_trees:from_orddict(~w)\",
 7334:                                       [gb_nodes(T, infinity, ElementFun)]),
 7335:                 io_lib:format(\"lists:flatmap(fun(K) -> \"
 7336:                               \"case gb_trees:lookup(K, ~s) of \"
 7337:                               \"{value, V} -> [{K,V}];none -> [] end \"
 7338:                               \"end, ~w)\",
 7339:                               [ValsS, [ElementFun(KV) || KV <- KeyValues]])
 7340:         end,
 7341:     qlc:table(TF, [{info_fun, InfoFun}, {format_fun, FormatFun},
 7342:                    {lookup_fun, LookupFun},{key_equality,'=='}]).
 7343: 
 7344: qlc_next({X, V, S}) ->
 7345:     [{X,V} | fun() -> qlc_next(gb_trees:next(S)) end];
 7346: qlc_next(none) ->
 7347:     [].
 7348: 
 7349: gb_nodes(T, infinity, ElementFun) ->
 7350:     gb_nodes(T, -1, ElementFun);
 7351: gb_nodes(T, NElements, ElementFun) ->
 7352:     gb_iter(gb_trees:iterator(T), NElements, ElementFun).
 7353: 
 7354: gb_iter(_I, 0, _EFun) ->
 7355:     '...';
 7356: gb_iter(I0, N, EFun) ->
 7357:     case gb_trees:next(I0) of
 7358:         {X, V, I} ->
 7359:             [EFun({X,V}) | gb_iter(I, N-1, EFun)];
 7360:         none ->
 7361:             []
 7362:     end.
 7363:     ">>.
 7364: 
 7365: 
 7366: backward(doc) ->
 7367:     "OTP-6674. Join info and extra constants.";
 7368: backward(suite) -> [];
 7369: backward(Config) when is_list(Config) ->
 7370:     try_old_join_info(Config),
 7371:     ok.
 7372: 
 7373: try_old_join_info(Config) ->
 7374:     %% Check join info for handlers of extra constants.
 7375:     File = filename:join(?datadir, "join_info_compat.erl"),
 7376:     M = join_info_compat,
 7377:     {ok, M} = compile:file(File, [{outdir, ?datadir}]),
 7378:     {module, M} = code:load_abs(filename:rootname(File)),
 7379:     H = M:create_handle(),
 7380:     {block,0,
 7381:      [{match,_,_,
 7382:        {call,_,_,
 7383:         [{lc,_,_,
 7384:           [_,
 7385:            {op,_,'=:=',
 7386:             {float,_,192.0},
 7387:             {call,_,{atom,_,element},[{integer,_,1},_]}}]}]}},
 7388:       _,_,
 7389:       {call,_,_,
 7390:        [{lc,_,_,
 7391:          [_,
 7392:           {op,_,'=:=',{var,_,'B'},{float,_,192.0}},
 7393:           {op,_,'==',{var,_,'X'},{var,_,'Y'}}]}]}]}
 7394:         = qlc:info(H,{format,abstract_code}),
 7395:     [{1,1},{2,2}] = qlc:e(H),
 7396: 
 7397:     H2 = M:lookup_handle(),
 7398:     {qlc,_,[{generate,_,{qlc,_,_,[{join,lookup}]}},_],[]} =
 7399:         qlc:info(H2, {format,debug}),
 7400:     [{1,1},{2,2}] = qlc:e(H2).
 7401: 
 7402: forward(doc) ->
 7403:     "";
 7404: forward(suite) -> [];
 7405: forward(Config) when is_list(Config) ->
 7406:     Ts = [
 7407:       %% LC_fun() returns something unknown.
 7408:       <<"FakeH = {qlc_handle,{qlc_lc,fun() -> {foo,bar} end,
 7409:                              {qlc_opt,false,false,-1,any,[],any,524288}}},
 7410:          {'EXIT', {{unsupported_qlc_handle,_},_}} = (catch qlc:e(FakeH))">>,
 7411: 
 7412: %% 'f1' should be used for new stuff that does not interfer with old behavior
 7413: %       %% The unused element 'f1' of #qlc_table seems to be used.
 7414: %       <<"DF = fun() -> foo end,
 7415: %          FakeH = {qlc_handle,{qlc_table,DF,
 7416: %                        true,DF,DF,DF,DF,DF,
 7417: %                        undefined,not_undefined,undefined,no_match_spec}},
 7418: %          {'EXIT', {{unsupported_qlc_handle,_},_}} = (catch qlc:e(FakeH))">>,
 7419: 
 7420:       %% #qlc_opt has changed.
 7421:       <<"H = qlc:q([X || X <- []]),
 7422:          {qlc_handle, {qlc_lc, Fun, _Opt}} = H,
 7423:          FakeH = {qlc_handle, {qlc_lc, Fun, {new_qlc_opt, a,b,c}}},
 7424:          {'EXIT', {{unsupported_qlc_handle,_},_}} = (catch qlc:e(FakeH))">>
 7425: 
 7426:      ],
 7427:     ?line run(Config, Ts),
 7428:     ok.
 7429: 
 7430: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 7431: 
 7432: bad_table_throw(Tab) ->
 7433:     Limit = 1,
 7434:     Select = fun(MS) -> cb(ets:select(Tab, MS, Limit)) end,
 7435:     PreFun = fun(_) -> throw({throw,bad_pre_fun}) end,
 7436:     PostFun = fun() -> throw({throw,bad_post_fun}) end,
 7437:     InfoFun = fun(Tag) -> info(Tab, Tag) end,
 7438:     qlc:table(Select, [{pre_fun,PreFun}, {post_fun, PostFun}, 
 7439:                        {info_fun, InfoFun}]).
 7440:     
 7441: bad_table_exit(Tab) ->
 7442:     Limit = 1,
 7443:     Select = fun(MS) -> cb(ets:select(Tab, MS, Limit)) end,
 7444:     PreFun = fun(_) -> erlang:error(bad_pre_fun) end,
 7445:     PostFun = fun() -> erlang:error(bad_post_fun) end,
 7446:     InfoFun = fun(Tag) -> info(Tab, Tag) end,
 7447:     qlc:table(Select, [{pre_fun,PreFun}, {post_fun, PostFun}, 
 7448:                        {info_fun, InfoFun}]).
 7449:     
 7450: info(_Tab, is_unique_objects) -> 
 7451:     false;
 7452: info(Tab, Tag) -> 
 7453:     try ets:info(Tab, Tag) catch _:_ -> undefined end.
 7454: 
 7455: create_ets(S, E) ->
 7456:     create_ets(lists:seq(S, E)).
 7457: 
 7458: create_ets(L) ->
 7459:     E1 = ets:new(e, []),
 7460:     true = ets:insert(E1, [{X,X} || X <- L]),
 7461:     E1.
 7462: 
 7463: etsc(F, Objs) ->
 7464:     etsc(F, [{keypos,1}], Objs).
 7465: 
 7466: etsc(F, Opts, Objs) ->
 7467:     E = ets:new(test, Opts),
 7468:     true = ets:insert(E, Objs),
 7469:     V = F(E),
 7470:     ets:delete(E),
 7471:     V.
 7472: 
 7473: join_info(H) ->
 7474:     {qlc, S, Options} = strip_qlc_call(H),
 7475:     %% "Hide" the call to qlc_pt from the test in run_test().
 7476:     LoadedPT = code:is_loaded(qlc_pt),
 7477:     QH = qlc:string_to_handle(S, Options),
 7478:     _ = [unload_pt() || false <- [LoadedPT]], % doesn't take long...
 7479:     case {join_info_count(H), join_info_count(QH)} of
 7480:         {N, N} -> 
 7481:             N;
 7482:         Ns -> 
 7483:             Ns
 7484:     end.
 7485: 
 7486: strip_qlc_call(H) ->
 7487:     S = qlc:info(H, {flat, false}),
 7488:     {ok, Tokens, _EndLine} = erl_scan:string(S++"."),
 7489:     {ok, [Expr]} = erl_parse:parse_exprs(Tokens),
 7490:     case Expr of
 7491:         {call,_,{remote,_,{atom,_,qlc},{atom,_,q}},[LC]} ->
 7492:             {qlc, lists:flatten([erl_pp:expr(LC), "."]), []};
 7493:         {call,_,{remote,_,{atom,_,qlc},{atom,_,q}},[LC, Opts]} ->
 7494:             {qlc, lists:flatten([erl_pp:expr(LC), "."]), 
 7495:              erl_parse:normalise(Opts)};
 7496:         {call,_,{remote,_,{atom,_,ets},{atom,_,match_spec_run}},_} ->
 7497:             {match_spec, Expr};
 7498:         {call,_,{remote,_,{atom,_,M},{atom,_,table}},_} ->
 7499:             {table, M, Expr};
 7500:         _ -> 
 7501:             []
 7502:     end.
 7503: 
 7504: -record(ji, {nmerge = 0, nlookup = 0, nnested_loop = 0, nkeysort = 0}).
 7505: 
 7506: %% Counts join options and (all) calls to qlc:keysort().
 7507: join_info_count(H) ->
 7508:     S = qlc:info(H, {flat, false}),    
 7509:     {ok, Tokens, _EndLine} = erl_scan:string(S++"."),
 7510:     {ok, [Expr]} = erl_parse:parse_exprs(Tokens),
 7511:     #ji{nmerge = Nmerge, nlookup = Nlookup, 
 7512:         nkeysort = NKeysort, nnested_loop = Nnested_loop} = 
 7513:         ji(Expr, #ji{}),
 7514:     {Nmerge, Nlookup, Nnested_loop, NKeysort}.
 7515: 
 7516: ji({call,_,{remote,_,{atom,_,qlc},{atom,_,q}},[LC,Options]}, JI) ->
 7517:     NJI = case lists:keysearch(join, 1, erl_parse:normalise(Options)) of
 7518:               {value, {join, merge}} ->
 7519:                   JI#ji{nmerge = JI#ji.nmerge + 1};
 7520:               {value, {join, lookup}} ->
 7521:                   JI#ji{nlookup = JI#ji.nlookup + 1};
 7522:               {value, {join, nested_loop}} ->
 7523:                   JI#ji{nnested_loop = JI#ji.nnested_loop + 1};
 7524:               _  ->
 7525:                   JI
 7526:           end,
 7527:     ji(LC, NJI);
 7528: ji({call,_,{remote,_,{atom,_,qlc},{atom,_,keysort}},[_KP,H,_Options]}, JI) ->
 7529:     ji(H, JI#ji{nkeysort = JI#ji.nkeysort + 1});
 7530: ji(T, JI) when is_tuple(T) ->
 7531:     ji(tuple_to_list(T), JI);
 7532: ji([E | Es], JI) ->
 7533:     ji(Es, ji(E, JI));
 7534: ji(_, JI) ->
 7535:     JI.
 7536: 
 7537: %% Designed for ETS' and gb_table's format funs.
 7538: lookup_keys(Q) ->
 7539:     case lists:flatten(lookup_keys(i(Q), [])) of
 7540:         [] -> false;
 7541:         L -> lists:usort(L)
 7542:     end.
 7543: 
 7544: lookup_keys([Q | Qs], L) ->
 7545:     lookup_keys(Qs, lookup_keys(Q, L));
 7546: lookup_keys({qlc,_,Quals,_}, L) ->
 7547:     lookup_keys(Quals, L);
 7548: lookup_keys({list,Q,_}, L) ->
 7549:     lookup_keys(Q, L);
 7550: lookup_keys({generate,_,Q}, L) ->
 7551:     lookup_keys(Q, L);
 7552: lookup_keys({table,Chars}, L) when is_list(Chars) ->
 7553:     {ok, Tokens, _} = erl_scan:string(lists:flatten(Chars++".")),
 7554:     {ok, [Expr]} = erl_parse:parse_exprs(Tokens),
 7555:     case Expr of
 7556:         {call,_,_,[_fun,AKs]} ->
 7557:             case erl_parse:normalise(AKs) of
 7558:                 Ks when is_list(Ks) ->
 7559:                     [lists:sort(Ks) | L];
 7560:                 K -> % assume keys are never lists (ets only)
 7561:                     [K | L]
 7562:             end;
 7563:         _ -> % gb_table
 7564:             L
 7565:     end;
 7566: lookup_keys(_Q, L) ->
 7567:     L.
 7568: 
 7569: bad_table_format(Tab) ->
 7570:     Limit = 1,
 7571:     SelectFun = fun(MS) -> cb(ets:select(Tab, MS, Limit)) end,
 7572:     FormatFun = {is, no, good},
 7573:     qlc:table(SelectFun, [{format_fun, FormatFun}]).
 7574: 
 7575: bad_table_format_arity(Tab) ->
 7576:     Limit = 1,
 7577:     SelectFun = fun(MS) -> cb(ets:select(Tab, MS, Limit)) end,
 7578:     FormatFun = fun() -> {?MODULE, bad_table_format_arity, [Tab]} end,
 7579:     qlc:table(SelectFun, [{format_fun, FormatFun}]).
 7580: 
 7581: bad_table_traverse(Tab) ->
 7582:     Limit = 1,
 7583:     Select = fun(MS, _) -> cb(ets:select(Tab, MS, Limit)) end,
 7584:     qlc:table(Select, []).
 7585:     
 7586: bad_table_post(Tab) ->
 7587:     Limit = 1,
 7588:     SelectFun = fun(MS) -> cb(ets:select(Tab, MS, Limit)) end,
 7589:     qlc:table(SelectFun, [{pre_fun,undefined}, 
 7590:                           {post_fun, fun(X) -> X end}, 
 7591:                           {info_fun, undefined}]).
 7592:     
 7593: bad_table_lookup(Tab) ->
 7594:     Limit = 1,
 7595:     SelectFun = fun(MS) -> cb(ets:select(Tab, MS, Limit)) end,
 7596:     qlc:table(SelectFun, {lookup_fun, fun(X) -> X end}).
 7597: 
 7598: bad_table_max_lookup(Tab) ->
 7599:     Limit = 1,
 7600:     SelectFun = fun(MS) -> cb(ets:select(Tab, MS, Limit)) end,
 7601:     qlc:table(SelectFun, {max_lookup, -2}).
 7602: 
 7603: bad_table_info_arity(Tab) ->
 7604:     Limit = 1,
 7605:     SelectFun = fun(MS) -> cb(ets:select(Tab, MS, Limit)) end,
 7606:     InfoFun = fun() -> {?MODULE, bad_table_info_arity, [Tab]} end,
 7607:     qlc:table(SelectFun, [{info_fun, InfoFun}]).
 7608: 
 7609: default_table(Tab) ->
 7610:     Limit = 1,
 7611:     SelectFun = fun(MS) -> cb(ets:select(Tab, MS, Limit)) end,
 7612:     qlc:table(SelectFun, [{format_fun, undefined},
 7613:                           {info_fun, undefined},
 7614:                           {lookup_fun, undefined},
 7615:                           {parent_fun, undefined},
 7616:                           {pre_fun,undefined}, 
 7617:                           {post_fun, undefined}]).
 7618:     
 7619: bad_table(Tab) ->
 7620:     Limit = 1,
 7621:     SelectFun = fun(MS) -> cb(ets:select(Tab, MS, Limit)) end,
 7622:     qlc:table(SelectFun, [{info, fun() -> ok end}]).
 7623: 
 7624: bad_table_info_fun_n_objects(Tab) ->
 7625:     Limit = 1,
 7626:     SelectFun = fun(MS) -> cb(ets:select(Tab, MS, Limit)) end,
 7627:     LookupFun = fun(_Pos, Ks) -> 
 7628:                         lists:flatmap(fun(K) -> ets:lookup(Tab, K) end, Ks) 
 7629:                 end,
 7630:     InfoFun = fun(num_of_objects) -> exit(finito);
 7631:                  (_) -> undefined
 7632:               end,
 7633:     qlc:table(SelectFun, [{info_fun, InfoFun}, {lookup_fun, LookupFun}]).
 7634: 
 7635: bad_table_info_fun_indices(Tab) ->
 7636:     Limit = 1,
 7637:     SelectFun = fun(MS) -> cb(ets:select(Tab, MS, Limit)) end,
 7638:     LookupFun = fun(_Pos, Ks) -> 
 7639:                         lists:flatmap(fun(K) -> ets:lookup(Tab, K) end, Ks) 
 7640:                 end,
 7641:     InfoFun = fun(indices) -> throw({throw,apa});
 7642:                  (_) -> undefined
 7643:               end,
 7644:     qlc:table(SelectFun, [{info_fun, InfoFun}, {lookup_fun, LookupFun}]).
 7645: 
 7646: bad_table_info_fun_keypos(Tab) ->
 7647:     Limit = 1,
 7648:     SelectFun = fun(MS) -> cb(ets:select(Tab, MS, Limit)) end,
 7649:     LookupFun = fun(_Pos, Ks) -> 
 7650:                         lists:flatmap(fun(K) -> ets:lookup(Tab, K) end, Ks) 
 7651:                 end,
 7652:     InfoFun = fun(indices) -> erlang:error(keypos);
 7653:                   (_) -> undefined
 7654:               end,
 7655:     qlc:table(SelectFun, [{info_fun, InfoFun}, {lookup_fun, LookupFun}]).
 7656: 
 7657: bad_table_key_equality(Tab) ->
 7658:     Limit = 1,
 7659:     SelectFun = fun(MS) -> cb(ets:select(Tab, MS, Limit)) end,
 7660:     LookupFun = fun(_Pos, Ks) -> 
 7661:                         lists:flatmap(fun(K) -> ets:lookup(Tab, K) end, Ks) 
 7662:                 end,
 7663:     qlc:table(SelectFun, [{lookup_fun, LookupFun},{key_equality,'=/='}]).
 7664: 
 7665: cb('$end_of_table') -> 
 7666:     [];
 7667: cb({Objects,Cont}) -> 
 7668:     Objects ++ fun() -> cb(ets:select(Cont)) end.
 7669: 
 7670: i(H) ->
 7671:     i(H, []).
 7672: 
 7673: i(H, Options) when is_list(Options) ->
 7674:     case has_format(Options) of
 7675:         true -> qlc:info(H, Options);
 7676:         false -> qlc:info(H, [{format, debug} | Options])
 7677:     end;
 7678: i(H, Option) ->
 7679:     i(H, [Option]).
 7680: 
 7681: has_format({format,_}) ->
 7682:     true;
 7683: has_format([E | Es]) ->
 7684:     has_format(E) or has_format(Es);
 7685: has_format(_) ->
 7686:     false.
 7687: 
 7688: format_info(H, Flat) ->
 7689:     L = qlc:info(H, [{flat, Flat}, {format,string}]),
 7690:     re:replace(L, "\s|\n|\t|\f|\r|\v", "", [{return,list},global]).
 7691: 
 7692: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 7693: %% A list turned into a table...
 7694: 
 7695: table_kill_parent(List, Indices) ->
 7696:     ParentFun = fun() -> exit(self(), kill) end,
 7697:     table_i(List, Indices, ParentFun).
 7698: 
 7699: table_parent_throws(List, Indices) ->
 7700:     ParentFun = fun() -> throw({throw,thrown}) end,
 7701:     table_i(List, Indices, ParentFun).
 7702: 
 7703: table_parent_exits(List, Indices) ->
 7704:     ParentFun = fun() -> 1 + Indices end,
 7705:     table_i(List, Indices, ParentFun).
 7706: 
 7707: table_bad_parent_fun(List, Indices) ->
 7708:     ParentFun = fun(X) -> X end, % parent_fun should be nullary
 7709:     table_i(List, Indices, ParentFun).
 7710: 
 7711: table(List, Indices) ->
 7712:     ParentFun = fun() -> self() end,
 7713:     table_i(List, Indices, ParentFun).    
 7714: 
 7715: table(List, KeyPos, Indices) ->
 7716:     ParentFun = fun() -> self() end,
 7717:     table(List, Indices, KeyPos, ParentFun).    
 7718: 
 7719: table_i(List, Indices, ParentFun) ->
 7720:     table(List, Indices, undefined, ParentFun).
 7721: 
 7722: table(List, Indices, KeyPos, ParentFun) ->
 7723:     TraverseFun = fun() -> list_traverse(List) end,
 7724:     PreFun = fun(PreArgs) ->
 7725:                      {value, {parent_value, Pid}} = 
 7726:                          lists:keysearch(parent_value, 1, PreArgs),
 7727:                      true = is_pid(Pid)
 7728:              end,
 7729:     PostFun = fun() -> ok end,
 7730:     InfoFun = fun(indices) ->
 7731:                       Indices;
 7732:                  (is_unique_objects) ->
 7733:                       undefined;
 7734:                  (keypos) ->
 7735:                       KeyPos;
 7736:                  (num_of_objects) ->
 7737:                       undefined;
 7738:                  (_) ->
 7739:                       undefined
 7740:               end,
 7741:     LookupFun =
 7742:         fun(Column, Values) ->
 7743:                 lists:flatmap(fun(V) ->
 7744:                                       case lists:keysearch(V, Column, List) of
 7745:                                           false -> [];
 7746:                                           {value,Val} -> [Val]
 7747:                                       end
 7748:                               end, Values)
 7749: 
 7750:                 end,
 7751:     FormatFun = fun(all) ->
 7752:                         L = 17,
 7753:                         {call,L,{remote,L,{atom,1,?MODULE},{atom,L,the_list}},
 7754:                                  [erl_parse:abstract(List, 17)]};
 7755:                    ({lookup, Column, Values}) ->
 7756:                         {?MODULE, list_keys, [Values, Column, List]}
 7757:                 end,
 7758:     qlc:table(TraverseFun, [{info_fun,InfoFun}, {pre_fun, PreFun}, 
 7759:                             {post_fun, PostFun}, {lookup_fun, LookupFun}, 
 7760:                             {format_fun, FormatFun}, 
 7761:                             {parent_fun, ParentFun}]).
 7762: 
 7763: stop_list(List, Ets) ->
 7764:     Traverse = fun() -> list_traverse(List) end,
 7765:     PV = a_sample_parent_value,
 7766:     ParentFun = fun() -> PV end,
 7767:     Pre = fun(PreArgs) ->
 7768:                   {value, {parent_value, PV}} = 
 7769:                       lists:keysearch(parent_value, 1, PreArgs),
 7770:                   {value, {stop_fun, Fun}} = 
 7771:                       lists:keysearch(stop_fun, 1, PreArgs),
 7772:                   true = ets:insert(Ets, {stop_fun, Fun})
 7773:           end,
 7774:     qlc:table(Traverse, [{pre_fun, Pre}, {parent_fun, ParentFun}]).
 7775: 
 7776: list_traverse([]) ->
 7777:     [];
 7778: list_traverse([E | Es]) ->
 7779:     [E | fun() -> list_traverse(Es) end].
 7780: 
 7781: table_error(List, Error) ->
 7782:     table_error(List, undefined, Error).
 7783: 
 7784: table_error(List, KeyPos, Error) ->
 7785:     TraverseFun = fun() -> list_traverse2(lists:sort(List), Error) end,
 7786:     InfoFun = fun(is_sorted_key) -> true;
 7787:                  (keypos) -> KeyPos;
 7788:                  (_) -> undefined
 7789:               end,
 7790:     qlc:table(TraverseFun, [{info_fun,InfoFun}]).
 7791: 
 7792: list_traverse2([], Err) ->
 7793:     Err;
 7794: list_traverse2([E | Es], Err) ->
 7795:     [E | fun() -> list_traverse2(Es, Err) end].
 7796: 
 7797: table_lookup_error(List) ->
 7798:     TraverseFun = fun() -> list_traverse(List) end,
 7799:     LookupFun = fun(_Column, _Values) -> {error,lookup,failed} end,
 7800:     InfoFun = fun(keypos) -> 1;
 7801:                  (_) -> undefined
 7802:               end,
 7803:     qlc:table(TraverseFun, [{lookup_fun,LookupFun},{info_fun,InfoFun}]).
 7804: 
 7805: prep_scratchdir(Dir) ->
 7806:     put('$qlc_tmpdir', true),
 7807:     _ = filelib:ensure_dir(Dir),
 7808:     lists:foreach(fun(F) -> file:delete(F)
 7809:                   end, filelib:wildcard(filename:join(Dir, "*"))),
 7810:     true.
 7811: 
 7812: %% Truncate just once.
 7813: truncate_tmpfile(Dir, Where) ->
 7814:     case get('$qlc_tmpdir') of
 7815:         true -> 
 7816:             {ok, [TmpFile0 | _]} = file:list_dir(Dir),
 7817:             TmpFile = filename:join(Dir, TmpFile0),
 7818:             truncate(TmpFile, Where),
 7819:             erase('$qlc_tmpdir');
 7820:         _ ->
 7821:             true
 7822:     end.
 7823: 
 7824: truncate(File, Where) ->
 7825:     {ok, Fd} = file:open(File, [read, write]),
 7826:     {ok, _} = file:position(Fd, Where),
 7827:     ok = file:truncate(Fd),
 7828:     ok = file:close(Fd).
 7829: 
 7830: %% Crash just once.
 7831: crash_tmpfile(Dir, Where) ->
 7832:     case get('$qlc_tmpdir') of
 7833:         true -> 
 7834:             {ok, [TmpFile0 | _]} = file:list_dir(Dir),
 7835:             TmpFile = filename:join(Dir, TmpFile0),
 7836:             crash(TmpFile, Where),
 7837:             erase('$qlc_tmpdir');
 7838:         _ ->
 7839:             true
 7840:     end.
 7841: 
 7842: crash(File, Where) ->
 7843:     {ok, Fd} = file:open(File, [read, write]),
 7844:     {ok, _} = file:position(Fd, Where),
 7845:     ok = file:write(Fd, [10]),
 7846:     ok = file:close(Fd).
 7847: 
 7848: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 7849: 
 7850: run(Config, Tests) ->
 7851:     run(Config, [], Tests).
 7852: 
 7853: run(Config, Extra, Tests) ->
 7854:     lists:foreach(fun(Body) -> run_test(Config, Extra, Body) end, Tests).
 7855: 
 7856: run_test(Config, Extra, {cres, Body, ExpectedCompileReturn}) ->
 7857:     run_test(Config, Extra, {cres, Body, _Opts = [], ExpectedCompileReturn});
 7858: run_test(Config, Extra, {cres, Body, Opts, ExpectedCompileReturn}) ->
 7859:     {SourceFile, Mod} = compile_file_mod(Config),
 7860:     P = [Extra,<<"function() -> ">>, Body, <<", ok. ">>],
 7861:     CompileReturn = compile_file(Config, P, Opts),
 7862:     case comp_compare(ExpectedCompileReturn, CompileReturn) of
 7863:         true -> ok;
 7864:         false -> expected(ExpectedCompileReturn, CompileReturn, SourceFile)
 7865:     end,
 7866:     AbsFile = filename:rootname(SourceFile, ".erl"),
 7867:     _ = code:purge(Mod),
 7868:     {module, _} = code:load_abs(AbsFile, Mod),
 7869: 
 7870:     Ms0 = erlang:process_info(self(),messages),
 7871:     Before = {get(), pps(), ets:all(), Ms0},
 7872: 
 7873:     %% Prepare the check that the qlc module does not call qlc_pt.
 7874:     _ = [unload_pt() || {file, Name} <- [code:is_loaded(qlc_pt)], 
 7875:                         Name =/= cover_compiled],
 7876: 
 7877:     R = case catch Mod:function() of
 7878:             {'EXIT', _Reason} = Error ->
 7879:                 ?t:format("failed, got ~p~n", [Error]),
 7880:                 fail(SourceFile);
 7881:             Reply ->
 7882:                 Reply
 7883:         end,
 7884: 
 7885:     %% Check that the qlc module does not call qlc_pt:
 7886:     case code:is_loaded(qlc_pt) of
 7887:         {file, cover_compiled} ->
 7888:             ok;
 7889:         {file, _} ->
 7890:             ?t:format("qlc_pt was loaded in runtime~n", []),
 7891:             fail(SourceFile);
 7892:         false ->
 7893:             ok
 7894:     end,
 7895: 
 7896:     wait_for_expected(R, Before, SourceFile, true),
 7897:     code:purge(Mod);
 7898: run_test(Config, Extra, Body) ->
 7899:     run_test(Config, Extra, {cres,Body,[]}).
 7900: 
 7901: wait_for_expected(R, Before, SourceFile, Wait) ->
 7902:     Ms = erlang:process_info(self(),messages),
 7903:     After = {get(), pps(), ets:all(), Ms},
 7904:     case {R, After} of
 7905:         {ok, Before} ->
 7906:             ok;
 7907:         _ when Wait ->
 7908:             timer:sleep(1000),
 7909:             wait_for_expected(R, Before, SourceFile, false);
 7910:         _ ->
 7911:             expected({ok,Before}, {R,After}, SourceFile)
 7912:     end.
 7913: 
 7914: unload_pt() ->
 7915:     erlang:garbage_collect(), % get rid of references to qlc_pt...
 7916:     _ = code:purge(qlc_pt),
 7917:     _ = code:delete(qlc_pt).
 7918: 
 7919: compile_format(Config, Tests) ->
 7920:     Fun = fun(Test, Opts) ->
 7921:                   Return = compile_file(Config, Test, Opts),
 7922:                   format_messages(Return)
 7923:           end, 
 7924:     compile(Config, Tests, Fun).    
 7925: 
 7926: format_messages({warnings,Ws}) ->
 7927:     format_messages({errors,[],Ws});
 7928: format_messages({errors,Es,Ws}) ->
 7929:     {[format_msg(E, Mod) || {_Line,Mod,E} <- Es],
 7930:      [format_msg(W, Mod) || {_Line,Mod,W} <- Ws]}.
 7931: 
 7932: format_msg(Msg, Mod) ->
 7933:     IOlist = Mod:format_error(Msg),
 7934:     binary_to_list(iolist_to_binary(IOlist)).
 7935: 
 7936: compile(Config, Tests) ->
 7937:     Fun = fun(Test, Opts) -> catch compile_file(Config, Test, Opts) end,
 7938:     compile(Config, Tests, Fun).
 7939: 
 7940: compile(Config, Tests, Fun) ->
 7941:     F = fun({TestName,Test,Opts,Expected}, BadL) ->
 7942:                 Return = Fun(Test, Opts),
 7943:                 case comp_compare(Expected, Return) of
 7944:                     true ->
 7945:                         BadL;
 7946:                     false -> 
 7947:                         {File, _Mod} = compile_file_mod(Config),
 7948:                         expected(TestName, Expected, Return, File)
 7949:                 end
 7950:         end,
 7951:     lists:foldl(F, [], Tests).
 7952: 
 7953: %% Compiles a test module and returns the list of errors and warnings.
 7954: 
 7955: compile_file(Config, Test0, Opts0) ->
 7956:     {File, Mod} = compile_file_mod(Config),
 7957:     Test = list_to_binary(["-module(", atom_to_list(Mod), "). "
 7958:                            "-compile(export_all). "
 7959:                            "-import(qlc_SUITE, [i/1,i/2,format_info/2]). "
 7960:                            "-import(qlc_SUITE, [etsc/2, etsc/3]). "
 7961:                            "-import(qlc_SUITE, [create_ets/2]). "
 7962:                            "-import(qlc_SUITE, [strip_qlc_call/1]). "
 7963:                            "-import(qlc_SUITE, [join_info/1]). "
 7964:                            "-import(qlc_SUITE, [join_info_count/1]). "
 7965:                            "-import(qlc_SUITE, [lookup_keys/1]). "
 7966:                            "-include_lib(\"stdlib/include/qlc.hrl\"). ",
 7967:                            Test0]),
 7968:     Opts = [export_all,return,nowarn_unused_record,{outdir,?privdir}|Opts0],
 7969:     ok = file:write_file(File, Test),
 7970:     case compile:file(File, Opts) of
 7971:         {ok, _M, Ws} -> warnings(File, Ws);
 7972:         {error, [{File,Es}], []} -> {errors, Es, []};
 7973:         {error, [{File,Es}], [{File,Ws}]} -> {error, Es, Ws}
 7974:     end.
 7975: 
 7976: comp_compare(T, T) ->
 7977:     true;
 7978: comp_compare(T1, T2_0) ->
 7979:     T2 = wskip(T2_0),
 7980:     T1 =:= T2
 7981:        %% This clause should eventually be removed. 
 7982:        orelse ln(T1) =:= T2 orelse T1 =:= ln(T2).
 7983: 
 7984: wskip([]) ->
 7985:     [];
 7986: wskip([{_,sys_core_fold,{eval_failure,badarg}}|L]) ->
 7987:     wskip(L);
 7988: wskip([{{L,_C},sys_core_fold,M}|L]) ->
 7989:     [{L,sys_core_fold,M}|wskip(L)];
 7990: wskip({T,L}) ->
 7991:     {T,wskip(L)};
 7992: wskip([M|L]) ->
 7993:     [M|wskip(L)];
 7994: wskip(T) ->
 7995:     T.
 7996: 
 7997: %% Replaces locations like {Line,Column} with Line. 
 7998: ln({warnings,L}) ->
 7999:     {warnings,ln0(L)};
 8000: ln({errors,EL,WL}) ->
 8001:     {errors,ln0(EL),ln0(WL)};
 8002: ln(L) ->
 8003:     ln0(L).
 8004: 
 8005: ln0(L) ->
 8006:     lists:sort(ln1(L)).
 8007: 
 8008: ln1([]) ->
 8009:     [];
 8010: ln1([{File,Ms}|MsL]) when is_list(File) ->
 8011:     [{File,ln0(Ms)}|ln1(MsL)];
 8012: ln1([{{L,_C},Mod,Mess0}|Ms]) ->
 8013:     Mess = case Mess0 of
 8014:                {exported_var,V,{Where,{L1,_C1}}} ->
 8015:                    {exported_var,V,{Where,L1}};
 8016:                {unsafe_var,V,{Where,{L1,_C1}}} ->
 8017:                    {unsafe_var,V,{Where,L1}};
 8018:                %% There are more...
 8019:                M ->
 8020:                    M
 8021:            end,
 8022:     [{L,Mod,Mess}|ln1(Ms)];
 8023: ln1([M|Ms]) ->
 8024:     [M|ln1(Ms)].
 8025: 
 8026: %% -> {FileName, Module}; {string(), atom()}
 8027: compile_file_mod(Config) ->
 8028:     NameL = lists:concat([?TESTMODULE, "_", ?testcase]),
 8029:     Name = list_to_atom(NameL),
 8030:     File = filename(NameL ++ ".erl", Config),
 8031:     {File, Name}.
 8032: 
 8033: filename(Name, Config) when is_atom(Name) ->
 8034:     filename(atom_to_list(Name), Config);
 8035: filename(Name, Config) ->
 8036:     filename:join(?privdir, Name).
 8037: 
 8038: pps() ->
 8039:     {port_list(), process_list()}.
 8040: 
 8041: port_list() ->
 8042:     [{P,safe_second_element(erlang:port_info(P, name))} || 
 8043:         P <- erlang:ports()].
 8044: 
 8045: process_list() ->
 8046:     [{P,process_info(P, registered_name),
 8047:       safe_second_element(process_info(P, initial_call))} || 
 8048:         P <- processes(), is_process_alive(P)].
 8049: 
 8050: safe_second_element({_,Info}) -> Info;
 8051: safe_second_element(Other) -> Other.
 8052: 
 8053: warnings(File, Ws) ->
 8054:     case lists:append([W || {F, W} <- Ws, F =:= File]) of
 8055:         [] -> [];
 8056:         L -> {warnings, L}
 8057:     end.
 8058: 
 8059: expected(Test, Expected, Got, File) ->
 8060:     ?t:format("~nTest ~p failed. ", [Test]),
 8061:     expected(Expected, Got, File).
 8062: 
 8063: expected(Expected, Got, File) ->
 8064:     ?t:format("Expected~n  ~p~n, but got~n  ~p~n", [Expected, Got]),
 8065:     fail(File).
 8066: 
 8067: fail(Source) ->
 8068:     io:format("failed~n"),
 8069:     ?t:fail({failed,testcase,on,Source}).
 8070: 
 8071: %% Copied from global_SUITE.erl.
 8072: 
 8073: install_error_logger() ->
 8074:     error_logger:add_report_handler(?MODULE, self()).
 8075: 
 8076: uninstall_error_logger() ->
 8077:     error_logger:delete_report_handler(?MODULE).
 8078: 
 8079: read_error_logger() ->
 8080:     receive
 8081: 	{error, Why} ->
 8082:             {error, Why};
 8083:         {info, Why} ->
 8084:             {info, Why};
 8085:         {error, Pid, Tuple} ->
 8086:             {error, Pid, Tuple}
 8087:     after 1000 ->
 8088: 	    ?line io:format("No reply after 1 s\n", []),
 8089: 	    ?line ?t:fail()
 8090:     end.
 8091: 
 8092: %%-----------------------------------------------------------------
 8093: %% The error_logger handler used.
 8094: %% (Copied from stdlib/test/proc_lib_SUITE.erl.)
 8095: %%-----------------------------------------------------------------
 8096: init(Tester) ->
 8097:     {ok, Tester}.
 8098:     
 8099: handle_event({error, _GL, {_Pid, _Msg, [Why, _]}}, Tester) 
 8100:                      when is_atom(Why) ->
 8101:     Tester ! {error, Why},
 8102:     {ok, Tester};
 8103: handle_event({error, _GL, {_Pid, _Msg, [P, T]}}, Tester) when is_pid(P) ->
 8104:     Tester ! {error, P, T},
 8105:     {ok, Tester};
 8106: handle_event({info_msg, _GL, {_Pid, _Msg, [Why, _]}}, Tester) ->
 8107:     Tester ! {info, Why},
 8108:     {ok, Tester};
 8109: handle_event(_Event, State) ->
 8110:     {ok, State}.
 8111: 
 8112: handle_info(_, State) ->
 8113:     {ok, State}.
 8114: 
 8115: handle_call(_Query, State) -> {ok, {error, bad_query}, State}.
 8116: 
 8117: terminate(_Reason, State) ->
 8118:     State.