rubyfb 0.6.2 → 0.6.3

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.
data/CHANGELOG CHANGED
@@ -1,3 +1,10 @@
1
+ v0.6.3 ==
2
+ Fix change_column() migration method
3
+ Fix Segmentation fault in Row class (GC integration issues)
4
+ Remove deprecated require in rubyfb_adapter.rb
5
+ Fix Rails 3.2 "undefined method `accept' for nil:NilClass" - https://github.com/rails/rails/issues/4632
6
+ Add Rails 3.2 explain() support
7
+
1
8
  v0.6.2 ==
2
9
  Update arel visitors
3
10
  Use round() when scaling fixed parameter values
data/Rakefile CHANGED
@@ -1,5 +1,5 @@
1
1
  require 'echoe'
2
- e = Echoe.new('rubyfb', '0.6.2') do |p|
2
+ e = Echoe.new('rubyfb', '0.6.3') do |p|
3
3
  p.description = "Firebird SQL access library"
4
4
  p.url = "http://rubyforge.org/projects/rubyfb"
5
5
  p.author = "George Georgiev"
data/ext/Blob.c CHANGED
@@ -100,13 +100,12 @@ static VALUE getBlobData(VALUE self) {
100
100
  Data_Get_Struct(self, BlobHandle, blob);
101
101
  if(blob->size > 0) {
102
102
  char *buffer = loadBlobData(blob);
103
-
104
103
  if(buffer != NULL) {
105
104
  data = rfbstr(connection, blob->charset, buffer, blob->size);
105
+ free(buffer);
106
+ rb_iv_set(self, "@data", data);
106
107
  }
107
- free(buffer);
108
108
  }
109
- rb_iv_set(self, "@data", data);
110
109
  }
111
110
 
112
111
  return(data);
data/ext/Row.c CHANGED
@@ -58,6 +58,43 @@ static VALUE rowValuesAt(int, VALUE *, VALUE);
58
58
  /* Globals. */
59
59
  VALUE cRow;
60
60
 
61
+ /**
62
+ * This function integrates with the Ruby garbage collector to insure that
63
+ * all resources associated with a Row object are marked during the mark phase
64
+ *
65
+ * @param row A pointer to the RowHandle object for the Row object.
66
+ *
67
+ */
68
+ void rowGCMark(void *handle) {
69
+ if(handle != NULL) {
70
+ RowHandle *row = (RowHandle *)handle;
71
+ int i;
72
+ for(i = 0; i < row->size; i++) {
73
+ rb_gc_mark(row->columns[i].value);
74
+ rb_gc_mark(row->columns[i].type);
75
+ rb_gc_mark(row->columns[i].scale);
76
+ }
77
+ }
78
+ }
79
+
80
+ /**
81
+ * This function integrates with the Ruby garbage collector to insure that
82
+ * all resources associated with a Row object are released whenever the Row
83
+ * object is collected.
84
+ *
85
+ * @param row A pointer to the RowHandle object for the Row object.
86
+ *
87
+ */
88
+ void freeRow(void *row) {
89
+ if(row != NULL) {
90
+ RowHandle *handle = (RowHandle *)row;
91
+
92
+ if(handle->columns != NULL) {
93
+ free(handle->columns);
94
+ }
95
+ free(handle);
96
+ }
97
+ }
61
98
 
62
99
  /**
63
100
  * This function integrates with the Ruby memory allocation system to allocate
@@ -77,7 +114,7 @@ static VALUE allocateRow(VALUE klass) {
77
114
  handle->size = 0;
78
115
  handle->number = 0;
79
116
  handle->columns = NULL;
80
- row = Data_Wrap_Struct(klass, NULL, freeRow, handle);
117
+ row = Data_Wrap_Struct(klass, rowGCMark, freeRow, handle);
81
118
  } else {
82
119
  /* Generate an exception. */
83
120
  rb_raise(rb_eNoMemError, "Memory allocation failure allocating a row.");
@@ -816,26 +853,6 @@ VALUE rowValuesAt(int size, VALUE *keys, VALUE self) {
816
853
  }
817
854
 
818
855
 
819
- /**
820
- * This function integrates with the Ruby garbage collector to insure that
821
- * all resources associated with a Row object are released whenever the Row
822
- * object is collected.
823
- *
824
- * @param row A pointer to the RowHandle object for the Row object.
825
- *
826
- */
827
- void freeRow(void *row) {
828
- if(row != NULL) {
829
- RowHandle *handle = (RowHandle *)row;
830
-
831
- if(handle->columns != NULL) {
832
- free(handle->columns);
833
- }
834
- free(handle);
835
- }
836
- }
837
-
838
-
839
856
  /**
840
857
  * This function provides a programmatic means of creating a Row object.
841
858
  *
data/ext/Row.h CHANGED
@@ -48,7 +48,6 @@ typedef struct {
48
48
 
49
49
  /* Function prototypes. */
50
50
  void Init_Row(VALUE);
51
- void freeRow(void *);
52
51
  VALUE rb_row_new(VALUE, VALUE, VALUE);
53
52
 
54
53
  #endif // FIRERUBY_ROW_H
data/ext/Statement.c CHANGED
@@ -45,6 +45,7 @@ static VALUE execAndCloseStatement(int, VALUE*, VALUE);
45
45
  static VALUE closeStatement(VALUE);
46
46
  static VALUE getStatementPrepared(VALUE);
47
47
  static VALUE prepareStatement(int, VALUE*, VALUE);
48
+ static VALUE getStatementPlan(VALUE);
48
49
 
49
50
  VALUE execAndManageTransaction(VALUE, VALUE, VALUE);
50
51
  VALUE execAndManageStatement(VALUE, VALUE, VALUE);
@@ -687,6 +688,48 @@ static VALUE prepareStatement(int argc, VALUE *argv, VALUE self) {
687
688
  return (self);
688
689
  }
689
690
 
