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

feat: foreign key on delete cascade action testing and samples #910

Merged
merged 14 commits into from
Jul 26, 2023
99 changes: 99 additions & 0 deletions samples/samples/snippets.py
Original file line number Diff line number Diff line change
Expand Up @@ -2428,6 +2428,105 @@ def enable_fine_grained_access(
# [END spanner_enable_fine_grained_access]


# [START spanner_create_table_with_foreign_key_delete_cascade]
def create_table_with_foreign_key_delete_cascade(instance_id, database_id):
"""Creates a table with foreign key delete cascade action"""
spanner_client = spanner.Client()
instance = spanner_client.instance(instance_id)
database = instance.database(database_id)

operation = database.update_ddl(
[
"""CREATE TABLE Customers (
CustomerId INT64 NOT NULL,
CustomerName STRING(62) NOT NULL,
) PRIMARY KEY (CustomerId)
""",
"""
CREATE TABLE ShoppingCarts (
CartId INT64 NOT NULL,
CustomerId INT64 NOT NULL,
CustomerName STRING(62) NOT NULL,
CONSTRAINT FKShoppingCartsCustomerId FOREIGN KEY (CustomerId)
REFERENCES Customers (CustomerId) ON DELETE CASCADE
) PRIMARY KEY (CartId)
"""
]
)

print("Waiting for operation to complete...")
operation.result(OPERATION_TIMEOUT_SECONDS)

print(
"""Created Customers and ShoppingCarts table with FKShoppingCartsCustomerId
foreign key constraint on database {} on instance {}""".format(
database_id, instance_id
)
)


# [END spanner_create_table_with_foreign_key_delete_cascade]


# [START spanner_alter_table_with_foreign_key_delete_cascade]
def alter_table_with_foreign_key_delete_cascade(instance_id, database_id):
"""Creates a table with foreign key delete cascade action"""
asthamohta marked this conversation as resolved.
Show resolved Hide resolved
spanner_client = spanner.Client()
instance = spanner_client.instance(instance_id)
database = instance.database(database_id)

operation = database.update_ddl(
[
"""ALTER TABLE ShoppingCarts
ADD CONSTRAINT FKShoppingCartsCustomerName
FOREIGN KEY (CustomerName)
REFERENCES Customers(CustomerName)
ON DELETE CASCADE"""
]
)

print("Waiting for operation to complete...")
operation.result(OPERATION_TIMEOUT_SECONDS)

print(
"""Altered ShoppingCarts table with FKShoppingCartsCustomerName
foreign key constraint on database {} on instance {}""".format(
database_id, instance_id
)
)


# [END spanner_alter_table_with_foreign_key_delete_cascade]


# [START spanner_drop_foreign_key_constraint_delete_cascade]
def drop_foreign_key_constraint_delete_cascade(instance_id, database_id):
"""Creates a table with foreign key delete cascade action"""
asthamohta marked this conversation as resolved.
Show resolved Hide resolved
spanner_client = spanner.Client()
instance = spanner_client.instance(instance_id)
database = instance.database(database_id)

operation = database.update_ddl(
[
"""ALTER TABLE ShoppingCarts
DROP CONSTRAINT FKShoppingCartsCustomerName"""
]
)

print("Waiting for operation to complete...")
operation.result(OPERATION_TIMEOUT_SECONDS)

print(
"""Altered ShoppingCarts table to drop FKShoppingCartsCustomerName
foreign key constraint on database {} on instance {}""".format(
database_id, instance_id
)
)


# [END spanner_drop_foreign_key_constraint_delete_cascade]


if __name__ == "__main__": # noqa: C901
parser = argparse.ArgumentParser(
description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter
Expand Down
22 changes: 22 additions & 0 deletions samples/samples/snippets_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -781,3 +781,25 @@ def test_list_database_roles(capsys, instance_id, sample_database):
snippets.list_database_roles(instance_id, sample_database.database_id)
out, _ = capsys.readouterr()
assert "new_parent" in out


@pytest.mark.dependency(name="create_table_with_foreign_key_delete_cascade")
def test_create_table_with_foreign_key_delete_cascade(capsys, instance_id, sample_database):
snippets.create_table_with_foreign_key_delete_cascade(instance_id, sample_database.database_id)
out, _ = capsys.readouterr()
assert "Created Customers and ShoppingCarts table with FKShoppingCartsCustomerId" in out

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May be instead of checking the output message we should verify that the table was actually created/ altered by the sample or not ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For IT, yes but for samples we just need the to check if an error is not thrown



@pytest.mark.dependency(name="alter_table_with_foreign_key_delete_cascade",
depends=["create_table_with_foreign_key_delete_cascade"])
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, As we are adding Foreign Key Delete Cascade constraint , this should Not depend on sample which has already added the constraints while creating the tables, isn't it ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is common in samples to have this dependency to reduce the time to run these

def test_alter_table_with_foreign_key_delete_cascade(capsys, instance_id, sample_database):
snippets.alter_table_with_foreign_key_delete_cascade(instance_id, sample_database.database_id)
out, _ = capsys.readouterr()
assert "Altered ShoppingCarts table with FKShoppingCartsCustomerName" in out


@pytest.mark.dependency(depends=["alter_table_with_foreign_key_delete_cascade"])
def test_drop_foreign_key_contraint_delete_cascade(capsys, instance_id, sample_database):
snippets.drop_foreign_key_contraint_delete_cascade(instance_id, sample_database.database_id)
out, _ = capsys.readouterr()
assert "Altered ShoppingCarts table to drop FKShoppingCartsCustomerName" in out
62 changes: 62 additions & 0 deletions tests/_fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,19 @@
email STRING(MAX),
deleted BOOL NOT NULL )
PRIMARY KEY(id, commit_ts DESC);

CREATE TABLE Customers (
surbhigarg92 marked this conversation as resolved.
Show resolved Hide resolved
CustomerId INT64 NOT NULL,
CustomerName STRING(62) NOT NULL,
) PRIMARY KEY (CustomerId);

CREATE TABLE ShoppingCarts (
CartId INT64 NOT NULL,
CustomerId INT64 NOT NULL,
CustomerName STRING(62) NOT NULL,
CONSTRAINT FKShoppingCartsCustomerId FOREIGN KEY (CustomerId)
REFERENCES Customers (CustomerId) ON DELETE CASCADE
) PRIMARY KEY (CartId);
"""

EMULATOR_DDL = """\
Expand Down Expand Up @@ -157,10 +170,59 @@
name VARCHAR(16),
PRIMARY KEY (id));
CREATE INDEX name ON contacts(first_name, last_name);
CREATE TABLE Customers (
CustomerId BIGINT,
CustomerName VARCHAR(62) NOT NULL,
PRIMARY KEY (CustomerId));

