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 +7 -0
- data/Rakefile +1 -1
- data/ext/Blob.c +2 -3
- data/ext/Row.c +38 -21
- data/ext/Row.h +0 -1
- data/ext/Statement.c +44 -0
- data/lib/active_record/connection_adapters/rubyfb_adapter.rb +16 -3
- data/lib/rubyfb_lib.so +0 -0
- data/lib/src.rb +10 -0
- data/rubyfb.gemspec +3 -3
- data/test/StatementTest.rb +10 -0
- metadata +21 -39
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
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,
|
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
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
|
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.
|
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-
|
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.
|
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
|
data/test/StatementTest.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
149
|
-
|
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
|
-
|
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.
|
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
|
-
|