Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Utilities for duplicating tables and creating a table with the results of a query #449

Closed
davidleejy opened this issue Jun 22, 2022 · 4 comments · Fixed by #452
Closed
Labels
enhancement New feature or request python-library

Comments

@davidleejy
Copy link
Contributor

davidleejy commented Jun 22, 2022

is there a duplicate table functionality? Otherwise, I'd be happy to submit a PR.

In sqlite3 it would look like:

import sqlite3 as sl

con = sl.connect('prompt-tune.db')

def db_duplicate_table(table_name, table_name_new, con=con):
    # Duplicates table `table_name` to a new table `table_name_new`.
    try:
        cur = con.cursor()
        cur.execute(f"""CREATE TABLE {table_name_new} AS SELECT * FROM {table_name}""")
    except Exception as e:
        print(e)
    finally:
        cur.close()

db_duplicate_table('orig_table', 'new_table')
@davidleejy davidleejy changed the title [Feature Request] Duplicate Table How to Duplicate Table? Jun 24, 2022
@simonw
Copy link
Owner

simonw commented Jul 2, 2022

I like the idea of this as a feature - design could look like this:

db["my_table"].duplicate("new_table")

Then for the CLI tool:

sqlite-utils duplicate data.db my_table new_table

Additional features that might be useful:

  • Duplicate across connection aliases - so you can copy a table to another database using the duplicate method or command
  • Ability to execute an arbitrary SQL query and save the results to a new table - basically a wrapper around CREATE TABLE t AS SELECT ..., again with alias support for copying to another database

@simonw simonw changed the title How to Duplicate Table? Utilities for duplicating tables and creating a table with the results of a query Jul 2, 2022
@simonw simonw added the enhancement New feature or request label Jul 2, 2022
@davidleejy
Copy link
Contributor Author

davidleejy commented Jul 4, 2022

I've written the code and test. Would you be able to advise how to compare table columns in a pytest function properly? Experiencing a challenge when comparing columns.

Test:

def test_duplicate(fresh_db):
    table = fresh_db.create_table(
        "table1",
        {
            "text_col": str,
            "float_col": float,
            "int_col": int,
            "bool_col": bool,
            "bytes_col": bytes,
            "datetime_col": datetime.datetime,
        },
    )
    dt = datetime.datetime.now()
    b = bytes('hello world', 'utf-8')
    data = {"text_col": "Cleo", 
            "float_col": 3.14,
            "int_col": -2,
            "bool_col": True,
            "bytes_col": b,
            "datetime_col": str(dt)}
    table1 = fresh_db["table1"]
    row_id = table1.insert(data).last_rowid
    table1.duplicate('table2')
    table2 = fresh_db["table2"]
    assert data == table2.get(row_id)
    assert table1.columns == table2.columns    # FAILS HERE

Result:
Screenshot 2022-07-05 at 1 31 55 AM

Failure is due to column types being named differently -- e.g. 'FLOAT' vs 'REAL', 'INTEGER' vs 'INT'. How should I go about comparing columns while accounting for equivalent types?

Or did I miss out something in my duplication code correctly? Here's how I did it: in db.py, I've added the following code:

class Table(Queryable):
    [...]
    def duplicate(
        self, 
        name_new: str
    ) -> "Table":
        """
        Duplicate this table in this database.

        :param name_new: Name of new table.
        """
        assert self.exists()
        with self.db.conn:
            sql = "CREATE TABLE [{new_table}] AS SELECT * FROM [{table}];".format(
                new_table = name_new,
                table = self.name,
            )
            self.db.execute(sql)
        return self.db[name_new]

@davidleejy
Copy link
Contributor Author

davidleejy commented Jul 9, 2022

Learnt that the types in Sqlite-utils differ somewhat from those in Sqlite. I've changed my test to account for this difference and the test has passed successfully. I will submit a PR.

@simonw simonw linked a pull request Jul 15, 2022 that will close this issue
simonw pushed a commit that referenced this issue Jul 15, 2022
simonw added a commit that referenced this issue Jul 15, 2022
Also made it so .duplicate() raises new NoTable exception rather than raising
an AssertionError if the source table does not exist.
simonw added a commit that referenced this issue Jul 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request python-library
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants