README.md in upsert-0.3.2 vs README.md in upsert-0.3.3

- old
+ new

@@ -1,40 +1,35 @@ # Upsert -Finally, all those SQL MERGE tricks codified so that you can do "upsert" on MySQL, PostgreSQL, and SQLite. +MySQL, PostgreSQL, and SQLite all have different SQL MERGE tricks that you can use to simulate upsert. This library codifies them under a single syntax. -You pass a selector that uniquely identifies a row, whether it exists or not. You pass a set of attributes that should be set on that row. Based on what database is being used, one of a number of SQL MERGE-like tricks are used. - -The second argument is currently (mis)named a "document" because this was inspired by [mongo-ruby-driver's update method](http://api.mongodb.org/ruby/1.6.4/Mongo/Collection.html#update-instance_method). - ## Usage -### One by one +You pass a selector that uniquely identifies a row, whether it exists or not. You pass a set of attributes that should be set on that row. Syntax inspired by [mongo-ruby-driver's update method](http://api.mongodb.org/ruby/1.6.4/Mongo/Collection.html#update-instance_method). -Faster than just doing `Pet.create`... 85% faster on PostgreSQL, for example, than all the different native ActiveRecord methods I've tried. But no validations or anything. +### Single record - upsert = Upsert.new Pet.connection, Pet.table_name + # if you have required 'upsert/active_record_upsert' + Pet.upsert({:name => 'Jerry'}, :breed => 'beagle') + + # if you're not using activerecord, that's ok + connection = Mysql2::Client.new([...]) + upsert = Upsert.new connection, 'pets' upsert.row({:name => 'Jerry'}, :breed => 'beagle') - upsert.row({:name => 'Pierre'}, :breed => 'tabby') -### Batch mode +### Multiple records (batch mode) -Rows are buffered in memory until it's efficient to send them to the database. Currently this only provides an advantage on MySQL because it uses `ON DUPLICATE KEY UPDATE`... but if a similar method appears in PostgreSQL, the same code will still work. +Rows are buffered in memory until it's efficient to send them to the database. - Upsert.batch(Pet.connection, Pet.table_name) do |upsert| + connection = Mysql2::Client.new([...]) + Upsert.batch(connection, 'pets') do |upsert| upsert.row({:name => 'Jerry'}, :breed => 'beagle') upsert.row({:name => 'Pierre'}, :breed => 'tabby') end -### `ActiveRecord::Base.upsert` (optional) +Tested to be much about 85% faster on PostgreSQL and 50% faster on MySQL than comparable methods (see the tests). -For bulk upserts, you probably still want to use `Upsert.batch`. - - require 'upsert/active_record_upsert' - Pet.upsert({:name => 'Jerry'}, :breed => 'beagle') - Pet.upsert({:name => 'Pierre'}, :breed => 'tabby') - ### Gotchas #### Undefined behavior if you use this without properly defining UNIQUE indexes Make sure you're upserting against either primary key columns or columns with UNIQUE indexes or both. @@ -56,12 +51,13 @@ ## Wishlist Pull requests for any of these would be greatly appreciated: 1. Fix SQLite tests. -2. Provide `require 'upsert/debug'` that will make sure you are selecting on columns that have unique indexes -2. If you think there's a fix for the "fixed column set" gotcha... -3. Naming suggestions: should "document" be called "setters" or "attributes"? +2. For PG, be smarter about when you create functions - try to re-use them within a connection. +3. Provide `require 'upsert/debug'` that will make sure you are selecting on columns that have unique indexes +4. Make `Upsert` instances accept arbitrary columns, which is what people probably expect. +5. Naming suggestions: should "document" be called "setters" or "attributes"? ## Real-world usage <p><a href="http://brighterplanet.com"><img src="https://s3.amazonaws.com/static.brighterplanet.com/assets/logos/flush-left/inline/green/rasterized/brighter_planet-160-transparent.png" alt="Brighter Planet logo"/></a></p>