From 03fd5d94d231a079529c96da85b88244bff84722 Mon Sep 17 00:00:00 2001 From: totoro Date: Mon, 4 Jan 2016 00:11:54 +0100 Subject: [PATCH] first commit of VTM generator ;-) The name of that application is not decided yet. The file organization is also messy and can change in the near future. --- .gitignore | 2 ++ .gitmodules | 3 +++ calexium_lib | 1 + model_manager.aproj | 693 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ model_manager.ide | 18 ++++++++++++++++++ src/generation/files.anubis | 150 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/generation/header.anubis | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/generation/types.anubis | 433 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.anubis | 27 +++++++++++++++++++++++++++ src/model.3.0.0.anubis | 149 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/types/db_model.anubis | 680 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 11 files changed, 2233 insertions(+), 0 deletions(-) create mode 100644 .gitignore create mode 100644 .gitmodules create mode 160000 calexium_lib create mode 100644 model_manager.aproj create mode 100644 model_manager.ide create mode 100644 src/generation/files.anubis create mode 100644 src/generation/header.anubis create mode 100644 src/generation/types.anubis create mode 100644 src/main.anubis create mode 100644 src/model.3.0.0.anubis create mode 100644 src/types/db_model.anubis diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e0dbe82 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +library/ +db_model_manager.sc diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..f2b1f41 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "calexium_lib"] + path = calexium_lib + url = ssh://git@gitlab.calexium.com:33022/calexium/calexium_lib.git diff --git a/calexium_lib b/calexium_lib new file mode 160000 index 0000000..4d677a6 --- /dev/null +++ b/calexium_lib @@ -0,0 +1 @@ +Subproject commit 4d677a6833d4c02037f913f30dd460500a390bf1 diff --git a/model_manager.aproj b/model_manager.aproj new file mode 100644 index 0000000..2a78202 --- /dev/null +++ b/model_manager.aproj @@ -0,0 +1,693 @@ + + + {89372B21-80FA-4EB8-B17C-072EB55713D6} + Debug + AnyCPU + Exe + model_manager + model_manager + src\main.anubis + ./%3b./src + False + False + False + + + bin\Debug\ + True + Full + False + -sc + + + bin\Release\ + False + None + True + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/model_manager.ide b/model_manager.ide new file mode 100644 index 0000000..f717561 --- /dev/null +++ b/model_manager.ide @@ -0,0 +1,18 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +# SharpDevelop 1.0.12.108 +Project("{B6712916-30DE-4a3e-A54C-2A79AC984AEE}") = "model_manager", "model_manager.aproj", "{89372B21-80FA-4EB8-B17C-072EB55713D6}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {89372B21-80FA-4EB8-B17C-072EB55713D6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {89372B21-80FA-4EB8-B17C-072EB55713D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {89372B21-80FA-4EB8-B17C-072EB55713D6}.Release|Any CPU.Build.0 = Release|Any CPU + {89372B21-80FA-4EB8-B17C-072EB55713D6}.Release|Any CPU.ActiveCfg = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/src/generation/files.anubis b/src/generation/files.anubis new file mode 100644 index 0000000..8391e0a --- /dev/null +++ b/src/generation/files.anubis @@ -0,0 +1,150 @@ +/* + * Created by PyramIDE. + * User: フランスのトトロ + * Date: 31/12/2015 + * Time: 09:29 + * © Calexium + */ + +read system/string.anubis + +read types/db_model.anubis +read tools/basis.anubis +read tools/streams.anubis +read tools/ISO-8601.anubis +read generation/header.anubis +read generation/types.anubis + +define Maybe(One) + generate_table + ( + DB_Table table + ) + = + since table is db_table(name, model, display), + since model is db_model(columns, show_string), + println("Generating file for table ["+name+"]"); + with file_name = name+".anubis", + if file(file_name, new) is + { + failure then println("can't create file "+file_name);failure, + success(fd) then + with strm = make_stream(fd), + if generate_header(strm, columns) is { failure then failure, success(_) then + if generate_type(strm, table) is { failure then failure, success(_) then + if generate_get_default(strm, table) is { failure then failure, success(_) then + if generate_extract_web_arg(strm, table) is { failure then failure, success(_) then + if generate_extract_db_cursor(strm, table) is { failure then failure, success(_) then + if generate_get_all(strm, table) is { failure then failure, success(_) then + if generate_get_one(strm, table) is { failure then failure, success(_) then + if generate_update(strm, table) is { failure then failure, success(_) then + if generate_show_string(strm, table) is { failure then failure, success(_) then + if generate_VT_view(strm, table) is { failure then failure, success(_) then + if generate_VT_edit(strm, table) is { failure then failure, success(_) then + success(unique)}}}}}}}}}}} + }. + +define One + make_all_tables + ( + List(DB_Table) tables //list of the table model description + ) + = + if tables is + { + [] then println("Generation finished"), + [h . t] then + if generate_table(h) is + { + failure then println("Generation error") + success(_) then make_all_tables(t) + } + }. + +define Maybe(One) + generate_vtm_file + ( + List(String) transmit, + List(String) view, + List(String) edit, + List(String) writer + )= + with file_name = "vtm.anubis", + if file(file_name, new) is + { + failure then println("can't create file "+file_name);failure, + success(fd) then + if write_string(make_stream(fd), +"/* + * Created by model_manager. + * User: Automat + * Date: "+_Int_to_ISO_8601_date(now)+" + * Time: "+_Int_to_ISO_8601_time(now)+" + * + */ +read tools/basis.anubis +read tools/base_tools.anubis +read calexium_lib/database/vtm/view_table_manager_types.anubis\n"+ +join("\n", transmit)+"\n\n"+ +"public define List(VTM_view)\n"+ +" generated_vtm_view_list =\n"+ +" [\n "+join(",\n ",view)+"\n"+ +" ].\n\n"+ +"public define List(VTM_edit)\n"+ +" generated_vtm_edit_list =\n"+ +" [\n "+join(",\n ",edit)+"\n"+ +" ].\n\n"+ +"public define List(TM_writer)\n"+ +" generated_tm_writer_list =\n"+ +" [\n "+join(",\n ",writer)+"\n"+ +" ].\n\n" + ) is //end of the function + { + failure then println("can't write vtm "); failure, + success(_) then success(unique) + }}. + + + +define One + _make_vtm + ( + List(DB_Table) tables, //list of the table model description + List(String) so_far_transmit, + List(String) so_far_view, + List(String) so_far_edit, + List(String) so_far_writer + )= + if tables is + { + [] then forget(generate_vtm_file(so_far_transmit, so_far_view, so_far_edit, so_far_writer));println("Generation finished"), + [table . t] then + since table is db_table(name, _, _), + with transmit = "transmit "+name+".anubis", + with view = "vtm_view(\""+name+"\", get_viewable_"+name+")", + with edit = "vtm_edit(\""+name+"\", get_editable_"+name+")", + with writer = "tm_writer(\""+name+"\", update_"+name+")", + + _make_vtm(t, [transmit . so_far_transmit], [view . so_far_view], [edit . so_far_edit], [writer . so_far_writer]) + }. + +define One + make_vtm + ( + List(DB_Table) tables //list of the table model description + ) + = + _make_vtm(tables, [], [], [], []). + + +public define One + generate_model_files + ( + DB_Database database //database model description + )= + since database is db_database(name, tables), + println("Generating models for Database "+name); + make_all_tables(tables); + println("Generating VTM for Database "+name); + make_vtm(tables). + diff --git a/src/generation/header.anubis b/src/generation/header.anubis new file mode 100644 index 0000000..7d68ec3 --- /dev/null +++ b/src/generation/header.anubis @@ -0,0 +1,77 @@ +/* + * Created by PyramIDE. + * User: フランスのトトロ + * Date: 31/12/2015 + * Time: 13:42 + * © Calexium + */ + +read types/db_model.anubis +read tools/basis.anubis +read tools/streams.anubis +read tools/ISO-8601.anubis + +define Maybe(One) + foreign_table_header + ( + Stream stream, + List(DB_Model_Column) columns + )= + if columns is + { + [] then success(unique), + [h . t] then + since h is db_column(_, type, _), + if type is foreign_key(table_name) then + if write_string(stream, "\nread database/generated/"+table_name+".anubis") is + { + failure then failure, + success(_) then foreign_table_header(stream, t) + } + else + foreign_table_header(stream, t) + } + . + + List(MetaSQL_ColStruct) + +public define Maybe(One) + generate_header + ( + Stream stream, + List(DB_Model_Column) columns + + )= + if write_string(stream, +"/* + * Created by model_manager. + * User: Automat + * Date: "+_Int_to_ISO_8601_date(now)+" + * Time: "+_Int_to_ISO_8601_time(now)+" + * + */ +read tools/basis.anubis +read tools/base_tools.anubis + +read calexium_lib/web/CXM_making_a_web_site.anubis +read calexium_lib/web/CXM_common.anubis +read calexium_lib/web/CXM_web_dump.anubis +read calexium_lib/web/CXM_web_arg_utils.anubis +read data_base/sqlite.anubis +read data_base/db_tools.anubis +read calexium_lib/database/db_utils.anubis +read calexium_lib/database/db_types.anubis +read calexium_lib/database/vtm/view_table_types.anubis + +read system/logger.anubis +read system/datetime.anubis +read system/convert.anubis +read system/string.anubis + +read calexium_lib/net_services_protocols/logger_service.anubis +read app/app_loggers.anubis + +") is failure then failure else + foreign_table_header(stream, columns) + . + diff --git a/src/generation/types.anubis b/src/generation/types.anubis new file mode 100644 index 0000000..87e869f --- /dev/null +++ b/src/generation/types.anubis @@ -0,0 +1,433 @@ +/* + * Created by PyramIDE. + * User: フランスのトトロ + * Date: 31/12/2015 + * Time: 16:18 + * © Calexium + */ + +read types/db_model.anubis +read tools/basis.anubis +read tools/streams.anubis +read system/string.anubis + + +define List(String) +/** + */ + _generate_type + ( + List(DB_Model_Column) columns, + List(String) so_far + )= + if columns is + { + [] then reverse(so_far), + [h . t ] then + since h is db_column(name, col_type, _), + _generate_type(t, [ " "+fill(to_Anubis_type(col_type), 12) + " " + name . so_far]) + }. + +public define Maybe(One) + generate_type + ( + Stream stream, + DB_Table table + )= + since table is db_table(name, model, display), + since model is db_model(columns, show_string), + with type_name = to_upper(name, 1), //make the first character to upper case to able to be a Anubis Type. + + //generate the type of the db_table that contain all components + if write_string(stream, + "\n\npublic type "+type_name+":\n "+name+"\n (\n"+ //head of the type declaration + join(",\n",_generate_type(columns, []))+ //all components of the type + "\n ).\n") is //end of declaration + { + failure then println("can't write type "+type_name); failure, + success(_) then success(unique) + }. + +define List(String) +/** + */ + _generate_get_default + ( + List(DB_Model_Column) columns, + List(String) so_far + )= + if columns is + { + [] then reverse(so_far), + [h . t ] then + since h is db_column(name, col_type, _), + _generate_get_default(t, [ to_Anubis_default(col_type) . so_far]) + }. +public define Maybe(One) + generate_get_default + ( + Stream stream, + DB_Table table + )= + since table is db_table(name, model, _), + since model is db_model(columns, show_string), + with type_name = to_upper(name, 1), //make the first character to upper case to able to be a Anubis Type. + + //generate the type of the table that contain all components + if write_string(stream, + "\n\ndefine "+type_name+"\n get_default_"+name+" =\n "+name+"("+ //head of the definition + join(", ",_generate_get_default(columns, []))+ //all components of the type + ").\n") is //end of the function + { + failure then println("can't write get_default "+type_name); failure, + success(_) then success(unique) + }. + +define (List(String), Int) +/** + */ + _generate_extract_web_arg + ( + List(DB_Model_Column) columns, + List(String) so_far, + Int closure + )= + if columns is + { + [] then (reverse(so_far), closure), + [h . t ] then + since h is db_column(name, col_type, _), + with result = from_web_arg(col_type, name), + //If the field is not editable no need to get it from the web + if result = "" then + _generate_extract_web_arg(t, so_far, closure) + else + if start_with(result, "with") then + _generate_extract_web_arg(t, [ " "+result . so_far], closure) + else + with line = " if "+fill(result, 45)+" is {failure then failure, "+fill("success("+name+")",25)+" then", + _generate_extract_web_arg(t, [ line . so_far], closure+1) + }. + +public define Maybe(One) + generate_extract_web_arg + ( + Stream stream, + DB_Table table + )= + since table is db_table(name, model, _), + since model is db_model(columns, _), + with type_name = to_upper(name, 1), //make the first character to upper case to able to be a Anubis Type. + since _generate_extract_web_arg(columns, [], 0) is ((List(String))list_of_web_arg, (Int) nb_closure), + //generate the type of the table that contain all components + if write_string(stream, + "\n\ndefine Maybe("+type_name+")\n extract_from_web_arg\n (\n List(Web_arg) lwa\n )=\n"+ //head of the definition + to_String(list_of_web_arg)+ //all editable components of the type + " success(\n"+generate_constructor(name, columns, " ")+")\n"+ //generate type construction with values got from web arg + " "+fill(nb_closure, '}')+ //add close } according to number of web arg + ".\n") is //end of the function + { + failure then println("can't write extract_from_web_arg "+type_name); failure, + success(_) then success(unique) + }. + +public define Maybe(One) + generate_extract_db_cursor + ( + Stream stream, + DB_Table table + )= + since table is db_table(name, model, display), + since model is db_model(columns, _), + with type_name = to_upper(name, 1), //make the first character to upper case to able to be a Anubis Type. + + //generate the type of the table that contain all components + if write_string(stream, + "\n\n"+ + "define Maybe("+type_name+")\n"+ + " extract_"+name+"\n"+ + " (\n"+ + " One -> SQLite3Row table_cursor\n"+ + " ) =\n"+ + " if table_cursor(unique) is\n"+ + " {\n"+ + " error(sql_error) then println(db_error(sql_error, \"extract_"+name+"\")); failure,\n"+ + " no_more_row then failure,\n"+ + " row(cursor) then\n"+ + " success(\n"+generate_constructor_from_cursor(name, "cursor", columns, " ")+")\n"+ //generate type construction with values got from web arg + " }.\n") is //end of the function + { + failure then println("can't write generate_extract_db_cursor "+type_name); failure, + success(_) then success(unique) + }. + + +public define Maybe(One) + generate_get_all + ( + Stream stream, + DB_Table table + )= + since table is db_table(name, model, _), + since model is db_model(columns, _), + with type_name = to_upper(name, 1), //make the first character to upper case to able to be a Anubis Type. + + //generate the type of the table that contain all components + if write_string(stream, + "\n\n"+ + "define List("+type_name+")\n"+ + " _get_all_"+name+"\n"+ + " (\n"+ + " One -> SQLite3Row table_cursor,\n"+ + " List("+type_name+") so_far\n"+ + " ) =\n"+ + " if extract_"+name+"(table_cursor) is\n"+ + " {\n"+ + " failure then reverse(so_far),\n"+ + " success(data) then _get_all_"+name+"(table_cursor, [data . so_far])\n"+ + " }.\n"+ + "\n\n"+ + //SQL query + "public define List("+type_name+")\n"+ + " get_all_"+name+"\n"+ + " (\n"+ + " SQLite3DataBase db,\n"+ + " )=\n"+ + " if sql_query_timeout(db, \"SELECT "+join(", ", components(columns, []))+" FROM "+name+";\", [], \"get_all_"+name+"\") is\n"+ + " {\n"+ + " error(_) then [],\n"+ + " ok(_, cursor, _) then _get_all_"+name+"(cursor, [])\n"+ + " }.\n" + + ) is //end of the function + { + failure then println("can't write generate_get_all "+type_name); failure, + success(_) then success(unique) + }. + +public define Maybe(One) + generate_get_one + ( + Stream stream, + DB_Table table + )= + since table is db_table(name, model, _), + since model is db_model(columns, show_string), + with type_name = to_upper(name, 1), //make the first character to upper case to able to be a Anubis Type. + + //generate the type of the table that contain all components + if write_string(stream, + "\n\n"+ + //SQL query + "public define Maybe("+type_name+")\n"+ + " get_"+name+"\n"+ + " (\n"+ + " SQLite3DataBase db,\n"+ + " String idx\n"+ + " )=\n"+ + " if sql_query_timeout(db, \"SELECT "+join(", ", components(columns, []))+" FROM "+name+" WHERE id=\"+idx+\";\", [], \"get_"+name+"\") is\n"+ + " {\n"+ + " error(_) then failure,\n"+ + " ok(_, cursor, _) then extract_"+name+"(cursor)\n"+ + " }.\n\n"+ + //SQL query + "public define Maybe("+type_name+")\n"+ + " get_"+name+"\n"+ + " (\n"+ + " SQLite3DataBase db,\n"+ + " Int idx\n"+ + " )=\n"+ + " get_"+name+"(db, to_decimal(idx))." + ) is //end of the function + { + failure then println("can't write generate_get_one "+type_name); failure, + success(_) then success(unique) + }. + + +public define Maybe(One) + generate_update + ( + Stream stream, + DB_Table table + )= + since table is db_table(name, model, _), + since model is db_model( columns, _), + with type_name = to_upper(name, 1), //make the first character to upper case to able to be a Anubis Type. + + //generate the type of the table that contain all components + if write_string(stream, + "\n\n"+ + //SQL query + "public define One\n"+ + " update_"+name+"\n"+ + " (\n"+ + " SQLite3DataBase db,\n"+ + " "+type_name+" "+name+"\n"+ + " )=\n"+ + " if "+name+".id is\n"+ + " {\n"+ + //INSERT SQL query + " none then\n"+ + " forget(sql_query_timeout(db,\n"+ + " \"INSERT INTO "+name+"\n"+ + insert_values(columns, " ")+";\",\n"+ + generate_Bind_list(columns, name, " ", true)+",\n"+ + " \"update_"+name+" (INSERT)\")),\n"+ + //UPDATE SQL query + " db_id(idx) then\n"+ + " forget(sql_query_timeout(db,\n"+ + " \"UPDATE "+name+" SET\n"+ + update_values(columns, " ")+"\n"+ + " WHERE id = \"+idx+\";\",\n"+ + generate_Bind_list(columns, name, " ", false)+",\n"+ + " \"update_"+name+" (UPDATE)\"))\n"+ + " }.\n\n"+ + "public define Maybe(One)\n"+ + " update_"+name+"\n"+ + " (\n"+ + " SQLite3DataBase db,\n"+ + " List(Web_arg) lwa\n"+ + " )=\n"+ + " if extract_from_web_arg(lwa) is\n"+ + " {\n"+ + " failure then failure,\n"+ + " success("+name+") then success(update_"+name+"(db, "+name+"))\n"+ + " }.\n\n" + + ) is //end of the function + { + failure then println("can't write generate_update "+type_name); failure, + success(_) then success(unique) + }. + +public define Maybe(One) + generate_show_string + ( + Stream stream, + DB_Table table + )= + since table is db_table(name, model, _), + since model is db_model( columns, show_string), + with type_name = to_upper(name, 1), //make the first character to upper case to able to be a Anubis Type. + + //generate the type of the table that contain all components + if write_string(stream, + "\n\n"+ + //SQL query + "public define String\n"+ + " get_"+name+"_show_string\n"+ + " (\n"+ + " SQLite3DataBase db,\n"+ + " Int idx\n"+ + " )=\n"+ + " if get_"+name+"(db, idx) is\n"+ + " {\n"+ + " failure then default_select,\n"+ + " success(obj) then "+show_string+"\n"+ + " }." + ) is //end of the function + { + failure then println("can't write generate_update "+type_name); failure, + success(_) then success(unique) + }. + +public define Maybe(One) + generate_VT_view + ( + Stream stream, + DB_Table table + )= + since table is db_table(name, model, display), + since model is db_model( columns, _), + since display is db_display(list_view, list_edit), + + with type_name = to_upper(name, 1), //make the first character to upper case to able to be a Anubis Type. + + //generate the type of the table that contain all components + if write_string(stream, + "\n\n"+ + //SQL query + "define VT_view\n"+ + " _get_viewable_"+name+"\n"+ + " (\n"+ + " SQLite3DataBase db,\n"+ + " List("+type_name+") list,\n"+ + " List(VT_view_row) so_far\n"+ + " )=\n"+ + " if list is\n"+ + " {\n"+ + " [] then\n"+ + " with header = vt_view_row([\n"+ + // view row header + make_list_view_header(list_view, " ")+"\n"+ + " ]),\n"+ + " vt_view(\""+name+"\", header, reverse(so_far)),\n"+ + " [ h . t ] then\n"+ + " with entry = vt_view_row([\n"+ + // view row + make_list_view_row(model, list_view, "h", " ")+"\n"+ + " ]),\n"+ + " _get_viewable_"+name+"(db, t, [entry . so_far])\n"+ + " }.\n\n"+ + "public define VT_view\n"+ + " get_viewable_"+name+"\n"+ + " (\n"+ + " SQLite3DataBase db\n"+ + " )=\n"+ + " _get_viewable_"+name+"(db, get_all_"+name+"(db), []).\n\n" + ) is //end of the function + { + failure then println("can't write generate_VT_view "+type_name); failure, + success(_) then success(unique) + }. + +public define Maybe(One) + generate_VT_edit + ( + Stream stream, + DB_Table table + )= + since table is db_table(name, model, display), + since model is db_model( columns, _), + since display is db_display(list_view, list_edit), + with type_name = to_upper(name, 1), //make the first character to upper case to able to be a Anubis Type. + + //generate the type of the table that contain all components + if write_string(stream, + "\n ********** EDITABLE VIEWs ***************\n"+ + //SQL query + "define VT_edit\n"+ + " _get_editable_"+name+"\n"+ + " (\n"+ + " "+type_name+" "+name+",\n"+ + " SQLite3DataBase db\n"+ + " )=\n"+ + " with edit_entries = (List(VT_edit_entry))\n"+ + " [\n"+ + edit_entries(columns, name, " ", [])+"\n"+ + " ],\n"+ + " vt_edit(\""+name+"\", edit_entries).\n\n"+ + + "public define VT_edit\n"+ + " get_editable_"+name+"\n"+ + " (\n"+ + " SQLite3DataBase db,\n"+ + " VT_action action\n"+ + " )=\n"+ + " with "+name+" = if action is\n"+ + " {\n"+ + " new_entry then get_default_"+name+"\n"+ + " edit_entry(idx) then\n"+ + " if get_"+name+"(db, idx) is\n"+ + " {\n"+ + " failure then get_default_"+name+",\n"+ + " success(data) then data\n"+ + " }\n"+ + " },\n"+ + " _get_editable_"+name+"("+name+", db).\n\n" + ) is //end of the function + { + failure then println("can't write generate_VT_edit "+type_name); failure, + success(_) then success(unique) + }. diff --git a/src/main.anubis b/src/main.anubis new file mode 100644 index 0000000..7357f41 --- /dev/null +++ b/src/main.anubis @@ -0,0 +1,27 @@ +/************************************************* + * *Project* The Anubis Project + * + * *Title* Database model manager + * + * *Copyright* Copyright © David René 2015. + * + * + * + * + * *Overview* + * generate database management interface under Anubis according on model description file'. + * Like django + */ + +read tools/string.anubis +read generation/files.anubis +read types/db_model.anubis +read model.3.0.0.anubis + +global define One + db_model_manager + ( + List(String) args + ) = + generate_model_files(the_database_description). + diff --git a/src/model.3.0.0.anubis b/src/model.3.0.0.anubis new file mode 100644 index 0000000..35821a6 --- /dev/null +++ b/src/model.3.0.0.anubis @@ -0,0 +1,149 @@ + +read types/db_model.anubis + +public define DB_Table settings_table = + db_table("settings", + db_model( + [ + db_column("id", p_key, []), + db_column("var_name", char_field(20), []), + db_column("var_value", char_field(20), []), + ], + "obj.var_name+\" = \"+obj.var_value" + ), + db_display( + //list_view + ["var_name", "var_value"], + //list edit + ["type"] + ) + ). + +public define DB_Table production_memory_type_table = + db_table("production_memory_type", + db_model( + [ + db_column("id", p_key, []), + db_column("type", char_field(20), []), + ], + "to_String(obj.id)+\":\"+obj.type" + ), + db_display( + //list_view + ["id", "type"], + //list edit + ["type"] + ) + ). + +public define DB_Table production_mass_storage_type_table = + db_table("production_mass_storage_type", + db_model( + [ + db_column("id", p_key, []), + db_column("type", char_field(20), []), + ], + "to_String(obj.id)+\":\"+obj.type" + ), + db_display( + //list_view + ["id", "type"], + //list edit + ["type"] + ) + ). + +public define DB_Table production_mass_storage_model_table = + db_table("production_mass_storage_model", + db_model( + [ + db_column("id", p_key, []), + db_column("manufacturer", char_field(20), []), + db_column("type_id", foreign_key("production_mass_storage_type"), [indexed]), + db_column("capacity", integer_field, []), // + db_column("tr_min", integer_field, []), // + db_column("date_created", datetime_field(auto_now_add), []), + db_column("last_modified", datetime_field(auto_now), []), + db_column("comments", text_field, []) // whatever the user wants to keep + ], + "obj.manufacturer" + ), + db_display( + //list_view + ["id", "manufacturer", "type_id", "capacity", "tr_min", "last_modified", "date_created"], + //list_edit + [] + ) + ). + +public define DB_Table production_mass_storage_table = + db_table("production_mass_storage", + db_model( + [ + db_column("id", p_key, []), + db_column("purchase_id", foreign_key("production_purchase"), [indexed]), + db_column("model_id", foreign_key("production_mass_storage_model"), [indexed]), + db_column("serial", char_field(40), []), // + db_column("status", char_field(10), []), // + db_column("date_created", datetime_field(auto_now_add), []), + db_column("last_modified", datetime_field(auto_now), []), + db_column("comments", text_field, []) // whatever the user wants to keep + ], + "obj.purchase_id.string" + ), + db_display( + //list_view + ["model_id", "serial", "status", "date_created"], + //list_edit + ["purchase_id", "model_id", "serial", "status", "comments"] + ) + ). + + "CREATE TABLE production_purchase ( + id integer NOT NULL PRIMARY KEY, + date date NOT NULL, + buyer_id integer NOT NULL REFERENCES staff_staff (id), + supplier_id integer NOT NULL REFERENCES production_supplier (id), + order_ref varchar(50) NOT NULL, + description varchar(200) NOT NULL, + date_created datetime NOT NULL, + last_modified datetime NOT NULL, + comments text NOT NULL + )" + +public define DB_Table production_purchase_table = + db_table("production_purchase", + db_model( + [ + db_column("id", p_key, []), + db_column("date", date_field(none), []), + db_column("buyer_id", foreign_key("staff_staff"), [indexed]), + db_column("supplier_id", foreign_key("production_supplier"), [indexed]), + db_column("order_ref", char_field(50), []), // + db_column("description", char_field(200), []), // description of the purchase + db_column("date_created", datetime_field(auto_now_add), []), + db_column("last_modified", datetime_field(auto_now), []), + db_column("comments", text_field, []), // whatever the user wants to keep + ], + "" + ), + db_display( + //list_view + ["date", "supplier_id", "description"], + //list_edit + ["date", "buyer_id", "supplier_id", "order_ref", "description", "comments"] + ) + ). + +public define DB_Database + the_database_description + = + db_database("prod_manager", + [ + settings_table, + production_mass_storage_type_table, + production_mass_storage_model_table, + production_memory_type_table + //production_mass_storage_table, + //production_purchase_table + ]). diff --git a/src/types/db_model.anubis b/src/types/db_model.anubis new file mode 100644 index 0000000..5ff90a2 --- /dev/null +++ b/src/types/db_model.anubis @@ -0,0 +1,680 @@ +/* + * Created by PyramIDE. + * User: フランスのトトロ + * Date: 01/01/2016 + * Time: 1:34 + * © Calexium + */ + + The Anubis project + + Interfacing a database with Anubis + + + Author: David René + + + + In order to generate such tools, DB_Model needs a formal + description of the database. + + + *** (1) Formal description of the database. + + *** (1.1) 'DB_Model_Field' (data types of table columns). +public type DB_Datetime_Field_Attr: + none, //Nothing special, normal behaviour + auto_now, //Always update datetime at SQL update + auto_now_add. //Set current datetime when row is created and can't be edited anymore + +public type DB_Model_Field: + //anubis(String _T), // the datum of type _T is serialized and base64 encoded + p_key, + //binary, // contains a byte array + boolean_field, // true or false + date_field(DB_Datetime_Field_Attr), // date with the precision of the day + time_field(DB_Datetime_Field_Attr), // time with the precision of the second + datetime_field(DB_Datetime_Field_Attr), // datetime with the precision of the second + foreign_key(String table_name), // foreign key to 'id' in another (or same) table and column_name for choice selector. + integer_field, // integer of arbitrary size + char_field(Int size), // text of maximal size 'size' (number of characters) + text_field. // text of variable size + + From the point of view of your Anubis program, these data will be of types: + + Name | Anubis type | Type within the database + ----------------+-------------------+-------------------------------------------------- + //anubis | T (serializable) | text (base64 encoded serialization) + p_key | DB_id | primary key (integer) + //binary | ByteArray | text (the byte array base64 encoded) + boolean_field | Bool | boolean + date_field | DB_date | text (date in ISO-8601 format: yyyy-mm-dd) + time_field | DB_time | text (date in ISO-8601 format: hh:mm:ss) + datetime_field | DB_datetime | text (date in ISO-8601 format: yyyy-mm-dd hh:mm:ss) + foreign_key | Int | integer + integer_field | Int | arbitrary size integer (numeric) + char_field | String | max size text + text_field | String | arbitrary size text + + + + *** (1.2) 'MaybeNull'. + + This type scheme is isomorphic to 'Maybe', and is used for representing data which + can have the value 'NULL'. We don't use 'Maybe' for this purpose because + we want to avoid the misleading 'Maybe(Maybe(...))'. Instead, we will have + sometimes 'Maybe(MaybeNull(...))', so that 'null' means 'NULL', and 'failure' + means an error. + +public type MaybeNull($T): + null, + not_null($T value). + + Conversion tools between date, time and datetime in ISO-8601 format and 'Int' + (number of seconds since the epoch) are provided in 'library/tools/ISO-8601.anubis'. + + + + *** (1.3) 'DB_Model_Attr' (attributes of columns). + + Possible attributes of columns: (each column has a list of such attributes) + +public type DB_Model_Attr: + unique, // by default, the values in a column are not required to be all different + indexed, // by default, a column is not indexed + default(String). // default value (used in case of creation of a NON NULL column + // in a table which already contains some rows) + + Of course, 'NOT NULL' is not an alternative of 'DB_Model_Attr' because it is already coded into the + database type itself (type 'DB_Model_Field' above). + + + *** (1.4) 'DB_Model_Column' (describing a column in a table). + + Description of a column: + +public type DB_Model_Column: + db_column (String name, // name of ordinary column (i.e. all but 'id') + DB_Model_Field type, + List(DB_Model_Attr) attributes). + + + *** (3.7) 'DB_Model_Table' (describing a table). + + Description of a table: + +public type DB_Model: + db_model( List(DB_Model_Column) columns, // columns other than the primary key column (if any) + String show_string). + + +public type DB_Display: + db_display(List(String) list_view, + List(String) edit_view). + +public type DB_Table: + db_table ( String name, // name of the table + DB_Model model, + DB_Display display). + + *** (3.8) 'DB_Database' (describing a whole database). + + Description of a whole database: + +public type DB_Database: + db_database (String name, // name of the database + List(DB_Table) tables). // list of all tables in the database + + Note: indexes are described via the attributes and will be generated accordingly. + + + Dates (of type 'String' in Anubis) are stored into the database as ISO-8601 strings, + for example: 2013-05-24 09:34:23 + + We provide functions for conversion into Int (number of seconds since the 'epoch') and conversely + in 'library/tools/ISO-8601.anubis'. + +public define Maybe(String) convert_to_date (MaybeNull(ByteArray) b). +public define MaybeNull(String) convert_to_date_or_null (MaybeNull(ByteArray) b). + + *** (8.3.6) Converting 'integer?' and 'integer?_or_null' to and fro. + + The next functions are used for integer16, integer32 and integer. + +public define Maybe(Int) convert_to_integer (MaybeNull(ByteArray) b). +public define MaybeNull(Int) convert_to_integer_or_null (MaybeNull(ByteArray) b). + + + *** (8.3.7) Converting 'char/text' and 'char_or_null/text_or_null' to and fro. + + The same functions are used for 'text/text_or_null' and 'vartext/vartext_or_null'. + + Litteral texts must be 'prepared' before they can be included into + SQL commands (this amounts to doubling the single quotes). + + public define MetaSQL_Prepared prepare_text (String t). + public define MetaSQL_Prepared prepare_text_or_null (MaybeNull(String) t). + + Conversely, texts arrive from the database in the form of byte arrays which must be + converted to strings. The two functions for converting to 'text' and to 'text_or_null' + are almost the same one. The only difference is that 'null' is interpreted as an error in + the case of 'text'. + + --- That's all for the public part !---------------------------------------------------------------- + +read tools/basis.anubis +read tools/base64.anubis +read system/string.anubis +read tools/ISO-8601.anubis + + + *** [1] Tools. + + *** [1.1] Concatenating strings which may not exist. + + The concatenation function '+' for strings is defined in 'tools/basis.anubis'. Here we define + an extension of it to strings which may not exist (i.e. data of type 'Maybe(String)'). Of course, + the result is always of type 'Maybe(String)'. + +define macro Maybe(String) + Maybe(String) s + String t + = + if s is + { + failure then failure, + success(s1) then success(s1+t) + }. + +define macro Maybe(String) + String s + Maybe(String) t + = + if t is + { + failure then failure, + success(t1) then success(s+t1) + }. + +define macro Maybe(String) + Maybe(String) s + Maybe(String) t + = + if s is + { + failure then failure, + success(s1) then if t is + { + failure then failure, + success(t1) then success(s1+t1) + } + }. + + + + *** [2] Verifications concerning the description of the database and queries. + + + + define Bool + has_forbidden_references + ( + String table_name, // the first 3 arguments concern the current table. + MetaSQL_PrimKey pk, + List(DB_Model_Column) columns, + List(DB_Model_Column) forwards, // subsequent tables + List(String) backwards // list of backwards table names + ) = + if columns is + { + [ ] then false, // no forbidden reference found + [col1 . other_cols] then + if is_forbidden_reference(table_name,col1,forwards,backwards) + then true + else has_forbidden_references(table_name,pk,other_cols,forwards,backwards) + }. + + define Bool // returns 'true' if there is at least one forbidden cycle. + has_forbidden_cycles + ( + String db_name, + List(DB_Model_Column) tables, + List(String) backwards // names of 'backwards' tables + ) = + if tables is + { + [ ] then false, // no forbidden cycle found + [tab1 . other_tabs] then if tab1 is table(name1,pk1,cols1) then + if has_forbidden_references(name1,pk1,cols1,other_tabs,backwards) + then true + else has_forbidden_cycles(db_name,other_tabs,[name1 . backwards]) + }. + + define Bool + is_forbidden_column_name + ( + String name + ) = + name = "id" | name = "metasqlcheck". + + define Bool + has_forbidden_column_names + ( + DB_Model_Column tab + ) = + if tab is table(_,_,cols) then + mapor((DB_Model_Column cs) |-> + if cs is col(name,_,_) then is_forbidden_column_name(name), + cols). + + define Bool + has_forbidden_column_names + ( + DB_Model_DB db + ) = + if db is database(_,tables) then + mapor(has_forbidden_column_names,tables). + + + + *** [3] Generating the target file. + + *** [3.1] Converting a database type into the corresponding Anubis type: + +public define String + to_Anubis_type + ( + DB_Model_Field t + ) = + if t is + { + //anubis(_T) then "ByteArray", + p_key then "DB_id", + //binary then "ByteArray", + boolean_field then "Bool", + date_field(_) then "DB_date", + time_field(_) then "DB_time", + datetime_field(_) then "DB_datetime", + foreign_key(_) then "Int", + integer_field then "Int", + char_field(Int size) then "String", + text_field then "String" + }. + + +public define String + to_Anubis_default + ( + DB_Model_Field t + ) = + if t is + { + //anubis(_T) then "constant_byte_array(0,0)", + p_key then "none", + //binary then "constant_byte_array(0,0)", + boolean_field then "false", + date_field(_) then "db_date(\"\")", + time_field(_) then "db_time(\"\")", + datetime_field(_) then "db_datetime(\"\")", + foreign_key(_) then "0", + integer_field then "0", + char_field(Int size) then "\"\"", + text_field then "\"\"" + }. + +public define String + from_DB_cursor + ( + DB_Model_Field t, + String cursor, + Int index + ) = + with cursor_index = "("+cursor+")("+index+")", + if t is + { + //anubis(_T) then "constant_byte_array(0,0)", + p_key then "db_id((Int)db_integer"+cursor_index+")", + //binary then "constant_byte_array(0,0)", + boolean_field then "db_bool"+cursor_index, + date_field(_) then "db_date(text"+cursor_index+")", + time_field(_) then "db_time(text"+cursor_index+")", + datetime_field(_) then "db_datetime(text"+cursor_index+")", + foreign_key(_) then "(Int)db_integer"+cursor_index, + integer_field then "(Int)db_integer"+cursor_index, + char_field(Int size) then "text"+cursor_index, + text_field then "text"+cursor_index + }. + +define List(String) +/** + */ + components + ( + List(DB_Model_Column) columns, + String cursor_name, + List(String) so_far, + Int idx + )= + if columns is + { + [] then reverse(so_far), + [h . t ] then + since h is db_column(name, col_type, _), + with line = fill(from_DB_cursor(col_type, cursor_name, idx), 35)+ "/* "+name+" */", + components(t, cursor_name, [line . so_far], idx + 1 ) + }. + +public define String + generate_constructor_from_cursor + ( + String constructor_name, + String cursor_name, + List(DB_Model_Column) columns, + String indent + )= + indent+constructor_name+"(\n"+indent+" "+join(",\n"+indent+" ", components(columns, cursor_name, [], 0))+"\n"+indent+")". + + +public define String + from_web_arg + ( + DB_Model_Field t, + String name + ) = + if t is + { + //anubis(_T) then "constant_byte_array(0,0)", + p_key then "with "+name+" = get_DB_id(lwa, \""+name+"\"),", + //binary then "constant_byte_array(0,0)", + boolean_field then "with "+name+" = get_Bool(lwa, \""+name+"\"),", + date_field(attrs) then if attrs = none then "get_DB_date(lwa, \""+name+"\")" else "with "+name+" = get_dummy_DB_date,", + time_field(attrs) then if attrs = none then "get_DB_time(lwa, \""+name+"\")" else "with "+name+" = get_dummy_DB_time,", + datetime_field(attrs) then if attrs = none then "get_DB_datetime(lwa, \""+name+"\")" else "with "+name+" = get_dummy_DB_datetime,", + foreign_key(String table) then "get_Int(lwa, \""+name+"\")", + integer_field then "get_Int(lwa, \""+name+"\")", + char_field(Int size) then "get_String(lwa, \""+name+"\")", + text_field then "get_String(lwa, \""+name+"\")" + }. + +public define List(String) +/** + */ + components + ( + List(DB_Model_Column) columns, + List(String) so_far + )= + if columns is + { + [] then reverse(so_far), + [h . t ] then + since h is db_column(name, col_type, _), + components(t, [ name . so_far]) + }. + +public define String + generate_constructor + ( + String constructor_name, + List(DB_Model_Column) columns, + String indent + )= + indent+constructor_name+"(\n"+indent+" "+join(",\n"+indent+" ", components(columns, []))+")". + +public define String + to_Bind + ( + DB_Model_Field t, + String type_name, //name of the type + String name, //name of component into the type + Bool insert //true if insert time else false for update + ) = + if t is + { + //anubis(_T) then "constant_byte_array(0,0)", + p_key then "", + //binary then "constant_byte_array(0,0)", + boolean_field then "bind_Bool(\":v_"+name+"\", "+type_name+"."+name+")", + date_field(attrs) then "bind_Date(\":v_"+name+"\", "+type_name+"."+name+")", + time_field(attrs) then "bind_Time(\":v_"+name+"\", "+type_name+"."+name+")", + datetime_field(attrs) then if attrs is + { + none then "bind_Datetime(\":v_"+name+"\", "+type_name+"."+name+")", + auto_now then "bind_Datetime(\":v_"+name+"\", now)", + auto_now_add then + if insert then + "bind_Datetime(\":v_"+name+"\", now)" + else + "" + }, + foreign_key(_) then "bind_Int(\":v_"+name+"\", "+type_name+"."+name+")", + integer_field then "bind_Int(\":v_"+name+"\", "+type_name+"."+name+")", + char_field(Int size) then "bind_String(\":v_"+name+"\", "+type_name+"."+name+")", + text_field then "bind_String(\":v_"+name+"\", "+type_name+"."+name+")" + }. + +public define List(String) +/** + */ + to_Bind_list + ( + List(DB_Model_Column) columns, + String type_name, //name of the type + List(String) so_far, + Bool insert + )= + if columns is + { + [] then reverse(so_far), + [h . t ] then + since h is db_column(name, col_type, _), + with result = to_Bind(col_type, type_name, name, insert), + //we eliminate the empty string because during the join it will have an empty line + if result = "" then + to_Bind_list(t, type_name, so_far, insert) + else + to_Bind_list(t, type_name, [result . so_far], insert) + }. + +public define String + generate_Bind_list + ( + List(DB_Model_Column) columns, + String type_name, + String indent, + Bool insert + )= + indent+"[\n"+indent+" "+join(",\n"+indent+" ", to_Bind_list(columns, type_name, [], insert))+"]". + + +public define Maybe(String) + get_column_name + ( + DB_Model_Column col, + Bool insert //true if insert time else false for update + ) = + since col is db_column(name, col_type, _), + if col_type is + { + //anubis(_T) then "constant_byte_array(0,0)", + p_key then failure, + //binary then "constant_byte_array(0,0)", + boolean_field then success(name), + date_field(attrs) then success(name), + time_field(attrs) then success(name), + datetime_field(attrs) then if attrs is + { + none then success(name), + auto_now then success(name), + auto_now_add then + if insert then success(name) else failure + }, + foreign_key(_) then success(name), + integer_field then success(name), + char_field(Int size) then success(name), + text_field then success(name) + }. + +public define List(String) + columns_name + ( + List(DB_Model_Column) columns, + Bool insert, //true if insert time else false for update + List(String) so_far + ) = + if columns is + { + [] then reverse(so_far), + [h . t] then + if get_column_name(h, insert) is + { + failure then columns_name(t, insert, so_far) + success(result) then + if insert then + columns_name(t, insert, [result . so_far]) + else + columns_name(t, insert, [result+" = :v_"+result . so_far]) + } + }. + +public define String +/* + Generate the SQL "(xxx, yyy, ...) VALUES ( :v_xxx, :v_yyy, ...)" for the insert + SQL query. + */ + insert_values + ( + List(DB_Model_Column) columns, + String indent + )= + with columns_list = columns_name(columns, true, []), + indent+" ("+join(", ", columns_list)+")\n"+indent+"VALUES\n"+indent+" ("+prefixed_join(":v_", columns_list, ", ")+")". + + +public define String +/* + Generate the SQL "xxx = :v_xxx, yyy = :v_yyy, ..." for the update + SQL query. + */ + update_values + ( + List(DB_Model_Column) columns, + String indent + )= + with columns_list = columns_name(columns, false, []), + indent+" "+join(", ", columns_list). + + +public define Maybe(String) + get_VT_edit_entry + ( + DB_Model_Column col, + String type_name + ) = + since col is db_column(name, col_type, _), + if col_type is + { + //anubis(_T) then "constant_byte_array(0,0)", + p_key then success("primary_key(to_String("+type_name+"."+name+"))"), + //binary then "constant_byte_array(0,0)", + boolean_field then success("boolean(\""+to_upper(name)+"\", \""+name+"\", "+type_name+"."+name+")"), + date_field(attrs) then success("date(\""+to_upper(name)+"\", \""+name+"\", "+type_name+"."+name+")"), + time_field(attrs) then success("time(\""+to_upper(name)+"\", \""+name+"\", "+type_name+"."+name+")"), + datetime_field(attrs) then if attrs is + { + none then success("datetime(\""+to_upper(name)+"\", \""+name+"\", "+type_name+"."+name+")"), + auto_now then success("information(\""+to_upper(name)+"\", \""+name+"\", "+type_name+"."+name+".datetime)"), + auto_now_add then success("information(\""+to_upper(name)+"\", \""+name+"\", "+type_name+"."+name+".datetime)") + }, + foreign_key(_) then success("information(\"FOREIGN_TODO\", \""+name+"\", to_String("+type_name+"."+name+"))"), + integer_field then success("integer(\""+to_upper(name)+"\", \""+name+"\", "+type_name+"."+name+")"), + char_field(Int size) then success("text(\""+to_upper(name)+"\", \""+name+"\", "+type_name+"."+name+")"), + text_field then success("text_area(\""+to_upper(name)+"\", \""+name+"\", "+type_name+"."+name+")") + }. + +public define String + edit_entries + ( + List(DB_Model_Column) columns, + String type_name, + String indent, + List(String) so_far + ) = + if columns is + { + [] then indent+" "+join(",\n"+indent+" ", reverse(so_far)), + [h . t] then + if get_VT_edit_entry(h, type_name) is + { + failure then edit_entries(t, type_name, indent, so_far) + success(result) then edit_entries(t, type_name, indent, [result . so_far]) + } + }. + +public define String + make_list_view_header + ( + List(String) list_view, + String indent + )= + indent+join(",\n"+indent, map((String text) |-> "text(\""+to_upper(text)+"\")", list_view)). + +public define Maybe(DB_Model_Column) + get_column_type + ( + List(DB_Model_Column) columns, //columns in wich we search + String name_to_find //Column name to find in previous list + )= + if columns is + { + [] then failure, + [h . t] then + since h is db_column(name, field, attr), + if name_to_find = name then + success(h) + else + get_column_type(t, name_to_find) + }. + +public define String + to_cell_view + ( + DB_Model_Column col, + String type_name + ) = + since col is db_column(name, col_type, _), + if col_type is + { + //anubis(_T) then "constant_byte_array(0,0)", + p_key then "link(to_String("+type_name+".id), to_String("+type_name+".id))", + //binary then "constant_byte_array(0,0)", + boolean_field then "text(to_String("+type_name+"."+name+"))", + date_field(attrs) then "text(to_String("+type_name+"."+name+"))", + time_field(attrs) then "text(to_String("+type_name+"."+name+"))", + datetime_field(attrs) then "text(to_String("+type_name+"."+name+"))" + foreign_key(foreign_table) then "text(get_"+foreign_table+"_show_string(db, "+type_name+"."+name+"))", + integer_field then "text(to_String("+type_name+"."+name+"))", + char_field(Int size) then "text("+type_name+"."+name+")", + text_field then "text("+type_name+"."+name+")" + }. + +public define String + to_cell_view + ( + List(DB_Model_Column) columns, + String column_name, + String data_name + )= + if get_column_type(columns, column_name) is + { + failure then "column name "+column_name+"doesn't exist", + success(column) then to_cell_view(column, data_name) + }. + +public define String + make_list_view_row + ( + DB_Model model, + List(String) list_view, + String data_name, + String indent + )= + since model is db_model(columns, _), + indent+join(",\n"+indent, map((String column_name) |-> to_cell_view(columns, column_name, data_name), list_view)). -- libgit2 0.21.4