diff --git a/colab_logica.py b/colab_logica.py index 0703e92..ae2be13 100755 --- a/colab_logica.py +++ b/colab_logica.py @@ -189,9 +189,16 @@ def RunSQL(sql, engine, connection=None, is_final=False): psql_logica.PostgresExecute(sql, connection) elif engine == 'duckdb': if is_final: - return duckdb.sql(sql).df() + df = connection.sql(sql).df() + for c in df.columns: + if df.dtypes[c] == 'float64': + if df[c].isna().values.any(): + return df + if set(df[c] - df[c].astype(int)) == {0.0}: + df[c] = df[c].astype(int) + return df else: - duckdb.sql(sql) + connection.sql(sql) elif engine == 'sqlite': try: if is_final: @@ -229,7 +236,11 @@ def __call__(self, sql, engine, is_final): class DuckdbRunner(object): def __init__(self): - self.connection = duckdb_logica.SqliteConnect() + global DB_CONNECTION + if not DB_CONNECTION: + DB_CONNECTION = duckdb.connect() + self.connection = DB_CONNECTION + def __call__(self, sql, engine, is_final): return RunSQL(sql, engine, self.connection, is_final) diff --git a/common/duckdb_logica.py b/common/duckdb_logica.py index 1bd87ee..a12d16b 100644 --- a/common/duckdb_logica.py +++ b/common/duckdb_logica.py @@ -14,9 +14,5 @@ # See the License for the specific language governing permissions and # limitations under the License. -from decimal import Decimal -import sqlite3 - -def SqliteConnect(): - con = sqlite3.connect(':memory:') - return con \ No newline at end of file +# Keeping the placeholder, but we may never needed. +# DuckDB is too easy to connect! \ No newline at end of file diff --git a/compiler/universe.py b/compiler/universe.py index 506ff6b..b924b5b 100755 --- a/compiler/universe.py +++ b/compiler/universe.py @@ -188,6 +188,11 @@ def Preamble(self): 'create schema if not exists logica_home;\n' '-- Empty record, has to have a field by DuckDB syntax.\n' 'drop type if exists logicarecord893574736 cascade; create type logicarecord893574736 as struct(nirvana numeric);\n' + ) + if self.annotations['@Engine']['duckdb'].get('motherduck'): + preamble += '\n' # Sequences are not supported in MotherDuck. + else: + preamble += ( 'create sequence if not exists eternal_logical_sequence;\n\n') return preamble diff --git a/integration_tests/duckdb_flow_test.txt b/integration_tests/duckdb_flow_test.txt index 12553c7..0fb09f5 100644 --- a/integration_tests/duckdb_flow_test.txt +++ b/integration_tests/duckdb_flow_test.txt @@ -1,18 +1,18 @@ -+------+------+--------------------+ -| col0 | col1 | logica_value | -+------+------+--------------------+ -| 0.0 | 1.0 | 2.9970000000000003 | -| 0.0 | 4.0 | 9.994999999999997 | -| 1.0 | 0.0 | 0.0 | -| 1.0 | 2.0 | 0.0 | -| 1.0 | 5.0 | 9.992999999999999 | -| 2.0 | 1.0 | 6.995999999999998 | -| 2.0 | 3.0 | 2.999 | -| 2.0 | 4.0 | 0.0 | -| 3.0 | 2.0 | 0.0 | -| 3.0 | 5.0 | 0.0 | -| 4.0 | 0.0 | 0.0 | -| 4.0 | 2.0 | 9.994999999999997 | -| 5.0 | 1.0 | 0.0 | -| 5.0 | 3.0 | 9.992999999999999 | -+------+------+--------------------+ \ No newline at end of file ++-------+-------+--------------------+ +| col0 | col1 | logica_value | ++-------+-------+--------------------+ +| 0.000 | 1.000 | 2.9970000000000003 | +| 0.000 | 4.000 | 9.994999999999997 | +| 1.000 | 0.000 | 0.0 | +| 1.000 | 2.000 | 0.0 | +| 1.000 | 5.000 | 9.992999999999999 | +| 2.000 | 1.000 | 6.995999999999998 | +| 2.000 | 3.000 | 2.999 | +| 2.000 | 4.000 | 0.0 | +| 3.000 | 2.000 | 0.0 | +| 3.000 | 5.000 | 0.0 | +| 4.000 | 0.000 | 0.0 | +| 4.000 | 2.000 | 9.994999999999997 | +| 5.000 | 1.000 | 0.0 | +| 5.000 | 3.000 | 9.992999999999999 | ++-------+-------+--------------------+ \ No newline at end of file diff --git a/integration_tests/psqld_empty_list_type_duck_test.txt b/integration_tests/psqld_empty_list_type_duck_test.txt index e053ebc..cb93a8b 100644 --- a/integration_tests/psqld_empty_list_type_duck_test.txt +++ b/integration_tests/psqld_empty_list_type_duck_test.txt @@ -1,5 +1,5 @@ +--------------+ | logica_value | +--------------+ -| nan | +| None | +--------------+ \ No newline at end of file diff --git a/logica.py b/logica.py index deea994..d1be7cc 100755 --- a/logica.py +++ b/logica.py @@ -261,10 +261,9 @@ def main(argv): format).encode() elif engine == 'duckdb': import duckdb - df = duckdb.sql(formatted_sql).df() - o = sqlite3_logica.ArtisticTable(list(df.columns), - df.values - .tolist()).encode() + cur = duckdb.sql(formatted_sql) + o = sqlite3_logica.ArtisticTable(cur.columns, + cur.fetchall()).encode() elif engine == 'psql': connection_str = os.environ.get('LOGICA_PSQL_CONNECTION') if connection_str: diff --git a/tools/run_in_terminal.py b/tools/run_in_terminal.py index e11b70b..53d1070 100644 --- a/tools/run_in_terminal.py +++ b/tools/run_in_terminal.py @@ -105,8 +105,9 @@ def RunSQL(sql, engine, connection=None, is_final=False, elif engine == 'duckdb': import duckdb if is_final: - df = duckdb.sql(sql).df() - return list(df.columns), df.values.tolist() + import duckdb + cur = duckdb.sql(sql) + return cur.columns, cur.fetchall() else: duckdb.sql(sql)