CREATE TABLE ShoppingCarts (
CartId BIGINT,
CustomerId BIGINT NOT NULL,
CustomerName VARCHAR(62) NOT NULL,
CONSTRAINT "FKShoppingCartsCustomerId" FOREIGN KEY (CustomerId)
REFERENCES Customers (CustomerId) ON DELETE CASCADE,
PRIMARY KEY (CartId)
);
"""

DDL_STATEMENTS = [stmt.strip() for stmt in DDL.split(";") if stmt.strip()]
EMULATOR_DDL_STATEMENTS = [
stmt.strip() for stmt in EMULATOR_DDL.split(";") if stmt.strip()
]
PG_DDL_STATEMENTS = [stmt.strip() for stmt in PG_DDL.split(";") if stmt.strip()]

FKDAC_DDL = """\
CREATE TABLE Customers_ (
CustomerId INT64 NOT NULL,
CustomerName STRING(62) NOT NULL,
) PRIMARY KEY (CustomerId);

CREATE TABLE ShoppingCarts_ (
CartId INT64 NOT NULL,
CustomerId INT64 NOT NULL,
CustomerName STRING(62) NOT NULL,
CONSTRAINT FKShoppingCartsCustomerId FOREIGN KEY (CustomerId)
REFERENCES Customers_ (CustomerId) ON DELETE CASCADE
) PRIMARY KEY (CartId);
"""

PG_FKDAC_DDL = """\
CREATE TABLE Customers_ (
CustomerId BIGINT,
CustomerName VARCHAR(62) NOT NULL,
PRIMARY KEY (CustomerId));

CREATE TABLE ShoppingCarts_ (
CartId BIGINT,
CustomerId BIGINT NOT NULL,
CustomerName VARCHAR(62) NOT NULL,
CONSTRAINT "FKShoppingCartsCustomerId" FOREIGN KEY (CustomerId)
REFERENCES Customers_ (CustomerId) ON DELETE CASCADE,
PRIMARY KEY (CartId)
);
"""

FKDAC_DDL_STATEMENTS = [stmt.strip() for stmt in FKDAC_DDL.split(";") if stmt.strip()]
PG_FKDAC_DDL_STATEMENTS = [
stmt.strip() for stmt in PG_FKDAC_DDL.split(";") if stmt.strip()
]
6 changes: 6 additions & 0 deletions tests/system/_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@
)
)

FKADC_DDL_STATEMENTS = (
_fixtures.PG_FKDAC_DDL_STATEMENTS
if DATABASE_DIALECT == "POSTGRESQL"
else _fixtures.FKDAC_DDL_STATEMENTS
)

retry_true = retry.RetryResult(operator.truth)
retry_false = retry.RetryResult(operator.not_)

Expand Down