<commit_before>-module(imem_sql_index).

-include("imem_seco.hrl").

-export([ exec/5
        ]).

exec(SKey, {'drop index', IndexName, TableName}=_ParseTree, _Stmt, _Opts, IsSec) ->
    % ?LogDebug("Drop Index Parse Tree~n~p~n", [_ParseTree]),
    {TableSchema, Tbl} = imem_sql_expr:binstr_to_qname2(TableName),
    {IndexSchema, Index} = imem_sql_expr:binstr_to_qname2(IndexName),
    if not (IndexSchema =:= TableSchema) ->
           ?ClientError({"Index and table are in different schema"
                         , {IndexSchema, TableSchema}});
       true -> ok
    end,
    Table = if TableSchema =:= undefined ->
                   {imem_meta:schema()
                    , list_to_existing_atom(binary_to_list(Tbl))};
               true ->
                   {list_to_existing_atom(binary_to_list(TableSchema))
                    , list_to_existing_atom(binary_to_list(Tbl))}
            end,
    if_call_mfa(IsSec, 'drop_index', [SKey,Table,Index]);

exec(SKey, {'create index', IndexType, IndexName, TableName
            , IndexDefn, NormWithFun, FilterWithFun} = _ParseTree
     , _Stmt, _Opts, IsSec) ->
    % ?Info("Create Index Parse Tree~n~p~n", [_ParseTree]),
    {TableSchema, Tbl} = imem_sql_expr:binstr_to_qname2(TableName),
    {IndexSchema, Index} = imem_sql_expr:binstr_to_qname2(IndexName),
    if not (IndexSchema =:= TableSchema) ->
           ?ClientError({"Index and table are in different schema"
                         , {IndexSchema, TableSchema}});
       true -> ok
    end,
    Table = if TableSchema =:= undefined ->
                   {imem_meta:schema()
                    , list_to_existing_atom(binary_to_list(Tbl))};
               true ->
                   {list_to_existing_atom(binary_to_list(TableSchema))
                    , list_to_existing_atom(binary_to_list(Tbl))}
            end,
    IndexDefs = case imem_meta:read(ddTable, Table) of
        [#ddTable{}=D] -> 
            case lists:keysearch(index, 1, D#ddTable.opts) of
                {value,{index, ExistingIndexDefs}} -> ExistingIndexDefs;
                false -> []
            end;
        [] ->
            ?ClientError({"Table dictionary does not exist for",Table})
    end,
    case length([IDf || IDf <- IndexDefs, IDf#ddIdxDef.name =:= Index]) of
        MatchedIndexes when MatchedIndexes > 0 ->
            ?ClientError({"Index already exists in table", IndexName, TableName});
        _ -> ok
    end,
    MaxIdx = if length(IndexDefs) =:= 0 -> 0;
                true -> lists:max([IdxDef#ddIdxDef.id || IdxDef <- IndexDefs])
             end,
    NewIdx = #ddIdxDef{id = MaxIdx+1
                       , name = Index
                       , pl = IndexDefn},
    NewIdx1 = case NormWithFun of
                  {} ->             NewIdx;
                  {norm, NormF} ->  NewIdx#ddIdxDef{vnf = NormF};
                  NormWithFun ->    ?ClientError({"Bad norm with function", NormWithFun})
              end,
    NewIdx2 = case FilterWithFun of
                    {} ->                   NewIdx1;
                    {filter, FilterF} ->    NewIdx#ddIdxDef{iff = FilterF};
                    FilterWithFun ->        ?ClientError({"Bad filter with function", FilterWithFun})
                end,
    %% TODO: IndexType is not used
    %%       #ddIdxDef.type is hardcoded to ivk
    NewIdx3 = NewIdx2#ddIdxDef{type = ivk},
    create_index(SKey, IndexType, Table, [NewIdx3|IndexDefs], IsSec).

create_index(SKey, IndexType, TableName, [#ddIdxDef{}|_] = IndexDefinitions, IsSec)
  when IndexType =:= {}; IndexType =:= bitmap;
       IndexType =:= keylist; IndexType =:= hashmap ->
    %io:format(user,
    %%?LogDebug(<commit_msg>IndexType supported by mapping<commit_after>-module(imem_sql_index).

-include("imem_seco.hrl").

-export([ exec/5
        ]).

exec(SKey, {'drop index', IndexName, TableName}=_ParseTree, _Stmt, _Opts, IsSec) ->
    % ?LogDebug("Drop Index Parse Tree~n~p~n", [_ParseTree]),
    {TableSchema, Tbl} = imem_sql_expr:binstr_to_qname2(TableName),
    {IndexSchema, Index} = imem_sql_expr:binstr_to_qname2(IndexName),
    if not (IndexSchema =:= TableSchema) ->
           ?ClientError({"Index and table are in different schema"
                         , {IndexSchema, TableSchema}});
       true -> ok
    end,
    Table = if TableSchema =:= undefined ->
                   {imem_meta:schema()
                    , list_to_existing_atom(binary_to_list(Tbl))};
               true ->
                   {list_to_existing_atom(binary_to_list(TableSchema))
                    , list_to_existing_atom(binary_to_list(Tbl))}
            end,
    if_call_mfa(IsSec, 'drop_index', [SKey,Table,Index]);

exec(SKey, {'create index', IndexType, IndexName, TableName
            , IndexDefn, NormWithFun, FilterWithFun} = _ParseTree
     , _Stmt, _Opts, IsSec) ->
    % ?Info("Create Index Parse Tree~n~p~n", [_ParseTree]),
    {TableSchema, Tbl} = imem_sql_expr:binstr_to_qname2(TableName),
    {IndexSchema, Index} = imem_sql_expr:binstr_to_qname2(IndexName),
    if not (IndexSchema =:= TableSchema) ->
           ?ClientError({"Index and table are in different schema"
                         , {IndexSchema, TableSchema}});
       true -> ok
    end,
    Table = if TableSchema =:= undefined ->
                   {imem_meta:schema()
                    , list_to_existing_atom(binary_to_list(Tbl))};
               true ->
                   {list_to_existing_atom(binary_to_list(TableSchema))
                    , list_to_existing_atom(binary_to_list(Tbl))}
            end,
    IndexDefs = case imem_meta:read(ddTable, Table) of
        [#ddTable{}=D] -> 
            case lists:keysearch(index, 1, D#ddTable.opts) of
                {value,{index, ExistingIndexDefs}} -> ExistingIndexDefs;
                false -> []
            end;
        [] ->
            ?ClientError({"Table dictionary does not exist for",Table})
    end,
    case length([IDf || IDf <- IndexDefs, IDf#ddIdxDef.name =:= Index]) of
        MatchedIndexes when MatchedIndexes > 0 ->
            ?ClientError({"Index already exists in table", IndexName, TableName});
        _ -> ok
    end,
    MaxIdx = if length(IndexDefs) =:= 0 -> 0;
                true -> lists:max([IdxDef#ddIdxDef.id || IdxDef <- IndexDefs])
             end,
    NewIdx = #ddIdxDef{id = MaxIdx+1
                       , name = Index
                       , pl = IndexDefn},
    NewIdx1 = case NormWithFun of
                  {} ->             NewIdx;
                  {norm, NormF} ->  NewIdx#ddIdxDef{vnf = NormF};
                  NormWithFun ->    ?ClientError({"Bad norm with function", NormWithFun})
              end,
    NewIdx2 = case FilterWithFun of
                    {} ->                   NewIdx1;
                    {filter, FilterF} ->    NewIdx#ddIdxDef{iff = FilterF};
                    FilterWithFun ->        ?ClientError({"Bad filter with function", FilterWithFun})
                end,

    IndexTypeAtom = case (catch list_to_existing_atom(
                      lists:flatten(
                        ["i", lists:duplicate(length(IndexDefn), "v")
                         , case IndexType of
                               bitmap ->    "_b";
                               keylist ->   "_kl";
                               hashmap ->   "_h";
                               unique ->    "_k";
                               _ ->         "k"
                           end]))) of
                        {'EXIT', _} ->
                            ?ClientError({"Index type not supported", IndexType});
                        IdxTypAtom -> IdxTypAtom
                    end,

    NewIdx3 = NewIdx2#ddIdxDef{type = IndexTypeAtom},
    create_index(SKey, IndexType, Table, [NewIdx3|IndexDefs], IsSec).

create_index(SKey, IndexType, TableName, [#ddIdxDef{}|_] = IndexDefinitions, IsSec)
  when IndexType =:= {}; IndexType =:= bitmap;
       IndexType =:= keylist; IndexType =:= hashmap ->
    %io:format(user,
    %%?LogDebug(
{'fraction_non_alphanumeric': 0.12226964599548079, 'fraction_numerical': 0.004017072558373086, 'mean_word_length': 1.902367941712204, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 62, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2935647', 'n_tokens_mistral': 2468, 'n_tokens_neox': 2371, 'n_words': 479}