facebookincubator / CG-SQL

CG/SQL is a compiler that converts a SQL Stored Procedure like language into C for SQLite. SQLite has no stored procedures of its own. CG/CQL can also generate other useful artifacts for testing and schema maintenance.
https://cgsql.dev/
MIT License
391 stars 34 forks source link

CG-SQL-Lua online playground #164

Open mingodad opened 1 year ago

mingodad commented 1 year ago

I've just created the first draft of an online playground for CG-SQL with Lua runtime at https://mingodad.github.io/CG-SQL-Lua-playground/ .

The repository is at https://github.com/mingodad/CG-SQL-Lua-playground .

Any feedback is welcome !

mingodad commented 1 year ago

Testing the online playground I'm copying and pasting from the documentation and found this example https://cgsql.dev/cql-guide/ch10/#using-regions with an error:

--- <unnamed>
+++ <unnamed>
@@ -16,7 +16,7 @@
    details text
 );

-create proc get_detail(integer id_)
+create proc get_detail(id_ integer)
 begin
   select T1.id, T1.details, T2.name from details T1
   inner join main T2 on T1.id = T2.id
@@ -32,7 +32,7 @@
    f1_info text
 );

-create proc get_detail(integer id_)
+create proc get_detail(id_ integer)
 begin
   select T1.id, T1.details, T2.name, f1_info from details T1
   inner join f T2 on T1.id = T2.id
ricomariani commented 1 year ago

This is super cool :D

mingodad commented 1 year ago

