/* * Created by PyramIDE. * User: フランスのトトロ * Date: 01/01/2016 * Time: 1:34 * © David RENÉ */ The HayamiKi (早見木) project Interfacing, generating and controling a database with Anubis Author: David René In order to generate such tools, DB_Model needs a formal description of the database. *** (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) 'HK_Model_Attr' (attributes of columns). Possible attributes of columns: (each column has a list of such attributes) Of course, 'NOT NULL' is not an alternative of 'HK_Model_Attr' because it is already coded into the database type itself (type 'HK_Model_Field' above). *** (3.7) 'DB_Model_Table' (describing a table). Description of a table: Description of a whole database: // list of all tables in the database //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 read xlib/web/widgets/icons_set.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(HK_Model_Column) columns, List(HK_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(HK_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 ( HK_Model_Column tab ) = if tab is table(_,_,cols) then mapor((HK_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: