{"id":2182,"date":"2010-10-26T14:18:22","date_gmt":"2010-10-26T04:18:22","guid":{"rendered":"http:\/\/www.flamingspork.com\/blog\/?p=2182"},"modified":"2010-10-26T14:18:22","modified_gmt":"2010-10-26T04:18:22","slug":"cursor-states","status":"publish","type":"post","link":"https:\/\/www.flamingspork.com\/blog\/2010\/10\/26\/cursor-states\/","title":{"rendered":"Cursor states"},"content":{"rendered":"<p>Following on from my <a href=\"http:\/\/www.flamingspork.com\/blog\/2010\/10\/25\/storage-engine-api-state-graph\/\">post yesterday on the various states of a Storage Engine<\/a>, I said I&#8217;d have a go with the Cursor object too. A Cursor is used by the Drizzle kernel to get and set data in a table. There can be more than one cursor open at once, and more than one per thread. If your engine cannot cope with this, it is its responsibility to figure it out and return the appropriate errors.<\/p>\n<p>Let&#8217;s look at a really simple operation, inserting a couple of rows and then reading them back via a full table scan.<\/p>\n<p><a href=\"https:\/\/i0.wp.com\/www.flamingspork.com\/blog\/wp-content\/uploads\/2010\/10\/graph1.png\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" data-attachment-id=\"2183\" data-permalink=\"https:\/\/www.flamingspork.com\/blog\/2010\/10\/26\/cursor-states\/graph1\/\" data-orig-file=\"https:\/\/i0.wp.com\/www.flamingspork.com\/blog\/wp-content\/uploads\/2010\/10\/graph1.png?fit=408%2C430&amp;ssl=1\" data-orig-size=\"408,430\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}\" data-image-title=\"Cursor states: insert record, full table scan\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/www.flamingspork.com\/blog\/wp-content\/uploads\/2010\/10\/graph1.png?fit=408%2C430&amp;ssl=1\" class=\"aligncenter size-medium wp-image-2183\" title=\"Cursor states: insert record, full table scan\" src=\"https:\/\/i0.wp.com\/www.flamingspork.com\/blog\/wp-content\/uploads\/2010\/10\/graph1-284x300.png?resize=284%2C300\" alt=\"\" width=\"284\" height=\"300\" srcset=\"https:\/\/i0.wp.com\/www.flamingspork.com\/blog\/wp-content\/uploads\/2010\/10\/graph1.png?resize=284%2C300&amp;ssl=1 284w, https:\/\/i0.wp.com\/www.flamingspork.com\/blog\/wp-content\/uploads\/2010\/10\/graph1.png?w=408&amp;ssl=1 408w\" sizes=\"auto, (max-width: 284px) 100vw, 284px\" \/><\/a><\/p>\n<p>Now, this graph is slightly incomplete as there is no doEndTableScan() call. But you can see in which order things are meant to happen. In this case, &#8220;store_lock()&#8221; means that store_lock() has been called, so when coming back from doInsertRecord() we do <strong>not<\/strong> call store_lock() again, rather, we&#8217;re just in a state where it has already been executed.<\/p>\n<p>For MySQL handler, think ::write_row() for doInsertRecord() and ::rnd_init() for doStartTableScan().<\/p>\n<p>This diagram was again auto-generated from my test engine.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Following on from my post yesterday on the various states of a Storage Engine, I said I&#8217;d have a go with the Cursor object too. A Cursor is used by the Drizzle kernel to get and set data in a &hellip; <a href=\"https:\/\/www.flamingspork.com\/blog\/2010\/10\/26\/cursor-states\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[76,75,14],"tags":[382,70,628,80],"class_list":["post-2182","post","type-post","status-publish","format-standard","hentry","category-code","category-drizzle-work-et-al","category-mysql","tag-cursor","tag-drizzle","tag-mysql","tag-storage-engine-api"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p5a6n8-zc","jetpack-related-posts":[{"id":1879,"url":"https:\/\/www.flamingspork.com\/blog\/2010\/05\/24\/using-the-row-buffer-in-drizzle-and-mysql\/","url_meta":{"origin":2182,"position":0},"title":"Using the row buffer in Drizzle (and MySQL)","author":"Stewart Smith","date":"2010-05-24","format":false,"excerpt":"Here's another bit of the API you may need to use in your storage engine (it also seems to be a rather unknown. I believe the only place where this has really been documented is ha_ndbcluster.cc, so here goes.... Drizzle (through inheritance from MySQL) has its own (in memory) row\u2026","rel":"","context":"In &quot;drizzle&quot;","block_context":{"text":"drizzle","link":"https:\/\/www.flamingspork.com\/blog\/category\/work-et-al\/drizzle-work-et-al\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.flamingspork.com\/blog\/wp-content\/uploads\/2010\/04\/row-300x85.png?resize=350%2C200","width":350,"height":200},"classes":[]},{"id":2210,"url":"https:\/\/www.flamingspork.com\/blog\/2010\/11\/29\/a-more-complete-look-at-storage-engine-api\/","url_meta":{"origin":2182,"position":1},"title":"A more complete look at Storage Engine API","author":"Stewart Smith","date":"2010-11-29","format":false,"excerpt":"Okay... So I've blogged many times before about the Storage Engine API in Drizzle. This API is somewhat inherited from MySQL. We have very much attempted to make it a much cleaner interface. Our goals in making changes include: make it much easier to write and maintain a storage engine,\u2026","rel":"","context":"In &quot;drizzle&quot;","block_context":{"text":"drizzle","link":"https:\/\/www.flamingspork.com\/blog\/category\/work-et-al\/drizzle-work-et-al\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.flamingspork.com\/blog\/wp-content\/uploads\/2010\/11\/engine-300x140.png?resize=350%2C200","width":350,"height":200},"classes":[]},{"id":1931,"url":"https:\/\/www.flamingspork.com\/blog\/2010\/05\/26\/blobs-in-the-drizzlemysql-storage-engine-api\/","url_meta":{"origin":2182,"position":2},"title":"BLOBS in the Drizzle\/MySQL Storage Engine API","author":"Stewart Smith","date":"2010-05-26","format":false,"excerpt":"Another (AFAIK) undocumented part of the Storage Engine API: We all know what a normal row looks like in Drizzle\/MySQL row format (a NULL bitmap and then column data): Nothing that special. It's a fixed sized buffer, Field objects reference into it, you read out of it and write the\u2026","rel":"","context":"In &quot;drizzle&quot;","block_context":{"text":"drizzle","link":"https:\/\/www.flamingspork.com\/blog\/category\/work-et-al\/drizzle-work-et-al\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.flamingspork.com\/blog\/wp-content\/uploads\/2010\/05\/rect28161-300x67.png?resize=350%2C200","width":350,"height":200},"classes":[]},{"id":2168,"url":"https:\/\/www.flamingspork.com\/blog\/2010\/10\/25\/storage-engine-api-state-graph\/","url_meta":{"origin":2182,"position":3},"title":"Storage Engine API state graph","author":"Stewart Smith","date":"2010-10-25","format":false,"excerpt":"Drizzle still has a number of quirks inherited from the MySQL Storage Engine API (e.g. BLOBs, row buffer, CREATE SELECT and lack of DDL transaction boundaries, key tuple format). One of the things we fixed a long time ago was to have proper methods for StorageEngines to be called for:\u2026","rel":"","context":"In &quot;code&quot;","block_context":{"text":"code","link":"https:\/\/www.flamingspork.com\/blog\/category\/code\/"},"img":{"alt_text":"State transitions for a transaction. Transaction can be empty OR have one or more statements","src":"https:\/\/i0.wp.com\/www.flamingspork.com\/blog\/wp-content\/uploads\/2010\/10\/edge30-300x163.png?resize=350%2C200","width":350,"height":200},"classes":[]},{"id":1903,"url":"https:\/\/www.flamingspork.com\/blog\/2010\/04\/21\/storage-engine-api-write_row-create-select-and-ddl\/","url_meta":{"origin":2182,"position":4},"title":"Storage Engine API: write_row, CREATE SELECT and DDL","author":"Stewart Smith","date":"2010-04-21","format":false,"excerpt":"(this probably applies exactly the same for MySQL and Drizzle... but I'm just speaking about current Drizzle here) In my current merge request for the embedded-innodb\u00ef\u00bb\u00bf-create-select-transaction-arrgh branch (also see this specific revision), you'll notice an odd hoop that we have to jump through to make CREATE SELECT statements work with\u2026","rel":"","context":"In &quot;drizzle&quot;","block_context":{"text":"drizzle","link":"https:\/\/www.flamingspork.com\/blog\/category\/work-et-al\/drizzle-work-et-al\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1876,"url":"https:\/\/www.flamingspork.com\/blog\/2010\/04\/02\/the-drizzle-and-mysql-key-tuple-format\/","url_meta":{"origin":2182,"position":5},"title":"The Drizzle (and MySQL) Key tuple format","author":"Stewart Smith","date":"2010-04-02","format":false,"excerpt":"Here's something that's not really documented anywhere (unless you count ha_innodb.cc as a source of server documentation). You may have some idea about the MySQL\/Drizzle row buffer format. This is passed around the storage engine interface: in for write_row and update_row and out for the various scan and index read\u2026","rel":"","context":"In &quot;drizzle&quot;","block_context":{"text":"drizzle","link":"https:\/\/www.flamingspork.com\/blog\/category\/work-et-al\/drizzle-work-et-al\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/www.flamingspork.com\/blog\/wp-json\/wp\/v2\/posts\/2182","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.flamingspork.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.flamingspork.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.flamingspork.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.flamingspork.com\/blog\/wp-json\/wp\/v2\/comments?post=2182"}],"version-history":[{"count":1,"href":"https:\/\/www.flamingspork.com\/blog\/wp-json\/wp\/v2\/posts\/2182\/revisions"}],"predecessor-version":[{"id":2184,"href":"https:\/\/www.flamingspork.com\/blog\/wp-json\/wp\/v2\/posts\/2182\/revisions\/2184"}],"wp:attachment":[{"href":"https:\/\/www.flamingspork.com\/blog\/wp-json\/wp\/v2\/media?parent=2182"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.flamingspork.com\/blog\/wp-json\/wp\/v2\/categories?post=2182"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.flamingspork.com\/blog\/wp-json\/wp\/v2\/tags?post=2182"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}