rubyfb 0.6.2 → 0.6.3

Sign up to get free protection for your applications and to get access to all the features.
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
-