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

add_foreign_key(...., ignore=True) #112

Closed
simonw opened this issue May 12, 2020 · 4 comments
Closed

add_foreign_key(...., ignore=True) #112

simonw opened this issue May 12, 2020 · 4 comments
Labels
enhancement New feature or request
Milestone

Comments

@simonw
Copy link
Owner

simonw commented May 12, 2020

When using this library I often find myself wanting to "add this foreign key, but only if it doesn't exist yet". The ignore=True parameter is increasingly being used for this else where in the library (e.g. in create_view()).

@simonw simonw added the enhancement New feature or request label May 12, 2020
@simonw
Copy link
Owner Author

simonw commented May 12, 2020

I would add ignore=True/False as a parameter here:

def add_foreign_key(self, column, other_table=None, other_column=None):
# Ensure column exists
if column not in self.columns_dict:
raise AlterError("No such column: {}".format(column))
# If other_table is not specified, attempt to guess it from the column
if other_table is None:
other_table = self.guess_foreign_table(column)
# If other_column is not specified, detect the primary key on other_table
if other_column is None:
other_column = self.guess_foreign_column(other_table)
# Sanity check that the other column exists
if (
not [c for c in self.db[other_table].columns if c.name == other_column]
and other_column != "rowid"
):
raise AlterError("No such column: {}.{}".format(other_table, other_column))
# Check we do not already have an existing foreign key
if any(
fk
for fk in self.foreign_keys
if fk.column == column
and fk.other_table == other_table
and fk.other_column == other_column
):
raise AlterError(
"Foreign key already exists for {} => {}.{}".format(
column, other_table, other_column
)
)
self.db.add_foreign_keys([(self.name, column, other_table, other_column)])

@simonw
Copy link
Owner Author

simonw commented May 12, 2020

Here's how it works for create_view:

def create_view(self, name, sql, ignore=False, replace=False):
assert not (
ignore and replace
), "Use one or the other of ignore/replace, not both"
create_sql = "CREATE VIEW {name} AS {sql}".format(name=name, sql=sql)
if ignore or replace:
# Does view exist already?
if name in self.view_names():
if ignore:
return self

@simonw
Copy link
Owner Author

simonw commented May 12, 2020

Question: if you use ignore=True should it still raise an error if one of the columns you referenced does not exist?

That's tricky. I'm leaning towards "that's still an error".

Are we ignoring an already existing foreign key, or ignoring all errors?

@simonw
Copy link
Owner Author

simonw commented May 12, 2020

Here's an example of some code that would be cleaner with this mechanism: https://github.com/dogsheep/swarm-to-sqlite/blob/f4a82633da927cde672c9d9af92930bfca2e3ddf/swarm_to_sqlite/utils.py#L120-L143

@simonw simonw added this to the 2.19 milestone Sep 20, 2020
@simonw simonw closed this as completed in e23eedb Sep 20, 2020
simonw added a commit that referenced this issue Sep 20, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant