extralite-bundle 1.27 → 2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/CHANGELOG.md +9 -0
 - data/Gemfile.lock +1 -1
 - data/LICENSE +1 -1
 - data/README.md +40 -14
 - data/TODO.md +5 -0
 - data/ext/extralite/common.c +75 -58
 - data/ext/extralite/database.c +21 -12
 - data/ext/extralite/extconf.rb +16 -16
 - data/ext/extralite/extralite.h +61 -16
 - data/ext/extralite/extralite_ext.c +4 -2
 - data/ext/extralite/iterator.c +180 -0
 - data/ext/extralite/query.c +479 -0
 - data/lib/extralite/sqlite3_constants.rb +1 -1
 - data/lib/extralite/version.rb +1 -1
 - data/lib/sequel/adapters/extralite.rb +104 -106
 - data/test/perf_prepared.rb +2 -2
 - data/test/test_database.rb +9 -9
 - data/test/test_extralite.rb +1 -1
 - data/test/test_iterator.rb +99 -0
 - data/test/test_query.rb +502 -0
 - data/test/test_sequel.rb +23 -4
 - metadata +6 -4
 - data/ext/extralite/prepared_statement.c +0 -333
 - data/test/test_prepared_statement.rb +0 -225
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: '065380a4b010e7a2e34c7f79ac1e1b2aae0a999e73f8a1263f47332de7257190'
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 8dcad5df68d791e4411e347ae55b88a61a4fef7f93e33200cdd144716f17e087
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 6e190b0418ad9a59b08039948ae69985b3264d177990eb4e1eb80b82514502e36cf33cddb60cecd5a780d5d47fd8db47d04f9f91c0a735fbc4032e2d4cdf3c77
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 435ab81c615f2fcd3f7a6ed49d3ba28390ae8ed9f6c25f9ddeca51c26c32e5ccbf7ab7276a8ff9f8812d8f6c27d951bb47add5f4edbd5948b05bf68ebecb6663
         
     | 
    
        data/CHANGELOG.md
    CHANGED
    
    | 
         @@ -1,3 +1,12 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # 2.0 2023-07-08
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            - Fix Sequel migrations (#8)
         
     | 
| 
      
 4 
     | 
    
         
            +
            - Redesign prepared statement functionality (#24)
         
     | 
| 
      
 5 
     | 
    
         
            +
              - Rewrite `Extralite::PreparedStatement` into `Extralite::Query` with breaking API changes
         
     | 
| 
      
 6 
     | 
    
         
            +
              - Add `Extralite::Iterator` class for external iteration
         
     | 
| 
      
 7 
     | 
    
         
            +
              - Add `Query#each_xxx`, `Query#to_a_xxx` method
         
     | 
| 
      
 8 
     | 
    
         
            +
              - Add `Query#eof?` method
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
       1 
10 
     | 
    
         
             
            # 1.27 2023-06-12
         
     | 
| 
       2 
11 
     | 
    
         | 
| 
       3 
12 
     | 
    
         
             
            - Fix execution of prepared statements in Sequel adapter (#23 @gschlager)
         
     | 
    
        data/Gemfile.lock
    CHANGED
    
    
    
        data/LICENSE
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | 
         @@ -9,7 +9,7 @@ 
     | 
|
| 
       9 
9 
     | 
    
         | 
| 
       10 
10 
     | 
    
         
             
            Extralite is a super fast, extra-lightweight (about 1300 lines of C-code)
         
     | 
| 
       11 
11 
     | 
    
         
             
            SQLite3 wrapper for Ruby. It provides a minimal set of methods for interacting
         
     | 
| 
       12 
     | 
    
         
            -
            with an SQLite3 database, as well as prepared statements.
         
     | 
| 
      
 12 
     | 
    
         
            +
            with an SQLite3 database, as well as prepared queries (prepared statements).
         
     | 
| 
       13 
13 
     | 
    
         | 
| 
       14 
14 
     | 
    
         
             
            Extralite comes in two flavors: the `extralite` gem which uses the
         
     | 
| 
       15 
15 
     | 
    
         
             
            system-installed sqlite3 library, and the `extralite-bundle` gem which bundles
         
     | 
| 
         @@ -26,11 +26,11 @@ latest features and enhancements. 
     | 
|
| 
       26 
26 
     | 
    
         
             
              as arrays, single row, single column, single value.
         
     | 
| 
       27 
27 
     | 
    
         
             
            - Prepared statements.
         
     | 
| 
       28 
28 
     | 
    
         
             
            - Parameter binding.
         
     | 
| 
      
 29 
     | 
    
         
            +
            - External iteration - get single records or batches of records.
         
     | 
| 
       29 
30 
     | 
    
         
             
            - Use system-installed sqlite3, or the [bundled latest version of
         
     | 
| 
       30 
31 
     | 
    
         
             
              SQLite3](#installing-the-extralite-sqlite3-bundle).
         
     | 
| 
       31 
32 
     | 
    
         
             
            - Improved [concurrency](#concurrency) for multithreaded apps: the Ruby GVL is
         
     | 
| 
       32 
33 
     | 
    
         
             
              released while preparing SQL statements and while iterating over results.
         
     | 
| 
       33 
     | 
    
         
            -
            - Iterate over records with a block, or collect records into an array.
         
     | 
| 
       34 
34 
     | 
    
         
             
            - Automatically execute SQL strings containing multiple semicolon-separated
         
     | 
| 
       35 
35 
     | 
    
         
             
              queries (handy for creating/modifying schemas).
         
     | 
| 
       36 
36 
     | 
    
         
             
            - Execute the same query with multiple parameter lists (useful for inserting records).
         
     | 
| 
         @@ -111,11 +111,37 @@ db.query('select * from foo where bar = :bar', ':bar' => 42) 
     | 
|
| 
       111 
111 
     | 
    
         
             
            db.execute_multi('insert into foo values (?)', ['bar', 'baz'])
         
     | 
| 
       112 
112 
     | 
    
         
             
            db.execute_multi('insert into foo values (?, ?)', [[1, 2], [3, 4]])
         
     | 
| 
       113 
113 
     | 
    
         | 
| 
       114 
     | 
    
         
            -
            # prepared  
     | 
| 
       115 
     | 
    
         
            -
             
     | 
| 
       116 
     | 
    
         
            -
             
     | 
| 
       117 
     | 
    
         
            -
             
     | 
| 
       118 
     | 
    
         
            -
             
     | 
| 
      
 114 
     | 
    
         
            +
            # prepared queries
         
     | 
| 
      
 115 
     | 
    
         
            +
            query = db.prepare('select ? as foo, ? as bar') #=> Extralite::Query
         
     | 
| 
      
 116 
     | 
    
         
            +
            query.bind(1, 2) #=> [{ :foo => 1, :bar => 2 }]
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
            query.next #=> next row in result_set (as hash)
         
     | 
| 
      
 119 
     | 
    
         
            +
            query.next_hash #=> next row in result_set (as hash)
         
     | 
| 
      
 120 
     | 
    
         
            +
            query.next_ary #=> next row in result_set (as array)
         
     | 
| 
      
 121 
     | 
    
         
            +
            query.next_single_column #=> next row in result_set (as single value)
         
     | 
| 
      
 122 
     | 
    
         
            +
             
     | 
| 
      
 123 
     | 
    
         
            +
            query.next(10) #=> next 10 rows in result_set (as hash)
         
     | 
| 
      
 124 
     | 
    
         
            +
            query.next_hash(10) #=> next 10 rows in result_set (as hash)
         
     | 
| 
      
 125 
     | 
    
         
            +
            query.next_ary(10) #=> next 10 rows in result_set (as array)
         
     | 
| 
      
 126 
     | 
    
         
            +
            query.next_single_column(10) #=> next 10 rows in result_set (as single value)
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
            query.to_a #=> all rows as array of hashes
         
     | 
| 
      
 129 
     | 
    
         
            +
            query.to_a_hash #=> all rows as array of hashes
         
     | 
| 
      
 130 
     | 
    
         
            +
            query.to_a_ary #=> all rows as array of arrays
         
     | 
| 
      
 131 
     | 
    
         
            +
            query.to_a_single_column #=> all rows as array of single values
         
     | 
| 
      
 132 
     | 
    
         
            +
             
     | 
| 
      
 133 
     | 
    
         
            +
            query.each { |r| ... } #=> iterate over all rows as hashes
         
     | 
| 
      
 134 
     | 
    
         
            +
            query.each_hash { |r| ... } #=> iterate over all rows as hashes
         
     | 
| 
      
 135 
     | 
    
         
            +
            query.each_ary { |r| ... } #=> iterate over all rows as arrays
         
     | 
| 
      
 136 
     | 
    
         
            +
            query.each_single_column { |r| ... } #=> iterate over all rows as single columns
         
     | 
| 
      
 137 
     | 
    
         
            +
             
     | 
| 
      
 138 
     | 
    
         
            +
            iterator = query.each #=> create enumerable iterator
         
     | 
| 
      
 139 
     | 
    
         
            +
            iterator.next #=> next row
         
     | 
| 
      
 140 
     | 
    
         
            +
            iterator.each { |r| ... } #=> iterate over all rows
         
     | 
| 
      
 141 
     | 
    
         
            +
            values = iterator.map { |r| r[:foo] * 10 } #=> map all rows
         
     | 
| 
      
 142 
     | 
    
         
            +
             
     | 
| 
      
 143 
     | 
    
         
            +
            iterator = query.each_ary #=> create enumerable iterator with rows as arrays
         
     | 
| 
      
 144 
     | 
    
         
            +
            iterator = query.each_single_column #=> create enumerable iterator with single values
         
     | 
| 
       119 
145 
     | 
    
         | 
| 
       120 
146 
     | 
    
         
             
            # get last insert rowid
         
     | 
| 
       121 
147 
     | 
    
         
             
            rowid = db.last_insert_rowid
         
     | 
| 
         @@ -195,10 +221,10 @@ end 
     | 
|
| 
       195 
221 
     | 
    
         | 
| 
       196 
222 
     | 
    
         
             
            Extralite provides methods for retrieving status information about the sqlite
         
     | 
| 
       197 
223 
     | 
    
         
             
            runtime, database-specific status and prepared statement-specific status,
         
     | 
| 
       198 
     | 
    
         
            -
            `Extralite.runtime_status`, `Database#status` and ` 
     | 
| 
       199 
     | 
    
         
            -
             
     | 
| 
       200 
     | 
    
         
            -
             
     | 
| 
       201 
     | 
    
         
            -
             
     | 
| 
      
 224 
     | 
    
         
            +
            `Extralite.runtime_status`, `Database#status` and `Query#status` respectively.
         
     | 
| 
      
 225 
     | 
    
         
            +
            You can also reset the high water mark for the specific status code by providing
         
     | 
| 
      
 226 
     | 
    
         
            +
            true as the reset argument. The status codes mirror those defined by the SQLite
         
     | 
| 
      
 227 
     | 
    
         
            +
            API. Some examples:
         
     | 
| 
       202 
228 
     | 
    
         | 
| 
       203 
229 
     | 
    
         
             
            ```ruby
         
     | 
| 
       204 
230 
     | 
    
         
             
            # The Extralite.runtime_status returns a tuple consisting of the current value
         
     | 
| 
         @@ -212,9 +238,9 @@ current, high_watermark = Extralite.runtime_status(Extralite::SQLITE_STATUS_MEMO 
     | 
|
| 
       212 
238 
     | 
    
         
             
            # argument in order to reset the high watermark):
         
     | 
| 
       213 
239 
     | 
    
         
             
            current, high_watermark = db.status(Extralite::SQLITE_DBSTATUS_CACHE_USED)
         
     | 
| 
       214 
240 
     | 
    
         | 
| 
       215 
     | 
    
         
            -
            # The  
     | 
| 
      
 241 
     | 
    
         
            +
            # The Query#status method returns a single value (pass true as a
         
     | 
| 
       216 
242 
     | 
    
         
             
            # second argument in order to reset the high watermark):
         
     | 
| 
       217 
     | 
    
         
            -
            value =  
     | 
| 
      
 243 
     | 
    
         
            +
            value = query.status(Extralite::SQLITE_STMTSTATUS_RUN)
         
     | 
| 
       218 
244 
     | 
    
         
             
            ```
         
     | 
| 
       219 
245 
     | 
    
         | 
| 
       220 
246 
     | 
    
         
             
            ### Working with Database Limits
         
     | 
| 
         @@ -302,7 +328,7 @@ large number of rows. 
     | 
|
| 
       302 
328 
     | 
    
         
             
            |1K|502.1K rows/s|2.065M rows/s|__4.11x__|
         
     | 
| 
       303 
329 
     | 
    
         
             
            |100K|455.7K rows/s|2.511M rows/s|__5.51x__|
         
     | 
| 
       304 
330 
     | 
    
         | 
| 
       305 
     | 
    
         
            -
            ### Prepared Statements
         
     | 
| 
      
 331 
     | 
    
         
            +
            ### Prepared Queries (Prepared Statements)
         
     | 
| 
       306 
332 
     | 
    
         | 
| 
       307 
333 
     | 
    
         
             
            [Benchmark source code](https://github.com/digital-fabric/extralite/blob/main/test/perf_prepared.rb)
         
     | 
| 
       308 
334 
     | 
    
         | 
    
        data/TODO.md
    CHANGED
    
    
    
        data/ext/extralite/common.c
    CHANGED
    
    | 
         @@ -75,13 +75,11 @@ inline void bind_parameter_value(sqlite3_stmt *stmt, int pos, VALUE value) { 
     | 
|
| 
       75 
75 
     | 
    
         
             
              }
         
     | 
| 
       76 
76 
     | 
    
         
             
            }
         
     | 
| 
       77 
77 
     | 
    
         | 
| 
       78 
     | 
    
         
            -
            void bind_all_parameters(sqlite3_stmt *stmt, int argc, VALUE *argv) {
         
     | 
| 
       79 
     | 
    
         
            -
              for (int i = 0; i < argc; i++)  
     | 
| 
       80 
     | 
    
         
            -
                bind_parameter_value(stmt, i + 1, argv[i]);
         
     | 
| 
       81 
     | 
    
         
            -
              }
         
     | 
| 
      
 78 
     | 
    
         
            +
            inline void bind_all_parameters(sqlite3_stmt *stmt, int argc, VALUE *argv) {
         
     | 
| 
      
 79 
     | 
    
         
            +
              for (int i = 0; i < argc; i++) bind_parameter_value(stmt, i + 1, argv[i]);
         
     | 
| 
       82 
80 
     | 
    
         
             
            }
         
     | 
| 
       83 
81 
     | 
    
         | 
| 
       84 
     | 
    
         
            -
            void bind_all_parameters_from_object(sqlite3_stmt *stmt, VALUE obj) {
         
     | 
| 
      
 82 
     | 
    
         
            +
            inline void bind_all_parameters_from_object(sqlite3_stmt *stmt, VALUE obj) {
         
     | 
| 
       85 
83 
     | 
    
         
             
              if (TYPE(obj) == T_ARRAY) {
         
     | 
| 
       86 
84 
     | 
    
         
             
                int count = RARRAY_LEN(obj);
         
     | 
| 
       87 
85 
     | 
    
         
             
                for (int i = 0; i < count; i++)
         
     | 
| 
         @@ -233,22 +231,23 @@ void *stmt_iterate_without_gvl(void *ptr) { 
     | 
|
| 
       233 
231 
     | 
    
         
             
              return NULL;
         
     | 
| 
       234 
232 
     | 
    
         
             
            }
         
     | 
| 
       235 
233 
     | 
    
         | 
| 
       236 
     | 
    
         
            -
            int stmt_iterate( 
     | 
| 
       237 
     | 
    
         
            -
              struct step_ctx  
     | 
| 
       238 
     | 
    
         
            -
              rb_thread_call_without_gvl(stmt_iterate_without_gvl, (void *)& 
     | 
| 
       239 
     | 
    
         
            -
              switch ( 
     | 
| 
      
 234 
     | 
    
         
            +
            inline int stmt_iterate(query_ctx *ctx) {
         
     | 
| 
      
 235 
     | 
    
         
            +
              struct step_ctx step_ctx = {ctx->stmt, 0};
         
     | 
| 
      
 236 
     | 
    
         
            +
              rb_thread_call_without_gvl(stmt_iterate_without_gvl, (void *)&step_ctx, RUBY_UBF_IO, 0);
         
     | 
| 
      
 237 
     | 
    
         
            +
              switch (step_ctx.rc) {
         
     | 
| 
       240 
238 
     | 
    
         
             
                case SQLITE_ROW:
         
     | 
| 
       241 
239 
     | 
    
         
             
                  return 1;
         
     | 
| 
       242 
240 
     | 
    
         
             
                case SQLITE_DONE:
         
     | 
| 
      
 241 
     | 
    
         
            +
                  ctx->eof = 1;
         
     | 
| 
       243 
242 
     | 
    
         
             
                  return 0;
         
     | 
| 
       244 
243 
     | 
    
         
             
                case SQLITE_BUSY:
         
     | 
| 
       245 
244 
     | 
    
         
             
                  rb_raise(cBusyError, "Database is busy");
         
     | 
| 
       246 
245 
     | 
    
         
             
                case SQLITE_INTERRUPT:
         
     | 
| 
       247 
246 
     | 
    
         
             
                  rb_raise(cInterruptError, "Query was interrupted");
         
     | 
| 
       248 
247 
     | 
    
         
             
                case SQLITE_ERROR:
         
     | 
| 
       249 
     | 
    
         
            -
                  rb_raise(cSQLError, "%s", sqlite3_errmsg( 
     | 
| 
      
 248 
     | 
    
         
            +
                  rb_raise(cSQLError, "%s", sqlite3_errmsg(ctx->sqlite3_db));
         
     | 
| 
       250 
249 
     | 
    
         
             
                default:
         
     | 
| 
       251 
     | 
    
         
            -
                  rb_raise(cError, "%s", sqlite3_errmsg( 
     | 
| 
      
 250 
     | 
    
         
            +
                  rb_raise(cError, "%s", sqlite3_errmsg(ctx->sqlite3_db));
         
     | 
| 
       252 
251 
     | 
    
         
             
              }
         
     | 
| 
       253 
252 
     | 
    
         | 
| 
       254 
253 
     | 
    
         
             
              return 0;
         
     | 
| 
         @@ -260,50 +259,61 @@ VALUE cleanup_stmt(query_ctx *ctx) { 
     | 
|
| 
       260 
259 
     | 
    
         
             
            }
         
     | 
| 
       261 
260 
     | 
    
         | 
| 
       262 
261 
     | 
    
         
             
            VALUE safe_query_hash(query_ctx *ctx) {
         
     | 
| 
       263 
     | 
    
         
            -
              VALUE  
     | 
| 
       264 
     | 
    
         
            -
               
     | 
| 
       265 
     | 
    
         
            -
               
     | 
| 
       266 
     | 
    
         
            -
               
     | 
| 
       267 
     | 
    
         
            -
               
     | 
| 
       268 
     | 
    
         
            -
             
     | 
| 
       269 
     | 
    
         
            -
              column_count = sqlite3_column_count(ctx->stmt);
         
     | 
| 
       270 
     | 
    
         
            -
              column_names = get_column_names(ctx->stmt, column_count);
         
     | 
| 
       271 
     | 
    
         
            -
             
     | 
| 
       272 
     | 
    
         
            -
              // block not given, so prepare the array of records to be returned
         
     | 
| 
       273 
     | 
    
         
            -
              if (!yield_to_block) result = rb_ary_new();
         
     | 
| 
      
 262 
     | 
    
         
            +
              VALUE array = MULTI_ROW_P(ctx->mode) ? rb_ary_new() : Qnil;
         
     | 
| 
      
 263 
     | 
    
         
            +
              VALUE row = Qnil;
         
     | 
| 
      
 264 
     | 
    
         
            +
              int column_count = sqlite3_column_count(ctx->stmt);
         
     | 
| 
      
 265 
     | 
    
         
            +
              VALUE column_names = get_column_names(ctx->stmt, column_count);
         
     | 
| 
      
 266 
     | 
    
         
            +
              int row_count = 0;
         
     | 
| 
       274 
267 
     | 
    
         | 
| 
       275 
     | 
    
         
            -
              while (stmt_iterate(ctx 
     | 
| 
      
 268 
     | 
    
         
            +
              while (stmt_iterate(ctx)) {
         
     | 
| 
       276 
269 
     | 
    
         
             
                row = row_to_hash(ctx->stmt, column_count, column_names);
         
     | 
| 
       277 
     | 
    
         
            -
                 
     | 
| 
       278 
     | 
    
         
            -
                 
     | 
| 
      
 270 
     | 
    
         
            +
                row_count++;
         
     | 
| 
      
 271 
     | 
    
         
            +
                switch (ctx->mode) {
         
     | 
| 
      
 272 
     | 
    
         
            +
                  case QUERY_YIELD:
         
     | 
| 
      
 273 
     | 
    
         
            +
                    rb_yield(row);
         
     | 
| 
      
 274 
     | 
    
         
            +
                    break;
         
     | 
| 
      
 275 
     | 
    
         
            +
                  case QUERY_MULTI_ROW:
         
     | 
| 
      
 276 
     | 
    
         
            +
                    rb_ary_push(array, row);
         
     | 
| 
      
 277 
     | 
    
         
            +
                    break;
         
     | 
| 
      
 278 
     | 
    
         
            +
                  case QUERY_SINGLE_ROW:
         
     | 
| 
      
 279 
     | 
    
         
            +
                    return row;
         
     | 
| 
      
 280 
     | 
    
         
            +
                }
         
     | 
| 
      
 281 
     | 
    
         
            +
                if (ctx->max_rows != ALL_ROWS && row_count >= ctx->max_rows)
         
     | 
| 
      
 282 
     | 
    
         
            +
                  return MULTI_ROW_P(ctx->mode) ? array : ctx->self;
         
     | 
| 
       279 
283 
     | 
    
         
             
              }
         
     | 
| 
       280 
284 
     | 
    
         | 
| 
       281 
285 
     | 
    
         
             
              RB_GC_GUARD(column_names);
         
     | 
| 
       282 
286 
     | 
    
         
             
              RB_GC_GUARD(row);
         
     | 
| 
       283 
     | 
    
         
            -
              RB_GC_GUARD( 
     | 
| 
       284 
     | 
    
         
            -
              return  
     | 
| 
      
 287 
     | 
    
         
            +
              RB_GC_GUARD(array);
         
     | 
| 
      
 288 
     | 
    
         
            +
              return MULTI_ROW_P(ctx->mode) ? array : Qnil;
         
     | 
| 
       285 
289 
     | 
    
         
             
            }
         
     | 
| 
       286 
290 
     | 
    
         | 
| 
       287 
291 
     | 
    
         
             
            VALUE safe_query_ary(query_ctx *ctx) {
         
     | 
| 
       288 
     | 
    
         
            -
               
     | 
| 
       289 
     | 
    
         
            -
              VALUE  
     | 
| 
       290 
     | 
    
         
            -
              int  
     | 
| 
       291 
     | 
    
         
            -
               
     | 
| 
       292 
     | 
    
         
            -
             
     | 
| 
       293 
     | 
    
         
            -
              column_count = sqlite3_column_count(ctx->stmt);
         
     | 
| 
       294 
     | 
    
         
            -
             
     | 
| 
       295 
     | 
    
         
            -
              // block not given, so prepare the array of records to be returned
         
     | 
| 
       296 
     | 
    
         
            -
              if (!yield_to_block) result = rb_ary_new();
         
     | 
| 
      
 292 
     | 
    
         
            +
              VALUE array = MULTI_ROW_P(ctx->mode) ? rb_ary_new() : Qnil;
         
     | 
| 
      
 293 
     | 
    
         
            +
              VALUE row = Qnil;
         
     | 
| 
      
 294 
     | 
    
         
            +
              int column_count = sqlite3_column_count(ctx->stmt);
         
     | 
| 
      
 295 
     | 
    
         
            +
              int row_count = 0;
         
     | 
| 
       297 
296 
     | 
    
         | 
| 
       298 
     | 
    
         
            -
              while (stmt_iterate(ctx 
     | 
| 
      
 297 
     | 
    
         
            +
              while (stmt_iterate(ctx)) {
         
     | 
| 
       299 
298 
     | 
    
         
             
                row = row_to_ary(ctx->stmt, column_count);
         
     | 
| 
       300 
     | 
    
         
            -
                 
     | 
| 
       301 
     | 
    
         
            -
                 
     | 
| 
      
 299 
     | 
    
         
            +
                row_count++;
         
     | 
| 
      
 300 
     | 
    
         
            +
                switch (ctx->mode) {
         
     | 
| 
      
 301 
     | 
    
         
            +
                  case QUERY_YIELD:
         
     | 
| 
      
 302 
     | 
    
         
            +
                    rb_yield(row);
         
     | 
| 
      
 303 
     | 
    
         
            +
                    break;
         
     | 
| 
      
 304 
     | 
    
         
            +
                  case QUERY_MULTI_ROW:
         
     | 
| 
      
 305 
     | 
    
         
            +
                    rb_ary_push(array, row);
         
     | 
| 
      
 306 
     | 
    
         
            +
                    break;
         
     | 
| 
      
 307 
     | 
    
         
            +
                  case QUERY_SINGLE_ROW:
         
     | 
| 
      
 308 
     | 
    
         
            +
                    return row;
         
     | 
| 
      
 309 
     | 
    
         
            +
                }
         
     | 
| 
      
 310 
     | 
    
         
            +
                if (ctx->max_rows != ALL_ROWS && row_count >= ctx->max_rows)
         
     | 
| 
      
 311 
     | 
    
         
            +
                  return MULTI_ROW_P(ctx->mode) ? array : ctx->self;
         
     | 
| 
       302 
312 
     | 
    
         
             
              }
         
     | 
| 
       303 
313 
     | 
    
         | 
| 
       304 
314 
     | 
    
         
             
              RB_GC_GUARD(row);
         
     | 
| 
       305 
     | 
    
         
            -
              RB_GC_GUARD( 
     | 
| 
       306 
     | 
    
         
            -
              return  
     | 
| 
      
 315 
     | 
    
         
            +
              RB_GC_GUARD(array);
         
     | 
| 
      
 316 
     | 
    
         
            +
              return MULTI_ROW_P(ctx->mode) ? array : Qnil;
         
     | 
| 
       307 
317 
     | 
    
         
             
            }
         
     | 
| 
       308 
318 
     | 
    
         | 
| 
       309 
319 
     | 
    
         
             
            VALUE safe_query_single_row(query_ctx *ctx) {
         
     | 
| 
         @@ -314,7 +324,7 @@ VALUE safe_query_single_row(query_ctx *ctx) { 
     | 
|
| 
       314 
324 
     | 
    
         
             
              column_count = sqlite3_column_count(ctx->stmt);
         
     | 
| 
       315 
325 
     | 
    
         
             
              column_names = get_column_names(ctx->stmt, column_count);
         
     | 
| 
       316 
326 
     | 
    
         | 
| 
       317 
     | 
    
         
            -
              if (stmt_iterate(ctx 
     | 
| 
      
 327 
     | 
    
         
            +
              if (stmt_iterate(ctx))
         
     | 
| 
       318 
328 
     | 
    
         
             
                row = row_to_hash(ctx->stmt, column_count, column_names);
         
     | 
| 
       319 
329 
     | 
    
         | 
| 
       320 
330 
     | 
    
         
             
              RB_GC_GUARD(row);
         
     | 
| 
         @@ -323,26 +333,33 @@ VALUE safe_query_single_row(query_ctx *ctx) { 
     | 
|
| 
       323 
333 
     | 
    
         
             
            }
         
     | 
| 
       324 
334 
     | 
    
         | 
| 
       325 
335 
     | 
    
         
             
            VALUE safe_query_single_column(query_ctx *ctx) {
         
     | 
| 
       326 
     | 
    
         
            -
               
     | 
| 
       327 
     | 
    
         
            -
              VALUE  
     | 
| 
       328 
     | 
    
         
            -
              int  
     | 
| 
       329 
     | 
    
         
            -
               
     | 
| 
       330 
     | 
    
         
            -
             
     | 
| 
       331 
     | 
    
         
            -
              column_count = sqlite3_column_count(ctx->stmt);
         
     | 
| 
       332 
     | 
    
         
            -
              if (column_count != 1)
         
     | 
| 
       333 
     | 
    
         
            -
                rb_raise(cError, "Expected query result to have 1 column");
         
     | 
| 
      
 336 
     | 
    
         
            +
              VALUE array = MULTI_ROW_P(ctx->mode) ? rb_ary_new() : Qnil;
         
     | 
| 
      
 337 
     | 
    
         
            +
              VALUE value = Qnil;
         
     | 
| 
      
 338 
     | 
    
         
            +
              int column_count = sqlite3_column_count(ctx->stmt);
         
     | 
| 
      
 339 
     | 
    
         
            +
              int row_count = 0;
         
     | 
| 
       334 
340 
     | 
    
         | 
| 
       335 
     | 
    
         
            -
               
     | 
| 
       336 
     | 
    
         
            -
              if (!yield_to_block) result = rb_ary_new();
         
     | 
| 
      
 341 
     | 
    
         
            +
              if (column_count != 1) rb_raise(cError, "Expected query result to have 1 column");
         
     | 
| 
       337 
342 
     | 
    
         | 
| 
       338 
     | 
    
         
            -
              while (stmt_iterate(ctx 
     | 
| 
      
 343 
     | 
    
         
            +
              while (stmt_iterate(ctx)) {
         
     | 
| 
       339 
344 
     | 
    
         
             
                value = get_column_value(ctx->stmt, 0, sqlite3_column_type(ctx->stmt, 0));
         
     | 
| 
       340 
     | 
    
         
            -
                 
     | 
| 
      
 345 
     | 
    
         
            +
                row_count++;
         
     | 
| 
      
 346 
     | 
    
         
            +
                switch (ctx->mode) {
         
     | 
| 
      
 347 
     | 
    
         
            +
                  case QUERY_YIELD:
         
     | 
| 
      
 348 
     | 
    
         
            +
                    rb_yield(value);
         
     | 
| 
      
 349 
     | 
    
         
            +
                    break;
         
     | 
| 
      
 350 
     | 
    
         
            +
                  case QUERY_MULTI_ROW:
         
     | 
| 
      
 351 
     | 
    
         
            +
                    rb_ary_push(array, value);
         
     | 
| 
      
 352 
     | 
    
         
            +
                    break;
         
     | 
| 
      
 353 
     | 
    
         
            +
                  case QUERY_SINGLE_ROW:
         
     | 
| 
      
 354 
     | 
    
         
            +
                    return value;
         
     | 
| 
      
 355 
     | 
    
         
            +
                }
         
     | 
| 
      
 356 
     | 
    
         
            +
                if (ctx->max_rows != ALL_ROWS && row_count >= ctx->max_rows)
         
     | 
| 
      
 357 
     | 
    
         
            +
                  return MULTI_ROW_P(ctx->mode) ? array : ctx->self;
         
     | 
| 
       341 
358 
     | 
    
         
             
              }
         
     | 
| 
       342 
359 
     | 
    
         | 
| 
       343 
360 
     | 
    
         
             
              RB_GC_GUARD(value);
         
     | 
| 
       344 
     | 
    
         
            -
              RB_GC_GUARD( 
     | 
| 
       345 
     | 
    
         
            -
              return  
     | 
| 
      
 361 
     | 
    
         
            +
              RB_GC_GUARD(array);
         
     | 
| 
      
 362 
     | 
    
         
            +
              return MULTI_ROW_P(ctx->mode) ? array : Qnil;
         
     | 
| 
       346 
363 
     | 
    
         
             
            }
         
     | 
| 
       347 
364 
     | 
    
         | 
| 
       348 
365 
     | 
    
         
             
            VALUE safe_query_single_value(query_ctx *ctx) {
         
     | 
| 
         @@ -353,7 +370,7 @@ VALUE safe_query_single_value(query_ctx *ctx) { 
     | 
|
| 
       353 
370 
     | 
    
         
             
              if (column_count != 1)
         
     | 
| 
       354 
371 
     | 
    
         
             
                rb_raise(cError, "Expected query result to have 1 column");
         
     | 
| 
       355 
372 
     | 
    
         | 
| 
       356 
     | 
    
         
            -
              if (stmt_iterate(ctx 
     | 
| 
      
 373 
     | 
    
         
            +
              if (stmt_iterate(ctx))
         
     | 
| 
       357 
374 
     | 
    
         
             
                value = get_column_value(ctx->stmt, 0, sqlite3_column_type(ctx->stmt, 0));
         
     | 
| 
       358 
375 
     | 
    
         | 
| 
       359 
376 
     | 
    
         
             
              RB_GC_GUARD(value);
         
     | 
| 
         @@ -369,7 +386,7 @@ VALUE safe_execute_multi(query_ctx *ctx) { 
     | 
|
| 
       369 
386 
     | 
    
         
             
                sqlite3_clear_bindings(ctx->stmt);
         
     | 
| 
       370 
387 
     | 
    
         
             
                bind_all_parameters_from_object(ctx->stmt, RARRAY_AREF(ctx->params, i));
         
     | 
| 
       371 
388 
     | 
    
         | 
| 
       372 
     | 
    
         
            -
                while (stmt_iterate(ctx 
     | 
| 
      
 389 
     | 
    
         
            +
                while (stmt_iterate(ctx));
         
     | 
| 
       373 
390 
     | 
    
         
             
                changes += sqlite3_changes(ctx->sqlite3_db);
         
     | 
| 
       374 
391 
     | 
    
         
             
              }
         
     | 
| 
       375 
392 
     | 
    
         | 
    
        data/ext/extralite/database.c
    CHANGED
    
    | 
         @@ -7,6 +7,7 @@ VALUE cSQLError; 
     | 
|
| 
       7 
7 
     | 
    
         
             
            VALUE cBusyError;
         
     | 
| 
       8 
8 
     | 
    
         
             
            VALUE cInterruptError;
         
     | 
| 
       9 
9 
     | 
    
         | 
| 
      
 10 
     | 
    
         
            +
            ID ID_bind;
         
     | 
| 
       10 
11 
     | 
    
         
             
            ID ID_call;
         
     | 
| 
       11 
12 
     | 
    
         
             
            ID ID_keys;
         
     | 
| 
       12 
13 
     | 
    
         
             
            ID ID_new;
         
     | 
| 
         @@ -155,7 +156,7 @@ static inline VALUE Database_perform_query(int argc, VALUE *argv, VALUE self, VA 
     | 
|
| 
       155 
156 
     | 
    
         
             
              RB_GC_GUARD(sql);
         
     | 
| 
       156 
157 
     | 
    
         | 
| 
       157 
158 
     | 
    
         
             
              bind_all_parameters(stmt, argc - 1, argv + 1);
         
     | 
| 
       158 
     | 
    
         
            -
              query_ctx ctx = { self, db->sqlite3_db, stmt };
         
     | 
| 
      
 159 
     | 
    
         
            +
              query_ctx ctx = { self, db->sqlite3_db, stmt, Qnil, QUERY_MODE(QUERY_MULTI_ROW), ALL_ROWS };
         
     | 
| 
       159 
160 
     | 
    
         | 
| 
       160 
161 
     | 
    
         
             
              return rb_ensure(SAFE(call), (VALUE)&ctx, SAFE(cleanup_stmt), (VALUE)&ctx);
         
     | 
| 
       161 
162 
     | 
    
         
             
            }
         
     | 
| 
         @@ -170,7 +171,7 @@ static inline VALUE Database_perform_query(int argc, VALUE *argv, VALUE self, VA 
     | 
|
| 
       170 
171 
     | 
    
         
             
             * 
         
     | 
| 
       171 
172 
     | 
    
         
             
             * Query parameters to be bound to placeholders in the query can be specified as
         
     | 
| 
       172 
173 
     | 
    
         
             
             * a list of values or as a hash mapping parameter names to values. When
         
     | 
| 
       173 
     | 
    
         
            -
             * parameters are given as  
     | 
| 
      
 174 
     | 
    
         
            +
             * parameters are given as an array, the query should specify parameters using
         
     | 
| 
       174 
175 
     | 
    
         
             
             * `?`:
         
     | 
| 
       175 
176 
     | 
    
         
             
             * 
         
     | 
| 
       176 
177 
     | 
    
         
             
             *     db.query('select * from foo where x = ?', 42)
         
     | 
| 
         @@ -195,7 +196,7 @@ VALUE Database_query_hash(int argc, VALUE *argv, VALUE self) { 
     | 
|
| 
       195 
196 
     | 
    
         
             
             *
         
     | 
| 
       196 
197 
     | 
    
         
             
             * Query parameters to be bound to placeholders in the query can be specified as
         
     | 
| 
       197 
198 
     | 
    
         
             
             * a list of values or as a hash mapping parameter names to values. When
         
     | 
| 
       198 
     | 
    
         
            -
             * parameters are given as  
     | 
| 
      
 199 
     | 
    
         
            +
             * parameters are given as an array, the query should specify parameters using
         
     | 
| 
       199 
200 
     | 
    
         
             
             * `?`:
         
     | 
| 
       200 
201 
     | 
    
         
             
             *
         
     | 
| 
       201 
202 
     | 
    
         
             
             *     db.query_ary('select * from foo where x = ?', 42)
         
     | 
| 
         @@ -219,7 +220,7 @@ VALUE Database_query_ary(int argc, VALUE *argv, VALUE self) { 
     | 
|
| 
       219 
220 
     | 
    
         
             
             *
         
     | 
| 
       220 
221 
     | 
    
         
             
             * Query parameters to be bound to placeholders in the query can be specified as
         
     | 
| 
       221 
222 
     | 
    
         
             
             * a list of values or as a hash mapping parameter names to values. When
         
     | 
| 
       222 
     | 
    
         
            -
             * parameters are given as  
     | 
| 
      
 223 
     | 
    
         
            +
             * parameters are given as an array, the query should specify parameters using
         
     | 
| 
       223 
224 
     | 
    
         
             
             * `?`:
         
     | 
| 
       224 
225 
     | 
    
         
             
             *
         
     | 
| 
       225 
226 
     | 
    
         
             
             *     db.query_single_row('select * from foo where x = ?', 42)
         
     | 
| 
         @@ -244,7 +245,7 @@ VALUE Database_query_single_row(int argc, VALUE *argv, VALUE self) { 
     | 
|
| 
       244 
245 
     | 
    
         
             
             *
         
     | 
| 
       245 
246 
     | 
    
         
             
             * Query parameters to be bound to placeholders in the query can be specified as
         
     | 
| 
       246 
247 
     | 
    
         
             
             * a list of values or as a hash mapping parameter names to values. When
         
     | 
| 
       247 
     | 
    
         
            -
             * parameters are given as  
     | 
| 
      
 248 
     | 
    
         
            +
             * parameters are given as an array, the query should specify parameters using
         
     | 
| 
       248 
249 
     | 
    
         
             
             * `?`:
         
     | 
| 
       249 
250 
     | 
    
         
             
             *
         
     | 
| 
       250 
251 
     | 
    
         
             
             *     db.query_single_column('select x from foo where x = ?', 42)
         
     | 
| 
         @@ -268,7 +269,7 @@ VALUE Database_query_single_column(int argc, VALUE *argv, VALUE self) { 
     | 
|
| 
       268 
269 
     | 
    
         
             
             *
         
     | 
| 
       269 
270 
     | 
    
         
             
             * Query parameters to be bound to placeholders in the query can be specified as
         
     | 
| 
       270 
271 
     | 
    
         
             
             * a list of values or as a hash mapping parameter names to values. When
         
     | 
| 
       271 
     | 
    
         
            -
             * parameters are given as  
     | 
| 
      
 272 
     | 
    
         
            +
             * parameters are given as an array, the query should specify parameters using
         
     | 
| 
       272 
273 
     | 
    
         
             
             * `?`:
         
     | 
| 
       273 
274 
     | 
    
         
             
             *
         
     | 
| 
       274 
275 
     | 
    
         
             
             *     db.query_single_value('select x from foo where x = ?', 42)
         
     | 
| 
         @@ -296,7 +297,7 @@ VALUE Database_query_single_value(int argc, VALUE *argv, VALUE self) { 
     | 
|
| 
       296 
297 
     | 
    
         
             
             *       [1, 2, 3],
         
     | 
| 
       297 
298 
     | 
    
         
             
             *       [4, 5, 6]
         
     | 
| 
       298 
299 
     | 
    
         
             
             *     ]
         
     | 
| 
       299 
     | 
    
         
            -
             *     db. 
     | 
| 
      
 300 
     | 
    
         
            +
             *     db.execute_multi('insert into foo values (?, ?, ?)', records)
         
     | 
| 
       300 
301 
     | 
    
         
             
             *
         
     | 
| 
       301 
302 
     | 
    
         
             
             */
         
     | 
| 
       302 
303 
     | 
    
         
             
            VALUE Database_execute_multi(VALUE self, VALUE sql, VALUE params_array) {
         
     | 
| 
         @@ -308,7 +309,7 @@ VALUE Database_execute_multi(VALUE self, VALUE sql, VALUE params_array) { 
     | 
|
| 
       308 
309 
     | 
    
         
             
              // prepare query ctx
         
     | 
| 
       309 
310 
     | 
    
         
             
              GetOpenDatabase(self, db);
         
     | 
| 
       310 
311 
     | 
    
         
             
              prepare_single_stmt(db->sqlite3_db, &stmt, sql);
         
     | 
| 
       311 
     | 
    
         
            -
              query_ctx ctx = { self, db->sqlite3_db, stmt, params_array };
         
     | 
| 
      
 312 
     | 
    
         
            +
              query_ctx ctx = { self, db->sqlite3_db, stmt, params_array, QUERY_MODE(QUERY_MULTI_ROW), ALL_ROWS };
         
     | 
| 
       312 
313 
     | 
    
         | 
| 
       313 
314 
     | 
    
         
             
              return rb_ensure(SAFE(safe_execute_multi), (VALUE)&ctx, SAFE(cleanup_stmt), (VALUE)&ctx);
         
     | 
| 
       314 
315 
     | 
    
         
             
            }
         
     | 
| 
         @@ -398,12 +399,16 @@ VALUE Database_load_extension(VALUE self, VALUE path) { 
     | 
|
| 
       398 
399 
     | 
    
         
             
            #endif
         
     | 
| 
       399 
400 
     | 
    
         | 
| 
       400 
401 
     | 
    
         
             
            /* call-seq:
         
     | 
| 
       401 
     | 
    
         
            -
             *   db.prepare(sql) -> Extralite:: 
     | 
| 
      
 402 
     | 
    
         
            +
             *   db.prepare(sql) -> Extralite::Query
         
     | 
| 
       402 
403 
     | 
    
         
             
             *
         
     | 
| 
       403 
404 
     | 
    
         
             
             * Creates a prepared statement with the given SQL query.
         
     | 
| 
       404 
405 
     | 
    
         
             
             */
         
     | 
| 
       405 
     | 
    
         
            -
            VALUE Database_prepare(VALUE  
     | 
| 
       406 
     | 
    
         
            -
               
     | 
| 
      
 406 
     | 
    
         
            +
            VALUE Database_prepare(int argc, VALUE *argv, VALUE self) {
         
     | 
| 
      
 407 
     | 
    
         
            +
              rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
         
     | 
| 
      
 408 
     | 
    
         
            +
              VALUE query = rb_funcall(cQuery, ID_new, 2, self, argv[0]);
         
     | 
| 
      
 409 
     | 
    
         
            +
              if (argc > 1) rb_funcallv(query, ID_bind, argc - 1, argv + 1);
         
     | 
| 
      
 410 
     | 
    
         
            +
              RB_GC_GUARD(query);
         
     | 
| 
      
 411 
     | 
    
         
            +
              return query;
         
     | 
| 
       407 
412 
     | 
    
         
             
            }
         
     | 
| 
       408 
413 
     | 
    
         | 
| 
       409 
414 
     | 
    
         
             
            /* call-seq:
         
     | 
| 
         @@ -540,6 +545,9 @@ VALUE Database_backup(int argc, VALUE *argv, VALUE self) { 
     | 
|
| 
       540 
545 
     | 
    
         
             
              backup_ctx ctx = { dst_db, dst_is_fn, backup, rb_block_given_p(), 0 };
         
     | 
| 
       541 
546 
     | 
    
         
             
              rb_ensure(SAFE(backup_safe_iterate), (VALUE)&ctx, SAFE(backup_cleanup), (VALUE)&ctx);
         
     | 
| 
       542 
547 
     | 
    
         | 
| 
      
 548 
     | 
    
         
            +
              RB_GC_GUARD(src_name);
         
     | 
| 
      
 549 
     | 
    
         
            +
              RB_GC_GUARD(dst_name);
         
     | 
| 
      
 550 
     | 
    
         
            +
             
     | 
| 
       543 
551 
     | 
    
         
             
              return self;
         
     | 
| 
       544 
552 
     | 
    
         
             
            }
         
     | 
| 
       545 
553 
     | 
    
         | 
| 
         @@ -717,7 +725,7 @@ void Init_ExtraliteDatabase(void) { 
     | 
|
| 
       717 
725 
     | 
    
         
             
              rb_define_method(cDatabase, "interrupt", Database_interrupt, 0);
         
     | 
| 
       718 
726 
     | 
    
         
             
              rb_define_method(cDatabase, "last_insert_rowid", Database_last_insert_rowid, 0);
         
     | 
| 
       719 
727 
     | 
    
         
             
              rb_define_method(cDatabase, "limit", Database_limit, -1);
         
     | 
| 
       720 
     | 
    
         
            -
              rb_define_method(cDatabase, "prepare", Database_prepare, 1);
         
     | 
| 
      
 728 
     | 
    
         
            +
              rb_define_method(cDatabase, "prepare", Database_prepare, -1);
         
     | 
| 
       721 
729 
     | 
    
         
             
              rb_define_method(cDatabase, "query", Database_query_hash, -1);
         
     | 
| 
       722 
730 
     | 
    
         
             
              rb_define_method(cDatabase, "query_ary", Database_query_ary, -1);
         
     | 
| 
       723 
731 
     | 
    
         
             
              rb_define_method(cDatabase, "query_hash", Database_query_hash, -1);
         
     | 
| 
         @@ -742,6 +750,7 @@ void Init_ExtraliteDatabase(void) { 
     | 
|
| 
       742 
750 
     | 
    
         
             
              rb_gc_register_mark_object(cBusyError);
         
     | 
| 
       743 
751 
     | 
    
         
             
              rb_gc_register_mark_object(cInterruptError);
         
     | 
| 
       744 
752 
     | 
    
         | 
| 
      
 753 
     | 
    
         
            +
              ID_bind   = rb_intern("bind");
         
     | 
| 
       745 
754 
     | 
    
         
             
              ID_call   = rb_intern("call");
         
     | 
| 
       746 
755 
     | 
    
         
             
              ID_keys   = rb_intern("keys");
         
     | 
| 
       747 
756 
     | 
    
         
             
              ID_new    = rb_intern("new");
         
     | 
    
        data/ext/extralite/extconf.rb
    CHANGED
    
    | 
         @@ -4,13 +4,13 @@ if ENV['EXTRALITE_BUNDLE'] 
     | 
|
| 
       4 
4 
     | 
    
         
             
              require_relative('extconf-bundle')
         
     | 
| 
       5 
5 
     | 
    
         
             
            else
         
     | 
| 
       6 
6 
     | 
    
         
             
              ENV['RC_ARCHS'] = '' if RUBY_PLATFORM =~ /darwin/
         
     | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
       8 
8 
     | 
    
         
             
              require 'mkmf'
         
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
       10 
10 
     | 
    
         
             
              # :stopdoc:
         
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
       12 
12 
     | 
    
         
             
              RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC']
         
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
       14 
14 
     | 
    
         
             
              ldflags = cppflags = nil
         
     | 
| 
       15 
15 
     | 
    
         
             
              if RbConfig::CONFIG["host_os"] =~ /darwin/
         
     | 
| 
       16 
16 
     | 
    
         
             
                begin
         
     | 
| 
         @@ -25,7 +25,7 @@ else 
     | 
|
| 
       25 
25 
     | 
    
         
             
                    cppflags  = "#{brew_prefix}/include"
         
     | 
| 
       26 
26 
     | 
    
         
             
                    pkg_conf  = "#{brew_prefix}/lib/pkgconfig"
         
     | 
| 
       27 
27 
     | 
    
         
             
                  end
         
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
       29 
29 
     | 
    
         
             
                  # pkg_config should be less error prone than parsing compiler
         
     | 
| 
       30 
30 
     | 
    
         
             
                  # commandline options, but we need to set default ldflags and cpp flags
         
     | 
| 
       31 
31 
     | 
    
         
             
                  # in case the user doesn't have pkg-config installed
         
     | 
| 
         @@ -33,13 +33,13 @@ else 
     | 
|
| 
       33 
33 
     | 
    
         
             
                rescue
         
     | 
| 
       34 
34 
     | 
    
         
             
                end
         
     | 
| 
       35 
35 
     | 
    
         
             
              end
         
     | 
| 
       36 
     | 
    
         
            -
             
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
       37 
37 
     | 
    
         
             
              if with_config('sqlcipher')
         
     | 
| 
       38 
38 
     | 
    
         
             
                pkg_config("sqlcipher")
         
     | 
| 
       39 
39 
     | 
    
         
             
              else
         
     | 
| 
       40 
40 
     | 
    
         
             
                pkg_config("sqlite3")
         
     | 
| 
       41 
41 
     | 
    
         
             
              end
         
     | 
| 
       42 
     | 
    
         
            -
             
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
       43 
43 
     | 
    
         
             
              # --with-sqlite3-{dir,include,lib}
         
     | 
| 
       44 
44 
     | 
    
         
             
              if with_config('sqlcipher')
         
     | 
| 
       45 
45 
     | 
    
         
             
                $CFLAGS << ' -DUSING_SQLCIPHER'
         
     | 
| 
         @@ -47,15 +47,15 @@ else 
     | 
|
| 
       47 
47 
     | 
    
         
             
              else
         
     | 
| 
       48 
48 
     | 
    
         
             
                dir_config("sqlite3", cppflags, ldflags)
         
     | 
| 
       49 
49 
     | 
    
         
             
              end
         
     | 
| 
       50 
     | 
    
         
            -
             
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
       51 
51 
     | 
    
         
             
              if RbConfig::CONFIG["host_os"] =~ /mswin/
         
     | 
| 
       52 
52 
     | 
    
         
             
                $CFLAGS << ' -W3'
         
     | 
| 
       53 
53 
     | 
    
         
             
              end
         
     | 
| 
       54 
     | 
    
         
            -
             
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
       55 
55 
     | 
    
         
             
              if RUBY_VERSION < '2.7'
         
     | 
| 
       56 
56 
     | 
    
         
             
                $CFLAGS << ' -DTAINTING_SUPPORT'
         
     | 
| 
       57 
57 
     | 
    
         
             
              end
         
     | 
| 
       58 
     | 
    
         
            -
             
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
       59 
59 
     | 
    
         
             
              # @!visibility private
         
     | 
| 
       60 
60 
     | 
    
         
             
              def asplode missing
         
     | 
| 
       61 
61 
     | 
    
         
             
                if RUBY_PLATFORM =~ /mingw|mswin/
         
     | 
| 
         @@ -70,25 +70,25 @@ else 
     | 
|
| 
       70 
70 
     | 
    
         
             
                    error
         
     | 
| 
       71 
71 
     | 
    
         
             
                  end
         
     | 
| 
       72 
72 
     | 
    
         
             
                end
         
     | 
| 
       73 
     | 
    
         
            -
             
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
       74 
74 
     | 
    
         
             
                asplode('sqlite3.h')  unless find_header  'sqlite3.h'
         
     | 
| 
       75 
75 
     | 
    
         
             
                find_library 'pthread', 'pthread_create' # 1.8 support. *shrug*
         
     | 
| 
       76 
     | 
    
         
            -
             
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
       77 
77 
     | 
    
         
             
                have_library 'dl' # for static builds
         
     | 
| 
       78 
     | 
    
         
            -
             
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
       79 
79 
     | 
    
         
             
                if with_config('sqlcipher')
         
     | 
| 
       80 
80 
     | 
    
         
             
                  asplode('sqlcipher') unless find_library 'sqlcipher', 'sqlite3_libversion_number'
         
     | 
| 
       81 
81 
     | 
    
         
             
                else
         
     | 
| 
       82 
82 
     | 
    
         
             
                  asplode('sqlite3') unless find_library 'sqlite3', 'sqlite3_libversion_number'
         
     | 
| 
       83 
83 
     | 
    
         
             
                end
         
     | 
| 
       84 
     | 
    
         
            -
             
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
       85 
85 
     | 
    
         
             
                have_func('sqlite3_enable_load_extension')
         
     | 
| 
       86 
86 
     | 
    
         
             
                have_func('sqlite3_load_extension')
         
     | 
| 
       87 
87 
     | 
    
         
             
                have_func('sqlite3_prepare_v2')
         
     | 
| 
       88 
88 
     | 
    
         
             
                have_func('sqlite3_error_offset')
         
     | 
| 
       89 
     | 
    
         
            -
             
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
       90 
90 
     | 
    
         
             
                $defs << "-DEXTRALITE_NO_BUNDLE"
         
     | 
| 
       91 
     | 
    
         
            -
             
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
       92 
92 
     | 
    
         
             
                dir_config('extralite_ext')
         
     | 
| 
       93 
93 
     | 
    
         
             
                create_makefile('extralite_ext')
         
     | 
| 
       94 
94 
     | 
    
         
             
              end
         
     |