Commit aef2e7132faffe8125687b30c6f9867ac3ea6e93

Authored by totoro
1 parent ad8efe02

move the db_model.anubis from db_model application to calexium_lib

add help text for VT_edit_entry : information and text
database/model/db_model.anubis 0 → 100644
  1 +/*
  2 + * Created by PyramIDE.
  3 + * User: フランスのトトロ
  4 + * Date: 01/01/2016
  5 + * Time: 1:34
  6 + * © Calexium
  7 + */
  8 +
  9 + The Anubis project
  10 +
  11 + Interfacing and generating a database with Anubis
  12 +
  13 +
  14 + Author: David René
  15 +
  16 +
  17 + In order to generate such tools, DB_Model needs a formal
  18 + description of the database.
  19 +
  20 +
  21 + *** (1) Formal description of the database.
  22 +
  23 + *** (1.1) 'DB_Model_Field' (data types of table columns).
  24 +
  25 +public type DB_Datetime_Field_Attr:
  26 + none, //Nothing special, normal behaviour
  27 + auto_now, //Always update datetime at SQL update
  28 + auto_now_add. //Set current datetime when row is created and can't be edited anymore
  29 +
  30 +public type DB_Model_Field:
  31 + //anubis(String _T), // the datum of type _T is serialized and base64 encoded
  32 + p_key,
  33 + //binary, // contains a byte array
  34 + boolean_field, // true or false
  35 + date_field(DB_Datetime_Field_Attr), // date with the precision of the day
  36 + time_field(DB_Datetime_Field_Attr), // time with the precision of the second
  37 + datetime_field(DB_Datetime_Field_Attr), // datetime with the precision of the second
  38 + foreign_key(String table_name), // foreign key to 'id' in another (or same) table and column_name for choice selector.
  39 + integer_field, // integer of arbitrary size
  40 + char_field(Int size), // text of maximal size 'size' (number of characters)
  41 + text_field. // text of variable size
  42 +
  43 + From the point of view of your Anubis program, these data will be of types:
  44 +
  45 + Name | Anubis type | Type within the database
  46 + ----------------+-------------------+--------------------------------------------------
  47 + //anubis | T (serializable) | text (base64 encoded serialization)
  48 + p_key | DB_id | primary key (integer)
  49 + //binary | ByteArray | text (the byte array base64 encoded)
  50 + boolean_field | Bool | boolean
  51 + date_field | DB_date | text (date in ISO-8601 format: yyyy-mm-dd)
  52 + time_field | DB_time | text (date in ISO-8601 format: hh:mm:ss)
  53 + datetime_field | DB_datetime | text (date in ISO-8601 format: yyyy-mm-dd hh:mm:ss)
  54 + foreign_key | Int | integer
  55 + integer_field | Int | arbitrary size integer (numeric)
  56 + char_field | String | max size text
  57 + text_field | String | arbitrary size text
  58 +
  59 +
  60 +
  61 + *** (1.2) 'MaybeNull'.
  62 +
  63 + This type scheme is isomorphic to 'Maybe', and is used for representing data which
  64 + can have the value 'NULL'. We don't use 'Maybe' for this purpose because
  65 + we want to avoid the misleading 'Maybe(Maybe(...))'. Instead, we will have
  66 + sometimes 'Maybe(MaybeNull(...))', so that 'null' means 'NULL', and 'failure'
  67 + means an error.
  68 +
  69 +public type MaybeNull($T):
  70 + null,
  71 + not_null($T value).
  72 +
  73 + Conversion tools between date, time and datetime in ISO-8601 format and 'Int'
  74 + (number of seconds since the epoch) are provided in 'library/tools/ISO-8601.anubis'.
  75 +
  76 +
  77 + *** (1.3) 'DB_Model_Attr' (attributes of columns).
  78 +
  79 + Possible attributes of columns: (each column has a list of such attributes)
  80 +
  81 +public type DB_Model_Attr:
  82 + unique, // by default, the values in a column are not required to be all different
  83 + indexed, // by default, a column is not indexed
  84 + default(String). // default value (used in case of creation of a NON NULL column
  85 + // in a table which already contains some rows)
  86 +
  87 +public type DB_Help_Text:
  88 + no_help_text, //no help text available
  89 + help_text_TAG(String), //TAG
  90 + help_text(String). //TAG
  91 +
  92 +public define String
  93 + to_Anubis_source
  94 + (
  95 + DB_Help_Text help
  96 + )=
  97 + if help is
  98 + {
  99 + no_help_text then "no_help_text",
  100 + help_text_TAG(tag) then "help_text_TAG(\""+tag+"\")",
  101 + help_text(str) then "help_text(\""+str+"\")"
  102 + }.
  103 +
  104 + Of course, 'NOT NULL' is not an alternative of 'DB_Model_Attr' because it is already coded into the
  105 + database type itself (type 'DB_Model_Field' above).
  106 +
  107 +
  108 + *** (1.4) 'DB_Model_Column' (describing a column in a table).
  109 +
  110 + Description of a column:
  111 +
  112 +public type DB_Model_Column:
  113 + db_column (String name, // name of ordinary column (i.e. all but 'id')
  114 + DB_Model_Field type,
  115 + List(DB_Model_Attr) attributes,
  116 + DB_Help_Text help
  117 + ).
  118 +
  119 +public define DB_Model_Column
  120 + db_column
  121 + (
  122 + String name,
  123 + DB_Model_Field type,
  124 + List(DB_Model_Attr) attributes,
  125 + )=
  126 + db_column(name, type, attributes, no_help_text).
  127 +
  128 +public define DB_Model_Column
  129 + db_column
  130 + (
  131 + String name,
  132 + DB_Model_Field type
  133 + )=
  134 + db_column(name, type, [], no_help_text).
  135 +
  136 +
  137 + *** (3.7) 'DB_Model_Table' (describing a table).
  138 +
  139 + Description of a table:
  140 +
  141 +public type DB_Model:
  142 + db_model( List(DB_Model_Column) columns, // columns other than the primary key column (if any)
  143 + String show_string).
  144 +
  145 +
  146 +public type DB_Display:
  147 + db_display(List(String) list_view,
  148 + List(String) edit_view).
  149 +
  150 +public type DB_Table:
  151 + db_table ( String name, // name of the table
  152 + DB_Model model,
  153 + DB_Display display).
  154 +
  155 + *** (3.8) 'DB_Database' (describing a whole database).
  156 +
  157 + Description of a whole database:
  158 +
  159 +public type DB_Database:
  160 + db_database (String name, // name of the database
  161 + List(DB_Table) tables).
  162 +// list of all tables in the database
  163 +
  164 +
  165 +
  166 +//public define Maybe(String) convert_to_date (MaybeNull(ByteArray) b).
  167 +//public define MaybeNull(String) convert_to_date_or_null (MaybeNull(ByteArray) b).
  168 +
  169 + *** (8.3.6) Converting 'integer?' and 'integer?_or_null' to and fro.
  170 +
  171 + The next functions are used for integer16, integer32 and integer.
  172 +
  173 +//public define Maybe(Int) convert_to_integer (MaybeNull(ByteArray) b).
  174 +//public define MaybeNull(Int) convert_to_integer_or_null (MaybeNull(ByteArray) b).
  175 +
  176 +
  177 + *** (8.3.7) Converting 'char/text' and 'char_or_null/text_or_null' to and fro.
  178 +
  179 + The same functions are used for 'text/text_or_null' and 'vartext/vartext_or_null'.
  180 +
  181 + Litteral texts must be 'prepared' before they can be included into
  182 + SQL commands (this amounts to doubling the single quotes).
  183 +
  184 + public define MetaSQL_Prepared prepare_text (String t).
  185 + public define MetaSQL_Prepared prepare_text_or_null (MaybeNull(String) t).
  186 +
  187 + Conversely, texts arrive from the database in the form of byte arrays which must be
  188 + converted to strings. The two functions for converting to 'text' and to 'text_or_null'
  189 + are almost the same one. The only difference is that 'null' is interpreted as an error in
  190 + the case of 'text'.
  191 +
  192 + --- That's all for the public part !----------------------------------------------------------------
  193 +
  194 +read tools/basis.anubis
  195 +read tools/base64.anubis
  196 +read system/string.anubis
  197 +read tools/ISO-8601.anubis
  198 +
  199 +
  200 + *** [1] Tools.
  201 +
  202 + *** [1.1] Concatenating strings which may not exist.
  203 +
  204 + The concatenation function '+' for strings is defined in 'tools/basis.anubis'. Here we define
  205 + an extension of it to strings which may not exist (i.e. data of type 'Maybe(String)'). Of course,
  206 + the result is always of type 'Maybe(String)'.
  207 +
  208 +define macro Maybe(String)
  209 + Maybe(String) s + String t
  210 + =
  211 + if s is
  212 + {
  213 + failure then failure,
  214 + success(s1) then success(s1+t)
  215 + }.
  216 +
  217 +define macro Maybe(String)
  218 + String s + Maybe(String) t
  219 + =
  220 + if t is
  221 + {
  222 + failure then failure,
  223 + success(t1) then success(s+t1)
  224 + }.
  225 +
  226 +define macro Maybe(String)
  227 + Maybe(String) s + Maybe(String) t
  228 + =
  229 + if s is
  230 + {
  231 + failure then failure,
  232 + success(s1) then if t is
  233 + {
  234 + failure then failure,
  235 + success(t1) then success(s1+t1)
  236 + }
  237 + }.
  238 +
  239 +
  240 +
  241 + *** [2] Verifications concerning the description of the database and queries.
  242 +
  243 +
  244 +
  245 + define Bool
  246 + has_forbidden_references
  247 + (
  248 + String table_name, // the first 3 arguments concern the current table.
  249 + MetaSQL_PrimKey pk,
  250 + List(DB_Model_Column) columns,
  251 + List(DB_Model_Column) forwards, // subsequent tables
  252 + List(String) backwards // list of backwards table names
  253 + ) =
  254 + if columns is
  255 + {
  256 + [ ] then false, // no forbidden reference found
  257 + [col1 . other_cols] then
  258 + if is_forbidden_reference(table_name,col1,forwards,backwards)
  259 + then true
  260 + else has_forbidden_references(table_name,pk,other_cols,forwards,backwards)
  261 + }.
  262 +
  263 + define Bool // returns 'true' if there is at least one forbidden cycle.
  264 + has_forbidden_cycles
  265 + (
  266 + String db_name,
  267 + List(DB_Model_Column) tables,
  268 + List(String) backwards // names of 'backwards' tables
  269 + ) =
  270 + if tables is
  271 + {
  272 + [ ] then false, // no forbidden cycle found
  273 + [tab1 . other_tabs] then if tab1 is table(name1,pk1,cols1) then
  274 + if has_forbidden_references(name1,pk1,cols1,other_tabs,backwards)
  275 + then true
  276 + else has_forbidden_cycles(db_name,other_tabs,[name1 . backwards])
  277 + }.
  278 +
  279 + define Bool
  280 + is_forbidden_column_name
  281 + (
  282 + String name
  283 + ) =
  284 + name = "id" | name = "metasqlcheck".
  285 +
  286 + define Bool
  287 + has_forbidden_column_names
  288 + (
  289 + DB_Model_Column tab
  290 + ) =
  291 + if tab is table(_,_,cols) then
  292 + mapor((DB_Model_Column cs) |->
  293 + if cs is col(name,_,_) then is_forbidden_column_name(name),
  294 + cols).
  295 +
  296 + define Bool
  297 + has_forbidden_column_names
  298 + (
  299 + DB_Model_DB db
  300 + ) =
  301 + if db is database(_,tables) then
  302 + mapor(has_forbidden_column_names,tables).
  303 +
  304 +
  305 +
  306 + *** [3] Generating the target file.
  307 +
  308 + *** [3.1] Converting a database type into the corresponding Anubis type:
  309 +
  310 +public define String
  311 + to_Anubis_type
  312 + (
  313 + DB_Model_Field t
  314 + ) =
  315 + if t is
  316 + {
  317 + //anubis(_T) then "ByteArray",
  318 + p_key then "DB_id",
  319 + //binary then "ByteArray",
  320 + boolean_field then "Bool",
  321 + date_field(_) then "DB_date",
  322 + time_field(_) then "DB_time",
  323 + datetime_field(_) then "DB_datetime",
  324 + foreign_key(_) then "Int",
  325 + integer_field then "Int",
  326 + char_field(Int size) then "String",
  327 + text_field then "String"
  328 + }.
  329 +
  330 +
  331 +public define String
  332 + to_Anubis_default
  333 + (
  334 + DB_Model_Field t
  335 + ) =
  336 + if t is
  337 + {
  338 + //anubis(_T) then "constant_byte_array(0,0)",
  339 + p_key then "none",
  340 + //binary then "constant_byte_array(0,0)",
  341 + boolean_field then "false",
  342 + date_field(_) then "db_date(\"\")",
  343 + time_field(_) then "db_time(\"\")",
  344 + datetime_field(_) then "db_datetime(\"\")",
  345 + foreign_key(_) then "0",
  346 + integer_field then "0",
  347 + char_field(Int size) then "\"\"",
  348 + text_field then "\"\""
  349 + }.
  350 +
  351 +public define String
  352 + from_DB_cursor
  353 + (
  354 + DB_Model_Field t,
  355 + String cursor,
  356 + Int index
  357 + ) =
  358 + with cursor_index = "("+cursor+")("+index+")",
  359 + if t is
  360 + {
  361 + //anubis(_T) then "constant_byte_array(0,0)",
  362 + p_key then "db_id((Int)db_integer"+cursor_index+")",
  363 + //binary then "constant_byte_array(0,0)",
  364 + boolean_field then "db_bool"+cursor_index,
  365 + date_field(_) then "db_date(text"+cursor_index+")",
  366 + time_field(_) then "db_time(text"+cursor_index+")",
  367 + datetime_field(_) then "db_datetime(text"+cursor_index+")",
  368 + foreign_key(_) then "(Int)db_integer"+cursor_index,
  369 + integer_field then "(Int)db_integer"+cursor_index,
  370 + char_field(Int size) then "text"+cursor_index,
  371 + text_field then "text"+cursor_index
  372 + }.
  373 +
  374 +define List(String)
  375 +/**
  376 + */
  377 + components
  378 + (
  379 + List(DB_Model_Column) columns,
  380 + String cursor_name,
  381 + List(String) so_far,
  382 + Int idx
  383 + )=
  384 + if columns is
  385 + {
  386 + [] then reverse(so_far),
  387 + [h . t ] then
  388 + since h is db_column(name, col_type, _, _),
  389 + with line = fill(from_DB_cursor(col_type, cursor_name, idx), 35)+ "/* "+name+" */",
  390 + components(t, cursor_name, [line . so_far], idx + 1 )
  391 + }.
  392 +
  393 +public define String
  394 + generate_constructor_from_cursor
  395 + (
  396 + String constructor_name,
  397 + String cursor_name,
  398 + List(DB_Model_Column) columns,
  399 + String indent
  400 + )=
  401 + indent+constructor_name+"(\n"+indent+" "+join(",\n"+indent+" ", components(columns, cursor_name, [], 0))+"\n"+indent+")".
  402 +
  403 +
  404 +public define String
  405 + from_web_arg
  406 + (
  407 + DB_Model_Field t,
  408 + String name
  409 + ) =
  410 + if t is
  411 + {
  412 + //anubis(_T) then "constant_byte_array(0,0)",
  413 + p_key then "with "+name+" = get_DB_id(lwa, \""+name+"\"),",
  414 + //binary then "constant_byte_array(0,0)",
  415 + boolean_field then "with "+name+" = get_Bool(lwa, \""+name+"\"),",
  416 + date_field(attrs) then if attrs = none then "get_DB_date(lwa, \""+name+"\")" else "with "+name+" = get_dummy_DB_date,",
  417 + time_field(attrs) then if attrs = none then "get_DB_time(lwa, \""+name+"\")" else "with "+name+" = get_dummy_DB_time,",
  418 + datetime_field(attrs) then if attrs = none then "get_DB_datetime(lwa, \""+name+"\")" else "with "+name+" = get_dummy_DB_datetime,",
  419 + foreign_key(String table) then "get_Int(lwa, \""+name+"\")",
  420 + integer_field then "get_Int(lwa, \""+name+"\")",
  421 + char_field(Int size) then "get_String(lwa, \""+name+"\")",
  422 + text_field then "get_String(lwa, \""+name+"\")"
  423 + }.
  424 +
  425 +public define List(String)
  426 +/**
  427 + */
  428 + components
  429 + (
  430 + List(DB_Model_Column) columns,
  431 + List(String) so_far
  432 + )=
  433 + if columns is
  434 + {
  435 + [] then reverse(so_far),
  436 + [h . t ] then
  437 + since h is db_column(name, col_type, _, _),
  438 + components(t, [ name . so_far])
  439 + }.
  440 +
  441 +public define String
  442 + generate_constructor
  443 + (
  444 + String constructor_name,
  445 + List(DB_Model_Column) columns,
  446 + String indent
  447 + )=
  448 + indent+constructor_name+"(\n"+indent+" "+join(",\n"+indent+" ", components(columns, []))+")".
  449 +
  450 +public define String
  451 + to_Bind
  452 + (
  453 + DB_Model_Field t,
  454 + String type_name, //name of the type
  455 + String name, //name of component into the type
  456 + Bool insert //true if insert time else false for update
  457 + ) =
  458 + if t is
  459 + {
  460 + //anubis(_T) then "constant_byte_array(0,0)",
  461 + p_key then "",
  462 + //binary then "constant_byte_array(0,0)",
  463 + boolean_field then "bind_Bool(\":v_"+name+"\", "+type_name+"."+name+")",
  464 + date_field(attrs) then "bind_Date(\":v_"+name+"\", "+type_name+"."+name+")",
  465 + time_field(attrs) then "bind_Time(\":v_"+name+"\", "+type_name+"."+name+")",
  466 + datetime_field(attrs) then if attrs is
  467 + {
  468 + none then "bind_Datetime(\":v_"+name+"\", "+type_name+"."+name+")",
  469 + auto_now then "bind_Datetime(\":v_"+name+"\", now)",
  470 + auto_now_add then
  471 + if insert then
  472 + "bind_Datetime(\":v_"+name+"\", now)"
  473 + else
  474 + ""
  475 + },
  476 + foreign_key(_) then "bind_Int(\":v_"+name+"\", "+type_name+"."+name+")",
  477 + integer_field then "bind_Int(\":v_"+name+"\", "+type_name+"."+name+")",
  478 + char_field(Int size) then "bind_String(\":v_"+name+"\", "+type_name+"."+name+")",
  479 + text_field then "bind_String(\":v_"+name+"\", "+type_name+"."+name+")"
  480 + }.
  481 +
  482 +public define List(String)
  483 +/**
  484 + */
  485 + to_Bind_list
  486 + (
  487 + List(DB_Model_Column) columns,
  488 + String type_name, //name of the type
  489 + List(String) so_far,
  490 + Bool insert
  491 + )=
  492 + if columns is
  493 + {
  494 + [] then reverse(so_far),
  495 + [h . t ] then
  496 + since h is db_column(name, col_type, _, _),
  497 + with result = to_Bind(col_type, type_name, name, insert),
  498 + //we eliminate the empty string because during the join it will have an empty line
  499 + if result = "" then
  500 + to_Bind_list(t, type_name, so_far, insert)
  501 + else
  502 + to_Bind_list(t, type_name, [result . so_far], insert)
  503 + }.
  504 +
  505 +public define String
  506 + generate_Bind_list
  507 + (
  508 + List(DB_Model_Column) columns,
  509 + String type_name,
  510 + String indent,
  511 + Bool insert
  512 + )=
  513 + indent+"[\n"+indent+" "+join(",\n"+indent+" ", to_Bind_list(columns, type_name, [], insert))+"]".
  514 +
  515 +
  516 +public define Maybe(String)
  517 + get_column_name
  518 + (
  519 + DB_Model_Column col,
  520 + Bool insert //true if insert time else false for update
  521 + ) =
  522 + since col is db_column(name, col_type, _, _),
  523 + if col_type is
  524 + {
  525 + //anubis(_T) then "constant_byte_array(0,0)",
  526 + p_key then failure,
  527 + //binary then "constant_byte_array(0,0)",
  528 + boolean_field then success(name),
  529 + date_field(attrs) then success(name),
  530 + time_field(attrs) then success(name),
  531 + datetime_field(attrs) then if attrs is
  532 + {
  533 + none then success(name),
  534 + auto_now then success(name),
  535 + auto_now_add then
  536 + if insert then success(name) else failure
  537 + },
  538 + foreign_key(_) then success(name),
  539 + integer_field then success(name),
  540 + char_field(Int size) then success(name),
  541 + text_field then success(name)
  542 + }.
  543 +
  544 +public define List(String)
  545 + columns_name
  546 + (
  547 + List(DB_Model_Column) columns,
  548 + Bool insert, //true if insert time else false for update
  549 + List(String) so_far
  550 + ) =
  551 + if columns is
  552 + {
  553 + [] then reverse(so_far),
  554 + [h . t] then
  555 + if get_column_name(h, insert) is
  556 + {
  557 + failure then columns_name(t, insert, so_far)
  558 + success(result) then
  559 + if insert then
  560 + columns_name(t, insert, [result . so_far])
  561 + else
  562 + columns_name(t, insert, [result+" = :v_"+result . so_far])
  563 + }
  564 + }.
  565 +
  566 +public define String
  567 +/*
  568 + Generate the SQL "(xxx, yyy, ...) VALUES ( :v_xxx, :v_yyy, ...)" for the insert
  569 + SQL query.
  570 + */
  571 + insert_values
  572 + (
  573 + List(DB_Model_Column) columns,
  574 + String indent
  575 + )=
  576 + with columns_list = columns_name(columns, true, []),
  577 + indent+" ("+join(", ", columns_list)+")\n"+indent+"VALUES\n"+indent+" ("+prefixed_join(":v_", columns_list, ", ")+")".
  578 +
  579 +
  580 +public define String
  581 +/*
  582 + Generate the SQL "xxx = :v_xxx, yyy = :v_yyy, ..." for the update
  583 + SQL query.
  584 + */
  585 + update_values
  586 + (
  587 + List(DB_Model_Column) columns,
  588 + String indent
  589 + )=
  590 + with columns_list = columns_name(columns, false, []),
  591 + indent+" "+join(", ", columns_list).
  592 +
  593 +
  594 +public define Maybe(String)
  595 + get_VT_edit_entry
  596 + (
  597 + DB_Model_Column col,
  598 + String type_name
  599 + ) =
  600 + since col is db_column(name, col_type, _, help),
  601 + if col_type is
  602 + {
  603 + //anubis(_T) then "constant_byte_array(0,0)",
  604 + p_key then success("primary_key(to_String("+type_name+"."+name+"))"),
  605 + //binary then "constant_byte_array(0,0)",
  606 + boolean_field then success("boolean(\""+to_upper(name)+"\", \""+name+"\", "+type_name+"."+name+")"),
  607 + date_field(attrs) then success("date(\""+to_upper(name)+"\", \""+name+"\", "+type_name+"."+name+")"),
  608 + time_field(attrs) then success("time(\""+to_upper(name)+"\", \""+name+"\", "+type_name+"."+name+")"),
  609 + datetime_field(attrs) then if attrs is
  610 + {
  611 + none then success("datetime(\""+to_upper(name)+"\", \""+name+"\", "+type_name+"."+name+".datetime)"),
  612 + auto_now then success("information(\""+to_upper(name)+"\", \""+name+"\", "+type_name+"."+name+".datetime)"),
  613 + auto_now_add then success("information(\""+to_upper(name)+"\", \""+name+"\", "+type_name+"."+name+".datetime)")
  614 + },
  615 + foreign_key(_) then success("information(\"FOREIGN_TODO\", \""+name+"\", to_String("+type_name+"."+name+"))"),
  616 + integer_field then success("integer(\""+to_upper(name)+"\", \""+name+"\", "+type_name+"."+name+")"),
  617 + char_field(Int size) then success("text(\""+to_upper(name)+"\", \""+name+"\", "+type_name+"."+name+")"),
  618 + text_field then success("text_area(\""+to_upper(name)+"\", \""+name+"\", "+type_name+"."+name+")")
  619 + }.
  620 +
  621 +public define String
  622 + edit_entries
  623 + (
  624 + List(DB_Model_Column) columns,
  625 + String type_name,
  626 + String indent,
  627 + List(String) so_far
  628 + ) =
  629 + if columns is
  630 + {
  631 + [] then indent+" "+join(",\n"+indent+" ", reverse(so_far)),
  632 + [h . t] then
  633 + if get_VT_edit_entry(h, type_name) is
  634 + {
  635 + failure then edit_entries(t, type_name, indent, so_far)
  636 + success(result) then edit_entries(t, type_name, indent, [result . so_far])
  637 + }
  638 + }.
  639 +
  640 +public define String
  641 + make_list_view_header
  642 + (
  643 + List(String) list_view,
  644 + String indent
  645 + )=
  646 + indent+join(",\n"+indent, map((String text) |-> "text(\""+to_upper(text)+"\")", list_view)).
  647 +
  648 +public define Maybe(DB_Model_Column)
  649 + get_column_type
  650 + (
  651 + List(DB_Model_Column) columns, //columns in wich we search
  652 + String name_to_find //Column name to find in previous list
  653 + )=
  654 + if columns is
  655 + {
  656 + [] then failure,
  657 + [h . t] then
  658 + since h is db_column(name, _, _, _),
  659 + if name_to_find = name then
  660 + success(h)
  661 + else
  662 + get_column_type(t, name_to_find)
  663 + }.
  664 +
  665 +public define String
  666 + to_cell_view
  667 + (
  668 + DB_Model_Column col,
  669 + String type_name
  670 + ) =
  671 + since col is db_column(name, col_type, _, _),
  672 + if col_type is
  673 + {
  674 + //anubis(_T) then "constant_byte_array(0,0)",
  675 + p_key then "link(to_String("+type_name+".id), to_String("+type_name+".id))",
  676 + //binary then "constant_byte_array(0,0)",
  677 + boolean_field then "text(to_String("+type_name+"."+name+"))",
  678 + date_field(attrs) then "text(to_String("+type_name+"."+name+"))",
  679 + time_field(attrs) then "text(to_String("+type_name+"."+name+"))",
  680 + datetime_field(attrs) then "text(to_String("+type_name+"."+name+"))"
  681 + foreign_key(foreign_table) then "text(get_"+foreign_table+"_show_string(db, "+type_name+"."+name+"))",
  682 + integer_field then "text(to_String("+type_name+"."+name+"))",
  683 + char_field(Int size) then "text("+type_name+"."+name+")",
  684 + text_field then "text("+type_name+"."+name+")"
  685 + }.
  686 +
  687 +public define String
  688 + to_cell_view
  689 + (
  690 + List(DB_Model_Column) columns,
  691 + String column_name,
  692 + String data_name
  693 + )=
  694 + if get_column_type(columns, column_name) is
  695 + {
  696 + failure then "column name "+column_name+"doesn't exist",
  697 + success(column) then to_cell_view(column, data_name)
  698 + }.
  699 +
  700 +public define String
  701 + make_list_view_row
  702 + (
  703 + DB_Model model,
  704 + List(String) list_view,
  705 + String data_name,
  706 + String indent
  707 + )=
  708 + since model is db_model(columns, _),
  709 + indent+join(",\n"+indent, map((String column_name) |-> to_cell_view(columns, column_name, data_name), list_view)).
database/vtm/view_table_renderer.anubis
@@ -28,7 +28,20 @@ read calexium_lib/web/jQuery/ui-addon/datetimepicker.anubis @@ -28,7 +28,20 @@ read calexium_lib/web/jQuery/ui-addon/datetimepicker.anubis
28 read calexium_lib/web/CXM_form.anubis 28 read calexium_lib/web/CXM_form.anubis
29 read calexium_lib/web/widgets/css_helper.anubis 29 read calexium_lib/web/widgets/css_helper.anubis
30 30
31 - 31 +define CXM_Form_Field
  32 + help_line
  33 + (
  34 + DB_Help_Text help,
  35 + (String) -> String _T
  36 + )=
  37 + if help is
  38 + {
  39 + no_help_text then empty,
  40 + help_text_TAG(tag) then explain(_T(tag)),
  41 + help_text(str) then explain(str)
  42 + }.
  43 +
  44 +
32 //Edit table part 45 //Edit table part
33 public define List(CXM_Form_Field) 46 public define List(CXM_Form_Field)
34 edit_form_lines 47 edit_form_lines
@@ -47,27 +60,27 @@ public define List(CXM_Form_Field) @@ -47,27 +60,27 @@ public define List(CXM_Form_Field)
47 { 60 {
48 hidden(name, value) then 61 hidden(name, value) then
49 print("hidden "+name+" = "+value); 62 print("hidden "+name+" = "+value);
50 - hidden(htmlId(""), wan(name), init(value)), 63 + [hidden(htmlId(""), wan(name), init(value))],
51 primary_key(idx) then 64 primary_key(idx) then
52 - hidden(htmlId(""), wan("id"), init(idx)),  
53 - information(s_name, c_name, value) then  
54 - input_readonly(_T(s_name), wan(c_name), init(value), narrow),  
55 - text(s_name, c_name, value) then  
56 - input(_T(s_name), wan(c_name), init(value), narrow, mandatory), 65 + [hidden(htmlId(""), wan("id"), init(idx))],
  66 + information(s_name, c_name, value, help) then
  67 + [input_readonly(_T(s_name), wan(c_name), init(value), narrow), help_line(help)],
  68 + text(s_name, c_name, value, help) then
  69 + [input(_T(s_name), wan(c_name), init(value), narrow, mandatory), help_line(help)],
57 foreign_text(s_name, c_name, value, select) then 70 foreign_text(s_name, c_name, value, select) then
58 - selector_c([],_T(s_name), htmlId(""), wan(c_name), 1, select.get(db), success(init(to_String(value))), mandatory), 71 + [selector_c([],_T(s_name), htmlId(""), wan(c_name), 1, select.get(db), success(init(to_String(value))), mandatory)],
59 text_area(s_name, c_name, value) then 72 text_area(s_name, c_name, value) then
60 - text_area([],_T(s_name), htmlId(""), wan(c_name), init(value), narrow, (Int)5, mandatory), 73 + [text_area([],_T(s_name), htmlId(""), wan(c_name), init(value), narrow, (Int)5, mandatory)],
61 boolean(s_name, c_name, value) then 74 boolean(s_name, c_name, value) then
62 - checkboxr([],_T(s_name), htmlId(""), wan(c_name), wav(c_name),value, mandatory), 75 + [checkboxr([],_T(s_name), htmlId(""), wan(c_name), wav(c_name),value, mandatory)],
63 integer(s_name, c_name, value) then 76 integer(s_name, c_name, value) then
64 - input(_T(s_name), wan(c_name), init(abs_to_decimal(value)), small, mandatory) 77 + [input(_T(s_name), wan(c_name), init(abs_to_decimal(value)), small, mandatory)],
65 date(s_name, c_name, value) then 78 date(s_name, c_name, value) then
66 - input([class("datepicker")], _T(s_name), htmlId(c_name), wan(c_name), init(value), narrow, non_mandatory), 79 + [input([class("datepicker")], _T(s_name), htmlId(c_name), wan(c_name), init(value), narrow, non_mandatory)],
67 datetime(s_name, c_name, value) then 80 datetime(s_name, c_name, value) then
68 - input([class("datetimepicker")], _T(s_name), htmlId(c_name), wan(c_name), init(value), narrow, mandatory), 81 + [input([class("datetimepicker")], _T(s_name), htmlId(c_name), wan(c_name), init(value), narrow, mandatory)],
69 }, 82 },
70 - edit_form_lines(db, _T, t, [line . so_far]) 83 + edit_form_lines(db, _T, t, [line]+[ so_far])
71 }. 84 }.
72 85
73 public define HTML_Partial_Content 86 public define HTML_Partial_Content
database/vtm/view_table_types.anubis
@@ -6,15 +6,16 @@ @@ -6,15 +6,16 @@
6 */ 6 */
7 7
8 read calexium_lib/web/CXM_making_a_web_site.anubis 8 read calexium_lib/web/CXM_making_a_web_site.anubis
9 - 9 +read calexium_lib/database/model/db_model.anubis
  10 +
