Commit e413a2e013eb09010af0dc7231e3f9069f02433e

Authored by Cédric RICARD
1 parent 87837894

Try to rehabilitate SQLITE using SQLAPI

calexium_lib/database/alter_table.anubis 0 → 100644
  1 +
  2 + *Project* Anubis
  3 +
  4 + *Title* SQLite Alter table function
  5 +
  6 + *Copyright* Copyright (c) Cédric Ricard 2007.
  7 +
  8 +
  9 +
  10 + *Author* Cédric Ricard
  11 +
  12 + *Created* 2007 02 17
  13 + *Satus* Released
  14 + *Compatibility* 1.7.10
  15 +
  16 +read tools/basis.anubis
  17 +read data_base/db_tools.anubis
  18 +read data_base/alter_table.anubis
  19 +read system/logger.anubis
  20 +read system/string.anubis
  21 +
  22 +
  23 +
  24 +public define Maybe(One)
  25 + alter_table
  26 + (
  27 + Database db,
  28 + String tableName,
  29 + String newTableQuery,
  30 + Logger log
  31 + ).
  32 +
  33 +
  34 +
  35 +
  36 +
  37 + --- That's all for the public part ! --------------------------------------------------
  38 +
  39 +define String
  40 + to_String
  41 + (
  42 + DbEntityType type
  43 + ) =
  44 + if type is
  45 + {
  46 + table then "table",
  47 + view then "view",
  48 + index then "index",
  49 + trigger then "trigger"
  50 + }.
  51 +
  52 +define One
  53 + print_list
  54 + (
  55 + List(String) l
  56 + ) =
  57 + if l is
  58 + {
  59 + [] then print(" <<<\n"),
  60 + [h . t] then print(h + ", "); print_list(t)
  61 + }.
  62 +
  63 +define Maybe(One)
  64 + my_sql_query
  65 + (
  66 + Database db,
  67 + String sql,
  68 + Logger log
  69 + ) =
  70 + if sql_query(db, sql) is
  71 + {
  72 + error(sql_error) then logError(log, "SQL ERROR: " + sql_error.text + "\n ...executing query [" + sql + "]"); failure,
  73 + ok(_,_,_) then success(unique)
  74 + }.
  75 +
  76 +define Maybe(String)
  77 + get_original_query
  78 + (
  79 + Database db,
  80 + String dbName, // alias for attached database, 'main' for main database.
  81 + DbEntityType object_type,
  82 + String tableName,
  83 + Logger log
  84 + ) =
  85 + if sql_query(db, "SELECT sql FROM " + dbName + ".sqlite_master where (type='"+to_String(object_type)+"') and tbl_name='" + tableName + "'") is
  86 + {
  87 + error(sql_error) then logError(log, "alter_table/get_original_query ERROR '" + sql_error.text + "'"); failure,
  88 + ok(_,table_cursor,_) then
  89 + if table_cursor(unique) is
  90 + {
  91 + error(sql_error) then logError(log, "alter_table/get_original_query ERROR '" + sql_error.text + "'"); failure,
  92 + no_more_row then failure, //can't find the table in sqlite_master, because the table is new
  93 + row(current) then success(text(current)(0))
  94 + }
  95 + }.
  96 +
  97 +define Bool
  98 + has_rows
  99 + (
  100 + Database db,
  101 + String tableName,
  102 + Logger log
  103 + ) =
  104 + if sql_query(db, "SELECT count(*) FROM " + tableName) is
  105 + {
  106 + error(sql_error) then logError(log, "has_rows query ERROR '" + sql_error.text + "'"); false,
  107 + ok(_,table_cursor,_) then
  108 + if table_cursor(unique) is
  109 + {
  110 + error(sql_error) then logError(log, "has_row run ERROR '" + sql_error.text + "'"); false,
  111 + no_more_row then false,
  112 + row(current) then db_integer(current)(0) /= 0
  113 + }
  114 + }.
  115 +
  116 +define List(String)
  117 + alter_table_extract_columns_list_sub
  118 + (
  119 + Int -> SQLite3Datum row,
  120 + Int colIndex
  121 + ) =
  122 + if row(colIndex) is text(name) then [name . alter_table_extract_columns_list_sub(row, colIndex+1)]
  123 + else [].
  124 +
  125 +define List(String)
  126 + alter_table_extract_columns_list
  127 + (
  128 + SQLite3HeadersOrRow -> SQLite3Row table_cursor,
  129 + Logger log
  130 + ) =
  131 + if table_cursor(headers) is
  132 + {
  133 + error(sql_error) then logError(log, "alter_table_extract_columns_list ERROR '" + sql_error.text + "'"); [],
  134 + no_more_row then [],
  135 + row(headers) then alter_table_extract_columns_list_sub(headers, 0)
  136 + }.
  137 +
  138 +define String
  139 + alter_table_extract_column_string
  140 + (
  141 + One -> DbRow table_cursor,
  142 + List(String) oldColumns,
  143 + Logger log
  144 + ) =
  145 + if table_cursor(unique) is
  146 + {
  147 + error(sql_error) then logError(log, "alter_table_extract_columns_list ERROR '" + sql_error.text + "'"); "",
  148 + no_more_row then /*logDebug(log, "Extract columns answers 'no more row'");*/ "",
  149 + row(row) then
  150 + if row(1) is db_text(name) then
  151 + with test = (String name2) |-> logDebug(log, "name: " + name + " / name2: " + name2); if name = name2 then true else false,
  152 + colString = alter_table_extract_column_string(table_cursor, oldColumns, log),
  153 + if find_element(oldColumns, test) is
  154 + {
  155 + failure then colString,
  156 + success(_) then logDebug(log, "found: " + name);
  157 + if is_empty(colString) then name else name + ", " + colString
  158 + }
  159 + else ""
  160 + }.
  161 +
  162 +// false = different, true = same
  163 +define Bool
  164 + compare_creation_queries
  165 + (
  166 + String tableName,
  167 + String query1,
  168 + String query2,
  169 + ) =
  170 + if find(tableName, query1, 0) is
  171 + {
  172 + failure then false,
  173 + success(p1) then
  174 + if find(tableName, query2, 0) is
  175 + {
  176 + failure then false,
  177 + success(p2) then
  178 + if sub_string(query1, p1, length(query1) - p1) is
  179 + {
  180 + failure then false,
  181 + success(s1) then
  182 + if sub_string(query2, p2, length(query2) - p2) is
  183 + {
  184 + failure then false,
  185 + success(s2) then s1 = s2
  186 + }
  187 + }
  188 + }
  189 + }.
  190 +
  191 +public define Maybe(One)
  192 + alter_table
  193 + (
  194 + Database db,
  195 + String dbName, // alias for attached database, 'main' for main database.
  196 + String tableName,
  197 + String newTableQuery,
  198 + Logger log
  199 + ) =
  200 + with fullTableName = dbName + "." + tableName,
  201 + if get_original_query(db, dbName, table, tableName, log) is
  202 + {
  203 + failure then
  204 + logInfo(log, "Creating table '" + fullTableName + "'... ");
  205 + if sql_query(db, newTableQuery) is error(sql_error)
  206 + then logError(log, "ERROR : " + sql_error.text); failure
  207 + else logInfo(log, " --> ok."); success(unique),
  208 + success(originalTableQuery) then
  209 + if compare_creation_queries(tableName, originalTableQuery, newTableQuery) = false then
  210 + logInfo(log, "Updating table '" + fullTableName + "' on database... ");
  211 + println(originalTableQuery);
  212 + println(newTableQuery);
  213 + if has_rows(db, fullTableName, log) is
  214 + {
  215 + false then
  216 + if my_sql_query(db, "DROP TABLE " + fullTableName, log) is failure
  217 + then failure
  218 + else if my_sql_query(db, newTableQuery, log ) is
  219 + {
  220 + failure then failure,
  221 + success(_) then logInfo(log, " --> ok."); success(unique)
  222 + },
  223 + true then
  224 + with tempNameTable = tableName + "_temp",
  225 + forget(sql_query(db, "DROP TABLE " + tempNameTable));
  226 + if my_sql_query(db, "CREATE TEMP TABLE " + tempNameTable + " AS SELECT * from " + fullTableName, log) is failure then failure else
  227 + if my_sql_query(db, "DROP TABLE " + fullTableName, log) is failure then failure else
  228 + if my_sql_query(db, newTableQuery , log) is failure then failure else
  229 + if sql_query(db, "SELECT * FROM " + tempNameTable) is
  230 + {
  231 + error(sql_error) then logError(log, "alter_table: select * tempTable ERROR '" + sql_error.text + "'"); failure,
  232 + ok(get_cols,table_cursor2,_) then
  233 + with oldColumns = get_cols(unique),
  234 + //print_list(oldColumns);
  235 + if sql_query(db, "PRAGMA " + dbName + ".table_info(" + tableName + ")") is
  236 + {
  237 + error(sql_error) then logError(log, "alter_table: pragma table_info() ERROR '" + sql_error.text + "'"); failure,
  238 + ok(_,table_cursor3,_) then
  239 + with newColumnsStr = alter_table_extract_column_string(table_cursor3, oldColumns, log),
  240 + sql = "INSERT INTO " + fullTableName + " (" + newColumnsStr + ") SELECT " + newColumnsStr + " FROM " + tempNameTable,
  241 + if sql_query(db, sql) is
  242 + {
  243 + error(sql_error) then logError(log, "alter_table ERROR '" + sql_error.text + "'\n\tquery = [" + sql + "]"); failure,
  244 + ok(_,_,_) then logInfo(log, " --> ok."); success(unique)
  245 + }
  246 + }
  247 + }
  248 + }
  249 + else
  250 + success(unique)
  251 + }.
  252 +
  253 +public define Maybe(One)
  254 + alter_table
  255 + (
  256 + Database db,
  257 + String tableName,
  258 + String newTableQuery,
  259 + Logger log
  260 + ) =
  261 + alter_table(db, "main", tableName, newTableQuery, log).
  262 +
  263 +
  264 +public define Maybe(One)
  265 + alter_view
  266 + (
  267 + Database db,
  268 + String dbName, // alias for attached database, 'main' for main database.
  269 + String viewName,
  270 + String newViewQuery,
  271 + Logger log
  272 + ) =
  273 + with fullViewName = dbName + "." + viewName,
  274 + if get_original_query(db, dbName, view, viewName, log) is
  275 + {
  276 + failure then
  277 + logInfo(log, "Creating view '" + fullViewName + "'... ");
  278 + if sql_query(db, newViewQuery) is error(sql_error)
  279 + then logError(log, "ERROR : " + sql_error.text); failure
  280 + else logInfo(log, " --> ok."); success(unique),
  281 + success(originalViewQuery) then
  282 + if compare_creation_queries(viewName, originalViewQuery, newViewQuery) = false then
  283 + logInfo(log, "Updating view '" + fullViewName + "' on database... ");
  284 + println(originalViewQuery);
  285 + println(newViewQuery);
  286 + if my_sql_query(db, "DROP VIEW " + fullViewName, log) is failure
  287 + then failure
  288 + else if my_sql_query(db, newViewQuery, log ) is
  289 + {
  290 + failure then failure,
  291 + success(_) then logInfo(log, " --> ok."); success(unique)
  292 + }
  293 + else
  294 + success(unique)
  295 + }.
  296 +
  297 +public define Maybe(One)
  298 + alter_view
  299 + (
  300 + Database db,
  301 + String viewName,
  302 + String newViewQuery,
  303 + Logger log
  304 + ) =
  305 + alter_view(db, "main", viewName, newViewQuery, log).
  306 +
calexium_lib/database/migration.anubis
@@ -10,10 +10,10 @@ read tools/basis.anubis @@ -10,10 +10,10 @@ read tools/basis.anubis
10 read system/files.anubis 10 read system/files.anubis
11 read system/logger.anubis 11 read system/logger.anubis
12 read system/string.anubis 12 read system/string.anubis
13 -read data_base/alter_table.anubis  
14 read data_base/db_tools.anubis 13 read data_base/db_tools.anubis
15 14
16 read calexium_lib/database/db_utils.anubis 15 read calexium_lib/database/db_utils.anubis
  16 +read calexium_lib/database/alter_table.anubis
17 read calexium_lib/net_services_protocols/logger_service.anubis 17 read calexium_lib/net_services_protocols/logger_service.anubis
18 18
19 read mf_constants.anubis 19 read mf_constants.anubis
@@ -60,14 +60,6 @@ public define Int @@ -60,14 +60,6 @@ public define Int
60 }, 60 },
61 compare(split(version1, '.'), split(version2, '.')). 61 compare(split(version1, '.'), split(version2, '.')).
62 62
63 -public define One  
64 - update_version_settings  
65 - (  
66 - Database db,  
67 - String version  
68 - )=  
69 - update_settings(db, "MF_version", version).  
70 -  
71 public define Maybe(One) 63 public define Maybe(One)
72 backup_database 64 backup_database
73 ( 65 (
@@ -88,7 +80,7 @@ public define Maybe(One) @@ -88,7 +80,7 @@ public define Maybe(One)
88 // } 80 // }
89 // else false, 81 // else false,
90 82
91 - if should_copy then 83 + //if should_copy then
92 with dir_save = db_path + dir_save_database, 84 with dir_save = db_path + dir_save_database,
93 if (Maybe(String))make_directory(dir_save) is 85 if (Maybe(String))make_directory(dir_save) is
94 { 86 {
@@ -119,7 +111,7 @@ public define Maybe(One) @@ -119,7 +111,7 @@ public define Maybe(One)
119 }, 111 },
120 copy_db([main_db_name . other_db_names]) 112 copy_db([main_db_name . other_db_names])
121 } 113 }
122 - else success(unique) 114 + //else success(unique)
123 . 115 .
124 116
125 117
@@ -144,7 +136,8 @@ define Maybe(One) @@ -144,7 +136,8 @@ define Maybe(One)
144 String current_version, 136 String current_version,
145 String db_ver, 137 String db_ver,
146 List(Migration) migrations, 138 List(Migration) migrations,
147 - Maybe(Migration) need_to_create_table // success in case of new DB or when no migration have been done 139 + Maybe(Migration) need_to_create_table, // success in case of new DB or when no migration have been done
  140 + (Database, String) -> One update_db_version,