691
+ /**
692
+ * This function provides the plan method for the Statement class.
693
+ *
694
+ * @param self A reference to the Statement object to call the method on.
695
+ *
696
+ * @return Query plan
697
+ *
698
+ */
699
+ VALUE getStatementPlan(VALUE self) {
700
+ StatementHandle *statement = getPreparedHandle(self);
701
+ ISC_STATUS status[ISC_STATUS_LENGTH];
702
+ unsigned int dataLength = 1024;
703
+ unsigned short retry = 1;
704
+ VALUE result = Qnil;
705
+ char items[] = {isc_info_sql_get_plan};
706
+ char *buffer = ALLOC_N(char, dataLength);
707
+ while(retry == 1) {
708
+ retry = 0;
709
+ if(!isc_dsql_sql_info(status, &statement->handle, sizeof(items), items,
710
+ dataLength, buffer)) {
711
+ switch(buffer[0]) {
712
+ case isc_info_truncated:
713
+ dataLength = dataLength + 1024;
714
+ buffer = REALLOC_N(buffer, char, dataLength);
715
+ retry = 1;
716
+ break;
717
+ case isc_info_sql_get_plan:
718
+ dataLength = isc_vax_integer(&buffer[1], 2);
719
+ result = rb_str_new(&buffer[3], dataLength);
720
+ rb_funcall(result, rb_intern("strip!"), 0);
721
+ default:
722
+ retry = 0;
723
+ }
724
+ }
725
+ }
726
+ free(buffer);
727
+ if (result == Qnil) {
728
+ rb_fireruby_raise(status, "Error retrieving query plan.");
729
+ }
730
+ return (result);
731
+ }
732
+
690
733
  /**
691
734
  * This function provides a programmatic means of creating a Statement object.
692
735
  *
@@ -797,6 +840,7 @@ void Init_Statement(VALUE module) {
797
840
  rb_define_method(cStatement, "parameter_count", getStatementParameterCount, 0);
798
841
  rb_define_method(cStatement, "prepare", prepareStatement, -1);
799
842
  rb_define_method(cStatement, "prepared?", getStatementPrepared, 0);
843
+ rb_define_method(cStatement, "plan", getStatementPlan, 0);
800
844
 
801
845
  rb_define_const(cStatement, "SELECT_STATEMENT",
802
846
  INT2FIX(isc_info_sql_stmt_select));
@@ -1,7 +1,6 @@
1
1
  # Author: Ken Kunz <kennethkunz@gmail.com>
2
2
  require 'digest/sha1'
3
3
  require 'active_record/connection_adapters/abstract_adapter'
4
- require 'active_support/core_ext/kernel/requires'
5
4
  require 'rubyfb_options'
6
5
 
7
6
  if defined?(Arel) then
@@ -332,6 +331,7 @@ module ActiveRecord
332
331
  @transaction = nil
333
332
  @blobs_disabled = 0
334
333
  @statements = {}
334
+ @visitor = Arel::Visitors::RubyFB.new self if defined?(Arel::Visitors::RubyFB)
335
335
  end
336
336
 
337
337
  def self.visitor_for(pool) # :nodoc:
@@ -516,12 +516,17 @@ module ActiveRecord
516
516
  end
517
517
  s = cache || @connection.create_statement(sql)
518
518
  s.prepare(@transaction) unless s.prepared?
519
+
519
520
  if Rubyfb::Statement::DDL_STATEMENT == s.type
520
521
  clear_cache!
521
522
  elsif cache.nil? && !binds.empty?
522
523
  @statements[sql] = cache = s
523
524
  end
524
- if cache
525
+ if name == 'EXPLAIN'
526
+ return s.plan.tap do
527
+ s.close unless cache
528
+ end
529
+ elsif cache
525
530
  s.exec(binds, @transaction, &block)
526
531
  else
527
532
  s.exec_and_close(binds, @transaction, &block)
@@ -952,7 +957,7 @@ module ActiveRecord
952
957
  end
953
958
 
954
959
  def change_column_type(table_name, column_name, type, options = {})
955
- sql = "ALTER TABLE #{quote_table_name(table_name)} ALTER COLUMN #{quote_column_name(column_name)} TYPE #{type_to_sql(type, options[:limit])}"
960
+ sql = "ALTER TABLE #{quote_table_name(table_name)} ALTER COLUMN #{quote_column_name(column_name)} TYPE #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
956
961
  exec_query(sql)
957
962
  rescue StatementInvalid
958
963
  raise unless non_existent_domain_error?
@@ -1084,6 +1089,14 @@ module ActiveRecord
1084
1089
  end
1085
1090
 
1086
1091
  class RubyfbAR31Adapter < RubyfbAdapter
1092
+ def supports_explain?
1093
+ true
1094
+ end
1095
+
1096
+ def explain(arel, binds = [])
1097
+ exec_query(to_sql(arel), 'EXPLAIN', binds)
1098
+ end
1099
+
1087
1100
  protected
1088
1101
  def log(sql, name, binds = nil) #:nodoc:
1089
1102
  super sql, name, binds
data/lib/rubyfb_lib.so CHANGED
Binary file
data/lib/src.rb CHANGED
@@ -712,6 +712,15 @@ module Rubyfb
712
712
  #
713
713
  def close
714
714
  end
715
+
716
+ #
717
+ # This method returns the SQL execution plan for the statement
718
+ #
719
+ # ==== Exceptions
720
+ # FireRubyError:: Generated whenever a problem occurs obtaining the plan
721
+ #
722
+ def plan
723
+ end
715
724
  end
716
725
 
717
726
 
@@ -1509,6 +1518,7 @@ module Rubyfb
1509
1518
  #
1510
1519
  # This method is used to set the indicator for whether checksum values
1511
1520
  # should be ignored in performing a backup.
1521
+
1512
1522
  #
1513
1523
  # ==== Parameters
1514
1524
  # setting:: True to ignore checksums, false otherwise.
data/rubyfb.gemspec CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "rubyfb"
5
- s.version = "0.6.2"
5
+ s.version = "0.6.3"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["George Georgiev"]
9
- s.date = "2012-01-04"
9
+ s.date = "2012-02-21"
10
10
  s.description = "Firebird SQL access library"
11
11
  s.email = "georgiev@heatbs.com"
12
12
  s.extensions = ["ext/extconf.rb"]
@@ -16,7 +16,7 @@ Gem::Specification.new do |s|
16
16
  s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Rubyfb", "--main", "README"]
17
17
  s.require_paths = ["lib", "ext"]
18
18
  s.rubyforge_project = "rubyfb"
19
- s.rubygems_version = "1.8.10"
19
+ s.rubygems_version = "1.8.11"
20
20
  s.summary = "Firebird SQL access library"
21
21
 
22
22
  if s.respond_to? :specification_version then
@@ -149,4 +149,14 @@ class StatementTest < Test::Unit::TestCase
149
149
  cxn.execute_immediate('DROP TABLE STRING_TEST')
150
150
  end
151
151
  end
152
+
153
+ def test05
154
+ @database.connect(DB_USER_NAME, DB_PASSWORD) do |cxn|
155
+ cxn.execute_immediate('CREATE TABLE PLAN_TEST(TEXT VARCHAR(100) CHARACTER SET UTF8)')
156
+ s = cxn.create_statement('SELECT * FROM PLAN_TEST')
157
+ assert_equal("PLAN (PLAN_TEST NATURAL)", s.plan)
158
+ s.close
159
+ cxn.execute_immediate('DROP TABLE PLAN_TEST')
160
+ end
161
+ end
152
162
  end
metadata CHANGED
@@ -1,30 +1,22 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: rubyfb
3
- version: !ruby/object:Gem::Version
4
- hash: 3
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.6.3
5
5
  prerelease:
6
- segments:
7
- - 0
8
- - 6
9
- - 2
10
- version: 0.6.2
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - George Georgiev
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2012-01-04 00:00:00 Z
12
+ date: 2012-02-21 00:00:00.000000000 Z
19
13
  dependencies: []
20
-
21
14
  description: Firebird SQL access library
22
15
  email: georgiev@heatbs.com
23
16
  executables: []
24
-
25
- extensions:
17
+ extensions:
26
18
  - ext/extconf.rb
27
- extra_rdoc_files:
19
+ extra_rdoc_files:
28
20
  - CHANGELOG
29
21
  - LICENSE
30
22
  - README
@@ -36,7 +28,7 @@ extra_rdoc_files:
36
28
  - lib/rubyfb.rb
37
29
  - lib/rubyfb_options.rb
38
30
  - lib/src.rb
39
- files:
31
+ files:
40
32
  - CHANGELOG
41
33
  - LICENSE
42
34
  - Manifest
@@ -128,43 +120,33 @@ files:
128
120
  - rubyfb.gemspec
129
121
  homepage: http://rubyforge.org/projects/rubyfb
130
122
  licenses: []
131
-
132
123
  post_install_message:
133
- rdoc_options:
124
+ rdoc_options:
134
125
  - --line-numbers
135
126
  - --inline-source
136
127
  - --title
137
128
  - Rubyfb
138
129
  - --main
139
130
  - README
140
- require_paths:
131
+ require_paths:
141
132
  - lib
142
133
  - ext
143
- required_ruby_version: !ruby/object:Gem::Requirement
134
+ required_ruby_version: !ruby/object:Gem::Requirement
144
135
  none: false
145
- requirements:
146
- - - ">="
147
- - !ruby/object:Gem::Version
148
- hash: 3
149
- segments:
150
- - 0
151
- version: "0"
152
- required_rubygems_version: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ! '>='
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ required_rubygems_version: !ruby/object:Gem::Requirement
153
141
  none: false
154
- requirements:
155
- - - ">="
156
- - !ruby/object:Gem::Version
157
- hash: 11
158
- segments:
159
- - 1
160
- - 2
161
- version: "1.2"
142
+ requirements:
143
+ - - ! '>='
144
+ - !ruby/object:Gem::Version
145
+ version: '1.2'
162
146
  requirements: []
163
-
164
147
  rubyforge_project: rubyfb
165
- rubygems_version: 1.8.10
148
+ rubygems_version: 1.8.11
166
149
  signing_key:
167
150
  specification_version: 3
168
151
  summary: Firebird SQL access library
169
152
  test_files: []
170
-