list_tables/1 now returns table names as they were first given.

The create_table/3 function will cast all table names to binaries, allowing
them to be given as atoms, binaries or strings. In order to recall what the
original type was, the CREATE TABLE statement includes a constant CHECK
constraint, e.g. CHECK('bin'='bin'), which is then parsed by the list_tables
function. The constraint is put last in the statement, and should not
interfere with any other constraints. Hopefully, the sqlite compiler is good
enough that this constant expression doesn't add too much overhead. :)
This commit is contained in:
Ulf Wiger
2012-02-24 09:11:24 +01:00
parent 6986d0bbde
commit bfbf038873
2 changed files with 33 additions and 7 deletions

View File

@@ -863,10 +863,10 @@ handle_call(close, _From, State) ->
Reply = ok,
{stop, normal, Reply, State};
handle_call(list_tables, _From, State) ->
SQL = "select name from sqlite_master where type='table';",
SQL = "select name, sql from sqlite_master where type='table';",
Data = do_sql_exec(SQL, State),
TableList = proplists:get_value(rows, Data),
TableNames = [erlang:list_to_atom(erlang:binary_to_list(Name)) || {Name} <- TableList],
TableNames = [cast_table_name(Name, SQLx) || {Name,SQLx} <- TableList],
{reply, TableNames, State};
handle_call({table_info, Tbl}, _From, State) when is_atom(Tbl) ->
% make sure we only get table info.
@@ -1242,6 +1242,20 @@ build_primary_key_constraint(Tail, []) ->
build_primary_key_constraint(Tail, Acc) ->
{{primary_key, lists:reverse(Acc)}, Tail}.
cast_table_name(Bin, SQL) ->
case re:run(SQL,<<"CHECK\\((.*)=(.*)\\)\\)">>,[{capture,all_but_first,binary}]) of
{match, [<<"'bin'">>, <<"'bin'">>]} ->
Bin;
{match, [<<"'lst'">>, <<"'lst'">>]} ->
binary_to_atom(Bin, latin1);
{match, [<<"'am'">>, <<"'am'">>]} ->
binary_to_atom(Bin, latin1);
_ ->
%% backwards compatible
binary_to_atom(Bin, latin1)
end.
%% conflict_clause(["ON", "CONFLICT", ResolutionString | Tail]) ->
%% Resolution = case ResolutionString of
%% "ROLLBACK" -> rollback;

View File

@@ -205,8 +205,10 @@ read_cols_sql(Columns) ->
%%--------------------------------------------------------------------
-spec create_table_sql(table(), table_info()) -> iolist().
create_table_sql(Tbl, Columns) ->
["CREATE TABLE ", to_iolist(Tbl), " (",
map_intersperse(fun column_sql_for_create_table/1, Columns, ", "), ");"].
{Type, TName} = encode_tbl(Tbl),
["CREATE TABLE ", TName, " (",
map_intersperse(fun column_sql_for_create_table/1, Columns, ", "),
" CHECK('", Type, "'='", Type, "'));"].
%%--------------------------------------------------------------------
%% @spec create_table_sql(Tbl :: table(), ColumnData, TableConstraints) -> iolist()
@@ -221,10 +223,11 @@ create_table_sql(Tbl, Columns) ->
%%--------------------------------------------------------------------
-spec create_table_sql(table(), table_info(), table_constraints()) -> iolist().
create_table_sql(Tbl, Columns, TblConstraints) ->
["CREATE TABLE ", to_iolist(Tbl), " (",
{Type, TName} = encode_tbl(Tbl),
["CREATE TABLE ", TName, " (",
map_intersperse(fun column_sql_for_create_table/1, Columns, ", "), ", ",
table_constraint_sql(TblConstraints),
");"].
" CHECK('", Type, "'='", Type, "'));"].
%%--------------------------------------------------------------------
%% @spec update_sql(Tbl, Key, Value, Data) -> iolist()
@@ -240,7 +243,8 @@ create_table_sql(Tbl, Columns, TblConstraints) ->
%%--------------------------------------------------------------------
-spec update_sql(table(), atom(), sql_value(), [{atom(), sql_value()}]) -> iolist().
update_sql(Tbl, Key, Value, Data) ->
["UPDATE ", to_iolist(Tbl), " SET ", update_set_sql(Data),
{_, TName} = encode_tbl(Tbl),
["UPDATE ", TName, " SET ", update_set_sql(Data),
" WHERE ", atom_to_list(Key), " = ", value_to_sql(Value), ";"].
%%--------------------------------------------------------------------
@@ -420,6 +424,14 @@ indexed_column_sql({ColumnName, asc}) -> [atom_to_list(ColumnName), " ASC"];
indexed_column_sql({ColumnName, desc}) -> [atom_to_list(ColumnName), " DESC"];
indexed_column_sql(ColumnName) -> atom_to_list(ColumnName).
encode_tbl(A) when is_atom(A) ->
{"am", atom_to_list(A)};
encode_tbl(B) when is_binary(B) ->
{"bin", B};
encode_tbl(L) when is_list(L) ->
{"lst", list_to_binary(L)}.
to_iolist(A) when is_atom(A) ->
atom_to_list(A);
to_iolist(L) when is_list(L) ->