sqlite3-ruby 1.3.0 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,12 @@
1
+ === 1.3.1 / 2010-07-09
2
+
3
+ * Enhancements
4
+ * Custom collations may be defined using SQLite3::Database#collation
5
+
6
+ * Bugfixes
7
+ * Statements returning 0 columns are automatically stepped. [RF #28308]
8
+ * SQLite3::Database#encoding works on 1.8 and 1.9
9
+
1
10
  === 1.3.0 / 2010-06-06
2
11
 
3
12
  * Enhancements
@@ -6,7 +15,7 @@
6
15
  This closes: Bug #27300, Bug #27241, Patch #16020
7
16
  * Improved UTF, Unicode, M17N, all that handling and proper BLOB handling [tenderlove, nurse]
8
17
  * Added support for type translations [tenderlove]
9
-
18
+
10
19
  @db.translator.add_translator('sometime') do |type, thing|
11
20
  'output' # this will be returned as value for that column
12
21
  end
@@ -32,6 +32,7 @@ tasks/gem.rake
32
32
  tasks/native.rake
33
33
  tasks/vendor_sqlite3.rake
34
34
  test/helper.rb
35
+ test/test_collation.rb
35
36
  test/test_database.rb
36
37
  test/test_deprecated.rb
37
38
  test/test_encoding.rb
@@ -42,3 +43,4 @@ test/test_integration_resultset.rb
42
43
  test/test_integration_statement.rb
43
44
  test/test_sqlite3.rb
44
45
  test/test_statement.rb
46
+ test/test_statement_execute.rb
@@ -3,6 +3,7 @@
3
3
  * http://github.com/luislavena/sqlite3-ruby
4
4
  * http://rubyforge.org/projects/sqlite-ruby
5
5
  * http://sqlite-ruby.rubyforge.org
6
+ * http://groups.google.com/group/sqlite3-ruby
6
7
 
7
8
  == DESCRIPTION
8
9
 
@@ -33,6 +34,25 @@ If you have sqlite3 installed in a non-standard location, you can specify the lo
33
34
  gem install sqlite3-ruby -- --with-sqlite3-include=/opt/local/include \
34
35
  --with-sqlite3-lib=/opt/local/lib
35
36
 
37
+ = SUPPORT!!!
38
+
39
+ == OMG! Something has gone wrong! Where do I get help?
40
+
41
+ The best place to get help is from the
42
+ {sqlite3-ruby mailing list}[http://groups.google.com/group/sqlite3-ruby] which
43
+ can be found here:
44
+
45
+ * http://groups.google.com/group/sqlite3-ruby
46
+
47
+ == I've found a bug! Where do I file it?
48
+
49
+ Uh oh. After contacting the mailing list, you've found that you've actually
50
+ discovered a bug. You can file the bug at the
51
+ {github issues page}[http://github.com/luislavena/sqlite3-ruby/issues]
52
+ which can be found here:
53
+
54
+ * http://github.com/luislavena/sqlite3-ruby/issues
55
+
36
56
  == Usage
37
57
 
38
58
  For help figuring out the SQLite3/Ruby interface, check out the
@@ -91,6 +91,7 @@ static VALUE initialize(int argc, VALUE *argv, VALUE self)
91
91
  rb_iv_set(self, "@authorizer", Qnil);
92
92
  rb_iv_set(self, "@encoding", Qnil);
93
93
  rb_iv_set(self, "@busy_handler", Qnil);
94
+ rb_iv_set(self, "@collations", rb_hash_new());
94
95
  rb_iv_set(self, "@results_as_hash", rb_hash_aref(opts, sym_results_as_hash));
95
96
  rb_iv_set(self, "@type_translation", rb_hash_aref(opts, sym_type_translation));
96
97
 
@@ -571,6 +572,64 @@ static VALUE set_busy_timeout(VALUE self, VALUE timeout)
571
572
  return self;
572
573
  }
573
574
 
575
+ int rb_comparator_func(void * ctx, int a_len, const void * a, int b_len, const void * b)
576
+ {
577
+ VALUE comparator;
578
+ VALUE a_str;
579
+ VALUE b_str;
580
+ VALUE comparison;
581
+ #ifdef HAVE_RUBY_ENCODING_H
582
+ rb_encoding * internal_encoding;
583
+
584
+ internal_encoding = rb_default_internal_encoding();
585
+ #endif
586
+
587
+ comparator = (VALUE)ctx;
588
+ a_str = rb_str_new((const char *)a, a_len);
589
+ b_str = rb_str_new((const char *)b, b_len);
590
+
591
+ #ifdef HAVE_RUBY_ENCODING_H
592
+ rb_enc_associate_index(a_str, rb_utf8_encindex());
593
+ rb_enc_associate_index(b_str, rb_utf8_encindex());
594
+
595
+ if(internal_encoding) {
596
+ a_str = rb_str_export_to_enc(a_str, internal_encoding);
597
+ b_str = rb_str_export_to_enc(b_str, internal_encoding);
598
+ }
599
+ #endif
600
+
601
+ comparison = rb_funcall(comparator, rb_intern("compare"), 2, a_str, b_str);
602
+
603
+ return NUM2INT(comparison);
604
+ }
605
+
606
+ /* call-seq: db.collation(name, comparator)
607
+ *
608
+ * Add a collation with name +name+, and a +comparator+ object. The
609
+ * +comparator+ object should implement a method called "compare" that takes
610
+ * two parameters and returns an integer less than, equal to, or greater than
611
+ * 0.
612
+ */
613
+ static VALUE collation(VALUE self, VALUE name, VALUE comparator)
614
+ {
615
+ sqlite3RubyPtr ctx;
616
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
617
+ REQUIRE_OPEN_DB(ctx);
618
+
619
+ CHECK(ctx->db, sqlite3_create_collation_v2(
620
+ ctx->db,
621
+ StringValuePtr(name),
622
+ SQLITE_UTF8,
623
+ (void *)comparator,
624
+ NIL_P(comparator) ? NULL : rb_comparator_func,
625
+ NULL));
626
+
627
+ /* Make sure our comparator doesn't get garbage collected. */
628
+ rb_hash_aset(rb_iv_get(self, "@collations"), name, comparator);
629
+
630
+ return self;
631
+ }
632
+
574
633
  /* call-seq: db.load_extension(file)
575
634
  *
576
635
  * Loads an SQLite extension library from the named file. Extension
@@ -623,6 +682,16 @@ static int enc_cb(void * _self, int UNUSED(columns), char **data, char **UNUSED(
623
682
 
624
683
  return 0;
625
684
  }
685
+ #else
686
+ static int enc_cb(void * _self, int UNUSED(columns), char **data, char **UNUSED(names))
687
+ {
688
+ VALUE self = (VALUE)_self;
689
+
690
+ rb_iv_set(self, "@encoding", rb_str_new2(data[0]));
691
+
692
+ return 0;
693
+ }
694
+ #endif
626
695
 
627
696
  /* call-seq: db.encoding
628
697
  *
@@ -644,7 +713,6 @@ static VALUE db_encoding(VALUE self)
644
713
 
645
714
  return rb_iv_get(self, "@encoding");
646
715
  }
647
- #endif
648
716
 
649
717
  void init_sqlite3_database()
650
718
  {
@@ -656,6 +724,7 @@ void init_sqlite3_database()
656
724
 
657
725
  rb_define_alloc_func(cSqlite3Database, allocate);
658
726
  rb_define_method(cSqlite3Database, "initialize", initialize, -1);
727
+ rb_define_method(cSqlite3Database, "collation", collation, 2);
659
728
  rb_define_method(cSqlite3Database, "close", sqlite3_rb_close, 0);
660
729
  rb_define_method(cSqlite3Database, "closed?", closed_p, 0);
661
730
  rb_define_method(cSqlite3Database, "total_changes", total_changes, 0);
@@ -680,9 +749,7 @@ void init_sqlite3_database()
680
749
  rb_define_method(cSqlite3Database, "enable_load_extension", enable_load_extension, 1);
681
750
  #endif
682
751
 
683
- #ifdef HAVE_RUBY_ENCODING_H
684
752
  rb_define_method(cSqlite3Database, "encoding", db_encoding, 0);
685
- #endif
686
753
 
687
754
  id_utf16 = rb_intern("utf16");
688
755
  sym_utf16 = ID2SYM(id_utf16);
@@ -31,6 +31,10 @@ asplode('sqlite3') unless find_library 'sqlite3', 'sqlite3_libversion_number'
31
31
  # Functions defined in 1.9 but not 1.8
32
32
  have_func('rb_proc_arity')
33
33
 
34
+ unless have_func('sqlite3_initialize') && have_func('sqlite3_next_stmt')
35
+ abort "sqlite3-ruby only supports sqlite3 versions 3.6.16+, please upgrade!"
36
+ end
37
+
34
38
  # These functions may not be defined
35
39
  have_func('sqlite3_column_database_name')
36
40
  have_func('sqlite3_enable_load_extension')
@@ -33,6 +33,8 @@ module SQLite3
33
33
  # module before performing a query, and if you have not enabled results as
34
34
  # hashes, then the results will all be indexible by field name.
35
35
  class Database
36
+ attr_reader :collations
37
+
36
38
  include Pragmas
37
39
 
38
40
  class << self
@@ -64,6 +64,8 @@ module SQLite3
64
64
  bind_params(*bind_vars) unless bind_vars.empty?
65
65
  @results = ResultSet.new(@connection, self)
66
66
 
67
+ step if 0 == column_count
68
+
67
69
  yield @results if block_given?
68
70
  @results
69
71
  end
@@ -4,13 +4,13 @@ module SQLite3
4
4
 
5
5
  MAJOR = 1
6
6
  MINOR = 3
7
- TINY = 0
7
+ TINY = 1
8
8
  BUILD = nil
9
9
 
10
10
  STRING = [ MAJOR, MINOR, TINY, BUILD ].compact.join( "." )
11
11
  #:beta-tag:
12
12
 
13
- VERSION = '1.3.0'
13
+ VERSION = '1.3.1'
14
14
  end
15
15
 
16
16
  end
@@ -1,6 +1,12 @@
1
1
  # use rake-compiler for building the extension
2
2
  require 'rake/extensiontask'
3
3
 
4
+ # NOTE: version used by cross compilation of Windows native extension
5
+ # It do not affect compilation under other operating systems
6
+ # The version indicated is the minimum DLL suggested for correct functionality
7
+ BINARY_VERSION = '3.6.23.1'
8
+ URL_VERSION = BINARY_VERSION.gsub('.', '_')
9
+
4
10
  # build sqlite3_native C extension
5
11
  Rake::ExtensionTask.new('sqlite3_native', HOE.spec) do |ext|
6
12
  # where to locate the extension
@@ -12,6 +18,9 @@ Rake::ExtensionTask.new('sqlite3_native', HOE.spec) do |ext|
12
18
  # reference to the sqlite3 library
13
19
  sqlite3_lib = File.expand_path(File.join(File.dirname(__FILE__), '..', 'vendor', 'sqlite3'))
14
20
 
21
+ # clean binary folders always
22
+ CLEAN.include("#{ext.lib_dir}/?.?")
23
+
15
24
  # automatically add build options to avoid need of manual input
16
25
  if RUBY_PLATFORM =~ /mswin|mingw/ then
17
26
  # define target for extension (supporting fat binaries)
@@ -22,6 +31,27 @@ Rake::ExtensionTask.new('sqlite3_native', HOE.spec) do |ext|
22
31
  ext.cross_compile = true
23
32
  ext.cross_platform = ['i386-mswin32-60', 'i386-mingw32']
24
33
  ext.cross_config_options << "--with-sqlite3-dir=#{sqlite3_lib}"
34
+ ext.cross_compiling do |gemspec|
35
+ gemspec.post_install_message = <<-POST_INSTALL_MESSAGE
36
+
37
+ =============================================================================
38
+
39
+ You've installed the binary version of #{gemspec.name}.
40
+ It was built using SQLite3 version #{BINARY_VERSION}.
41
+ It's recommended to use the exact same version to avoid potential issues.
42
+
43
+ At the time of building this gem, the necessary DLL files where available
44
+ in the following download:
45
+
46
+ http://www.sqlite.org/sqlitedll-#{URL_VERSION}.zip
47
+
48
+ You can put the sqlite3.dll available in this package in your Ruby bin
49
+ directory, for example C:\\Ruby\\bin
50
+
51
+ =============================================================================
52
+
53
+ POST_INSTALL_MESSAGE
54
+ end
25
55
  end
26
56
  end
27
57
 
@@ -25,15 +25,12 @@ def dlltool(dllname, deffile, libfile)
25
25
  end
26
26
  end
27
27
 
28
- SQLITE_VERSION = '3.6.22'
29
- url_version = SQLITE_VERSION.gsub('.', '_')
30
-
31
28
  # required folder structure for --with-sqlite3-dir (include + lib)
32
29
  directory "vendor/sqlite3/lib"
33
30
  directory "vendor/sqlite3/include"
34
31
 
35
32
  # download amalgamation version (for include files)
36
- file "vendor/sqlite-amalgamation-#{url_version}.zip" => ['vendor'] do |t|
33
+ file "vendor/sqlite-amalgamation-#{URL_VERSION}.zip" => ['vendor'] do |t|
37
34
  url = "http://www.sqlite.org/#{File.basename(t.name)}"
38
35
  when_writing "downloading #{t.name}" do
39
36
  cd File.dirname(t.name) do
@@ -43,7 +40,7 @@ file "vendor/sqlite-amalgamation-#{url_version}.zip" => ['vendor'] do |t|
43
40
  end
44
41
 
45
42
  # download dll binaries
46
- file "vendor/sqlitedll-#{url_version}.zip" => ['vendor'] do |t|
43
+ file "vendor/sqlitedll-#{URL_VERSION}.zip" => ['vendor'] do |t|
47
44
  url = "http://www.sqlite.org/#{File.basename(t.name)}"
48
45
  when_writing "downloading #{t.name}" do
49
46
  cd File.dirname(t.name) do
@@ -53,7 +50,7 @@ file "vendor/sqlitedll-#{url_version}.zip" => ['vendor'] do |t|
53
50
  end
54
51
 
55
52
  # extract header files into include folder
56
- file "vendor/sqlite3/include/sqlite3.h" => ['vendor/sqlite3/include', "vendor/sqlite-amalgamation-#{url_version}.zip"] do |t|
53
+ file "vendor/sqlite3/include/sqlite3.h" => ['vendor/sqlite3/include', "vendor/sqlite-amalgamation-#{URL_VERSION}.zip"] do |t|
57
54
  full_file = File.expand_path(t.prerequisites.last)
58
55
  when_writing "creating #{t.name}" do
59
56
  cd File.dirname(t.name) do
@@ -65,7 +62,7 @@ file "vendor/sqlite3/include/sqlite3.h" => ['vendor/sqlite3/include', "vendor/sq
65
62
  end
66
63
 
67
64
  # extract dll files into lib folder
68
- file "vendor/sqlite3/lib/sqlite3.dll" => ['vendor/sqlite3/lib', "vendor/sqlitedll-#{url_version}.zip"] do |t|
65
+ file "vendor/sqlite3/lib/sqlite3.dll" => ['vendor/sqlite3/lib', "vendor/sqlitedll-#{URL_VERSION}.zip"] do |t|
69
66
  full_file = File.expand_path(t.prerequisites.last)
70
67
  when_writing "creating #{t.name}" do
71
68
  cd File.dirname(t.name) do
@@ -0,0 +1,82 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'helper'
4
+
5
+ module SQLite3
6
+ class TestCollation < Test::Unit::TestCase
7
+ class Comparator
8
+ attr_reader :calls
9
+ def initialize
10
+ @calls = []
11
+ end
12
+
13
+ def compare left, right
14
+ @calls << [left, right]
15
+ left <=> right
16
+ end
17
+ end
18
+
19
+ def setup
20
+ @db = SQLite3::Database.new(':memory:')
21
+ @create = "create table ex(id int, data string)"
22
+ @db.execute(@create);
23
+ [ [1, 'hello'], [2, 'world'] ].each do |vals|
24
+ @db.execute('insert into ex (id, data) VALUES (?, ?)', vals)
25
+ end
26
+ end
27
+
28
+ def test_custom_collation
29
+ comparator = Comparator.new
30
+
31
+ @db.collation 'foo', comparator
32
+
33
+ assert_equal comparator, @db.collations['foo']
34
+ @db.execute('select data from ex order by 1 collate foo')
35
+ assert_equal 1, comparator.calls.length
36
+ end
37
+
38
+ def test_remove_collation
39
+ comparator = Comparator.new
40
+
41
+ @db.collation 'foo', comparator
42
+ @db.collation 'foo', nil
43
+
44
+ assert_nil @db.collations['foo']
45
+ assert_raises(SQLite3::SQLException) do
46
+ @db.execute('select data from ex order by 1 collate foo')
47
+ end
48
+ end
49
+
50
+ if RUBY_VERSION >= '1.9.1'
51
+ def test_encoding
52
+ comparator = Comparator.new
53
+ @db.collation 'foo', comparator
54
+ @db.execute('select data from ex order by 1 collate foo')
55
+
56
+ a, b = *comparator.calls.first
57
+
58
+ assert_equal Encoding.find('UTF-8'), a.encoding
59
+ assert_equal Encoding.find('UTF-8'), b.encoding
60
+ end
61
+
62
+ def test_encoding_default_internal
63
+ warn_before = $-w
64
+ $-w = false
65
+ before_enc = Encoding.default_internal
66
+
67
+ Encoding.default_internal = 'EUC-JP'
68
+ comparator = Comparator.new
69
+ @db.collation 'foo', comparator
70
+ @db.execute('select data from ex order by 1 collate foo')
71
+
72
+ a, b = *comparator.calls.first
73
+
74
+ assert_equal Encoding.find('EUC-JP'), a.encoding
75
+ assert_equal Encoding.find('EUC-JP'), b.encoding
76
+ ensure
77
+ Encoding.default_internal = before_enc
78
+ $-w = warn_before
79
+ end
80
+ end
81
+ end
82
+ end
@@ -7,6 +7,10 @@ module SQLite3
7
7
  @db = SQLite3::Database.new(':memory:')
8
8
  end
9
9
 
10
+ def test_encoding
11
+ assert @db.encoding, 'database has encoding'
12
+ end
13
+
10
14
  def test_changes
11
15
  @db.execute("CREATE TABLE items (id integer PRIMARY KEY AUTOINCREMENT, number integer)")
12
16
  assert_equal 0, @db.changes
@@ -3,9 +3,17 @@ require 'helper'
3
3
  module SQLite3
4
4
  class TestDeprecated < Test::Unit::TestCase
5
5
  def setup
6
+ super
7
+ @warn_before = $-w
8
+ $-w = false
6
9
  @db = SQLite3::Database.new(':memory:')
7
10
  end
8
11
 
12
+ def teardown
13
+ super
14
+ $-w = @warn_before
15
+ end
16
+
9
17
  def test_query_with_many_bind_params
10
18
  assert_equal [[nil, 1]], @db.query("select ?, ?", nil, 1).to_a
11
19
  end
@@ -12,6 +12,9 @@ module SQLite3
12
12
  end
13
13
 
14
14
  def test_default_internal_is_honored
15
+ warn_before = $-w
16
+ $-w = false
17
+
15
18
  before_enc = Encoding.default_internal
16
19
 
17
20
  str = "壁に耳あり、障子に目あり"
@@ -27,6 +30,7 @@ module SQLite3
27
30
  assert_equal str, string.encode(str.encoding)
28
31
  ensure
29
32
  Encoding.default_internal = before_enc
33
+ $-w = warn_before
30
34
  end
31
35
 
32
36
  def test_blob_is_binary
@@ -97,7 +101,7 @@ module SQLite3
97
101
 
98
102
  def test_utf_8
99
103
  str = "猫舌"
100
- @db.execute(@insert, 10, str)
104
+ @db.execute(@insert, [10, str])
101
105
  row = @db.execute("select data from ex")
102
106
  assert_equal @db.encoding, row.first.first.encoding
103
107
  assert_equal str, row.first.first
@@ -105,7 +109,7 @@ module SQLite3
105
109
 
106
110
  def test_euc_jp
107
111
  str = "猫舌".encode('EUC-JP')
108
- @db.execute(@insert, 10, str)
112
+ @db.execute(@insert, [10, str])
109
113
  row = @db.execute("select data from ex")
110
114
  assert_equal @db.encoding, row.first.first.encoding
111
115
  assert_equal str.encode('UTF-8'), row.first.first
@@ -261,7 +261,7 @@ class TC_Database_Integration < Test::Unit::TestCase
261
261
  end
262
262
 
263
263
  def test_execute_batch_with_bind
264
- @db.execute_batch( <<-SQL, 1 )
264
+ @db.execute_batch( <<-SQL, [1] )
265
265
  create table bar ( a, b, c );
266
266
  insert into bar values ( 'one', 2, ? );
267
267
  insert into bar values ( 'four', 5, ? );
@@ -20,6 +20,8 @@ class TC_Integration_Pending < Test::Unit::TestCase
20
20
  end
21
21
 
22
22
  def test_busy_handler_outwait
23
+ skip("not working in 1.9") if RUBY_VERSION >= '1.9'
24
+
23
25
  busy = Mutex.new
24
26
  busy.lock
25
27
  handler_call_count = 0
@@ -0,0 +1,35 @@
1
+ require 'helper'
2
+
3
+ module SQLite3
4
+ class TestStatementExecute < Test::Unit::TestCase
5
+ def setup
6
+ @db = SQLite3::Database.new(':memory:')
7
+ @db.execute_batch(
8
+ "CREATE TABLE items (id integer PRIMARY KEY, number integer)")
9
+ end
10
+
11
+ def test_execute_insert
12
+ ps = @db.prepare("INSERT INTO items (number) VALUES (:n)")
13
+ ps.execute('n'=>10)
14
+ assert_equal 1, @db.get_first_value("SELECT count(*) FROM items")
15
+ ps.close
16
+ end
17
+
18
+ def test_execute_update
19
+ @db.execute("INSERT INTO items (number) VALUES (?)", [10])
20
+
21
+ ps = @db.prepare("UPDATE items SET number = :new WHERE number = :old")
22
+ ps.execute('old'=>10, 'new'=>20)
23
+ assert_equal 20, @db.get_first_value("SELECT number FROM items")
24
+ ps.close
25
+ end
26
+
27
+ def test_execute_delete
28
+ @db.execute("INSERT INTO items (number) VALUES (?)", [20])
29
+ ps = @db.prepare("DELETE FROM items WHERE number = :n")
30
+ ps.execute('n' => 20)
31
+ assert_equal 0, @db.get_first_value("SELECT count(*) FROM items")
32
+ ps.close
33
+ end
34
+ end
35
+ end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 1
7
7
  - 3
8
- - 0
9
- version: 1.3.0
8
+ - 1
9
+ version: 1.3.1
10
10
  platform: ruby
11
11
  authors:
12
12
  - Jamis Buck
@@ -16,7 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2010-06-06 00:00:00 -03:00
19
+ date: 2010-07-10 00:00:00 -03:00
20
20
  default_executable:
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency
@@ -119,6 +119,7 @@ files:
119
119
  - tasks/native.rake
120
120
  - tasks/vendor_sqlite3.rake
121
121
  - test/helper.rb
122
+ - test/test_collation.rb
122
123
  - test/test_database.rb
123
124
  - test/test_deprecated.rb
124
125
  - test/test_encoding.rb
@@ -129,6 +130,7 @@ files:
129
130
  - test/test_integration_statement.rb
130
131
  - test/test_sqlite3.rb
131
132
  - test/test_statement.rb
133
+ - test/test_statement_execute.rb
132
134
  has_rdoc: true
133
135
  homepage: http://github.com/luislavena/sqlite3-ruby
134
136
  licenses: []
@@ -169,9 +171,11 @@ test_files:
169
171
  - test/test_integration_open_close.rb
170
172
  - test/test_database.rb
171
173
  - test/test_integration.rb
174
+ - test/test_collation.rb
172
175
  - test/test_statement.rb
173
176
  - test/test_integration_pending.rb
174
177
  - test/test_deprecated.rb
178
+ - test/test_statement_execute.rb
175
179
  - test/test_integration_statement.rb
176
180
  - test/test_encoding.rb
177
181
  - test/test_integration_resultset.rb