{"html_url": "https://github.com/simonw/sqlite-utils/issues/23#issuecomment-507050894", "issue_url": "https://api.github.com/repos/simonw/sqlite-utils/issues/23", "id": 507050894, "node_id": "MDEyOklzc3VlQ29tbWVudDUwNzA1MDg5NA==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2019-06-30T16:51:39Z", "updated_at": "2019-06-30T16:55:16Z", "author_association": "OWNER", "body": "One option:\r\n\r\n db.insert_m2m(\"dogs\", 1, \"breeds\", 3)\r\n\r\nThis would create the missing m2m table if it did not already exist, and call it `dogs_breeds`.\r\n\r\nYou can pass an optional `m2m_table=` argument to specify the table name:\r\n\r\n db.insert_m2m(\"dogs\", 1, \"breeds\", 3, m2m_table=\"dog_m2m_breeds\")\r\n\r\nMaybe allow passing extra key/value pairs that will be inserted into the m2m table?\r\n\r\n db.insert_m2m(\"dogs\", 1, \"breeds\", 3, m2m_extra={\"classified_on_date\": \"2019-04-01\"})\r\n\r\nCould even accept `alter=True` to cause the m2m table to be automatically altered to fit any `m2m_extra=` columns that do not already exist.\r\n\r\nIt would be nice if there was a `table.*` method for this which allowed you to send three arguments rather than four. Maybe something like this:\r\n\r\n db[\"dogs\"].insert_m2m(1, \"breeds\", 3)\r\n\r\nIt's a bit confusing them both having the same method name though. Also calling it `insert_m2m` here is odd because you're not inserting into the `dogs` table.\r\n\r\nMaybe this instead?\r\n\r\n db[\"dogs\"].m2m(1, \"breeds\", 3)", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 449565204, "label": "Syntactic sugar for creating m2m records"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/sqlite-utils/issues/23#issuecomment-507051067", "issue_url": "https://api.github.com/repos/simonw/sqlite-utils/issues/23", "id": 507051067, "node_id": "MDEyOklzc3VlQ29tbWVudDUwNzA1MTA2Nw==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2019-06-30T16:54:08Z", "updated_at": "2019-06-30T16:59:05Z", "author_association": "OWNER", "body": "There could be a version of this which inserts the related record into the other table if it is missing, but reuses it if it's already there. That might look like this:\r\n\r\n db[\"events\"].m2m(3, \"venues\", {\r\n \"id\": 4,\r\n \"venue_name\": \"Blah\",\r\n \"latitude\": 37.77\r\n \"longitude\": 122.42\r\n }, pk=\"id\")\r\n\r\nSince this is doing an `.upsert()` against `venues`, the `.m2m()` method could accept all of the other arguments to `.upsert()` - probably `pk=`, `column_order=` and `ignore=True` as well (actually borrowed from `.insert(...)`, it would mean don't update this row if you find it).", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 449565204, "label": "Syntactic sugar for creating m2m records"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/sqlite-utils/issues/23#issuecomment-507051516", "issue_url": "https://api.github.com/repos/simonw/sqlite-utils/issues/23", "id": 507051516, "node_id": "MDEyOklzc3VlQ29tbWVudDUwNzA1MTUxNg==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2019-06-30T17:01:26Z", "updated_at": "2019-06-30T17:03:16Z", "author_association": "OWNER", "body": "Question: do I set a compound primary key on `(event_id, venue_id)` or do I add an auto-incrementing surrogate key as well?\r\n\r\nI'm leaning towards compound primary key. Maybe that's the default and there's an option for including a regular incrementing primary key.\r\n```\r\ndb[\"events\"].m2m(3, \"venues\", {\r\n \"id\": 4,\r\n \"venue_name\": \"Blah\",\r\n \"latitude\": 37.77\r\n \"longitude\": 122.42\r\n}, pk=\"id\", m2m_surrogate_id=True)\r\n```\r\nIf you use `m2m_surrogate_id` I'll still make sure to set up a unique constraint on `(event_id, venue_id)`", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 449565204, "label": "Syntactic sugar for creating m2m records"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/sqlite-utils/issues/26#issuecomment-507051670", "issue_url": "https://api.github.com/repos/simonw/sqlite-utils/issues/26", "id": 507051670, "node_id": "MDEyOklzc3VlQ29tbWVudDUwNzA1MTY3MA==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2019-06-30T17:04:09Z", "updated_at": "2019-06-30T17:04:09Z", "author_association": "OWNER", "body": "I think the implementation of this will benefit from #23 (syntactic sugar for creating m2m records)", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 455486286, "label": "Mechanism for turning nested JSON into foreign keys / many-to-many"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/sqlite-utils/issues/23#issuecomment-507051825", "issue_url": "https://api.github.com/repos/simonw/sqlite-utils/issues/23", "id": 507051825, "node_id": "MDEyOklzc3VlQ29tbWVudDUwNzA1MTgyNQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2019-06-30T17:06:29Z", "updated_at": "2019-06-30T17:06:29Z", "author_association": "OWNER", "body": "For this method:\r\n```python\r\ndb[\"events\"].m2m(3, \"venues\", {\r\n \"id\": 4,\r\n \"venue_name\": \"Blah\",\r\n \"latitude\": 37.77\r\n \"longitude\": 122.42\r\n}, pk=\"id\")\r\n```\r\nLet's say that the first argument is allowed to be either a string/integer representing a primary key, OR it can be a full row record (a dictionary) which will have its primary key automatically extracted based on the table definition.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 449565204, "label": "Syntactic sugar for creating m2m records"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/sqlite-utils/issues/23#issuecomment-507052051", "issue_url": "https://api.github.com/repos/simonw/sqlite-utils/issues/23", "id": 507052051, "node_id": "MDEyOklzc3VlQ29tbWVudDUwNzA1MjA1MQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2019-06-30T17:09:51Z", "updated_at": "2019-06-30T17:15:09Z", "author_association": "OWNER", "body": "Maybe there's a case where we want to be able to insert a row AND add its m2m records in a single operation? Could look something like this:\r\n\r\n```python\r\ndb[\"events\"].insert({\r\n \"id\": 1,\r\n \"title\": \"Some event\"\r\n}, m2m={\r\n \"venues\": {\r\n \"id\": 4,\r\n \"venue_name\": \"Blah\",\r\n \"latitude\": 37.77\r\n \"longitude\": 122.42\r\n }\r\n})\r\n```\r\nThe `venues` key in that dictionary could be a single dictionary or a list of dictionary.\r\n\r\nI'm not sure about this though. If the `m2m=` argument causes the creation of the `venues` table, how would we pass in extra creation options like `pk=` for that table?\r\n\r\nMaybe some complex nested function mechanism like this?\r\n\r\n```python\r\ndb[\"events\"].insert({\r\n \"id\": 1,\r\n \"title\": \"Some event\"\r\n}, m2m=[db[\"venues\"].upsert({\r\n \"id\": 4,\r\n \"venue_name\": \"Blah\",\r\n \"latitude\": 37.77\r\n \"longitude\": 122.42\r\n }, pk=\"id\")]\r\n})\r\n```\r\n\r\nThis would require having `.insert()` and friends return a more interesting object than they do at the moment. They currently return `self` to support chaining. Changing this would be a backwards-incompatible change and hence would require a major version bump... _unless_ they continued to return `self` but remembered the last inserted record in a way that could be handled by that `m2m=` argument.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 449565204, "label": "Syntactic sugar for creating m2m records"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/sqlite-utils/issues/23#issuecomment-507053558", "issue_url": "https://api.github.com/repos/simonw/sqlite-utils/issues/23", "id": 507053558, "node_id": "MDEyOklzc3VlQ29tbWVudDUwNzA1MzU1OA==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2019-06-30T17:34:29Z", "updated_at": "2019-06-30T17:34:29Z", "author_association": "OWNER", "body": "Or... how about we use chaining like this:\r\n\r\n```python\r\ndb[\"events\"].insert({...}, pk=\"id\").m2m(\"venues\", {...}, pk=\"id\")\r\n```\r\nThis makes me think that maybe there should be some kind of mechanism for saying \"I'd should always be treated as a primary key\". Maybe as an argument passed to the `Database` constructor.\r\n", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 449565204, "label": "Syntactic sugar for creating m2m records"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/sqlite-utils/issues/23#issuecomment-507053731", "issue_url": "https://api.github.com/repos/simonw/sqlite-utils/issues/23", "id": 507053731, "node_id": "MDEyOklzc3VlQ29tbWVudDUwNzA1MzczMQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2019-06-30T17:37:33Z", "updated_at": "2019-06-30T17:37:33Z", "author_association": "OWNER", "body": "Implementing the `table.m2m()` method to have an optional _first_ argument (optional in that if it's in a chained operation it uses the last inserted thing) could be tricky. How to tell the difference between the two uses? A different method name would be better.\r\n", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 449565204, "label": "Syntactic sugar for creating m2m records"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/sqlite-utils/issues/23#issuecomment-507055345", "issue_url": "https://api.github.com/repos/simonw/sqlite-utils/issues/23", "id": 507055345, "node_id": "MDEyOklzc3VlQ29tbWVudDUwNzA1NTM0NQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2019-06-30T18:02:25Z", "updated_at": "2019-06-30T18:02:33Z", "author_association": "OWNER", "body": "I have a solution. If I introduce a `db[table_name].update(row_pk, {...})` method I can use that method without the dictionary argument to select a specific row as the \"currently editing / last inserted\" row in the table context. Then I can support the following:\r\n```python\r\ndb[\"events\"].update(3).m2m(\"venues\", {...}, pk=\"id\")\r\n```\r\nThis means that the `table.m2m()` method will only work in the context of a chain, and will throw an error if you attempt to call it without first using `.insert()` or `.update()` to select a record that you will be manipulating first.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 449565204, "label": "Syntactic sugar for creating m2m records"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/sqlite-utils/issues/33#issuecomment-507077631", "issue_url": "https://api.github.com/repos/simonw/sqlite-utils/issues/33", "id": 507077631, "node_id": "MDEyOklzc3VlQ29tbWVudDUwNzA3NzYzMQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2019-06-30T23:53:34Z", "updated_at": "2019-06-30T23:53:34Z", "author_association": "OWNER", "body": "This was needed for https://github.com/simonw/db-to-sqlite/issues/12", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 462423839, "label": "index_foreign_keys / index-foreign-keys utilities"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/sqlite-utils/issues/33#issuecomment-507077672", "issue_url": "https://api.github.com/repos/simonw/sqlite-utils/issues/33", "id": 507077672, "node_id": "MDEyOklzc3VlQ29tbWVudDUwNzA3NzY3Mg==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2019-06-30T23:54:11Z", "updated_at": "2019-06-30T23:54:11Z", "author_association": "OWNER", "body": "Released in 1.4: https://sqlite-utils.readthedocs.io/en/latest/changelog.html#v1-4", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 462423839, "label": "index_foreign_keys / index-foreign-keys utilities"}, "performed_via_github_app": null}