10 public type VT_edit_selector: 11 public type VT_edit_selector:
11 vt_edit_selector((SQLite3DataBase db) -> List((List(CoreAttrs), WebArgValue, String)) get). 12 vt_edit_selector((SQLite3DataBase db) -> List((List(CoreAttrs), WebArgValue, String)) get).
12 13
13 public type VT_edit_entry: 14 public type VT_edit_entry:
14 hidden(String name, String value), 15 hidden(String name, String value),
15 primary_key(String idx), 16 primary_key(String idx),
16 - information(String s_name, String c_name, String v_name), //s_name = show_name for translation, v_name = string to show  
17 - text(String s_name, String c_name, String value), //s_name = show_name for translation, c_name = table column name 17 + information(String s_name, String c_name, String v_name, DB_Help_Text help), //s_name = show_name for translation, v_name = string to show
  18 + text(String s_name, String c_name, String value, DB_Help_Text help), //s_name = show_name for translation, c_name = table column name
18 foreign_text(String s_name, String c_name, Int selected, VT_edit_selector selector), 19 foreign_text(String s_name, String c_name, Int selected, VT_edit_selector selector),
19 text_area(String s_name, String c_name, String value), //s_name = show_name for translate, c_name = table column name 20 text_area(String s_name, String c_name, String value), //s_name = show_name for translate, c_name = table column name
20 boolean(String s_name, String c_name, Bool value), 21 boolean(String s_name, String c_name, Bool value),