148 ) = 141 ) =
149 if migrations is 142 if migrations is
150 { 143 {
@@ -152,13 +145,13 @@ define Maybe(One) @@ -152,13 +145,13 @@ define Maybe(One)
152 if need_to_create_table is 145 if need_to_create_table is
153 { 146 {
154 failure then 147 failure then
155 - update_version_settings(db, current_version); 148 + update_db_version(db, current_version);
156 success(unique), 149 success(unique),
157 success(last) then 150 success(last) then
158 if last is migration(_, _, create_tables, create_indexes) then 151 if last is migration(_, _, create_tables, create_indexes) then
159 if create_tables(db, logger) is success(_) then 152 if create_tables(db, logger) is success(_) then
160 if create_indexes(db, logger) is success(_) then 153 if create_indexes(db, logger) is success(_) then
161 - update_version_settings(db, current_version); 154 + update_db_version(db, current_version);
162 success(unique) 155 success(unique)
163 else 156 else
164 failure 157 failure
@@ -172,9 +165,9 @@ define Maybe(One) @@ -172,9 +165,9 @@ define Maybe(One)
172 if migrate_to(db, logger) is failure then 165 if migrate_to(db, logger) is failure then
173 failure 166 failure
174 else 167 else
175 - do_migration_loop(db, logger, current_version, version, t, failure) 168 + do_migration_loop(db, logger, current_version, version, t, failure, update_db_version)
176 else 169 else
177 - do_migration_loop(db, logger, current_version, db_ver, t, success(h)), 170 + do_migration_loop(db, logger, current_version, db_ver, t, success(h), update_db_version),
178 }. 171 }.
179 172
180 173
@@ -185,17 +178,17 @@ public define Maybe(One) @@ -185,17 +178,17 @@ public define Maybe(One)
185 Database db, 178 Database db,
186 Logger logger, 179 Logger logger,
187 String current_version, 180 String current_version,
188 - (Database) |-> String get_db_version,  
189 - (Database, String) |-> One update_db_version, 181 + (Database) -> String get_db_version,
  182 + (Database, String) -> One update_db_version,
190 List(Migration) all_migrations, 183 List(Migration) all_migrations,
191 )= 184 )=
192 if is_empty_database(db) then // new empty database 185 if is_empty_database(db) then // new empty database
193 logInfo(logger, "No database found. Creating a new one..."); 186 logInfo(logger, "No database found. Creating a new one...");
194 - do_migration_loop(db, logger, current_version, "", [], last(all_migrations)) 187 + do_migration_loop(db, logger, current_version, "", [], last(all_migrations), update_db_version)
195 else 188 else
196 ( 189 (
197 - with db_version = get_version_settings(db),  
198 - do_migration_loop(db, logger, current_version, db_version, all_migrations, failure) 190 + with db_version = get_db_version(db),
  191 + do_migration_loop(db, logger, current_version, db_version, all_migrations, failure, update_db_version)
199 ). 192 ).
200 193
201 public define Maybe(One) 194 public define Maybe(One)
calexium_lib/database/migration_common.anubis
@@ -9,8 +9,8 @@ @@ -9,8 +9,8 @@
9 read tools/basis.anubis 9 read tools/basis.anubis
10 read system/logger.anubis 10 read system/logger.anubis
11 read data_base/db_tools.anubis 11 read data_base/db_tools.anubis
12 -read data_base/alter_table.anubis  
13 -read data_base/sqlite_foreign_key.anubis 12 +read alter_table.anubis
  13 +read sqlite_foreign_key.anubis
14 14
15 read calexium_lib/database/db_utils.anubis 15 read calexium_lib/database/db_utils.anubis
16 read calexium_lib/net_services_protocols/logger_service.anubis 16 read calexium_lib/net_services_protocols/logger_service.anubis
@@ -31,7 +31,7 @@ public define Bool @@ -31,7 +31,7 @@ public define Bool
31 String dbName, 31 String dbName,
32 String table_name 32 String table_name
33 )= 33 )=
34 - if sql_query_timeout(db, "SELECT * FROM " + dbName + ".sqlite_master WHERE type ='table' AND name = @table_name", [bind_String("@table_name", table_name)], "is_table_exists("+table_name+")") is 34 + if sql_query_timeout(db, "SELECT * FROM " + dbName + ".sqlite_master WHERE type ='table' AND name = :table_name", [db_bind("table_name", db_text(table_name))], "is_table_exists("+table_name+")") is
35 { 35 {
36 error(_) then false, //error in the SQL request 36 error(_) then false, //error in the SQL request
37 ok(_, cursor, _) then 37 ok(_, cursor, _) then
calexium_lib/database/sqlite_foreign_key.anubis 0 → 100644
  1 +
  2 + *Project* Anubis
  3 +
  4 + *Title* SQLite Foreign Key functions
  5 +
  6 + *Copyright* Copyright (c) Cédric Ricard 2007.
  7 +
  8 +
  9 +
  10 + *Author* Cédric Ricard
  11 +
  12 + *Created* 2007 12 21
  13 + *Satus* Released
  14 + *Compatibility* 1.8.4
  15 +
  16 +read tools/basis.anubis
  17 +read data_base/sqlite.anubis
  18 +read data_base/db_tools.anubis
  19 +read system/logger.anubis
  20 +
  21 +
  22 +
  23 +define Maybe(One)
  24 + my_sql_query
  25 + (
  26 + Database db,
  27 + String sql,
  28 + Logger log
  29 + ) =
  30 + if sql_query(db, sql) is
  31 + {
  32 + error(sql_error) then logError(log, "SQL ERROR: " + sql_error.text + "\n ...executing query [" + sql + "]"); failure,
  33 + ok(_,_,_) then success(unique)
  34 + }.
  35 +
  36 +public define Maybe(One)
  37 + alter_trigger
  38 + (
  39 + Database db,
  40 + String trigger_name,
  41 + String sql,
  42 + Logger log
  43 + ) =
  44 + if sql_query(db, "SELECT sql FROM sqlite_master WHERE type = 'trigger' AND name = " + db_make_sql_string(trigger_name)) is
  45 + {
  46 + error(sql_error) then logError(log, "SQL ERROR: " + sql_error.text + "\n ...looking for trigger named [" + trigger_name + "]"); failure,
  47 + ok(_,cursor,_) then
  48 + if cursor(unique) is
  49 + {
  50 + error(sql_error) then logError(log, "alter_trigger ERROR '" + sql_error.text + "'"); failure,
  51 + no_more_row then my_sql_query(db, sql, log),
  52 + row(current) then
  53 + with old_sql = text(current)(0),
  54 + if old_sql /= sql then
  55 + logDebug(log, "Old trigger was:\n" + old_sql + "\n");
  56 + logDebug(log, "New trigger is:\n" + sql + "\n");
  57 + logInfo(log, "Updating trigger '" + trigger_name + "'...");
  58 + forget(my_sql_query(db, "DROP TRIGGER [" + trigger_name + "]", log));
  59 + if my_sql_query(db, sql, log) is success(_) then logInfo (log, " --> ok."); success(unique)
  60 + else logError(log, " --> error!"); failure
  61 + else
  62 + success(unique)
  63 + }
  64 + }.
  65 +
  66 +
  67 +public type FK_Null:
  68 + null,
  69 + not_null.
  70 +
  71 +public type FK_Cascade:
  72 + delete_in_cascade,
  73 + block_if_children.
  74 +
  75 +public define Maybe(One)
  76 + make_foreign_key
  77 + (
  78 + Database db,
  79 + String table_name,
  80 + String field_name,
  81 + String foreign_table_name,
  82 + String foreign_field_name,
  83 + FK_Null fk_null,
  84 + FK_Cascade fk_cascade,
  85 + Logger log
  86 + ) =
  87 + with constrait_name = table_name + "__" + field_name + "__" + foreign_table_name,
  88 + sql_create =
  89 + "CREATE TRIGGER [fki__" + constrait_name + "] \n"
  90 + + "BEFORE INSERT ON [" + table_name + "] \n"
  91 + + "FOR EACH ROW BEGIN \n"
  92 + + " SELECT RAISE(ROLLBACK, 'insert on table \"" + table_name + "\" violates foreign key constraint \"fki__" + constrait_name + "\"') \n"
  93 + + " WHERE " + (if fk_null is null then " NEW.[" + field_name + "] IS NOT NULL AND \n" else "\n")
  94 + + " (SELECT [" + foreign_field_name + "] FROM [" + foreign_table_name + "] WHERE [" + foreign_field_name + "] = NEW.[" + field_name + "]) IS NULL; \n"
  95 + + "END",
  96 + sql_update =
  97 + "CREATE TRIGGER [fku__" + constrait_name + "] \n"
  98 + + "BEFORE UPDATE ON [" + table_name + "] \n"
  99 + + "FOR EACH ROW BEGIN \n"
  100 + + " SELECT RAISE(ROLLBACK, 'update on table \"" + table_name + "\" violates foreign key constraint \"fku__" + constrait_name + "\"') \n"
  101 + + " WHERE " + (if fk_null is null then " NEW.[" + field_name + "] IS NOT NULL AND \n" else "\n")
  102 + + " (SELECT [" + foreign_field_name + "] FROM [" + foreign_table_name + "] WHERE [" + foreign_field_name + "] = NEW.[" + field_name + "]) IS NULL; \n"
  103 + + "END",
  104 + sql_delete =
  105 + "CREATE TRIGGER [fkd__" + constrait_name + "] \n"
  106 + + "BEFORE DELETE ON [" + foreign_table_name + "] \n"
  107 + + "FOR EACH ROW BEGIN \n"
  108 + + if fk_cascade is {
  109 + delete_in_cascade then
  110 + " DELETE from [" + table_name + "] WHERE [" + field_name + "] = OLD.[" + foreign_field_name + "];\n",
  111 + block_if_children then
  112 + " SELECT RAISE(ROLLBACK, 'delete on table \"" + foreign_table_name + "\" violates foreign key constraint \"fku__" + constrait_name + "\"') \n"
  113 + + " WHERE (SELECT [" + field_name + "] FROM [" + table_name + "] WHERE [" + field_name + "] = OLD.[" + foreign_field_name + "]) IS NOT NULL; \n"
  114 + }
  115 + + "END",
  116 + if alter_trigger(db, "fki__" + constrait_name, sql_create, log) is failure
  117 + then failure
  118 + else if alter_trigger(db, "fku__" + constrait_name, sql_update, log) is failure
  119 + then failure
  120 + else if alter_trigger(db, "fkd__" + constrait_name, sql_delete, log) is failure
  121 + then failure
  122 + else
  123 + success(unique).
  124 +
  125 +
  126 +
  127 +public define Maybe(One)
  128 + make_foreign_key
  129 + (
  130 + Database db,
  131 + String table_name,
  132 + String field_name,
  133 + String foreign_table_name,
  134 + String foreign_field_name,
  135 + Bool field_can_be_null,
  136 + Bool delete, //delete_in_cascade ?
  137 + Logger log
  138 + ) =
  139 + make_foreign_key
  140 + (
  141 + db,
  142 + table_name,
  143 + field_name,
  144 + foreign_table_name,
  145 + foreign_field_name,
  146 + if field_can_be_null then null else not_null,
  147 + if delete then delete_in_cascade else block_if_children,
  148 + log
  149 + ).