With this changes to check a 32bits build on a multilib Linux (because wasm is 32bits and I'm getting a nasty bug) :

------------------------ sources/common/Makefile_common ------------------------
index a9dcf6ff3..447da662a 100644
@@ -23,8 +23,8 @@ endif
 SQLITE_LINK+=-pthread -ldl
 CFLAGS+=-I$(CQL_DIR)
 CFLAGS+=-I$O
-CFLAGS+=-g
-CFLAGS+=-Werror
+CFLAGS+=-g -m32
+CFLAGS+=-Wall #-Werror

 ifdef CGSQL_GCC
 CFLAGS += -std=c99

There is this warnings:

...
In file included from cql.h:38,
                 from ast.h:12,
                 from cg_common.h:10,
                 from sem.c:26:
sem.c: In function ‘sem_validate_object_ast_in_current_region’:
sem.c:1710:23: warning: suggest parentheses around ‘&&’ within ‘||’ [-Wparentheses]
 1710 |   Contract(err_target && msg || !err_target && !msg);
      |            ~~~~~~~~~~~^~~~~~
sem.c:1710:3: note: in expansion of macro ‘Contract’
 1710 |   Contract(err_target && msg || !err_target && !msg);
      |   ^~~~~~~~
sem.c:1710:23: warning: suggest parentheses around ‘&&’ within ‘||’ [-Wparentheses]
 1710 |   Contract(err_target && msg || !err_target && !msg);
      |            ~~~~~~~~~~~^~~~~~
sem.c:1710:3: note: in expansion of macro ‘Contract’
 1710 |   Contract(err_target && msg || !err_target && !msg);
      |   ^~~~~~~~
sem.c: In function ‘find_usable_table_or_view_even_deleted’:
sem.c:1763:23: warning: suggest parentheses around ‘&&’ within ‘||’ [-Wparentheses]
 1763 |   Contract(err_target && msg || !err_target && !msg);
      |            ~~~~~~~~~~~^~~~~~
sem.c:1763:3: note: in expansion of macro ‘Contract’
 1763 |   Contract(err_target && msg || !err_target && !msg);
      |   ^~~~~~~~
sem.c:1763:23: warning: suggest parentheses around ‘&&’ within ‘||’ [-Wparentheses]
 1763 |   Contract(err_target && msg || !err_target && !msg);
      |            ~~~~~~~~~~~^~~~~~
sem.c:1763:3: note: in expansion of macro ‘Contract’
 1763 |   Contract(err_target && msg || !err_target && !msg);
      |   ^~~~~~~~
sem.c: In function ‘find_usable_and_not_deleted_table_or_view’:
sem.c:1784:23: warning: suggest parentheses around ‘&&’ within ‘||’ [-Wparentheses]
 1784 |   Contract(err_target && msg || !err_target && !msg);
      |            ~~~~~~~~~~~^~~~~~
sem.c:1784:3: note: in expansion of macro ‘Contract’
 1784 |   Contract(err_target && msg || !err_target && !msg);
      |   ^~~~~~~~
sem.c:1784:23: warning: suggest parentheses around ‘&&’ within ‘||’ [-Wparentheses]
 1784 |   Contract(err_target && msg || !err_target && !msg);
      |            ~~~~~~~~~~~^~~~~~
sem.c:1784:3: note: in expansion of macro ‘Contract’
 1784 |   Contract(err_target && msg || !err_target && !msg);
      |   ^~~~~~~~
sem.c: In function ‘sem_select_expr_list_con’:
sem.c:10925:25: warning: suggest parentheses around ‘&&’ within ‘||’ [-Wparentheses]
10925 |     Invariant(from_jptr && query_parts || !from_jptr && !query_parts);
      |               ~~~~~~~~~~^~~~~~~~~~~~~~
sem.c:10925:5: note: in expansion of macro ‘Invariant’
10925 |     Invariant(from_jptr && query_parts || !from_jptr && !query_parts);
      |     ^~~~~~~~~
sem.c:10925:25: warning: suggest parentheses around ‘&&’ within ‘||’ [-Wparentheses]
10925 |     Invariant(from_jptr && query_parts || !from_jptr && !query_parts);
      |               ~~~~~~~~~~^~~~~~~~~~~~~~
sem.c:10925:5: note: in expansion of macro ‘Invariant’
10925 |     Invariant(from_jptr && query_parts || !from_jptr && !query_parts);
      |     ^~~~~~~~~
sem.c: In function ‘sem_validate_one_interface’:
sem.c:19190:44: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
19190 |     symtab_add(names, proc_sptr->names[i], (void *)(uint64_t)i);
      |                                            ^
sem.c:19206:28: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
19206 |     uint32_t j = (uint32_t)(uint64_t)entry->val;
      |                            ^
In file included from cql.h:38,
                 from ast.h:12,
                 from cg_common.h:10,
                 from sem.c:26:
sem.c: In function ‘sem_declare_cursor_for_expr’:
sem.c:20923:12: warning: the address of ‘is_ast_declare_cursor’ will always evaluate as ‘true’ [-Waddress]
20923 |   Contract(is_ast_declare_cursor);
      |            ^~~~~~~~~~~~~~~~~~~~~
sem.c:20923:3: note: in expansion of macro ‘Contract’
20923 |   Contract(is_ast_declare_cursor);
      |   ^~~~~~~~
sem.c: At top level:
sem.c:22696:1: warning: multi-line comment [-Wcomment]
22696 | //   #define LOGGING_PROC_BEGIN \
      | ^
sem.c:22702:1: warning: multi-line comment [-Wcomment]
22702 | //   #define LOGGING_PROC_END \
      | ^
...
cg_c.c: In function ‘cg_result_set_type_decl’:
cg_c.c:442:34: warning: value computed is not used [-Wunused-value]
  442 |   rt->result_set_type_decl_extra && rt->result_set_type_decl_extra(output, sym, ref);
      |                                  ^~
cg_c.c: In function ‘cg_intern_piece’:
cg_c.c:4406:21: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
 4406 |     return (int32_t)(int64_t)(entry->val);
      |                     ^
cg_c.c: In function ‘cg_proc_result_set’:
cg_c.c:7941:26: warning: value computed is not used [-Wunused-value]
 7941 |   rt->register_proc_name && rt->register_proc_name(name);
      |                          ^~
...
cg_schema.c: In function ‘topological_walk_recreate_group_deps_helper’:
cg_schema.c:1521:59: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
 1521 |     int32_t neighbor_ordinal = neighbor_entry ? (int32_t) (int64_t) (neighbor_entry->val) : -1;
      |                                                           ^
cg_schema.c:1527:16: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
 1527 |   entry->val = (void*) (int64_t) (max_group_ordinal++);
      |                ^
cg_schema.c: In function ‘topological_walk_recreate_group_deps’:
cg_schema.c:1547:34: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
 1547 |       int32_t ordinal = (int32_t)(int64_t)(entry.val);
      |                                  ^
cg_schema.c:1567:50: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
 1567 |       symtab_add(recreate_group_ordinals, gname, (void*)(int64_t)max_group_ordinal++);
      |                                                  ^
cg_schema.c:1570:48: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
 1570 |       (*recreates)[i].group_ordinal = (int32_t)(int64_t)entry->val;
      |                                                ^
...
cg_stats.c: In function ‘cg_stats_create_proc_stmt’:
cg_stats.c:71:69: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
   71 |     bprintf(stats_output, "\"%s\",\"%s\",%lld\n", name, entry->sym, (llint_t)entry->val);
      |                                                                     ^
...
cg_lua.c: In function ‘cg_lua_proc_result_set’:
cg_lua.c:4988:26: warning: value computed is not used [-Wunused-value]
 4988 |   rt->register_proc_name && rt->register_proc_name(name);
      |                          ^~
cc -DSQLITE_DEBUG -I./ -Iout -g -m32 -Wall  -o out/cql out/cql.y.o out/cql.o out/ast.o out/gen_sql.o out/sem.o out/list.o out/bytebuf.o out/charbuf.o out/cg_common.o out/cg_c.o out/cg_java.o out/cg_objc.o out/symtab.o out/compat.o out/cg_schema.o out/crc64xz.o out/sha256.o out/cg_json_schema.o out/cg_test_helpers.o out/encoders.o out/unit_tests.o out/cg_query_plan.o out/minipool.o out/cg_udf.o out/rt.o out/eval.o out/rewrite.o out/printf.o out/flow.o out/cg_stats.o out/cg_lua.o 
...
In file included from cqlrt.c:400:
cqlrt_common.c:1254:53: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
 1254 |           *prc = sqlite3_bind_int64(*pstmt, column, (int64_t)obj_ref);
      |                                                     ^
...
In file included from cqlrt.c:400:
cqlrt_common.c:1318:53: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
 1318 |           *prc = sqlite3_bind_int64(*pstmt, column, (int64_t)nullable_obj_ref);
      |                                                     ^
In file included from cqlrt.c:400:
cqlrt_common.c: In function ‘cql_key_retain_str’:
cqlrt_common.c:2676:16: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
 2676 |     cql_retain((cql_type_ref)(key));
      |                ^
cqlrt_common.c: In function ‘cql_key_release_str’:
cqlrt_common.c:2682:17: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
 2682 |     cql_release((cql_type_ref)(key));
      |                 ^
cqlrt_common.c: In function ‘cql_key_str_hash’:
cqlrt_common.c:2687:26: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
 2687 |   return cql_string_hash((cql_string_ref)key);
      |                          ^
cqlrt_common.c: In function ‘cql_key_str_eq’:
cqlrt_common.c:2691:27: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
 2691 |   return cql_string_equal((cql_string_ref)key1, (cql_string_ref)key2);
      |                           ^
cqlrt_common.c:2691:49: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
 2691 |   return cql_string_equal((cql_string_ref)key1, (cql_string_ref)key2);
      |                                                 ^
cqlrt_common.c: In function ‘cql_facet_add’:
cqlrt_common.c:2721:36: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
 2721 |     result = cql_hashtab_add(self, (cql_int64)name, crc);
      |                                    ^
cqlrt_common.c: In function ‘cql_facet_find’:
cqlrt_common.c:2731:57: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
 2731 |     cql_hashtab_entry *payload = cql_hashtab_find(self, (cql_int64)name);
      |                                                         ^
cqlrt_common.c: In function ‘cql_facet_upsert’:
cqlrt_common.c:2745:57: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
 2745 |     cql_hashtab_entry *payload = cql_hashtab_find(self, (cql_int64)name);
      |                                                         ^
cqlrt_common.c:2748:38: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
 2748 |       result = cql_hashtab_add(self, (cql_int64)name, crc);
      |                                      ^
...
In file included from cqlrt.c:400:
cqlrt_common.c: In function ‘cql_partition_key_release’:
cqlrt_common.c:3442:14: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
 3442 |   void *pv = (void *)key;
      |              ^
cqlrt_common.c: In function ‘cql_partition_val_release’:
cqlrt_common.c:3457:26: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
 3457 |     cql_object_ref obj = (cql_object_ref)(val & ~(cql_int64)1);
      |                          ^
cqlrt_common.c:3463:26: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
 3463 |   cql_bytebuf * buffer = (cql_bytebuf *)val;
      |                          ^
cqlrt_common.c: In function ‘cql_key_cursor_hash’:
cqlrt_common.c:3512:29: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
 3512 |   self->c_key.cursor_data = (void *)key;
      |                             ^
cqlrt_common.c: In function ‘cql_key_cursor_eq’:
cqlrt_common.c:3524:29: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
 3524 |   self->c_key.cursor_data = (void *)key1;
      |                             ^
cqlrt_common.c:3525:30: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
 3525 |   self->c_key2.cursor_data = (void *)key2;
      |                              ^
cqlrt_common.c: In function ‘cql_partition_cursor’:
cqlrt_common.c:3606:57: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
 3606 |   cql_hashtab_entry *entry = cql_hashtab_find(self->ht, (cql_int64)key->cursor_data);
      |                                                         ^
cqlrt_common.c:3611:11: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
 3611 |     buf = (cql_bytebuf *)entry->val;
      |           ^
cqlrt_common.c:3622:48: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
 3622 |     cql_bool added = cql_hashtab_add(self->ht, (cql_int64)k, (cql_int64)buf);
      |                                                ^
cqlrt_common.c:3622:62: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
 3622 |     cql_bool added = cql_hashtab_add(self->ht, (cql_int64)k, (cql_int64)buf);
      |                                                              ^
cqlrt_common.c: In function ‘cql_extract_partition’:
cqlrt_common.c:3655:59: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
 3655 |     cql_hashtab_entry *entry = cql_hashtab_find(self->ht, (cql_int64)key->cursor_data);
      |                                                           ^
cqlrt_common.c:3664:37: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
 3664 |         cql_object_ref result_set = (cql_object_ref)(entry->val & ~(cql_int64)1);
      |                                     ^
cqlrt_common.c:3670:13: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
 3670 |       buf = (cql_bytebuf *)entry->val;
      |             ^
cqlrt_common.c:3701:22: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
 3701 |       entry->val = 1|(cql_int64)result; // store the result but set the LSB so we know it's not a buffer
      |                      ^
...
In file included from cqlrt.c:400:
cqlrt_common.c: In function ‘cql_string_dictionary_add’:
cqlrt_common.c:3807:53: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
 3807 |   cql_hashtab_entry *entry = cql_hashtab_find(self, (cql_int64)key);
      |                                                     ^
In file included from cqlrt.c:8:
cqlrt_common.c:3811:24: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
 3811 |     cql_string_release((cql_string_ref)entry->val);
      |                        ^
cqlrt.h:108:62: note: in definition of macro ‘cql_string_release’
  108 | #define cql_string_release(string) cql_release((cql_type_ref)string);
      |                                                              ^~~~~~
In file included from cqlrt.c:400:
cqlrt_common.c:3812:18: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
 3812 |     entry->val = (cql_int64)val;
      |                  ^
cqlrt_common.c:3817:32: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
 3817 |   return cql_hashtab_add(self, (cql_int64)key, (cql_int64)val);
      |                                ^
cqlrt_common.c:3817:48: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
 3817 |   return cql_hashtab_add(self, (cql_int64)key, (cql_int64)val);
      |                                                ^
cqlrt_common.c: In function ‘cql_string_dictionary_find’:
cqlrt_common.c:3833:53: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
 3833 |   cql_hashtab_entry *entry = cql_hashtab_find(self, (cql_int64)key);
      |                                                     ^
cqlrt_common.c:3835:18: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
 3835 |   return entry ? (cql_string_ref)entry->val : NULL;
      |                  ^
...
mingodad commented 1 year ago

Building again for 64bits and doing the following tests with valgrind:

valgrind sources/out/cql --in schema.cql --rt schema --cg schema.sql0
==22885== Memcheck, a memory error detector
==22885== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==22885== Using Valgrind-3.17.0 and LibVEX; rerun with -h for copyright info
==22885== Command: sources/out/cql --in schema.cql --rt schema --cg schema.sql0
==22885== 
==22885== Conditional jump or move depends on uninitialised value(s)
==22885==    at 0x155A3C: sem_try_resolve_column (sem.c:5883)
==22885==    by 0x15693A: sem_resolve_id_with_type (sem.c:6230)
==22885==    by 0x156A44: sem_resolve_id (sem.c:6252)
==22885==    by 0x1571D7: sem_resolve_id_expr (sem.c:6423)
==22885==    by 0x18D03A: sem_expr_str (sem.c:23620)
==22885==    by 0x1631A8: sem_expr (sem.c:10061)
==22885==    by 0x163126: sem_root_expr (sem.c:10047)
==22885==    by 0x146854: sem_validate_index_expr_for_jptr (sem.c:693)
==22885==    by 0x1798EB: sem_name_check (sem.c:16951)
==22885==    by 0x14D2F0: sem_validate_name_list (sem.c:3191)
==22885==    by 0x14E10D: sem_create_index_stmt (sem.c:3416)
==22885==    by 0x18C796: sem_one_stmt (sem.c:23322)
==22885== 
==22885== 
==22885== HEAP SUMMARY:
==22885==     in use at exit: 17,074 bytes in 4 blocks
==22885==   total heap usage: 166 allocs, 162 frees, 190,405 bytes allocated
==22885== 
==22885== LEAK SUMMARY:
==22885==    definitely lost: 0 bytes in 0 blocks
==22885==    indirectly lost: 0 bytes in 0 blocks
==22885==      possibly lost: 0 bytes in 0 blocks
==22885==    still reachable: 17,074 bytes in 4 blocks
==22885==         suppressed: 0 bytes in 0 blocks
==22885== Rerun with --leak-check=full to see details of leaked memory
==22885== 
==22885== Use --track-origins=yes to see where uninitialised values come from
==22885== For lists of detected and suppressed errors, rerun with: -s
==22885== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

Here is schema.cql:

@attribute(an_attribute=(1,('foo', 'bar')))
CREATE TABLE foo(
  id INTEGER,
  name TEXT
);
create index foo_name on foo(name);

And here is the output schema.sql0:

-- @generated SignedSource<<deadbeef8badf00ddefec8edfacefeed>>

@ATTRIBUTE(an_attribute=(1, ('foo', 'bar')))
CREATE TABLE foo(
  id INTEGER,
  name TEXT
);

CREATE INDEX foo_name ON foo (name);

This change seems to fix this problem:

-------------------------------- sources/sem.c --------------------------------
index 2a4429339..fa3ea2d09 100644
@@ -2538,6 +2538,7 @@ static sem_struct * new_sem_struct(CSTR name, uint32_t count) {
   sptr->names = _ast_pool_new_array(CSTR, count);
   sptr->kinds = _ast_pool_new_array(CSTR, count);
   sptr->semtypes = _ast_pool_new_array(sem_t, count);
+  sptr->is_backed = false;

   for (int32_t i = 0; i < count; i++) {
     sptr->names[i] = NULL;
mingodad commented 1 year ago

Also when building for 32bits and adding -Wall -Wextra show several comparison unsigned/signed in for loops that seems not difficult to fix.

ricomariani commented 1 year ago

Pretty sure I've never built the compiler for 32 bits.

Get Outlook for Androidhttps://aka.ms/AAb9ysg


From: Domingo Alvarez Duarte @.> Sent: Saturday, December 17, 2022 2:43:11 AM To: facebookincubator/CG-SQL @.> Cc: Rico Mariani @.>; Comment @.> Subject: Re: [facebookincubator/CG-SQL] CG-SQL-Lua online playground (Issue #164)

Also when building for 32bits and adding -Wall -Wextra show several comparison unsigned/signed in for loops that seems not difficult to fix.

— Reply to this email directly, view it on GitHubhttps://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Ffacebookincubator%2FCG-SQL%2Fissues%2F164%23issuecomment-1356168798&data=05%7C01%7C%7C1f122c2d519545fc09eb08dae01b7f03%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C638068705959851568%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=qmv36rCdmw%2FlBU86ilQ02%2FIiuCZKu0iI4QGkDPTJ34Q%3D&reserved=0, or unsubscribehttps://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fnotifications%2Funsubscribe-auth%2FAHC3V7272F2OXE6Z57VGGYDWNWKL7ANCNFSM6AAAAAAS6PMXVM&data=05%7C01%7C%7C1f122c2d519545fc09eb08dae01b7f03%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C638068705959851568%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=VPIoz2aUxCO4tTXynOsdm2xt11%2BoDrT2Qo28FBBjdF8%3D&reserved=0. You are receiving this because you commented.Message ID: @.***>

mingodad commented 1 year ago

Also I just updated the online playground to also show C code and noticed that the @echo directive do not take in consideration if the selected runtime matches the one specified on the @echo line:

@echo lua, "function printf(...) io.write(cql_printf(...)) end\n";
@echo lua, "go(sqlite3.open_memory())\n";

Selecting the C runtime outputs:

function printf(...) io.write(cql_printf(...)) end
go(sqlite3.open_memory())

Obs.: My bad it does take in account the selected runtime.

mingodad commented 1 year ago

I've added more samples from sources/lua_demo and found a bug probably in emscripten the demo t6 fail in wasm due to a different number conversion: Output from native (clang15):

  print("testing code gen for min long and max long")
  min_l0 = (-9223372036854775807 - 1)  --!!!<<< notice here
  min_l1 = 0x8000000000000000
  min_l2 = 1 << 63
  min_l3 = (-9223372036854775807 - 1)
  max_l0 = 9223372036854775807
  max_l1 = 0x7fffffffffffffff
  max_l2 = ~ (1 << 63)
  max_l3 = 9223372036854775807

Output from wasm (clang15):

print("testing code gen for min long and max long")
  min_l0 = - 9223372036854775808  --!!!<<< notice here
  min_l1 = 0x8000000000000000
  min_l2 = 1 << 63
  min_l3 = (-9223372036854775807 - 1)
  max_l0 = 9223372036854775807
  max_l1 = 0x7fffffffffffffff
  max_l2 = ~ (1 << 63)
  max_l3 = 9223372036854775807
mingodad commented 1 year ago

It seems to be something with muslc I just build cql on an alpine64 vm:

Linux alpine.xxx 5.15.71-0-lts ...
gcc version 11.2.1 20220219 (Alpine 11.2.1...)

And here is the diff for the execution of cql --in t6.sql --rt lua --cg t6.lua:

--- /home/mingo/dev/dadbiz++/third-party/dad/CG-SQL0/sources/lua_demo/t6.lua
+++ /home/mingo/dev/dadbiz++/third-party/dad/CG-SQL0/sources/lua_demo/t6-alpine.lua
@@ -29,7 +29,7 @@
 CREATE PROC go ()
 BEGIN
   CALL print("testing code gen for min long and max long");
-  LET min_l0 := -9223372036854775808L;
+  LET min_l0 := -9223372036854775808;
   LET min_l1 := 0x8000000000000000L;
   LET min_l2 := 1L << 63;
   LET min_l3 := -9223372036854775808L;
@@ -47,8 +47,8 @@
   CALL expect(min_l1 + max_l0 = -1);
   CALL expect(min_l2 + max_l0 = -1);
   CALL expect(min_l3 + max_l0 = -1);
-  CALL expect(-9223372036854775808L + 9223372036854775807L = -1);
-  CALL expect(9223372036854775807L + -9223372036854775808L = -1);
+  CALL expect(-9223372036854775808 + 9223372036854775807L = -1);
+  CALL expect(9223372036854775807L + -9223372036854775808 = -1);
   CALL expect(0x7fffffffffffffffL + 0x8000000000000000L = -1);
   CALL expect(0x8000000000000000L + 0x7fffffffffffffffL = -1);
   DECLARE z REAL NOT NULL;
@@ -73,7 +73,7 @@
   local z = 0.0

   print("testing code gen for min long and max long")
-  min_l0 = (-9223372036854775807 - 1)
+  min_l0 = - 9223372036854775808
   min_l1 = 0x8000000000000000
   min_l2 = 1 << 63
   min_l3 = (-9223372036854775807 - 1)
@@ -91,8 +91,8 @@
   expect(min_l1 + max_l0 == - 1)
   expect(min_l2 + max_l0 == - 1)
   expect(min_l3 + max_l0 == - 1)
-  expect((-9223372036854775807 - 1) + 9223372036854775807 == - 1)
-  expect(9223372036854775807 + (-9223372036854775807 - 1) == - 1)
+  expect(- 9223372036854775808 + 9223372036854775807 == - 1)
+  expect(9223372036854775807 + - 9223372036854775808 == - 1)
   expect(0x7fffffffffffffff + 0x8000000000000000 == - 1)
   expect(0x8000000000000000 + 0x7fffffffffffffff == - 1)
   z = cql_to_float(9223372036854775807)
mingodad commented 1 year ago

I did a change on cql.l to see what's happening:

{d}+                         { char *s = Strdup(yytext); yylval.sval = s; printf("%s : %lld : %d : %d\n", s, atoll(s), 0x7fffffff, atoll(s) <= 0x7fffffff); return atoll(s) <= 0x7fffffff ? INTLIT: LONGLIT; }

Executing cql --in t6.sql --rt lua --cg t6.lua. And here is the output on alpine linux (muslc):

9223372036854775808 : -9223372036854775808 : 2147483647 : 1
63 : 63 : 2147483647 : 1
63 : 63 : 2147483647 : 1
9223372036854775807 : 9223372036854775807 : 2147483647 : 0
63 : 63 : 2147483647 : 1
63 : 63 : 2147483647 : 1
1 : 1 : 2147483647 : 1
1 : 1 : 2147483647 : 1
1 : 1 : 2147483647 : 1
1 : 1 : 2147483647 : 1
9223372036854775808 : -9223372036854775808 : 2147483647 : 1
9223372036854775807 : 9223372036854775807 : 2147483647 : 0
1 : 1 : 2147483647 : 1
9223372036854775807 : 9223372036854775807 : 2147483647 : 0
9223372036854775808 : -9223372036854775808 : 2147483647 : 1
1 : 1 : 2147483647 : 1
1 : 1 : 2147483647 : 1
1 : 1 : 2147483647 : 1
9223372036854775807 : 9223372036854775807 : 2147483647 : 0
1 : 1 : 2147483647 : 1
1 : 1 : 2147483647 : 1

And here the output on Ubuntu 18.04:

9223372036854775808 : 9223372036854775807 : 2147483647 : 0
63 : 63 : 2147483647 : 1
63 : 63 : 2147483647 : 1
9223372036854775807 : 9223372036854775807 : 2147483647 : 0
63 : 63 : 2147483647 : 1
63 : 63 : 2147483647 : 1
1 : 1 : 2147483647 : 1
1 : 1 : 2147483647 : 1
1 : 1 : 2147483647 : 1
1 : 1 : 2147483647 : 1
9223372036854775808 : 9223372036854775807 : 2147483647 : 0
9223372036854775807 : 9223372036854775807 : 2147483647 : 0
1 : 1 : 2147483647 : 1
9223372036854775807 : 9223372036854775807 : 2147483647 : 0
9223372036854775808 : 9223372036854775807 : 2147483647 : 0
1 : 1 : 2147483647 : 1
1 : 1 : 2147483647 : 1
1 : 1 : 2147483647 : 1
9223372036854775807 : 9223372036854775807 : 2147483647 : 0
1 : 1 : 2147483647 : 1
1 : 1 : 2147483647 : 1
mingodad commented 1 year ago

It seems that the problem is with atoll on musl testing with this program:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    const char *s = "9223372036854775808";
    long  long ll = atoll(s);
    long long ll2 = strtoll (s, (char **) NULL, 10);
    int imax = 0x7fffffff;
    printf("%s : %lld : %lld : %d : %d\n",  s, ll, ll2, imax, ll <= imax);
    return 0;
}

This is the output on alpine linux (musl):

9223372036854775808 : -9223372036854775808 : 9223372036854775807 : 2147483647 : 1

And here is on Ubuntu 18.04:

9223372036854775808 : 9223372036854775807 : 9223372036854775807 : 2147483647 : 0

The output of atoll and strtoll do not match on musl that is used on alpine linux and also on wasm/emscripten.

mingodad commented 1 year ago

For the playground I just replaced atoll with strtoll till the bug get fixed and it's running the t6.sql sample fine.

mingodad commented 1 year ago

Also while making tests on alpine linux I needed to replace all #!/bin/bash by #!/bin/sh to be able to build, it doesn't seem that this project is using any bashism so using #!/bin/sh would give less headaches on other operating systems.

mingodad commented 1 year ago

After reporting the problem to musl mailing list the conclusion seem that musl decided to try signal an out of range error giving a different value than the one from strtoll because in theory atoll do not set errno on error.

See this sample that shows it:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

int main(int argc, char *argv[])
{
    const char *s = "9223372036854775808";
    printf("before atoll errno = %d : %s\n", errno, strerror(errno));
    long  long ll = atoll(s);
    printf("after atoll errno = %d : %s\n", errno, strerror(errno));
    errno = 0;
    long long ll2 = strtoll (s, (char **) NULL, 10);
    printf("after strtoll errno = %d : %s\n", errno, strerror(errno));
    int imax = 0x7fffffff;
    printf("%s : %lld : %lld : %d : %d\n",  s, ll, ll2, imax, ll <= imax);
    return 0;
}

Output from glibc:

./test-ll
before atoll errno = 0 : Success
after atoll errno = 34 : Numerical result out of range
after strtoll errno = 34 : Numerical result out of range
9223372036854775808 : 9223372036854775807 : 9223372036854775807 : 2147483647 : 0

Output from musl:

before atoll errno = 0 : No error information
after atoll errno = 0 : No error information
after strtoll errno = 34 : Result not representable
9223372036854775808 : -9223372036854775808 : 9223372036854775807 : 2147483647 : 1

So the code on cql.l need to take in account errno when trying to convert numbers and definitely do not use atoll.

Here is the mailing list discussion https://www.openwall.com/lists/musl/2022/12/18/1