From dd6d0690e5b4a2153cb65a78d2978801ea9be5ef Mon Sep 17 00:00:00 2001 From: Grigorii Berezin Date: Sat, 4 May 2024 08:58:45 +0300 Subject: [PATCH 1/7] feat: draft test case with testcontainers --- build.sbt | 4 +- zio-quickstart-sql/build.sbt | 16 ++ .../src/test/resources/db_schema.sql | 209 ++++++++++++++++++ .../src/test/scala/JdbcRunnableSpec.scala | 65 ++++++ .../src/test/scala/PostgresSqlSpec.scala | 109 +++++++++ 5 files changed, 402 insertions(+), 1 deletion(-) create mode 100644 zio-quickstart-sql/build.sbt create mode 100644 zio-quickstart-sql/src/test/resources/db_schema.sql create mode 100644 zio-quickstart-sql/src/test/scala/JdbcRunnableSpec.scala create mode 100644 zio-quickstart-sql/src/test/scala/PostgresSqlSpec.scala diff --git a/build.sbt b/build.sbt index 6bb1bbc..45407e1 100644 --- a/build.sbt +++ b/build.sbt @@ -35,7 +35,8 @@ lazy val root = `zio-quickstart-encode-decode-json`, `zio-quickstart-cache`, `zio-quickstart-prelude`, - `zio-quickstart-stm` + `zio-quickstart-stm`, + `zio-quickstart-sql` ) lazy val `zio-quickstart-hello-world` = project @@ -54,3 +55,4 @@ lazy val `zio-quickstart-reloadable-services` = project lazy val `zio-quickstart-cache` = project lazy val `zio-quickstart-prelude` = project lazy val `zio-quickstart-stm` = project +lazy val `zio-quickstart-sql` = project diff --git a/zio-quickstart-sql/build.sbt b/zio-quickstart-sql/build.sbt new file mode 100644 index 0000000..5dbbdbc --- /dev/null +++ b/zio-quickstart-sql/build.sbt @@ -0,0 +1,16 @@ +scalaVersion := "2.13.13" + +libraryDependencies ++= Seq( + "org.slf4j" % "slf4j-simple" % "2.0.13", + "dev.zio" %% "zio-sql" % "0.1.2", + "dev.zio" %% "zio-sql-postgres" % "0.1.2", + "org.postgresql" % "postgresql" % "42.7.3" % Compile, + "dev.zio" %% "zio-test" % "2.0.22" % Test, + "dev.zio" %% "zio-test-sbt" % "2.0.22" % Test, + "dev.zio" %% "zio-test-junit" % "2.0.22" % Test, + "org.testcontainers" % "testcontainers" % "1.19.7" % Test, + "org.testcontainers" % "database-commons" % "1.19.7" % Test, + "org.testcontainers" % "postgresql" % "1.19.7" % Test, + "org.testcontainers" % "jdbc" % "1.19.7" % Test, + "com.dimafeng" %% "testcontainers-scala-postgresql" % "0.41.3" % Test +) diff --git a/zio-quickstart-sql/src/test/resources/db_schema.sql b/zio-quickstart-sql/src/test/resources/db_schema.sql new file mode 100644 index 0000000..c537fa6 --- /dev/null +++ b/zio-quickstart-sql/src/test/resources/db_schema.sql @@ -0,0 +1,209 @@ +create table "customers" +( + "id" uuid not null primary key, + "first_name" varchar not null, + "last_name" varchar not null, + "verified" boolean not null, + "dob" date not null, + "created_timestamp_string" varchar not null, + "created_timestamp" timestamp with time zone default now() +); + +create table orders +( + id uuid not null primary key, + customer_id uuid not null, + order_date date not null +); + +create table products +( + id uuid not null primary key, + name varchar, + description varchar not null, + image_url varchar +); + +create table product_prices +( + product_id uuid not null, + effective date not null, + price money not null +); + +create table order_details +( + order_id uuid not null, + product_id uuid not null, + quantity integer not null, + unit_price numeric(12,2) not null +); + +create table persons +( + id uuid not null primary key, + name varchar, + birth_date date +); + +insert into "customers" + ("id", "first_name", "last_name", "verified", "dob", "created_timestamp_string", "created_timestamp") +values + ('60b01fc9-c902-4468-8d49-3c0f989def37', 'Ronald', 'Russell', true, '1983-01-05', '2020-11-21T19:10:25+00:00', '2020-11-21 19:10:25+00'), + ('f76c9ace-be07-4bf3-bd4c-4a9c62882e64', 'Terrence', 'Noel', true, '1999-11-02', '2020-11-21T15:10:25-04:00', '2020-11-21 15:10:25-04'), + ('784426a5-b90a-4759-afbb-571b7a0ba35e', 'Mila', 'Paterso', true, '1990-11-16', '2020-11-22T02:10:25+07:00', '2020-11-22 02:10:25+07'), + ('df8215a2-d5fd-4c6c-9984-801a1b3a2a0b', 'Alana', 'Murray', true, '1995-11-12', '2020-11-21T12:10:25-07:00', '2020-11-21 12:10:25-07'), + ('636ae137-5b1a-4c8c-b11f-c47c624d9cdc', 'Jose', 'Wiggins', false, '1987-03-23', '2020-11-21T19:10:25+00:00', '2020-11-21 19:10:25+00'); + +insert into persons + (id, name, birth_date) +values + ('60b01fc9-c902-4468-8d49-3c0f989def37', 'Russell', '1983-01-05'), + ('f76c9ace-be07-4bf3-bd4c-4a9c62882e64', 'Noel', null), + ('784426a5-b90a-4759-afbb-571b7a0ba35e', 'Paterso', '1990-11-16'), + ('df8215a2-d5fd-4c6c-9984-801a1b3a2a0b', 'Murray', '1995-11-12'), + ('636ae137-5b1a-4c8c-b11f-c47c624d9cdc', null, null); + +insert into products + (id, name, description, image_url) +values + ('7368ABF4-AED2-421F-B426-1725DE756895', 'Thermometer', 'Make sure you don''t have a fever (could be covid!)', 'https://images.pexels.com/photos/3987152/pexels-photo-3987152.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260'), + ('4C770002-4C8F-455A-96FF-36A8186D5290', 'Slippers', 'Keep your feet warm this winter', 'https://images.pexels.com/photos/1989843/pexels-photo-1989843.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260'), + ('05182725-F5C8-4FD6-9C43-6671E179BF55', 'Mouse Pad', 'Who uses these anyway?', 'https://images.pexels.com/photos/3944396/pexels-photo-3944396.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260'), + ('105A2701-EF93-4E25-81AB-8952CC7D9DAA', 'Pants', 'Avoid a lawsuit, wear pants to work today!', 'https://images.pexels.com/photos/52518/jeans-pants-blue-shop-52518.jpeg?cs=srgb&dl=blue-jeans-clothes-shopping-52518.jpg&fm=jpg'), + ('F35B0053-855B-4145-ABE1-DC62BC1FDB96', 'Nail File', 'Keep those nails looking good', 'https://images.pexels.com/photos/3997373/pexels-photo-3997373.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260'), + ('D5137D3A-894A-4109-9986-E982541B434F', 'Teddy Bear', 'Because sometimes you just need something to hug', 'https://images.pexels.com/photos/1019471/stuffed-bear-teddy-child-girl-1019471.jpeg?cs=srgb&dl=closeup-photography-of-brown-teddy-bear-1019471.jpg&fm=jpg'); + +insert into product_prices + (product_id, effective, price) +values + ('7368ABF4-AED2-421F-B426-1725DE756895', '2018-01-01', 10.00), + ('7368ABF4-AED2-421F-B426-1725DE756895', '2019-01-01', 11.00), + ('7368ABF4-AED2-421F-B426-1725DE756895', '2020-01-01', 12.00), + ('4C770002-4C8F-455A-96FF-36A8186D5290', '2018-01-01', 20.00), + ('4C770002-4C8F-455A-96FF-36A8186D5290', '2019-01-01', 22.00), + ('4C770002-4C8F-455A-96FF-36A8186D5290', '2020-01-01', 22.00), + ('05182725-F5C8-4FD6-9C43-6671E179BF55', '2018-01-01', 2.00), + ('105A2701-EF93-4E25-81AB-8952CC7D9DAA', '2018-01-01', 70.00), + ('105A2701-EF93-4E25-81AB-8952CC7D9DAA', '2019-01-01', 74.00), + ('105A2701-EF93-4E25-81AB-8952CC7D9DAA', '2020-01-01', 80.00), + ('F35B0053-855B-4145-ABE1-DC62BC1FDB96', '2018-01-01', 5.00), + ('F35B0053-855B-4145-ABE1-DC62BC1FDB96', '2019-01-01', 6.00), + ('D5137D3A-894A-4109-9986-E982541B434F', '2018-01-01', 50.00), + ('D5137D3A-894A-4109-9986-E982541B434F', '2020-01-01', 55.00); + +insert into orders + (id, customer_id, order_date) +values + ('04912093-cc2e-46ac-b64c-1bd7bb7758c3', '60b01fc9-c902-4468-8d49-3c0f989def37', '2019-03-25'), + ('a243fa42-817a-44ec-8b67-22193d212d82', '60b01fc9-c902-4468-8d49-3c0f989def37', '2018-06-04'), + ('9022dd0d-06d6-4a43-9121-2993fc7712a1', 'df8215a2-d5fd-4c6c-9984-801a1b3a2a0b', '2019-08-19'), + ('38d66d44-3cfa-488a-ac77-30277751418f', '636ae137-5b1a-4c8c-b11f-c47c624d9cdc', '2019-08-30'), + ('7b2627d5-0150-44df-9171-3462e20797ee', '636ae137-5b1a-4c8c-b11f-c47c624d9cdc', '2019-03-07'), + ('62cd4109-3e5d-40cc-8188-3899fc1f8bdf', '60b01fc9-c902-4468-8d49-3c0f989def37', '2020-03-19'), + ('9473a0bc-396a-4936-96b0-3eea922af36b', 'df8215a2-d5fd-4c6c-9984-801a1b3a2a0b', '2020-05-11'), + ('b8bac18d-769f-48ed-809d-4b6c0e4d1795', 'df8215a2-d5fd-4c6c-9984-801a1b3a2a0b', '2019-02-21'), + ('852e2dc9-4ec3-4225-a6f7-4f42f8ff728e', '60b01fc9-c902-4468-8d49-3c0f989def37', '2018-05-06'), + ('bebbfe4d-4ec3-4389-bdc2-50e9eac2b15b', '784426a5-b90a-4759-afbb-571b7a0ba35e', '2019-02-11'), + ('742d45a0-e81a-41ce-95ad-55b4cabba258', 'f76c9ace-be07-4bf3-bd4c-4a9c62882e64', '2019-10-12'), + ('618aa21f-700b-4ca7-933c-67066cf4cd97', '60b01fc9-c902-4468-8d49-3c0f989def37', '2019-01-29'), + ('606da090-dd33-4a77-8746-6ed0e8443ab2', 'f76c9ace-be07-4bf3-bd4c-4a9c62882e64', '2019-02-10'), + ('4914028d-2e28-4033-a5f2-8f4fcdee8206', '60b01fc9-c902-4468-8d49-3c0f989def37', '2019-09-27'), + ('d4e77298-d829-4e36-a6a0-902403f4b7d3', 'df8215a2-d5fd-4c6c-9984-801a1b3a2a0b', '2018-11-13'), + ('fd0fa8d4-e1a0-4369-be07-945450db5d36', '636ae137-5b1a-4c8c-b11f-c47c624d9cdc', '2020-01-15'), + ('d6d8dddc-4b0b-4d74-8edc-a54e9b7f35f7', 'f76c9ace-be07-4bf3-bd4c-4a9c62882e64', '2018-07-10'), + ('876b6034-b33c-4497-81ee-b4e8742164c2', '784426a5-b90a-4759-afbb-571b7a0ba35e', '2019-08-01'), + ('91caa28a-a5fe-40d7-979c-bd6a128d0418', 'df8215a2-d5fd-4c6c-9984-801a1b3a2a0b', '2019-12-08'), + ('401c7ab1-41cf-4756-8af5-be25cf2ae67b', '784426a5-b90a-4759-afbb-571b7a0ba35e', '2019-11-04'), + ('2c3fc180-d0df-4d7b-a271-e6ccd2440393', '784426a5-b90a-4759-afbb-571b7a0ba35e', '2018-10-14'), + ('763a7c39-833f-4ee8-9939-e80dfdbfc0fc', 'f76c9ace-be07-4bf3-bd4c-4a9c62882e64', '2020-04-05'), + ('5011d206-8eff-42c4-868e-f1a625e1f186', '636ae137-5b1a-4c8c-b11f-c47c624d9cdc', '2019-01-23'), + ('0a48ffb0-ec61-4147-af56-fc4dbca8de0a', 'f76c9ace-be07-4bf3-bd4c-4a9c62882e64', '2019-05-14'), + ('5883cb62-d792-4ee3-acbc-fe85b6baa998', '784426a5-b90a-4759-afbb-571b7a0ba35e', '2020-04-30'); + +insert into order_details + (order_id, product_id, quantity, unit_price) +values + ('9022DD0D-06D6-4A43-9121-2993FC7712A1', '7368ABF4-AED2-421F-B426-1725DE756895', 4, 11.00), + ('38D66D44-3CFA-488A-AC77-30277751418F', '7368ABF4-AED2-421F-B426-1725DE756895', 1, 11.00), + ('7B2627D5-0150-44DF-9171-3462E20797EE', '7368ABF4-AED2-421F-B426-1725DE756895', 1, 11.00), + ('62CD4109-3E5D-40CC-8188-3899FC1F8BDF', '7368ABF4-AED2-421F-B426-1725DE756895', 2, 10.90), + ('9473A0BC-396A-4936-96B0-3EEA922AF36B', '7368ABF4-AED2-421F-B426-1725DE756895', 1, 12.00), + ('852E2DC9-4EC3-4225-A6F7-4F42F8FF728E', '7368ABF4-AED2-421F-B426-1725DE756895', 1, 9.09), + ('742D45A0-E81A-41CE-95AD-55B4CABBA258', '7368ABF4-AED2-421F-B426-1725DE756895', 2, 10.00), + ('618AA21F-700B-4CA7-933C-67066CF4CD97', '7368ABF4-AED2-421F-B426-1725DE756895', 2, 11.00), + ('606DA090-DD33-4A77-8746-6ED0E8443AB2', '7368ABF4-AED2-421F-B426-1725DE756895', 2, 10.00), + ('4914028D-2E28-4033-A5F2-8F4FCDEE8206', '7368ABF4-AED2-421F-B426-1725DE756895', 1, 10.00), + ('D4E77298-D829-4E36-A6A0-902403F4B7D3', '7368ABF4-AED2-421F-B426-1725DE756895', 2, 10.00), + ('FD0FA8D4-E1A0-4369-BE07-945450DB5D36', '7368ABF4-AED2-421F-B426-1725DE756895', 1, 12.00), + ('D6D8DDDC-4B0B-4D74-8EDC-A54E9B7F35F7', '7368ABF4-AED2-421F-B426-1725DE756895', 2, 10.00), + ('876B6034-B33C-4497-81EE-B4E8742164C2', '7368ABF4-AED2-421F-B426-1725DE756895', 1, 11.00), + ('91CAA28A-A5FE-40D7-979C-BD6A128D0418', '7368ABF4-AED2-421F-B426-1725DE756895', 3, 11.00), + ('2C3FC180-D0DF-4D7B-A271-E6CCD2440393', '7368ABF4-AED2-421F-B426-1725DE756895', 2, 10.00), + ('763A7C39-833F-4EE8-9939-E80DFDBFC0FC', '7368ABF4-AED2-421F-B426-1725DE756895', 4, 12.00), + ('5011D206-8EFF-42C4-868E-F1A625E1F186', '7368ABF4-AED2-421F-B426-1725DE756895', 4, 11.00), + ('0A48FFB0-EC61-4147-AF56-FC4DBCA8DE0A', '7368ABF4-AED2-421F-B426-1725DE756895', 1, 11.00), + ('5883CB62-D792-4EE3-ACBC-FE85B6BAA998', '7368ABF4-AED2-421F-B426-1725DE756895', 3, 12.00), + ('04912093-CC2E-46AC-B64C-1BD7BB7758C3', '4C770002-4C8F-455A-96FF-36A8186D5290', 2, 22.00), + ('A243FA42-817A-44EC-8B67-22193D212D82', '4C770002-4C8F-455A-96FF-36A8186D5290', 5, 18.18), + ('9022DD0D-06D6-4A43-9121-2993FC7712A1', '4C770002-4C8F-455A-96FF-36A8186D5290', 2, 22.00), + ('38D66D44-3CFA-488A-AC77-30277751418F', '4C770002-4C8F-455A-96FF-36A8186D5290', 1, 22.00), + ('62CD4109-3E5D-40CC-8188-3899FC1F8BDF', '4C770002-4C8F-455A-96FF-36A8186D5290', 1, 20.00), + ('852E2DC9-4EC3-4225-A6F7-4F42F8FF728E', '4C770002-4C8F-455A-96FF-36A8186D5290', 1, 18.18), + ('BEBBFE4D-4EC3-4389-BDC2-50E9EAC2B15B', '4C770002-4C8F-455A-96FF-36A8186D5290', 1, 20.00), + ('618AA21F-700B-4CA7-933C-67066CF4CD97', '4C770002-4C8F-455A-96FF-36A8186D5290', 1, 22.00), + ('606DA090-DD33-4A77-8746-6ED0E8443AB2', '4C770002-4C8F-455A-96FF-36A8186D5290', 3, 20.00), + ('4914028D-2E28-4033-A5F2-8F4FCDEE8206', '4C770002-4C8F-455A-96FF-36A8186D5290', 1, 20.00), + ('FD0FA8D4-E1A0-4369-BE07-945450DB5D36', '4C770002-4C8F-455A-96FF-36A8186D5290', 1, 22.00), + ('D6D8DDDC-4B0B-4D74-8EDC-A54E9B7F35F7', '4C770002-4C8F-455A-96FF-36A8186D5290', 1, 20.00), + ('876B6034-B33C-4497-81EE-B4E8742164C2', '4C770002-4C8F-455A-96FF-36A8186D5290', 2, 22.00), + ('91CAA28A-A5FE-40D7-979C-BD6A128D0418', '4C770002-4C8F-455A-96FF-36A8186D5290', 1, 22.00), + ('2C3FC180-D0DF-4D7B-A271-E6CCD2440393', '4C770002-4C8F-455A-96FF-36A8186D5290', 1, 20.00), + ('763A7C39-833F-4EE8-9939-E80DFDBFC0FC', '4C770002-4C8F-455A-96FF-36A8186D5290', 1, 22.00), + ('5011D206-8EFF-42C4-868E-F1A625E1F186', '4C770002-4C8F-455A-96FF-36A8186D5290', 1, 22.00), + ('0A48FFB0-EC61-4147-AF56-FC4DBCA8DE0A', '4C770002-4C8F-455A-96FF-36A8186D5290', 3, 22.00), + ('5883CB62-D792-4EE3-ACBC-FE85B6BAA998', '4C770002-4C8F-455A-96FF-36A8186D5290', 3, 22.00), + ('A243FA42-817A-44EC-8B67-22193D212D82', '05182725-F5C8-4FD6-9C43-6671E179BF55', 1, 1.81), + ('852E2DC9-4EC3-4225-A6F7-4F42F8FF728E', '05182725-F5C8-4FD6-9C43-6671E179BF55', 1, 1.81), + ('D4E77298-D829-4E36-A6A0-902403F4B7D3', '05182725-F5C8-4FD6-9C43-6671E179BF55', 1, 2.00), + ('D6D8DDDC-4B0B-4D74-8EDC-A54E9B7F35F7', '05182725-F5C8-4FD6-9C43-6671E179BF55', 3, 2.00), + ('04912093-CC2E-46AC-B64C-1BD7BB7758C3', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 1, 74.00), + ('9022DD0D-06D6-4A43-9121-2993FC7712A1', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 4, 74.00), + ('38D66D44-3CFA-488A-AC77-30277751418F', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 2, 74.00), + ('7B2627D5-0150-44DF-9171-3462E20797EE', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 1, 74.00), + ('62CD4109-3E5D-40CC-8188-3899FC1F8BDF', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 1, 72.72), + ('9473A0BC-396A-4936-96B0-3EEA922AF36B', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 2, 80.00), + ('B8BAC18D-769F-48ED-809D-4B6C0E4D1795', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 3, 67.27), + ('BEBBFE4D-4EC3-4389-BDC2-50E9EAC2B15B', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 2, 67.27), + ('742D45A0-E81A-41CE-95AD-55B4CABBA258', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 1, 67.27), + ('618AA21F-700B-4CA7-933C-67066CF4CD97', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 2, 74.00), + ('606DA090-DD33-4A77-8746-6ED0E8443AB2', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 1, 67.27), + ('FD0FA8D4-E1A0-4369-BE07-945450DB5D36', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 1, 80.00), + ('876B6034-B33C-4497-81EE-B4E8742164C2', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 2, 74.00), + ('91CAA28A-A5FE-40D7-979C-BD6A128D0418', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 5, 74.00), + ('2C3FC180-D0DF-4D7B-A271-E6CCD2440393', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 1, 70.00), + ('763A7C39-833F-4EE8-9939-E80DFDBFC0FC', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 3, 80.00), + ('5011D206-8EFF-42C4-868E-F1A625E1F186', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 6, 74.00), + ('0A48FFB0-EC61-4147-AF56-FC4DBCA8DE0A', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 2, 74.00), + ('04912093-CC2E-46AC-B64C-1BD7BB7758C3', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 1, 6.00), + ('A243FA42-817A-44EC-8B67-22193D212D82', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 4, 4.54), + ('9022DD0D-06D6-4A43-9121-2993FC7712A1', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 1, 6.00), + ('38D66D44-3CFA-488A-AC77-30277751418F', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 1, 6.00), + ('7B2627D5-0150-44DF-9171-3462E20797EE', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 2, 6.00), + ('B8BAC18D-769F-48ED-809D-4B6C0E4D1795', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 1, 5.45), + ('BEBBFE4D-4EC3-4389-BDC2-50E9EAC2B15B', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 1, 5.45), + ('742D45A0-E81A-41CE-95AD-55B4CABBA258', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 1, 5.45), + ('606DA090-DD33-4A77-8746-6ED0E8443AB2', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 1, 5.45), + ('4914028D-2E28-4033-A5F2-8F4FCDEE8206', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 1, 5.45), + ('D6D8DDDC-4B0B-4D74-8EDC-A54E9B7F35F7', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 1, 5.00), + ('91CAA28A-A5FE-40D7-979C-BD6A128D0418', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 1, 6.00), + ('401C7AB1-41CF-4756-8AF5-BE25CF2AE67B', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 2, 5.45), + ('5011D206-8EFF-42C4-868E-F1A625E1F186', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 1, 6.00), + ('0A48FFB0-EC61-4147-AF56-FC4DBCA8DE0A', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 5, 6.00), + ('A243FA42-817A-44EC-8B67-22193D212D82', 'D5137D3A-894A-4109-9986-E982541B434F', 1, 45.45), + ('62CD4109-3E5D-40CC-8188-3899FC1F8BDF', 'D5137D3A-894A-4109-9986-E982541B434F', 4, 50.00), + ('9473A0BC-396A-4936-96B0-3EEA922AF36B', 'D5137D3A-894A-4109-9986-E982541B434F', 2, 55.00), + ('852E2DC9-4EC3-4225-A6F7-4F42F8FF728E', 'D5137D3A-894A-4109-9986-E982541B434F', 1, 45.45), + ('D6D8DDDC-4B0B-4D74-8EDC-A54E9B7F35F7', 'D5137D3A-894A-4109-9986-E982541B434F', 2, 50.00), + ('2C3FC180-D0DF-4D7B-A271-E6CCD2440393', 'D5137D3A-894A-4109-9986-E982541B434F', 2, 50.00), + ('5883CB62-D792-4EE3-ACBC-FE85B6BAA998', 'D5137D3A-894A-4109-9986-E982541B434F', 1, 55.00); diff --git a/zio-quickstart-sql/src/test/scala/JdbcRunnableSpec.scala b/zio-quickstart-sql/src/test/scala/JdbcRunnableSpec.scala new file mode 100644 index 0000000..486b08c --- /dev/null +++ b/zio-quickstart-sql/src/test/scala/JdbcRunnableSpec.scala @@ -0,0 +1,65 @@ +import com.dimafeng.testcontainers.{JdbcDatabaseContainer, SingleContainer} +import zio.sql.postgresql.PostgresJdbcModule +import zio.sql.{ConnectionPool, ConnectionPoolConfig} +import zio.test.{Spec, TestEnvironment, ZIOSpecDefault} +import zio.{Scope, ZIO, ZLayer} + +import java.util.Properties + +trait JdbcRunnableSpec extends ZIOSpecDefault with PostgresJdbcModule { + + type JdbcEnvironment = TestEnvironment with SqlDriver + + def specLayered: Spec[JdbcEnvironment, Object] + + protected def getContainer: SingleContainer[_] with JdbcDatabaseContainer + + protected val autoCommit = false + + override def spec: Spec[TestEnvironment, Any] = + specLayered.provideCustomShared(jdbcLayer) + + private[this] def connProperties( + user: String, + password: String + ): Properties = { + val props = new Properties + props.setProperty("user", user) + props.setProperty("password", password) + props + } + + private[this] val poolConfigLayer + : ZLayer[Any, Throwable, ConnectionPoolConfig] = + ZLayer.scoped { + testContainer + .map(a => + ConnectionPoolConfig( + url = a.jdbcUrl, + properties = connProperties(a.username, a.password), + autoCommit = autoCommit + ) + ) + } + + val connectionPool: ZLayer[Any, Throwable, ConnectionPool] = + poolConfigLayer >>> ConnectionPool.live + + private[this] final lazy val jdbcLayer: ZLayer[Any, Any, SqlDriver] = + ZLayer.make[SqlDriver]( + connectionPool.orDie, + SqlDriver.live + ) + + val testContainer + : ZIO[Scope, Throwable, SingleContainer[_] with JdbcDatabaseContainer] = + ZIO.acquireRelease { + ZIO.attemptBlocking { + val c = getContainer + c.start() + c + } + } { container => + ZIO.attemptBlocking(container.stop()).orDie + } +} diff --git a/zio-quickstart-sql/src/test/scala/PostgresSqlSpec.scala b/zio-quickstart-sql/src/test/scala/PostgresSqlSpec.scala new file mode 100644 index 0000000..4e000f7 --- /dev/null +++ b/zio-quickstart-sql/src/test/scala/PostgresSqlSpec.scala @@ -0,0 +1,109 @@ +import com.dimafeng.testcontainers.{ + JdbcDatabaseContainer, + PostgreSQLContainer, + SingleContainer +} +import org.testcontainers.utility.DockerImageName +import zio.Chunk +import zio.schema.DeriveSchema +import zio.test.Assertion._ +import zio.test._ + +import java.time.LocalDate +import java.util.UUID + +object PostgresSqlSpec extends JdbcRunnableSpec { + override protected def getContainer + : SingleContainer[_] with JdbcDatabaseContainer = + new PostgreSQLContainer( + dockerImageNameOverride = + Option("postgres:alpine").map(DockerImageName.parse) + ).configure { a => + a.withInitScript("db_schema.sql") // initialize tables with rows + () + } + + final case class Product( + id: UUID, + name: String, + price: Double, + imageUrl: Option[String] // also work with optional fields + ) + + object ProductSchema { + implicit val productSchema = + DeriveSchema.gen[Product] // derive schema for model + val products = defineTableSmart[Product] // derive table instance for model + val (id, name, price, imageUrl) = + products.columns // you can extract all columns from table instance + } + + final case class Order( + id: UUID, + productId: UUID, + quantity: Int, + orderDate: LocalDate + ) + + object OrderSchema { + implicit val orderSchema = DeriveSchema.gen[Order] + val orders = defineTable[Order] + val (orderId, productId, quantity, date) = orders.columns + } + + override def specLayered: Spec[PostgresSqlSpec.JdbcEnvironment, Object] = + suite("Query")( + test("run select") { + import ProductSchema._ + + val selectQuery = select(name) + .from(products) + .where( + id === UUID.fromString("4C770002-4C8F-455A-96FF-36A8186D5290") + ) // type safe building sql query + val expectedName = "Slippers" + + for { + result <- execute(selectQuery).runCollect // return collection + } yield assert(result)( + hasSameElementsDistinct(Chunk.single(expectedName)) + ) + }, + test("render query") { + import OrderSchema._ + import ProductSchema._ + + val selectQuery = select(orderId, name) + .from(products.join(orders).on(productId === id)) + .limit(5) + .offset(10) + val selectQueryRender = + "SELECT \"order\".\"id\", \"products\".\"name\" FROM \"products\" INNER JOIN \"order\" ON \"order\".\"product_id\" = \"products\".\"id\" LIMIT 5 OFFSET 10" + + val insertQuery = insertInto(products)(id, name, price).values( + (UUID.randomUUID(), "Zionomicon", 10.5) + ) + val insertQueryRender = + "INSERT INTO \"products\" (\"id\", \"name\", \"price\") VALUES (?, ?, ?);" + + val uuid = UUID.randomUUID() + val updateQuery = update(products) + .set(name, "foo") + .set(price, price * 1.1) + .where(id === uuid) + val updateQueryRender = + s"UPDATE \"products\" SET \"name\" = 'foo', \"price\" = \"products\".\"price\" * 1.1 WHERE \"products\".\"id\" = '${uuid.toString}'" + + val deleteQuery = deleteFrom(products).where(id === uuid) + val deleteQueryRender = + s"DELETE FROM \"products\" WHERE \"products\".\"id\" = '${uuid.toString}'" + + assertTrue( + renderRead(selectQuery) == selectQueryRender && + renderInsert(insertQuery) == insertQueryRender && + renderUpdate(updateQuery) == updateQueryRender && + renderDelete(deleteQuery) == deleteQueryRender + ) + } + ) +} From b78abfeea2dee5296a281da033f1654079952721 Mon Sep 17 00:00:00 2001 From: Grigorii Berezin Date: Mon, 6 May 2024 14:41:06 +0300 Subject: [PATCH 2/7] feat: add batch insert with other query specs --- .../src/test/resources/db_schema.sql | 330 +++++++++--------- .../src/test/scala/PostgresSqlSpec.scala | 215 ++++++++++-- 2 files changed, 340 insertions(+), 205 deletions(-) diff --git a/zio-quickstart-sql/src/test/resources/db_schema.sql b/zio-quickstart-sql/src/test/resources/db_schema.sql index c537fa6..40061e4 100644 --- a/zio-quickstart-sql/src/test/resources/db_schema.sql +++ b/zio-quickstart-sql/src/test/resources/db_schema.sql @@ -1,209 +1,193 @@ create table "customers" ( - "id" uuid not null primary key, - "first_name" varchar not null, - "last_name" varchar not null, - "verified" boolean not null, - "dob" date not null, - "created_timestamp_string" varchar not null, + "id" uuid not null primary key, + "first_name" varchar not null, + "last_name" varchar not null, + "verified" boolean not null, + "dob" date not null, "created_timestamp" timestamp with time zone default now() ); create table orders ( - id uuid not null primary key, + id uuid not null primary key, customer_id uuid not null, - order_date date not null + order_date date not null ); create table products ( - id uuid not null primary key, - name varchar, + id uuid not null primary key, + name varchar not null, description varchar not null, - image_url varchar + image_url varchar ); create table product_prices ( - product_id uuid not null, - effective date not null, - price money not null + product_id uuid not null, + effective date not null, + price money not null ); create table order_details ( - order_id uuid not null, - product_id uuid not null, - quantity integer not null, - unit_price numeric(12,2) not null -); - -create table persons -( - id uuid not null primary key, - name varchar, - birth_date date + order_id uuid not null, + product_id uuid not null, + quantity integer not null, + unit_price numeric(12, 2) not null ); insert into "customers" - ("id", "first_name", "last_name", "verified", "dob", "created_timestamp_string", "created_timestamp") -values - ('60b01fc9-c902-4468-8d49-3c0f989def37', 'Ronald', 'Russell', true, '1983-01-05', '2020-11-21T19:10:25+00:00', '2020-11-21 19:10:25+00'), - ('f76c9ace-be07-4bf3-bd4c-4a9c62882e64', 'Terrence', 'Noel', true, '1999-11-02', '2020-11-21T15:10:25-04:00', '2020-11-21 15:10:25-04'), - ('784426a5-b90a-4759-afbb-571b7a0ba35e', 'Mila', 'Paterso', true, '1990-11-16', '2020-11-22T02:10:25+07:00', '2020-11-22 02:10:25+07'), - ('df8215a2-d5fd-4c6c-9984-801a1b3a2a0b', 'Alana', 'Murray', true, '1995-11-12', '2020-11-21T12:10:25-07:00', '2020-11-21 12:10:25-07'), - ('636ae137-5b1a-4c8c-b11f-c47c624d9cdc', 'Jose', 'Wiggins', false, '1987-03-23', '2020-11-21T19:10:25+00:00', '2020-11-21 19:10:25+00'); - -insert into persons - (id, name, birth_date) -values - ('60b01fc9-c902-4468-8d49-3c0f989def37', 'Russell', '1983-01-05'), - ('f76c9ace-be07-4bf3-bd4c-4a9c62882e64', 'Noel', null), - ('784426a5-b90a-4759-afbb-571b7a0ba35e', 'Paterso', '1990-11-16'), - ('df8215a2-d5fd-4c6c-9984-801a1b3a2a0b', 'Murray', '1995-11-12'), - ('636ae137-5b1a-4c8c-b11f-c47c624d9cdc', null, null); +("id", "first_name", "last_name", "verified", "dob", "created_timestamp") +values ('60b01fc9-c902-4468-8d49-3c0f989def37', 'Ronald', 'Russell', true, '1983-01-05', '2020-11-21 19:10:25+00'), + ('f76c9ace-be07-4bf3-bd4c-4a9c62882e64', 'Terrence', 'Noel', true, '1999-11-02', '2020-11-21 15:10:25-04'), + ('784426a5-b90a-4759-afbb-571b7a0ba35e', 'Mila', 'Paterso', true, '1990-11-16', '2020-11-22 02:10:25+07'), + ('df8215a2-d5fd-4c6c-9984-801a1b3a2a0b', 'Alana', 'Murray', true, '1995-11-12', '2020-11-21 12:10:25-07'), + ('636ae137-5b1a-4c8c-b11f-c47c624d9cdc', 'Jose', 'Wiggins', false, '1987-03-23', '2020-11-21 19:10:25+00'); insert into products (id, name, description, image_url) -values - ('7368ABF4-AED2-421F-B426-1725DE756895', 'Thermometer', 'Make sure you don''t have a fever (could be covid!)', 'https://images.pexels.com/photos/3987152/pexels-photo-3987152.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260'), - ('4C770002-4C8F-455A-96FF-36A8186D5290', 'Slippers', 'Keep your feet warm this winter', 'https://images.pexels.com/photos/1989843/pexels-photo-1989843.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260'), - ('05182725-F5C8-4FD6-9C43-6671E179BF55', 'Mouse Pad', 'Who uses these anyway?', 'https://images.pexels.com/photos/3944396/pexels-photo-3944396.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260'), - ('105A2701-EF93-4E25-81AB-8952CC7D9DAA', 'Pants', 'Avoid a lawsuit, wear pants to work today!', 'https://images.pexels.com/photos/52518/jeans-pants-blue-shop-52518.jpeg?cs=srgb&dl=blue-jeans-clothes-shopping-52518.jpg&fm=jpg'), - ('F35B0053-855B-4145-ABE1-DC62BC1FDB96', 'Nail File', 'Keep those nails looking good', 'https://images.pexels.com/photos/3997373/pexels-photo-3997373.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260'), - ('D5137D3A-894A-4109-9986-E982541B434F', 'Teddy Bear', 'Because sometimes you just need something to hug', 'https://images.pexels.com/photos/1019471/stuffed-bear-teddy-child-girl-1019471.jpeg?cs=srgb&dl=closeup-photography-of-brown-teddy-bear-1019471.jpg&fm=jpg'); +values ('7368ABF4-AED2-421F-B426-1725DE756895', 'Thermometer', 'Make sure you don''t have a fever (could be covid!)', + 'https://images.pexels.com/photos/3987152/pexels-photo-3987152.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260'), + ('4C770002-4C8F-455A-96FF-36A8186D5290', 'Slippers', 'Keep your feet warm this winter', + 'https://images.pexels.com/photos/1989843/pexels-photo-1989843.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260'), + ('05182725-F5C8-4FD6-9C43-6671E179BF55', 'Mouse Pad', 'Who uses these anyway?', + 'https://images.pexels.com/photos/3944396/pexels-photo-3944396.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260'), + ('105A2701-EF93-4E25-81AB-8952CC7D9DAA', 'Pants', 'Avoid a lawsuit, wear pants to work today!', + 'https://images.pexels.com/photos/52518/jeans-pants-blue-shop-52518.jpeg?cs=srgb&dl=blue-jeans-clothes-shopping-52518.jpg&fm=jpg'), + ('F35B0053-855B-4145-ABE1-DC62BC1FDB96', 'Nail File', 'Keep those nails looking good', + 'https://images.pexels.com/photos/3997373/pexels-photo-3997373.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260'), + ('D5137D3A-894A-4109-9986-E982541B434F', 'Teddy Bear', 'Because sometimes you just need something to hug', + 'https://images.pexels.com/photos/1019471/stuffed-bear-teddy-child-girl-1019471.jpeg?cs=srgb&dl=closeup-photography-of-brown-teddy-bear-1019471.jpg&fm=jpg'); insert into product_prices (product_id, effective, price) -values - ('7368ABF4-AED2-421F-B426-1725DE756895', '2018-01-01', 10.00), - ('7368ABF4-AED2-421F-B426-1725DE756895', '2019-01-01', 11.00), - ('7368ABF4-AED2-421F-B426-1725DE756895', '2020-01-01', 12.00), - ('4C770002-4C8F-455A-96FF-36A8186D5290', '2018-01-01', 20.00), - ('4C770002-4C8F-455A-96FF-36A8186D5290', '2019-01-01', 22.00), - ('4C770002-4C8F-455A-96FF-36A8186D5290', '2020-01-01', 22.00), - ('05182725-F5C8-4FD6-9C43-6671E179BF55', '2018-01-01', 2.00), - ('105A2701-EF93-4E25-81AB-8952CC7D9DAA', '2018-01-01', 70.00), - ('105A2701-EF93-4E25-81AB-8952CC7D9DAA', '2019-01-01', 74.00), - ('105A2701-EF93-4E25-81AB-8952CC7D9DAA', '2020-01-01', 80.00), - ('F35B0053-855B-4145-ABE1-DC62BC1FDB96', '2018-01-01', 5.00), - ('F35B0053-855B-4145-ABE1-DC62BC1FDB96', '2019-01-01', 6.00), - ('D5137D3A-894A-4109-9986-E982541B434F', '2018-01-01', 50.00), - ('D5137D3A-894A-4109-9986-E982541B434F', '2020-01-01', 55.00); +values ('7368ABF4-AED2-421F-B426-1725DE756895', '2018-01-01', 10.00), + ('7368ABF4-AED2-421F-B426-1725DE756895', '2019-01-01', 11.00), + ('7368ABF4-AED2-421F-B426-1725DE756895', '2020-01-01', 12.00), + ('4C770002-4C8F-455A-96FF-36A8186D5290', '2018-01-01', 20.00), + ('4C770002-4C8F-455A-96FF-36A8186D5290', '2019-01-01', 22.00), + ('4C770002-4C8F-455A-96FF-36A8186D5290', '2020-01-01', 22.00), + ('05182725-F5C8-4FD6-9C43-6671E179BF55', '2018-01-01', 2.00), + ('105A2701-EF93-4E25-81AB-8952CC7D9DAA', '2018-01-01', 70.00), + ('105A2701-EF93-4E25-81AB-8952CC7D9DAA', '2019-01-01', 74.00), + ('105A2701-EF93-4E25-81AB-8952CC7D9DAA', '2020-01-01', 80.00), + ('F35B0053-855B-4145-ABE1-DC62BC1FDB96', '2018-01-01', 5.00), + ('F35B0053-855B-4145-ABE1-DC62BC1FDB96', '2019-01-01', 6.00), + ('D5137D3A-894A-4109-9986-E982541B434F', '2018-01-01', 50.00), + ('D5137D3A-894A-4109-9986-E982541B434F', '2020-01-01', 55.00); insert into orders (id, customer_id, order_date) -values - ('04912093-cc2e-46ac-b64c-1bd7bb7758c3', '60b01fc9-c902-4468-8d49-3c0f989def37', '2019-03-25'), - ('a243fa42-817a-44ec-8b67-22193d212d82', '60b01fc9-c902-4468-8d49-3c0f989def37', '2018-06-04'), - ('9022dd0d-06d6-4a43-9121-2993fc7712a1', 'df8215a2-d5fd-4c6c-9984-801a1b3a2a0b', '2019-08-19'), - ('38d66d44-3cfa-488a-ac77-30277751418f', '636ae137-5b1a-4c8c-b11f-c47c624d9cdc', '2019-08-30'), - ('7b2627d5-0150-44df-9171-3462e20797ee', '636ae137-5b1a-4c8c-b11f-c47c624d9cdc', '2019-03-07'), - ('62cd4109-3e5d-40cc-8188-3899fc1f8bdf', '60b01fc9-c902-4468-8d49-3c0f989def37', '2020-03-19'), - ('9473a0bc-396a-4936-96b0-3eea922af36b', 'df8215a2-d5fd-4c6c-9984-801a1b3a2a0b', '2020-05-11'), - ('b8bac18d-769f-48ed-809d-4b6c0e4d1795', 'df8215a2-d5fd-4c6c-9984-801a1b3a2a0b', '2019-02-21'), - ('852e2dc9-4ec3-4225-a6f7-4f42f8ff728e', '60b01fc9-c902-4468-8d49-3c0f989def37', '2018-05-06'), - ('bebbfe4d-4ec3-4389-bdc2-50e9eac2b15b', '784426a5-b90a-4759-afbb-571b7a0ba35e', '2019-02-11'), - ('742d45a0-e81a-41ce-95ad-55b4cabba258', 'f76c9ace-be07-4bf3-bd4c-4a9c62882e64', '2019-10-12'), - ('618aa21f-700b-4ca7-933c-67066cf4cd97', '60b01fc9-c902-4468-8d49-3c0f989def37', '2019-01-29'), - ('606da090-dd33-4a77-8746-6ed0e8443ab2', 'f76c9ace-be07-4bf3-bd4c-4a9c62882e64', '2019-02-10'), - ('4914028d-2e28-4033-a5f2-8f4fcdee8206', '60b01fc9-c902-4468-8d49-3c0f989def37', '2019-09-27'), - ('d4e77298-d829-4e36-a6a0-902403f4b7d3', 'df8215a2-d5fd-4c6c-9984-801a1b3a2a0b', '2018-11-13'), - ('fd0fa8d4-e1a0-4369-be07-945450db5d36', '636ae137-5b1a-4c8c-b11f-c47c624d9cdc', '2020-01-15'), - ('d6d8dddc-4b0b-4d74-8edc-a54e9b7f35f7', 'f76c9ace-be07-4bf3-bd4c-4a9c62882e64', '2018-07-10'), - ('876b6034-b33c-4497-81ee-b4e8742164c2', '784426a5-b90a-4759-afbb-571b7a0ba35e', '2019-08-01'), - ('91caa28a-a5fe-40d7-979c-bd6a128d0418', 'df8215a2-d5fd-4c6c-9984-801a1b3a2a0b', '2019-12-08'), - ('401c7ab1-41cf-4756-8af5-be25cf2ae67b', '784426a5-b90a-4759-afbb-571b7a0ba35e', '2019-11-04'), - ('2c3fc180-d0df-4d7b-a271-e6ccd2440393', '784426a5-b90a-4759-afbb-571b7a0ba35e', '2018-10-14'), - ('763a7c39-833f-4ee8-9939-e80dfdbfc0fc', 'f76c9ace-be07-4bf3-bd4c-4a9c62882e64', '2020-04-05'), - ('5011d206-8eff-42c4-868e-f1a625e1f186', '636ae137-5b1a-4c8c-b11f-c47c624d9cdc', '2019-01-23'), - ('0a48ffb0-ec61-4147-af56-fc4dbca8de0a', 'f76c9ace-be07-4bf3-bd4c-4a9c62882e64', '2019-05-14'), - ('5883cb62-d792-4ee3-acbc-fe85b6baa998', '784426a5-b90a-4759-afbb-571b7a0ba35e', '2020-04-30'); +values ('04912093-cc2e-46ac-b64c-1bd7bb7758c3', '60b01fc9-c902-4468-8d49-3c0f989def37', '2019-03-25'), + ('a243fa42-817a-44ec-8b67-22193d212d82', '60b01fc9-c902-4468-8d49-3c0f989def37', '2018-06-04'), + ('9022dd0d-06d6-4a43-9121-2993fc7712a1', 'df8215a2-d5fd-4c6c-9984-801a1b3a2a0b', '2019-08-19'), + ('38d66d44-3cfa-488a-ac77-30277751418f', '636ae137-5b1a-4c8c-b11f-c47c624d9cdc', '2019-08-30'), + ('7b2627d5-0150-44df-9171-3462e20797ee', '636ae137-5b1a-4c8c-b11f-c47c624d9cdc', '2019-03-07'), + ('62cd4109-3e5d-40cc-8188-3899fc1f8bdf', '60b01fc9-c902-4468-8d49-3c0f989def37', '2020-03-19'), + ('9473a0bc-396a-4936-96b0-3eea922af36b', 'df8215a2-d5fd-4c6c-9984-801a1b3a2a0b', '2020-05-11'), + ('b8bac18d-769f-48ed-809d-4b6c0e4d1795', 'df8215a2-d5fd-4c6c-9984-801a1b3a2a0b', '2019-02-21'), + ('852e2dc9-4ec3-4225-a6f7-4f42f8ff728e', '60b01fc9-c902-4468-8d49-3c0f989def37', '2018-05-06'), + ('bebbfe4d-4ec3-4389-bdc2-50e9eac2b15b', '784426a5-b90a-4759-afbb-571b7a0ba35e', '2019-02-11'), + ('742d45a0-e81a-41ce-95ad-55b4cabba258', 'f76c9ace-be07-4bf3-bd4c-4a9c62882e64', '2019-10-12'), + ('618aa21f-700b-4ca7-933c-67066cf4cd97', '60b01fc9-c902-4468-8d49-3c0f989def37', '2019-01-29'), + ('606da090-dd33-4a77-8746-6ed0e8443ab2', 'f76c9ace-be07-4bf3-bd4c-4a9c62882e64', '2019-02-10'), + ('4914028d-2e28-4033-a5f2-8f4fcdee8206', '60b01fc9-c902-4468-8d49-3c0f989def37', '2019-09-27'), + ('d4e77298-d829-4e36-a6a0-902403f4b7d3', 'df8215a2-d5fd-4c6c-9984-801a1b3a2a0b', '2018-11-13'), + ('fd0fa8d4-e1a0-4369-be07-945450db5d36', '636ae137-5b1a-4c8c-b11f-c47c624d9cdc', '2020-01-15'), + ('d6d8dddc-4b0b-4d74-8edc-a54e9b7f35f7', 'f76c9ace-be07-4bf3-bd4c-4a9c62882e64', '2018-07-10'), + ('876b6034-b33c-4497-81ee-b4e8742164c2', '784426a5-b90a-4759-afbb-571b7a0ba35e', '2019-08-01'), + ('91caa28a-a5fe-40d7-979c-bd6a128d0418', 'df8215a2-d5fd-4c6c-9984-801a1b3a2a0b', '2019-12-08'), + ('401c7ab1-41cf-4756-8af5-be25cf2ae67b', '784426a5-b90a-4759-afbb-571b7a0ba35e', '2019-11-04'), + ('2c3fc180-d0df-4d7b-a271-e6ccd2440393', '784426a5-b90a-4759-afbb-571b7a0ba35e', '2018-10-14'), + ('763a7c39-833f-4ee8-9939-e80dfdbfc0fc', 'f76c9ace-be07-4bf3-bd4c-4a9c62882e64', '2020-04-05'), + ('5011d206-8eff-42c4-868e-f1a625e1f186', '636ae137-5b1a-4c8c-b11f-c47c624d9cdc', '2019-01-23'), + ('0a48ffb0-ec61-4147-af56-fc4dbca8de0a', 'f76c9ace-be07-4bf3-bd4c-4a9c62882e64', '2019-05-14'), + ('5883cb62-d792-4ee3-acbc-fe85b6baa998', '784426a5-b90a-4759-afbb-571b7a0ba35e', '2020-04-30'); insert into order_details (order_id, product_id, quantity, unit_price) -values - ('9022DD0D-06D6-4A43-9121-2993FC7712A1', '7368ABF4-AED2-421F-B426-1725DE756895', 4, 11.00), - ('38D66D44-3CFA-488A-AC77-30277751418F', '7368ABF4-AED2-421F-B426-1725DE756895', 1, 11.00), - ('7B2627D5-0150-44DF-9171-3462E20797EE', '7368ABF4-AED2-421F-B426-1725DE756895', 1, 11.00), - ('62CD4109-3E5D-40CC-8188-3899FC1F8BDF', '7368ABF4-AED2-421F-B426-1725DE756895', 2, 10.90), - ('9473A0BC-396A-4936-96B0-3EEA922AF36B', '7368ABF4-AED2-421F-B426-1725DE756895', 1, 12.00), - ('852E2DC9-4EC3-4225-A6F7-4F42F8FF728E', '7368ABF4-AED2-421F-B426-1725DE756895', 1, 9.09), - ('742D45A0-E81A-41CE-95AD-55B4CABBA258', '7368ABF4-AED2-421F-B426-1725DE756895', 2, 10.00), - ('618AA21F-700B-4CA7-933C-67066CF4CD97', '7368ABF4-AED2-421F-B426-1725DE756895', 2, 11.00), - ('606DA090-DD33-4A77-8746-6ED0E8443AB2', '7368ABF4-AED2-421F-B426-1725DE756895', 2, 10.00), - ('4914028D-2E28-4033-A5F2-8F4FCDEE8206', '7368ABF4-AED2-421F-B426-1725DE756895', 1, 10.00), - ('D4E77298-D829-4E36-A6A0-902403F4B7D3', '7368ABF4-AED2-421F-B426-1725DE756895', 2, 10.00), - ('FD0FA8D4-E1A0-4369-BE07-945450DB5D36', '7368ABF4-AED2-421F-B426-1725DE756895', 1, 12.00), - ('D6D8DDDC-4B0B-4D74-8EDC-A54E9B7F35F7', '7368ABF4-AED2-421F-B426-1725DE756895', 2, 10.00), - ('876B6034-B33C-4497-81EE-B4E8742164C2', '7368ABF4-AED2-421F-B426-1725DE756895', 1, 11.00), - ('91CAA28A-A5FE-40D7-979C-BD6A128D0418', '7368ABF4-AED2-421F-B426-1725DE756895', 3, 11.00), - ('2C3FC180-D0DF-4D7B-A271-E6CCD2440393', '7368ABF4-AED2-421F-B426-1725DE756895', 2, 10.00), - ('763A7C39-833F-4EE8-9939-E80DFDBFC0FC', '7368ABF4-AED2-421F-B426-1725DE756895', 4, 12.00), - ('5011D206-8EFF-42C4-868E-F1A625E1F186', '7368ABF4-AED2-421F-B426-1725DE756895', 4, 11.00), - ('0A48FFB0-EC61-4147-AF56-FC4DBCA8DE0A', '7368ABF4-AED2-421F-B426-1725DE756895', 1, 11.00), - ('5883CB62-D792-4EE3-ACBC-FE85B6BAA998', '7368ABF4-AED2-421F-B426-1725DE756895', 3, 12.00), - ('04912093-CC2E-46AC-B64C-1BD7BB7758C3', '4C770002-4C8F-455A-96FF-36A8186D5290', 2, 22.00), - ('A243FA42-817A-44EC-8B67-22193D212D82', '4C770002-4C8F-455A-96FF-36A8186D5290', 5, 18.18), - ('9022DD0D-06D6-4A43-9121-2993FC7712A1', '4C770002-4C8F-455A-96FF-36A8186D5290', 2, 22.00), - ('38D66D44-3CFA-488A-AC77-30277751418F', '4C770002-4C8F-455A-96FF-36A8186D5290', 1, 22.00), - ('62CD4109-3E5D-40CC-8188-3899FC1F8BDF', '4C770002-4C8F-455A-96FF-36A8186D5290', 1, 20.00), - ('852E2DC9-4EC3-4225-A6F7-4F42F8FF728E', '4C770002-4C8F-455A-96FF-36A8186D5290', 1, 18.18), - ('BEBBFE4D-4EC3-4389-BDC2-50E9EAC2B15B', '4C770002-4C8F-455A-96FF-36A8186D5290', 1, 20.00), - ('618AA21F-700B-4CA7-933C-67066CF4CD97', '4C770002-4C8F-455A-96FF-36A8186D5290', 1, 22.00), - ('606DA090-DD33-4A77-8746-6ED0E8443AB2', '4C770002-4C8F-455A-96FF-36A8186D5290', 3, 20.00), - ('4914028D-2E28-4033-A5F2-8F4FCDEE8206', '4C770002-4C8F-455A-96FF-36A8186D5290', 1, 20.00), - ('FD0FA8D4-E1A0-4369-BE07-945450DB5D36', '4C770002-4C8F-455A-96FF-36A8186D5290', 1, 22.00), - ('D6D8DDDC-4B0B-4D74-8EDC-A54E9B7F35F7', '4C770002-4C8F-455A-96FF-36A8186D5290', 1, 20.00), - ('876B6034-B33C-4497-81EE-B4E8742164C2', '4C770002-4C8F-455A-96FF-36A8186D5290', 2, 22.00), - ('91CAA28A-A5FE-40D7-979C-BD6A128D0418', '4C770002-4C8F-455A-96FF-36A8186D5290', 1, 22.00), - ('2C3FC180-D0DF-4D7B-A271-E6CCD2440393', '4C770002-4C8F-455A-96FF-36A8186D5290', 1, 20.00), - ('763A7C39-833F-4EE8-9939-E80DFDBFC0FC', '4C770002-4C8F-455A-96FF-36A8186D5290', 1, 22.00), - ('5011D206-8EFF-42C4-868E-F1A625E1F186', '4C770002-4C8F-455A-96FF-36A8186D5290', 1, 22.00), - ('0A48FFB0-EC61-4147-AF56-FC4DBCA8DE0A', '4C770002-4C8F-455A-96FF-36A8186D5290', 3, 22.00), - ('5883CB62-D792-4EE3-ACBC-FE85B6BAA998', '4C770002-4C8F-455A-96FF-36A8186D5290', 3, 22.00), - ('A243FA42-817A-44EC-8B67-22193D212D82', '05182725-F5C8-4FD6-9C43-6671E179BF55', 1, 1.81), - ('852E2DC9-4EC3-4225-A6F7-4F42F8FF728E', '05182725-F5C8-4FD6-9C43-6671E179BF55', 1, 1.81), - ('D4E77298-D829-4E36-A6A0-902403F4B7D3', '05182725-F5C8-4FD6-9C43-6671E179BF55', 1, 2.00), - ('D6D8DDDC-4B0B-4D74-8EDC-A54E9B7F35F7', '05182725-F5C8-4FD6-9C43-6671E179BF55', 3, 2.00), - ('04912093-CC2E-46AC-B64C-1BD7BB7758C3', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 1, 74.00), - ('9022DD0D-06D6-4A43-9121-2993FC7712A1', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 4, 74.00), - ('38D66D44-3CFA-488A-AC77-30277751418F', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 2, 74.00), - ('7B2627D5-0150-44DF-9171-3462E20797EE', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 1, 74.00), - ('62CD4109-3E5D-40CC-8188-3899FC1F8BDF', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 1, 72.72), - ('9473A0BC-396A-4936-96B0-3EEA922AF36B', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 2, 80.00), - ('B8BAC18D-769F-48ED-809D-4B6C0E4D1795', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 3, 67.27), - ('BEBBFE4D-4EC3-4389-BDC2-50E9EAC2B15B', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 2, 67.27), - ('742D45A0-E81A-41CE-95AD-55B4CABBA258', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 1, 67.27), - ('618AA21F-700B-4CA7-933C-67066CF4CD97', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 2, 74.00), - ('606DA090-DD33-4A77-8746-6ED0E8443AB2', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 1, 67.27), - ('FD0FA8D4-E1A0-4369-BE07-945450DB5D36', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 1, 80.00), - ('876B6034-B33C-4497-81EE-B4E8742164C2', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 2, 74.00), - ('91CAA28A-A5FE-40D7-979C-BD6A128D0418', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 5, 74.00), - ('2C3FC180-D0DF-4D7B-A271-E6CCD2440393', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 1, 70.00), - ('763A7C39-833F-4EE8-9939-E80DFDBFC0FC', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 3, 80.00), - ('5011D206-8EFF-42C4-868E-F1A625E1F186', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 6, 74.00), - ('0A48FFB0-EC61-4147-AF56-FC4DBCA8DE0A', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 2, 74.00), - ('04912093-CC2E-46AC-B64C-1BD7BB7758C3', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 1, 6.00), - ('A243FA42-817A-44EC-8B67-22193D212D82', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 4, 4.54), - ('9022DD0D-06D6-4A43-9121-2993FC7712A1', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 1, 6.00), - ('38D66D44-3CFA-488A-AC77-30277751418F', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 1, 6.00), - ('7B2627D5-0150-44DF-9171-3462E20797EE', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 2, 6.00), - ('B8BAC18D-769F-48ED-809D-4B6C0E4D1795', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 1, 5.45), - ('BEBBFE4D-4EC3-4389-BDC2-50E9EAC2B15B', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 1, 5.45), - ('742D45A0-E81A-41CE-95AD-55B4CABBA258', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 1, 5.45), - ('606DA090-DD33-4A77-8746-6ED0E8443AB2', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 1, 5.45), - ('4914028D-2E28-4033-A5F2-8F4FCDEE8206', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 1, 5.45), - ('D6D8DDDC-4B0B-4D74-8EDC-A54E9B7F35F7', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 1, 5.00), - ('91CAA28A-A5FE-40D7-979C-BD6A128D0418', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 1, 6.00), - ('401C7AB1-41CF-4756-8AF5-BE25CF2AE67B', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 2, 5.45), - ('5011D206-8EFF-42C4-868E-F1A625E1F186', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 1, 6.00), - ('0A48FFB0-EC61-4147-AF56-FC4DBCA8DE0A', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 5, 6.00), - ('A243FA42-817A-44EC-8B67-22193D212D82', 'D5137D3A-894A-4109-9986-E982541B434F', 1, 45.45), - ('62CD4109-3E5D-40CC-8188-3899FC1F8BDF', 'D5137D3A-894A-4109-9986-E982541B434F', 4, 50.00), - ('9473A0BC-396A-4936-96B0-3EEA922AF36B', 'D5137D3A-894A-4109-9986-E982541B434F', 2, 55.00), - ('852E2DC9-4EC3-4225-A6F7-4F42F8FF728E', 'D5137D3A-894A-4109-9986-E982541B434F', 1, 45.45), - ('D6D8DDDC-4B0B-4D74-8EDC-A54E9B7F35F7', 'D5137D3A-894A-4109-9986-E982541B434F', 2, 50.00), - ('2C3FC180-D0DF-4D7B-A271-E6CCD2440393', 'D5137D3A-894A-4109-9986-E982541B434F', 2, 50.00), - ('5883CB62-D792-4EE3-ACBC-FE85B6BAA998', 'D5137D3A-894A-4109-9986-E982541B434F', 1, 55.00); +values ('9022DD0D-06D6-4A43-9121-2993FC7712A1', '7368ABF4-AED2-421F-B426-1725DE756895', 4, 11.00), + ('38D66D44-3CFA-488A-AC77-30277751418F', '7368ABF4-AED2-421F-B426-1725DE756895', 1, 11.00), + ('7B2627D5-0150-44DF-9171-3462E20797EE', '7368ABF4-AED2-421F-B426-1725DE756895', 1, 11.00), + ('62CD4109-3E5D-40CC-8188-3899FC1F8BDF', '7368ABF4-AED2-421F-B426-1725DE756895', 2, 10.90), + ('9473A0BC-396A-4936-96B0-3EEA922AF36B', '7368ABF4-AED2-421F-B426-1725DE756895', 1, 12.00), + ('852E2DC9-4EC3-4225-A6F7-4F42F8FF728E', '7368ABF4-AED2-421F-B426-1725DE756895', 1, 9.09), + ('742D45A0-E81A-41CE-95AD-55B4CABBA258', '7368ABF4-AED2-421F-B426-1725DE756895', 2, 10.00), + ('618AA21F-700B-4CA7-933C-67066CF4CD97', '7368ABF4-AED2-421F-B426-1725DE756895', 2, 11.00), + ('606DA090-DD33-4A77-8746-6ED0E8443AB2', '7368ABF4-AED2-421F-B426-1725DE756895', 2, 10.00), + ('4914028D-2E28-4033-A5F2-8F4FCDEE8206', '7368ABF4-AED2-421F-B426-1725DE756895', 1, 10.00), + ('D4E77298-D829-4E36-A6A0-902403F4B7D3', '7368ABF4-AED2-421F-B426-1725DE756895', 2, 10.00), + ('FD0FA8D4-E1A0-4369-BE07-945450DB5D36', '7368ABF4-AED2-421F-B426-1725DE756895', 1, 12.00), + ('D6D8DDDC-4B0B-4D74-8EDC-A54E9B7F35F7', '7368ABF4-AED2-421F-B426-1725DE756895', 2, 10.00), + ('876B6034-B33C-4497-81EE-B4E8742164C2', '7368ABF4-AED2-421F-B426-1725DE756895', 1, 11.00), + ('91CAA28A-A5FE-40D7-979C-BD6A128D0418', '7368ABF4-AED2-421F-B426-1725DE756895', 3, 11.00), + ('2C3FC180-D0DF-4D7B-A271-E6CCD2440393', '7368ABF4-AED2-421F-B426-1725DE756895', 2, 10.00), + ('763A7C39-833F-4EE8-9939-E80DFDBFC0FC', '7368ABF4-AED2-421F-B426-1725DE756895', 4, 12.00), + ('5011D206-8EFF-42C4-868E-F1A625E1F186', '7368ABF4-AED2-421F-B426-1725DE756895', 4, 11.00), + ('0A48FFB0-EC61-4147-AF56-FC4DBCA8DE0A', '7368ABF4-AED2-421F-B426-1725DE756895', 1, 11.00), + ('5883CB62-D792-4EE3-ACBC-FE85B6BAA998', '7368ABF4-AED2-421F-B426-1725DE756895', 3, 12.00), + ('04912093-CC2E-46AC-B64C-1BD7BB7758C3', '4C770002-4C8F-455A-96FF-36A8186D5290', 2, 22.00), + ('A243FA42-817A-44EC-8B67-22193D212D82', '4C770002-4C8F-455A-96FF-36A8186D5290', 5, 18.18), + ('9022DD0D-06D6-4A43-9121-2993FC7712A1', '4C770002-4C8F-455A-96FF-36A8186D5290', 2, 22.00), + ('38D66D44-3CFA-488A-AC77-30277751418F', '4C770002-4C8F-455A-96FF-36A8186D5290', 1, 22.00), + ('62CD4109-3E5D-40CC-8188-3899FC1F8BDF', '4C770002-4C8F-455A-96FF-36A8186D5290', 1, 20.00), + ('852E2DC9-4EC3-4225-A6F7-4F42F8FF728E', '4C770002-4C8F-455A-96FF-36A8186D5290', 1, 18.18), + ('BEBBFE4D-4EC3-4389-BDC2-50E9EAC2B15B', '4C770002-4C8F-455A-96FF-36A8186D5290', 1, 20.00), + ('618AA21F-700B-4CA7-933C-67066CF4CD97', '4C770002-4C8F-455A-96FF-36A8186D5290', 1, 22.00), + ('606DA090-DD33-4A77-8746-6ED0E8443AB2', '4C770002-4C8F-455A-96FF-36A8186D5290', 3, 20.00), + ('4914028D-2E28-4033-A5F2-8F4FCDEE8206', '4C770002-4C8F-455A-96FF-36A8186D5290', 1, 20.00), + ('FD0FA8D4-E1A0-4369-BE07-945450DB5D36', '4C770002-4C8F-455A-96FF-36A8186D5290', 1, 22.00), + ('D6D8DDDC-4B0B-4D74-8EDC-A54E9B7F35F7', '4C770002-4C8F-455A-96FF-36A8186D5290', 1, 20.00), + ('876B6034-B33C-4497-81EE-B4E8742164C2', '4C770002-4C8F-455A-96FF-36A8186D5290', 2, 22.00), + ('91CAA28A-A5FE-40D7-979C-BD6A128D0418', '4C770002-4C8F-455A-96FF-36A8186D5290', 1, 22.00), + ('2C3FC180-D0DF-4D7B-A271-E6CCD2440393', '4C770002-4C8F-455A-96FF-36A8186D5290', 1, 20.00), + ('763A7C39-833F-4EE8-9939-E80DFDBFC0FC', '4C770002-4C8F-455A-96FF-36A8186D5290', 1, 22.00), + ('5011D206-8EFF-42C4-868E-F1A625E1F186', '4C770002-4C8F-455A-96FF-36A8186D5290', 1, 22.00), + ('0A48FFB0-EC61-4147-AF56-FC4DBCA8DE0A', '4C770002-4C8F-455A-96FF-36A8186D5290', 3, 22.00), + ('5883CB62-D792-4EE3-ACBC-FE85B6BAA998', '4C770002-4C8F-455A-96FF-36A8186D5290', 3, 22.00), + ('A243FA42-817A-44EC-8B67-22193D212D82', '05182725-F5C8-4FD6-9C43-6671E179BF55', 1, 1.81), + ('852E2DC9-4EC3-4225-A6F7-4F42F8FF728E', '05182725-F5C8-4FD6-9C43-6671E179BF55', 1, 1.81), + ('D4E77298-D829-4E36-A6A0-902403F4B7D3', '05182725-F5C8-4FD6-9C43-6671E179BF55', 1, 2.00), + ('D6D8DDDC-4B0B-4D74-8EDC-A54E9B7F35F7', '05182725-F5C8-4FD6-9C43-6671E179BF55', 3, 2.00), + ('04912093-CC2E-46AC-B64C-1BD7BB7758C3', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 1, 74.00), + ('9022DD0D-06D6-4A43-9121-2993FC7712A1', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 4, 74.00), + ('38D66D44-3CFA-488A-AC77-30277751418F', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 2, 74.00), + ('7B2627D5-0150-44DF-9171-3462E20797EE', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 1, 74.00), + ('62CD4109-3E5D-40CC-8188-3899FC1F8BDF', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 1, 72.72), + ('9473A0BC-396A-4936-96B0-3EEA922AF36B', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 2, 80.00), + ('B8BAC18D-769F-48ED-809D-4B6C0E4D1795', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 3, 67.27), + ('BEBBFE4D-4EC3-4389-BDC2-50E9EAC2B15B', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 2, 67.27), + ('742D45A0-E81A-41CE-95AD-55B4CABBA258', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 1, 67.27), + ('618AA21F-700B-4CA7-933C-67066CF4CD97', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 2, 74.00), + ('606DA090-DD33-4A77-8746-6ED0E8443AB2', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 1, 67.27), + ('FD0FA8D4-E1A0-4369-BE07-945450DB5D36', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 1, 80.00), + ('876B6034-B33C-4497-81EE-B4E8742164C2', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 2, 74.00), + ('91CAA28A-A5FE-40D7-979C-BD6A128D0418', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 5, 74.00), + ('2C3FC180-D0DF-4D7B-A271-E6CCD2440393', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 1, 70.00), + ('763A7C39-833F-4EE8-9939-E80DFDBFC0FC', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 3, 80.00), + ('5011D206-8EFF-42C4-868E-F1A625E1F186', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 6, 74.00), + ('0A48FFB0-EC61-4147-AF56-FC4DBCA8DE0A', '105A2701-EF93-4E25-81AB-8952CC7D9DAA', 2, 74.00), + ('04912093-CC2E-46AC-B64C-1BD7BB7758C3', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 1, 6.00), + ('A243FA42-817A-44EC-8B67-22193D212D82', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 4, 4.54), + ('9022DD0D-06D6-4A43-9121-2993FC7712A1', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 1, 6.00), + ('38D66D44-3CFA-488A-AC77-30277751418F', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 1, 6.00), + ('7B2627D5-0150-44DF-9171-3462E20797EE', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 2, 6.00), + ('B8BAC18D-769F-48ED-809D-4B6C0E4D1795', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 1, 5.45), + ('BEBBFE4D-4EC3-4389-BDC2-50E9EAC2B15B', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 1, 5.45), + ('742D45A0-E81A-41CE-95AD-55B4CABBA258', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 1, 5.45), + ('606DA090-DD33-4A77-8746-6ED0E8443AB2', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 1, 5.45), + ('4914028D-2E28-4033-A5F2-8F4FCDEE8206', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 1, 5.45), + ('D6D8DDDC-4B0B-4D74-8EDC-A54E9B7F35F7', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 1, 5.00), + ('91CAA28A-A5FE-40D7-979C-BD6A128D0418', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 1, 6.00), + ('401C7AB1-41CF-4756-8AF5-BE25CF2AE67B', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 2, 5.45), + ('5011D206-8EFF-42C4-868E-F1A625E1F186', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 1, 6.00), + ('0A48FFB0-EC61-4147-AF56-FC4DBCA8DE0A', 'F35B0053-855B-4145-ABE1-DC62BC1FDB96', 5, 6.00), + ('A243FA42-817A-44EC-8B67-22193D212D82', 'D5137D3A-894A-4109-9986-E982541B434F', 1, 45.45), + ('62CD4109-3E5D-40CC-8188-3899FC1F8BDF', 'D5137D3A-894A-4109-9986-E982541B434F', 4, 50.00), + ('9473A0BC-396A-4936-96B0-3EEA922AF36B', 'D5137D3A-894A-4109-9986-E982541B434F', 2, 55.00), + ('852E2DC9-4EC3-4225-A6F7-4F42F8FF728E', 'D5137D3A-894A-4109-9986-E982541B434F', 1, 45.45), + ('D6D8DDDC-4B0B-4D74-8EDC-A54E9B7F35F7', 'D5137D3A-894A-4109-9986-E982541B434F', 2, 50.00), + ('2C3FC180-D0DF-4D7B-A271-E6CCD2440393', 'D5137D3A-894A-4109-9986-E982541B434F', 2, 50.00), + ('5883CB62-D792-4EE3-ACBC-FE85B6BAA998', 'D5137D3A-894A-4109-9986-E982541B434F', 1, 55.00); diff --git a/zio-quickstart-sql/src/test/scala/PostgresSqlSpec.scala b/zio-quickstart-sql/src/test/scala/PostgresSqlSpec.scala index 4e000f7..d54a666 100644 --- a/zio-quickstart-sql/src/test/scala/PostgresSqlSpec.scala +++ b/zio-quickstart-sql/src/test/scala/PostgresSqlSpec.scala @@ -4,12 +4,13 @@ import com.dimafeng.testcontainers.{ SingleContainer } import org.testcontainers.utility.DockerImageName -import zio.Chunk +import zio.{Cause, Chunk} import zio.schema.DeriveSchema import zio.test.Assertion._ import zio.test._ -import java.time.LocalDate +import java.math.BigDecimal +import java.time.{LocalDate, ZonedDateTime} import java.util.UUID object PostgresSqlSpec extends JdbcRunnableSpec { @@ -23,78 +24,228 @@ object PostgresSqlSpec extends JdbcRunnableSpec { () } - final case class Product( - id: UUID, - name: String, - price: Double, - imageUrl: Option[String] // also work with optional fields - ) - + // define schemes object ProductSchema { + final case class Product( + id: UUID, + name: String, + description: String, + imageUrl: Option[String] // also work with optional fields + ) implicit val productSchema = DeriveSchema.gen[Product] // derive schema for model val products = defineTableSmart[Product] // derive table instance for model - val (id, name, price, imageUrl) = + val (productId, name, description, imageUrl) = products.columns // you can extract all columns from table instance } - final case class Order( - id: UUID, - productId: UUID, - quantity: Int, - orderDate: LocalDate - ) + object CustomerSchema { + final case class Customer( + id: UUID, + firstName: String, + lastName: String, + verified: Boolean, + dob: LocalDate, + createdTimestamp: ZonedDateTime = ZonedDateTime.now() + ) + implicit val customerSchema = DeriveSchema.gen[Customer] + val customers = defineTableSmart[Customer] + val (customerId, firstName, lastName, verified, dob, createdTimestamp) = + customers.columns + + val ALL = + customerId ++ firstName ++ lastName ++ verified ++ dob ++ createdTimestamp + } object OrderSchema { - implicit val orderSchema = DeriveSchema.gen[Order] - val orders = defineTable[Order] - val (orderId, productId, quantity, date) = orders.columns + final case class Order(id: UUID, customerId: UUID, orderDate: LocalDate) + implicit val orderSchema = DeriveSchema.gen[Order] + val orders = defineTable[Order] + val (orderId, fkCustomerId, orderDate) = orders.columns + } + + object ProductPriceSchema { + case class ProductPrices( + productId: UUID, + effective: LocalDate, + price: BigDecimal + ) + implicit val productPricesSchema = DeriveSchema.gen[ProductPrices] + val productPrices = defineTableSmart[ProductPrices] + val (productPricesOrderId, effectiveDate, productPrice) = + productPrices.columns + } + + object OrderDetailsSchema { + case class OrderDetails( + orderId: UUID, + productId: UUID, + quantity: Int, + unitPrice: BigDecimal + ) + implicit val orderDetailsSchema = DeriveSchema.gen[OrderDetails] + val orderDetails = defineTableSmart[OrderDetails] + val (orderDetailsOrderId, orderDetailsProductId, quantity, unitPrice) = + orderDetails.columns } override def specLayered: Spec[PostgresSqlSpec.JdbcEnvironment, Object] = suite("Query")( - test("run select") { + test("run simple select") { import ProductSchema._ val selectQuery = select(name) .from(products) .where( - id === UUID.fromString("4C770002-4C8F-455A-96FF-36A8186D5290") + productId === UUID.fromString( + "4C770002-4C8F-455A-96FF-36A8186D5290" + ) ) // type safe building sql query val expectedName = "Slippers" for { - result <- execute(selectQuery).runCollect // return collection + result <- execute( + selectQuery + ).runHead // return option of one row } yield assert(result)( - hasSameElementsDistinct(Chunk.single(expectedName)) + isSome(equalTo(expectedName)) + ) // save assert on option + }, + test("run simple select with mapping into model") { + import OrderSchema._ + + val selectQuery = select(orderId, fkCustomerId, orderDate) + .from(orders) + .orderBy(Ordering.Desc(orderDate)) // sorting results by field + .limit(2) // set limit + .offset(1) // set offset + + val expected = Chunk.empty + + for { + result <- execute(selectQuery) + .map(Order tupled _) + .runCollect // return chunk of founded rows + } yield assert(result)(hasSameElementsDistinct(expected)) + }, + test("run select with join") { + import ProductSchema._ + import OrderDetailsSchema._ + + val orderId = UUID.fromString("D4E77298-D829-4E36-A6A0-902403F4B7D3") + val joinSelectQuery = select(name) + .from( + products + .join(orderDetails) + .on(productId === orderDetailsProductId) + ) + .where(orderDetailsOrderId === orderId) + + val expected = Chunk("Mouse Pad", "Thermometer") + + for { + result <- execute(joinSelectQuery).runCollect + } yield assert(result)(hasSameElementsDistinct(expected)) + }, + test("run select with aggregation functions") { + import AggregationDef._ // to use aggregations + import OrderDetailsSchema._ + + val query = select( + SumDec(unitPrice) as "totalAmount", + SumInt(quantity) as "soldQuantity" + ) // use aliases + .from(orderDetails) + .where( + orderDetailsProductId === UUID.fromString( + "7368ABF4-AED2-421F-B426-1725DE756895" + ) + ) + + for { + result <- execute(query).runHead + } yield assert(result)(isSome(equalTo((new BigDecimal(215.99), 40)))) + }, + test("run custom function") { + import PostgresFunctionDef._ // to use custom functions + + assertZIO(execute(select(GenRandomUuid)).runHead.some)(!isNull) + }, + test("run batch insert") { + import CustomerSchema._ + + val id1 = UUID.randomUUID() + val id2 = UUID.randomUUID() + val id3 = UUID.randomUUID() + val id4 = UUID.randomUUID() + val c1 = Customer( + id1, + "fnameCustomer1", + "lnameCustomer1", + verified = true, + LocalDate.now() + ) + val c2 = Customer( + id2, + "fnameCustomer2", + "lnameCustomer2", + true, + LocalDate.now() + ) + val c3 = Customer( + id3, + "fnameCustomer3", + "lnameCustomer3", + verified = true, + LocalDate.now() ) + val c4 = Customer( + id4, + "fnameCustomer4", + "lnameCustomer4", + verified = false, + LocalDate.now() + ) + + val allCustomer = List(c1, c2, c3, c4) + val data = allCustomer.map(Customer.unapply(_).get) + val query = insertInto(customers)(ALL).values(data) + + val insertAssertion = for { + result <- execute(query) + } yield assert(result)(equalTo(4)) + insertAssertion.mapErrorCause(cause => Cause.stackless(cause.untraced)) }, test("render query") { import OrderSchema._ import ProductSchema._ val selectQuery = select(orderId, name) - .from(products.join(orders).on(productId === id)) + .from(products.join(orders).on(productId === orderId)) .limit(5) .offset(10) val selectQueryRender = "SELECT \"order\".\"id\", \"products\".\"name\" FROM \"products\" INNER JOIN \"order\" ON \"order\".\"product_id\" = \"products\".\"id\" LIMIT 5 OFFSET 10" - val insertQuery = insertInto(products)(id, name, price).values( - (UUID.randomUUID(), "Zionomicon", 10.5) - ) + val insertQuery = + insertInto(products)(productId, name, description).values( + ( + UUID.randomUUID(), + "Zionomicon", + "Good book to start your journey in zio" + ) + ) val insertQueryRender = - "INSERT INTO \"products\" (\"id\", \"name\", \"price\") VALUES (?, ?, ?);" + "INSERT INTO \"products\" (\"id\", \"name\", \"description\") VALUES (?, ?, ?);" val uuid = UUID.randomUUID() val updateQuery = update(products) .set(name, "foo") - .set(price, price * 1.1) - .where(id === uuid) + .where(productId === uuid) val updateQueryRender = - s"UPDATE \"products\" SET \"name\" = 'foo', \"price\" = \"products\".\"price\" * 1.1 WHERE \"products\".\"id\" = '${uuid.toString}'" + s"UPDATE \"products\" SET \"name\" = 'foo', WHERE \"products\".\"id\" = '${uuid.toString}'" - val deleteQuery = deleteFrom(products).where(id === uuid) + val deleteQuery = deleteFrom(products).where(productId === uuid) val deleteQueryRender = s"DELETE FROM \"products\" WHERE \"products\".\"id\" = '${uuid.toString}'" From 2bb8269cd63ca0608a4dd2ae31e6eab8f21c74a0 Mon Sep 17 00:00:00 2001 From: Grigorii Berezin Date: Mon, 6 May 2024 14:55:03 +0300 Subject: [PATCH 3/7] feat: add tests into ci --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ff436b5..6ee7088 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,6 +35,8 @@ jobs: uses: coursier/cache-action@v6 - name: Check all code compiles run: sbt +Test/compile + - name: Check all tests + run: sbt test - name: Check artifacts build process run: sbt +publishLocal lint: From 434b04a47820d6e30d23089d0013a9c07c715493 Mon Sep 17 00:00:00 2001 From: Grigorii Berezin Date: Mon, 6 May 2024 16:59:24 +0300 Subject: [PATCH 4/7] fix: fix tests --- build.sbt | 3 ++ zio-quickstart-prelude/build.sbt | 1 + zio-quickstart-sql/build.sbt | 1 + .../src/test/scala/PostgresSqlSpec.scala | 31 +++++++++++-------- 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/build.sbt b/build.sbt index 45407e1..e6470dc 100644 --- a/build.sbt +++ b/build.sbt @@ -38,6 +38,9 @@ lazy val root = `zio-quickstart-stm`, `zio-quickstart-sql` ) + .settings( + testFrameworks += new TestFramework("zio.test.sbt.ZTestFramework") + ) lazy val `zio-quickstart-hello-world` = project lazy val `zio-quickstart-junit-integration` = project diff --git a/zio-quickstart-prelude/build.sbt b/zio-quickstart-prelude/build.sbt index 3c2a8b8..c8ab310 100644 --- a/zio-quickstart-prelude/build.sbt +++ b/zio-quickstart-prelude/build.sbt @@ -1,4 +1,5 @@ scalaVersion := "2.13.13" +Test / fork := true libraryDependencies ++= Seq( "dev.zio" %% "zio-prelude" % "1.0.0-RC23", diff --git a/zio-quickstart-sql/build.sbt b/zio-quickstart-sql/build.sbt index 5dbbdbc..d48f0ce 100644 --- a/zio-quickstart-sql/build.sbt +++ b/zio-quickstart-sql/build.sbt @@ -1,4 +1,5 @@ scalaVersion := "2.13.13" +Test / fork := true libraryDependencies ++= Seq( "org.slf4j" % "slf4j-simple" % "2.0.13", diff --git a/zio-quickstart-sql/src/test/scala/PostgresSqlSpec.scala b/zio-quickstart-sql/src/test/scala/PostgresSqlSpec.scala index d54a666..9133a12 100644 --- a/zio-quickstart-sql/src/test/scala/PostgresSqlSpec.scala +++ b/zio-quickstart-sql/src/test/scala/PostgresSqlSpec.scala @@ -9,7 +9,7 @@ import zio.schema.DeriveSchema import zio.test.Assertion._ import zio.test._ -import java.math.BigDecimal +import java.math.{BigDecimal, RoundingMode} import java.time.{LocalDate, ZonedDateTime} import java.util.UUID @@ -58,9 +58,9 @@ object PostgresSqlSpec extends JdbcRunnableSpec { } object OrderSchema { - final case class Order(id: UUID, customerId: UUID, orderDate: LocalDate) - implicit val orderSchema = DeriveSchema.gen[Order] - val orders = defineTable[Order] + final case class Orders(id: UUID, customerId: UUID, orderDate: LocalDate) + implicit val orderSchema = DeriveSchema.gen[Orders] + val orders = defineTable[Orders] val (orderId, fkCustomerId, orderDate) = orders.columns } @@ -124,7 +124,7 @@ object PostgresSqlSpec extends JdbcRunnableSpec { for { result <- execute(selectQuery) - .map(Order tupled _) + .map(Orders tupled _) .runCollect // return chunk of founded rows } yield assert(result)(hasSameElementsDistinct(expected)) }, @@ -164,6 +164,9 @@ object PostgresSqlSpec extends JdbcRunnableSpec { for { result <- execute(query).runHead + roundedResult = result.map { case (totalAmount, soldQuantity) => + (totalAmount.setScale(2, RoundingMode.HALF_EVEN), soldQuantity) + } } yield assert(result)(isSome(equalTo((new BigDecimal(215.99), 40)))) }, test("run custom function") { @@ -217,33 +220,35 @@ object PostgresSqlSpec extends JdbcRunnableSpec { insertAssertion.mapErrorCause(cause => Cause.stackless(cause.untraced)) }, test("render query") { - import OrderSchema._ + import OrderDetailsSchema._ import ProductSchema._ - val selectQuery = select(orderId, name) - .from(products.join(orders).on(productId === orderId)) + val selectQuery = select(quantity, name) + .from( + products.join(orderDetails).on(orderDetailsProductId === productId) + ) .limit(5) .offset(10) val selectQueryRender = - "SELECT \"order\".\"id\", \"products\".\"name\" FROM \"products\" INNER JOIN \"order\" ON \"order\".\"product_id\" = \"products\".\"id\" LIMIT 5 OFFSET 10" + "SELECT \"order_details\".\"quantity\", \"products\".\"name\" FROM \"products\" INNER JOIN \"order_details\" ON \"order_details\".\"product_id\" = \"products\".\"id\" LIMIT 5 OFFSET 10" + val uuid = UUID.randomUUID() val insertQuery = insertInto(products)(productId, name, description).values( ( - UUID.randomUUID(), + uuid, "Zionomicon", "Good book to start your journey in zio" ) ) val insertQueryRender = - "INSERT INTO \"products\" (\"id\", \"name\", \"description\") VALUES (?, ?, ?);" + s"INSERT INTO \"products\" (\"id\", \"name\", \"description\") VALUES ('${uuid.toString}', 'Zionomicon', 'Good book to start your journey in zio');" - val uuid = UUID.randomUUID() val updateQuery = update(products) .set(name, "foo") .where(productId === uuid) val updateQueryRender = - s"UPDATE \"products\" SET \"name\" = 'foo', WHERE \"products\".\"id\" = '${uuid.toString}'" + s"UPDATE \"products\" SET \"name\" = 'foo' WHERE \"products\".\"id\" = '${uuid.toString}'" val deleteQuery = deleteFrom(products).where(productId === uuid) val deleteQueryRender = From f78d9fc3342733ca2e17dfcd77c0a641615bdcbb Mon Sep 17 00:00:00 2001 From: Grigorii Berezin Date: Fri, 10 May 2024 17:23:28 +0300 Subject: [PATCH 5/7] fix: fix tests --- .github/workflows/ci.yml | 4 ++-- build.sbt | 4 +++- .../src/test/scala/PostgresSqlSpec.scala | 23 +++++++++++++++++-- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6ee7088..0bdada6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,8 +35,6 @@ jobs: uses: coursier/cache-action@v6 - name: Check all code compiles run: sbt +Test/compile - - name: Check all tests - run: sbt test - name: Check artifacts build process run: sbt +publishLocal lint: @@ -73,6 +71,8 @@ jobs: - '8' scala-project: - ++2.13.8 zio-quickstart-encode-decode-json + - ++2.13.13 zio-quickstart-sql + - ++2.13.13 zio-quickstart-prelude steps: - name: Install libuv run: sudo apt-get update && sudo apt-get install -y libuv1-dev diff --git a/build.sbt b/build.sbt index e6470dc..509d01a 100644 --- a/build.sbt +++ b/build.sbt @@ -10,7 +10,9 @@ inThisBuild( ciCheckWebsiteBuildProcess := Seq.empty, scalaVersion := "2.13.8", ciTargetScalaVersions := makeTargetScalaMap( - `zio-quickstart-encode-decode-json` + `zio-quickstart-encode-decode-json`, + `zio-quickstart-sql`, + `zio-quickstart-prelude` ).value, ciDefaultTargetJavaVersions := Seq("8"), semanticdbEnabled := true, diff --git a/zio-quickstart-sql/src/test/scala/PostgresSqlSpec.scala b/zio-quickstart-sql/src/test/scala/PostgresSqlSpec.scala index 9133a12..f510fa6 100644 --- a/zio-quickstart-sql/src/test/scala/PostgresSqlSpec.scala +++ b/zio-quickstart-sql/src/test/scala/PostgresSqlSpec.scala @@ -120,7 +120,20 @@ object PostgresSqlSpec extends JdbcRunnableSpec { .limit(2) // set limit .offset(1) // set offset - val expected = Chunk.empty + val expected = Chunk( + Orders( + id = UUID.fromString("5883cb62-d792-4ee3-acbc-fe85b6baa998"), + customerId = + UUID.fromString("784426a5-b90a-4759-afbb-571b7a0ba35e"), + orderDate = LocalDate.of(2020, 4, 30) + ), + Orders( + id = UUID.fromString("763a7c39-833f-4ee8-9939-e80dfdbfc0fc"), + customerId = + UUID.fromString("f76c9ace-be07-4bf3-bd4c-4a9c62882e64"), + orderDate = LocalDate.of(2020, 4, 5) + ) + ) for { result <- execute(selectQuery) @@ -167,7 +180,13 @@ object PostgresSqlSpec extends JdbcRunnableSpec { roundedResult = result.map { case (totalAmount, soldQuantity) => (totalAmount.setScale(2, RoundingMode.HALF_EVEN), soldQuantity) } - } yield assert(result)(isSome(equalTo((new BigDecimal(215.99), 40)))) + } yield assert(roundedResult)( + isSome( + equalTo( + (new BigDecimal(215.99).setScale(2, RoundingMode.HALF_EVEN), 40) + ) + ) + ) }, test("run custom function") { import PostgresFunctionDef._ // to use custom functions From 972ef55a0219f76eb29b173f195bb81081dc5624 Mon Sep 17 00:00:00 2001 From: Grigorii Berezin Date: Mon, 20 May 2024 08:37:12 +0300 Subject: [PATCH 6/7] feat: remove real urls --- zio-quickstart-sql/src/test/resources/db_schema.sql | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/zio-quickstart-sql/src/test/resources/db_schema.sql b/zio-quickstart-sql/src/test/resources/db_schema.sql index 40061e4..dfb9309 100644 --- a/zio-quickstart-sql/src/test/resources/db_schema.sql +++ b/zio-quickstart-sql/src/test/resources/db_schema.sql @@ -49,17 +49,17 @@ values ('60b01fc9-c902-4468-8d49-3c0f989def37', 'Ronald', 'Russell', true, '1983 insert into products (id, name, description, image_url) values ('7368ABF4-AED2-421F-B426-1725DE756895', 'Thermometer', 'Make sure you don''t have a fever (could be covid!)', - 'https://images.pexels.com/photos/3987152/pexels-photo-3987152.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260'), + 'Thermometer picture'), ('4C770002-4C8F-455A-96FF-36A8186D5290', 'Slippers', 'Keep your feet warm this winter', - 'https://images.pexels.com/photos/1989843/pexels-photo-1989843.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260'), + 'Slippers picture'), ('05182725-F5C8-4FD6-9C43-6671E179BF55', 'Mouse Pad', 'Who uses these anyway?', - 'https://images.pexels.com/photos/3944396/pexels-photo-3944396.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260'), + 'Mouse Pad picture'), ('105A2701-EF93-4E25-81AB-8952CC7D9DAA', 'Pants', 'Avoid a lawsuit, wear pants to work today!', - 'https://images.pexels.com/photos/52518/jeans-pants-blue-shop-52518.jpeg?cs=srgb&dl=blue-jeans-clothes-shopping-52518.jpg&fm=jpg'), + 'Pants picture'), ('F35B0053-855B-4145-ABE1-DC62BC1FDB96', 'Nail File', 'Keep those nails looking good', - 'https://images.pexels.com/photos/3997373/pexels-photo-3997373.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260'), + 'Nail File picture'), ('D5137D3A-894A-4109-9986-E982541B434F', 'Teddy Bear', 'Because sometimes you just need something to hug', - 'https://images.pexels.com/photos/1019471/stuffed-bear-teddy-child-girl-1019471.jpeg?cs=srgb&dl=closeup-photography-of-brown-teddy-bear-1019471.jpg&fm=jpg'); + 'Teddy Bear picture'); insert into product_prices (product_id, effective, price) From 8dcf38d42fa3da83bf70560e5eb139459b8e0281 Mon Sep 17 00:00:00 2001 From: Grigorii Berezin Date: Mon, 20 May 2024 15:22:38 +0300 Subject: [PATCH 7/7] feat: update README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 6613f76..c7b2538 100644 --- a/README.md +++ b/README.md @@ -36,4 +36,5 @@ $ sbt run - [ZIO RESTful webservice with docker](zio-quickstart-restful-webservice-dockerize) - [ZIO RESTful webservice with metrics](zio-quickstart-restful-webservice-metrics) - [ZIO STM](zio-quickstart-stm) - many thanks to [@jorge-vasquez-2301](https://github.com/jorge-vasquez-2301) and his [article](https://scalac.io/blog/how-to-write-a-completely-lock-free-concurrent-lru-cache-with-zio-stm/) for this example +- [ZIO SQL](zio-quickstart-sql) - [ZIO Streams](zio-quickstart-streams)