lore 0.4.8 → 0.9.2
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/Manifest.txt +16 -7
- data/README.rdoc +91 -0
- data/benchmark/benchmark.sql +11 -0
- data/benchmark/results.txt +28 -0
- data/benchmark/select.rb +352 -0
- data/lib/lore.rb +22 -8
- data/lib/lore/adapters/context.rb +64 -0
- data/lib/lore/adapters/postgres-pr.rb +6 -0
- data/lib/lore/adapters/postgres-pr/connection.rb +93 -0
- data/lib/lore/adapters/postgres-pr/result.rb +63 -0
- data/lib/lore/{types.rb → adapters/postgres-pr/types.rb} +36 -0
- data/lib/lore/adapters/postgres.rb +24 -0
- data/lib/lore/adapters/postgres/connection.rb +81 -0
- data/lib/lore/adapters/postgres/result.rb +82 -0
- data/lib/lore/adapters/postgres/types.rb +91 -0
- data/lib/lore/bits.rb +18 -0
- data/lib/lore/cache/abstract_entity_cache.rb +2 -1
- data/lib/lore/cache/cacheable.rb +12 -177
- data/lib/lore/cache/memcache_entity_cache.rb +89 -0
- data/lib/lore/cache/memory_entity_cache.rb +77 -0
- data/lib/lore/cache/mmap_entity_cache.rb +2 -2
- data/lib/lore/cache/mmap_entity_cache_bork.rb +86 -0
- data/lib/lore/clause.rb +107 -35
- data/lib/lore/{exception → exceptions}/ambiguous_attribute.rb +2 -2
- data/lib/lore/{exception → exceptions}/cache_exception.rb +1 -1
- data/lib/lore/exceptions/database_exception.rb +16 -0
- data/lib/lore/{exception/invalid_parameter.rb → exceptions/invalid_field.rb} +7 -4
- data/lib/lore/exceptions/unknown_type.rb +18 -0
- data/lib/lore/exceptions/validation_failure.rb +71 -0
- data/lib/lore/gui/form_generator.rb +109 -60
- data/lib/lore/gui/lore_model_select_field.rb +1 -0
- data/lib/lore/migration.rb +84 -25
- data/lib/lore/model.rb +3 -18
- data/lib/lore/{aspect.rb → model/aspect.rb} +0 -0
- data/lib/lore/model/associations.rb +225 -0
- data/lib/lore/model/attribute_settings.rb +233 -0
- data/lib/lore/model/filters.rb +34 -0
- data/lib/lore/model/mockable.rb +62 -0
- data/lib/lore/{model_factory.rb → model/model_factory.rb} +68 -39
- data/lib/lore/model/model_instance.rb +382 -0
- data/lib/lore/{model_shortcuts.rb → model/model_shortcuts.rb} +7 -0
- data/lib/lore/model/polymorphic.rb +53 -0
- data/lib/lore/model/prepare.rb +97 -0
- data/lib/lore/model/table_accessor.rb +1016 -0
- data/lib/lore/query.rb +71 -0
- data/lib/lore/query_shortcuts.rb +43 -11
- data/lib/lore/strategies/table_delete.rb +115 -0
- data/lib/lore/strategies/table_insert.rb +146 -0
- data/lib/lore/strategies/table_select.rb +299 -0
- data/lib/lore/strategies/table_update.rb +155 -0
- data/lib/lore/validation/parameter_validator.rb +85 -26
- data/lib/lore/validation/type_validator.rb +34 -78
- data/{custom_models.rb → lore-0.9.2.gem} +0 -0
- data/lore.gemspec +26 -17
- data/spec/clause.rb +37 -0
- data/spec/fixtures/blank_models.rb +37 -0
- data/{test/model.rb → spec/fixtures/models.rb} +64 -41
- data/spec/fixtures/polymorphic_models.rb +68 -0
- data/spec/model_associations.rb +86 -0
- data/spec/model_create.rb +47 -0
- data/spec/model_definition.rb +151 -0
- data/spec/model_delete.rb +31 -0
- data/spec/model_inheritance.rb +50 -0
- data/spec/model_polymorphic.rb +85 -0
- data/spec/model_select.rb +101 -0
- data/spec/model_select_eager.rb +42 -0
- data/spec/model_union_select.rb +33 -0
- data/spec/model_update.rb +45 -0
- data/spec/model_validation.rb +20 -0
- data/spec/spec_db.sql +808 -0
- data/spec/spec_env.rb +19 -0
- data/spec/spec_helpers.rb +77 -0
- metadata +93 -82
- data/lib/lore/README.txt +0 -84
- data/lib/lore/behaviours/lockable.rb +0 -55
- data/lib/lore/behaviours/movable.rb +0 -72
- data/lib/lore/behaviours/paginated.rb +0 -31
- data/lib/lore/behaviours/versioned.rb +0 -36
- data/lib/lore/connection.rb +0 -152
- data/lib/lore/exception/invalid_klass_parameters.rb +0 -63
- data/lib/lore/exception/unknown_typecode.rb +0 -19
- data/lib/lore/result.rb +0 -119
- data/lib/lore/symbol.rb +0 -58
- data/lib/lore/table_accessor.rb +0 -1790
- data/lib/lore/table_deleter.rb +0 -116
- data/lib/lore/table_inserter.rb +0 -170
- data/lib/lore/table_instance.rb +0 -389
- data/lib/lore/table_selector.rb +0 -285
- data/lib/lore/table_updater.rb +0 -157
- data/lib/lore/validation.rb +0 -65
- data/lib/lore/validation/message.rb +0 -60
- data/lib/lore/validation/reason.rb +0 -52
- data/lore_test.log +0 -2366
- data/test/README +0 -31
- data/test/custom_models.rb +0 -18
- data/test/env.rb +0 -5
- data/test/prepare.rb +0 -37
- data/test/tc_aspect.rb +0 -58
- data/test/tc_cache.rb +0 -83
- data/test/tc_clause.rb +0 -104
- data/test/tc_deep_inheritance.rb +0 -49
- data/test/tc_factory.rb +0 -57
- data/test/tc_filter.rb +0 -37
- data/test/tc_form.rb +0 -32
- data/test/tc_model.rb +0 -140
- data/test/tc_prepare.rb +0 -44
- data/test/tc_refined_query.rb +0 -88
- data/test/tc_table_accessor.rb +0 -267
- data/test/tc_thread.rb +0 -100
- data/test/test_db.sql +0 -400
- data/test/test_lore.rb +0 -50
data/Manifest.txt
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
lib
|
|
7
|
-
|
|
1
|
+
|
|
2
|
+
'*',
|
|
3
|
+
'benchmark/*',
|
|
4
|
+
'spec/*',
|
|
5
|
+
'spec/fixtures/*',
|
|
6
|
+
'lib/*',
|
|
7
|
+
'lib/lore/*',
|
|
8
|
+
'lib/lore/adapters/*',
|
|
9
|
+
'lib/lore/cache/*',
|
|
10
|
+
'lib/lore/exceptions/*',
|
|
11
|
+
'lib/lore/gui/*',
|
|
12
|
+
'lib/lore/gui/templates/*',
|
|
13
|
+
'lib/lore/model/*',
|
|
14
|
+
'lib/lore/strategies/*',
|
|
15
|
+
'lib/lore/validation/*',
|
|
16
|
+
'bin/*'].to_a
|
data/README.rdoc
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
|
|
2
|
+
Didn't have the time to write a "real" readme, but let me show you ...
|
|
3
|
+
|
|
4
|
+
= A short comparison
|
|
5
|
+
|
|
6
|
+
== Use Case:
|
|
7
|
+
|
|
8
|
+
class Content < Lore::Model
|
|
9
|
+
table :contents, :public
|
|
10
|
+
primary_key :id, :content_id_seq
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
class Article < Lore::Model
|
|
14
|
+
table :articles, :public
|
|
15
|
+
primary_key :id, :article_id_seq
|
|
16
|
+
is_a Content, :content_id
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
== Selecting Articles using ActiveRecord
|
|
20
|
+
|
|
21
|
+
Article.find(:all, :include => :content,
|
|
22
|
+
:conditions => "id between 1 AND 100")
|
|
23
|
+
|
|
24
|
+
== Selecting Articles using Sequel
|
|
25
|
+
|
|
26
|
+
DB[:articles].left_outer_join(:contents, :id => :content_id).filter( :articles__id => (1..100))
|
|
27
|
+
|
|
28
|
+
== Selecting Articles using Lore
|
|
29
|
+
|
|
30
|
+
Article.all_with(Article.id.in(1..100))
|
|
31
|
+
|
|
32
|
+
(joins Content automatically)
|
|
33
|
+
|
|
34
|
+
== Benchmark results (1000 queries each returning 100 rows)
|
|
35
|
+
Most recent benchmark results from lore/benchmark/results.txt,
|
|
36
|
+
generated by running
|
|
37
|
+
|
|
38
|
+
ruby lore/benchmarks/select.rb 1000
|
|
39
|
+
|
|
40
|
+
Output on my machine:
|
|
41
|
+
|
|
42
|
+
Rehearsal ------------------------------------------------------------
|
|
43
|
+
unprocessed query 0.030000 0.030000 0.060000 ( 1.269820)
|
|
44
|
+
result fetching in lore 0.400000 0.050000 0.450000 ( 1.661275)
|
|
45
|
+
result parsing in lore 0.540000 0.080000 0.620000 ( 3.600497)
|
|
46
|
+
ac_instances unfiltered 2.440000 0.430000 2.870000 ( 4.113851)
|
|
47
|
+
ac_instances filtered 4.650000 0.700000 5.350000 ( 6.601500)
|
|
48
|
+
lore select unfiltered 2.720000 0.330000 3.050000 ( 4.355712)
|
|
49
|
+
lore shortcut filtered 5.110000 0.790000 5.900000 ( 7.507479)
|
|
50
|
+
--> lore shortcut unfiltered 3.030000 0.420000 3.450000 ( 4.675418) <--
|
|
51
|
+
--> activerecord 15.060000 1.960000 17.020000 ( 22.098705) <--
|
|
52
|
+
--> sequel 8.400000 0.940000 9.340000 ( 11.373551) <--
|
|
53
|
+
lore using cache 2.060000 0.080000 2.140000 ( 2.131782)
|
|
54
|
+
lore prepared 2.400000 0.460000 2.860000 ( 4.334760)
|
|
55
|
+
-------------------------------------------------- total: 53.110000sec
|
|
56
|
+
|
|
57
|
+
user system total real
|
|
58
|
+
unprocessed query 0.040000 0.020000 0.060000 ( 1.255553)
|
|
59
|
+
result fetching in lore 0.380000 0.050000 0.430000 ( 1.731519)
|
|
60
|
+
result parsing in lore 0.600000 0.120000 0.720000 ( 3.630439)
|
|
61
|
+
ac_instances unfiltered 2.580000 0.330000 2.910000 ( 4.138985)
|
|
62
|
+
ac_instances filtered 4.660000 0.710000 5.370000 ( 6.590051)
|
|
63
|
+
lore select unfiltered 2.640000 0.490000 3.130000 ( 4.357413)
|
|
64
|
+
lore shortcut filtered 5.150000 0.760000 5.910000 ( 7.518942)
|
|
65
|
+
lore shortcut unfiltered 2.660000 0.450000 3.110000 ( 4.647531)
|
|
66
|
+
activerecord 15.330000 2.180000 17.510000 ( 22.384284)
|
|
67
|
+
sequel 8.470000 0.880000 9.350000 ( 11.396475)
|
|
68
|
+
lore using cache 2.070000 0.070000 2.140000 ( 2.137200)
|
|
69
|
+
lore prepared 2.610000 0.390000 3.000000 ( 4.199908)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
NOTE: Perhaps results for AR and Sequel can be improved by
|
|
73
|
+
doing things differently - i'm using default behaviours for
|
|
74
|
+
benchmarking, but all SQL queries look alright, so my benchmark
|
|
75
|
+
code can't be that wrong.
|
|
76
|
+
If you know how to optimize my usage or AR and Sequel, please
|
|
77
|
+
let me know!
|
|
78
|
+
|
|
79
|
+
Also be aware that most applications aren't slow because of
|
|
80
|
+
its ORM, but because of ... sub-optimal algorithms using them.
|
|
81
|
+
Don't choose an ORM just because of a benchmark.
|
|
82
|
+
|
|
83
|
+
I just want to state that an ORM with both great performance
|
|
84
|
+
and convenient usage is feasible, and Lore is an example.
|
|
85
|
+
|
|
86
|
+
Apart from that: In case you don't like Lore, use Sequel. It's
|
|
87
|
+
incredibly stable, well-maintained, not that inefficient and
|
|
88
|
+
inconvenient as AR (see above), and its maintainer is a nice
|
|
89
|
+
guy - which is more important than you might think.
|
|
90
|
+
|
|
91
|
+
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
|
|
2
|
+
create table contents ( id integer not null, title varchar(100) );
|
|
3
|
+
create table articles ( id integer not null, content_id integer not null, content text );
|
|
4
|
+
|
|
5
|
+
create sequence content_id_seq start with 1 increment by 1;
|
|
6
|
+
create sequence article_id_seq start with 1 increment by 1;
|
|
7
|
+
|
|
8
|
+
grant all on contents to cuba;
|
|
9
|
+
grant all on articles to cuba;
|
|
10
|
+
grant all on content_id_seq to cuba;
|
|
11
|
+
grant all on article_id_seq to cuba;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
Rehearsal ------------------------------------------------------------
|
|
2
|
+
unprocessed query 0.030000 0.030000 0.060000 ( 1.269820)
|
|
3
|
+
result fetching in lore 0.400000 0.050000 0.450000 ( 1.661275)
|
|
4
|
+
result parsing in lore 0.540000 0.080000 0.620000 ( 3.600497)
|
|
5
|
+
ac_instances unfiltered 2.440000 0.430000 2.870000 ( 4.113851)
|
|
6
|
+
ac_instances filtered 4.650000 0.700000 5.350000 ( 6.601500)
|
|
7
|
+
lore select unfiltered 2.720000 0.330000 3.050000 ( 4.355712)
|
|
8
|
+
lore shortcut filtered 5.110000 0.790000 5.900000 ( 7.507479)
|
|
9
|
+
lore shortcut unfiltered 3.030000 0.420000 3.450000 ( 4.675418)
|
|
10
|
+
activerecord 15.060000 1.960000 17.020000 ( 22.098705)
|
|
11
|
+
sequel 8.400000 0.940000 9.340000 ( 11.373551)
|
|
12
|
+
lore using cache 2.060000 0.080000 2.140000 ( 2.131782)
|
|
13
|
+
lore prepared 2.400000 0.460000 2.860000 ( 4.334760)
|
|
14
|
+
-------------------------------------------------- total: 53.110000sec
|
|
15
|
+
|
|
16
|
+
user system total real
|
|
17
|
+
unprocessed query 0.040000 0.020000 0.060000 ( 1.255553)
|
|
18
|
+
result fetching in lore 0.380000 0.050000 0.430000 ( 1.731519)
|
|
19
|
+
result parsing in lore 0.600000 0.120000 0.720000 ( 3.630439)
|
|
20
|
+
ac_instances unfiltered 2.580000 0.330000 2.910000 ( 4.138985)
|
|
21
|
+
ac_instances filtered 4.660000 0.710000 5.370000 ( 6.590051)
|
|
22
|
+
lore select unfiltered 2.640000 0.490000 3.130000 ( 4.357413)
|
|
23
|
+
lore shortcut filtered 5.150000 0.760000 5.910000 ( 7.518942)
|
|
24
|
+
lore shortcut unfiltered 2.660000 0.450000 3.110000 ( 4.647531)
|
|
25
|
+
activerecord 15.330000 2.180000 17.510000 ( 22.384284)
|
|
26
|
+
sequel 8.470000 0.880000 9.350000 ( 11.396475)
|
|
27
|
+
lore using cache 2.070000 0.070000 2.140000 ( 2.137200)
|
|
28
|
+
lore prepared 2.610000 0.390000 3.000000 ( 4.199908)
|
data/benchmark/select.rb
ADDED
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
|
|
2
|
+
require('rubygems')
|
|
3
|
+
require('lore')
|
|
4
|
+
require('lore/model')
|
|
5
|
+
require('lore/cache/mmap_entity_cache')
|
|
6
|
+
|
|
7
|
+
Lore::Model.use_entity_cache Lore::Cache::Mmap_Entity_Cache
|
|
8
|
+
# Aurita.load_project :default
|
|
9
|
+
# Aurita.import_plugin_model :wiki, :article
|
|
10
|
+
|
|
11
|
+
# include Aurita::Plugins::Wiki
|
|
12
|
+
|
|
13
|
+
require('benchmark')
|
|
14
|
+
include Benchmark
|
|
15
|
+
# require('profile')
|
|
16
|
+
Lore.disable_logging
|
|
17
|
+
Lore.disable_query_log
|
|
18
|
+
|
|
19
|
+
require('rubygems')
|
|
20
|
+
require('activerecord')
|
|
21
|
+
require('sequel')
|
|
22
|
+
|
|
23
|
+
ActiveRecord::Base.establish_connection(
|
|
24
|
+
:adapter => 'postgresql',
|
|
25
|
+
:host => 'localhost',
|
|
26
|
+
:username => 'cuba',
|
|
27
|
+
:password => 'cuba23',
|
|
28
|
+
:database => 'artest'
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
Lore.add_login_data('artest' => ['cuba', 'cuba23'])
|
|
32
|
+
Lore::Context.enter :artest
|
|
33
|
+
|
|
34
|
+
DB = Sequel.connect('postgres://cuba:cuba23@localhost/artest')
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
range_from = 1000
|
|
38
|
+
range_to = 1100
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
module AR
|
|
42
|
+
class Content < ActiveRecord::Base
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
class Article < ActiveRecord::Base
|
|
46
|
+
belongs_to :content
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
module Lore
|
|
51
|
+
class Content < Lore::Model
|
|
52
|
+
table :contents, :public
|
|
53
|
+
primary_key :id, :content_id_seq
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
class Article < Lore::Model
|
|
57
|
+
table :articles, :public
|
|
58
|
+
primary_key :id, :article_id_seq
|
|
59
|
+
is_a Content, :content_id
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
Article.prepare(:id_in_range, Lore::Type.integer, Lore::Type.integer) { |a|
|
|
63
|
+
a.where(Article.id.between('$1', '$2'))
|
|
64
|
+
a.limit(100)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
num_loops = ARGV[0].to_i
|
|
70
|
+
num_loops = 100 if num_loops == 0
|
|
71
|
+
|
|
72
|
+
class Result_Parser
|
|
73
|
+
# {{{
|
|
74
|
+
require 'inline'
|
|
75
|
+
|
|
76
|
+
def initialize(result) # expects PGresult
|
|
77
|
+
|
|
78
|
+
@result = result
|
|
79
|
+
@field_types = nil
|
|
80
|
+
@result_rows = Array.new
|
|
81
|
+
@num_fields = @result.num_fields
|
|
82
|
+
@field_name_split = Array.new
|
|
83
|
+
@field_name = String.new
|
|
84
|
+
@table_name = String.new
|
|
85
|
+
@field_counter = 0
|
|
86
|
+
|
|
87
|
+
end # def initialize
|
|
88
|
+
|
|
89
|
+
=begin
|
|
90
|
+
inline { |builder|
|
|
91
|
+
builder.c <<-EOC
|
|
92
|
+
VALUE get_row_c(VALUE result, int row_num) {
|
|
93
|
+
unsigned int field_counter;
|
|
94
|
+
VALUE row_result, field_name, table_name, field_name_split;
|
|
95
|
+
VALUE value_set = rb_hash_new();
|
|
96
|
+
field_name = rb_string_new();
|
|
97
|
+
table_name = rb_string_new();
|
|
98
|
+
row_result = rb_hash_new();
|
|
99
|
+
for(field_counter = 0; field_counter < num_fields; field_counter++) {
|
|
100
|
+
value_set = result->getvalue(row_num, UINT2NUM(field_counter));
|
|
101
|
+
// if(row_result[@table_name].nil?) then
|
|
102
|
+
if(rb_hash_aref(row_result, table_name) == QNil) {
|
|
103
|
+
// row_result[@table_name] = Hash.new()
|
|
104
|
+
rb_hash_aset(row_result, table_name, value_set)
|
|
105
|
+
}
|
|
106
|
+
rb_hash_aset(rb_hash_aref)row_result, table_name), value_set);
|
|
107
|
+
}
|
|
108
|
+
return row_result;
|
|
109
|
+
}
|
|
110
|
+
EOC
|
|
111
|
+
}
|
|
112
|
+
=end
|
|
113
|
+
|
|
114
|
+
def get_row(row_num=0)
|
|
115
|
+
|
|
116
|
+
return if @result.num_tuples == 0
|
|
117
|
+
|
|
118
|
+
row_result = Hash.new
|
|
119
|
+
|
|
120
|
+
@field_name_split = Array.new
|
|
121
|
+
@field_name = String.new
|
|
122
|
+
@table_name = String.new
|
|
123
|
+
@field_counter = 0
|
|
124
|
+
for @field_counter in 0...@num_fields do
|
|
125
|
+
# admin.rd__content.name -> [admin, rd__content, name]
|
|
126
|
+
@field_name = @result.fieldname(@field_counter)
|
|
127
|
+
|
|
128
|
+
row_result[@field_name] = @result.getvalue(row_num,@field_counter)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
@result_rows[row_num] = row_result
|
|
132
|
+
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def get_rows()
|
|
136
|
+
if !@result_rows.first then
|
|
137
|
+
for tuple_counter in 0...@result.num_tuples do
|
|
138
|
+
get_row(tuple_counter)
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
@result_rows
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
end # }}}
|
|
145
|
+
|
|
146
|
+
# SQL raw definitions
|
|
147
|
+
# {{{
|
|
148
|
+
db_name = 'artest'
|
|
149
|
+
connection = PGconn.connect(Lore.pg_server, Lore.pg_port, '', '', db_name.to_s, Lore.user_for(db_name), Lore.pass_for(db_name.to_s))
|
|
150
|
+
|
|
151
|
+
sql = "SELECT *
|
|
152
|
+
FROM public.articles
|
|
153
|
+
JOIN public.contents on (public.contents.id = public.articles.content_id)
|
|
154
|
+
WHERE public.articles.id BETWEEN #{range_from} AND #{range_to} LIMIT #{range_to-range_from} OFFSET 0"
|
|
155
|
+
|
|
156
|
+
sql_exec = "EXECUTE public_articles__id_in_range(#{range_from},#{range_to}); "
|
|
157
|
+
|
|
158
|
+
sql_prep = 'PREPARE public_articles__id_in_range(integer,integer) AS
|
|
159
|
+
SELECT
|
|
160
|
+
public.contents.id AS "public.contents.id",
|
|
161
|
+
public.contents.user_group_id AS "public.contents.user_group_id",
|
|
162
|
+
public.contents.tags AS "public.contents.tags",
|
|
163
|
+
public.contents.changed AS "public.contents.changed",
|
|
164
|
+
public.contents.created AS "public.contents.created",
|
|
165
|
+
public.contents.hits AS "public.contents.hits",
|
|
166
|
+
public.contents.locked AS "public.contents.locked",
|
|
167
|
+
public.contents.deleted AS "public.contents.deleted",
|
|
168
|
+
public.contents.version AS "public.contents.version",
|
|
169
|
+
public.articles.id AS "public.articles.id",
|
|
170
|
+
public.articles.content_id AS "public.articles.content_id",
|
|
171
|
+
public.articles.template_id AS "public.articles.template_id",
|
|
172
|
+
public.articles.title AS "public.articles.title",
|
|
173
|
+
public.articles.view_count AS "public.articles.view_count",
|
|
174
|
+
public.articles.published AS "public.articles.published"
|
|
175
|
+
FROM public.articles
|
|
176
|
+
JOIN public.contents on (public.contents.id = public.articles.content_id)
|
|
177
|
+
WHERE public.articles.id BETWEEN $1 AND $2 LIMIT 100 OFFSET 0'
|
|
178
|
+
|
|
179
|
+
# }}}
|
|
180
|
+
|
|
181
|
+
(0..3000).to_a.each { |i|
|
|
182
|
+
# Lore::Article.create(:title => "title_#{i}",
|
|
183
|
+
# :tags => [ :foo, :bar, :wombat ],
|
|
184
|
+
# :text => "text #{i}")
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
bmbm(12) { |test|
|
|
189
|
+
test.report("unprocessed query") {
|
|
190
|
+
num_loops.times {
|
|
191
|
+
result = connection.exec(sql)
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
# test.report("row parsing") {
|
|
195
|
+
# num_loops.times {
|
|
196
|
+
# result = connection.exec(sql)
|
|
197
|
+
# p = Result_Parser.new(result)
|
|
198
|
+
# p.get_rows
|
|
199
|
+
# }
|
|
200
|
+
# }
|
|
201
|
+
# test.report("result fetching in lore") {
|
|
202
|
+
# num_loops.times {
|
|
203
|
+
# result = connection.exec(sql)
|
|
204
|
+
# result = Lore::Result.new('',result)
|
|
205
|
+
# result.get_rows.each { |row|
|
|
206
|
+
# # noop
|
|
207
|
+
# }
|
|
208
|
+
# }
|
|
209
|
+
# }
|
|
210
|
+
# test.report("result parsing in lore") {
|
|
211
|
+
# num_loops.times {
|
|
212
|
+
# result = connection.exec(sql)
|
|
213
|
+
# result = Lore::Connection.perform(sql)
|
|
214
|
+
# result.get_rows.each { |row|
|
|
215
|
+
# # noop
|
|
216
|
+
# }
|
|
217
|
+
# }
|
|
218
|
+
# }
|
|
219
|
+
# test.report("ac_instances unfiltered") {
|
|
220
|
+
# Lore.disable_cache
|
|
221
|
+
# Lore::Article.disable_output_filters if Lore::Article.respond_to?(:disable_output_filters)
|
|
222
|
+
# num_loops.times {
|
|
223
|
+
# result = Lore::Connection.perform(sql).get_rows()
|
|
224
|
+
# result.map! { |row|
|
|
225
|
+
# row = (Lore::Article.new(row))
|
|
226
|
+
# }
|
|
227
|
+
# }
|
|
228
|
+
# }
|
|
229
|
+
# test.report("ac_instances filtered") {
|
|
230
|
+
# Lore.disable_cache
|
|
231
|
+
# Lore::Article.enable_output_filters if Lore::Article.respond_to?(:enable_output_filters)
|
|
232
|
+
# num_loops.times {
|
|
233
|
+
# result = Lore::Connection.perform(sql).get_rows()
|
|
234
|
+
# result.map! { |row|
|
|
235
|
+
# row = (Lore::Article.new(row))
|
|
236
|
+
# }
|
|
237
|
+
# }
|
|
238
|
+
# }
|
|
239
|
+
test.report("lore select unfiltered") {
|
|
240
|
+
Lore.disable_cache
|
|
241
|
+
Lore::Article.disable_output_filters if Lore::Article.respond_to?(:disable_output_filters)
|
|
242
|
+
id_error = false
|
|
243
|
+
count = 0
|
|
244
|
+
num_loops.times {
|
|
245
|
+
count = range_from
|
|
246
|
+
Lore::Article.select { |a|
|
|
247
|
+
a.where(Lore::Article.id.in(range_from..range_to))
|
|
248
|
+
a.limit(100)
|
|
249
|
+
}.each { |a|
|
|
250
|
+
raise ::Exception.new("ID ERROR: #{a.id.inspect} != #{count.inspect}") if a.id.to_s != count.to_s
|
|
251
|
+
count += 1
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
test.report("lore shortcut filtered") {
|
|
256
|
+
id_error = false
|
|
257
|
+
Lore.disable_cache
|
|
258
|
+
Lore::Article.enable_output_filters if Lore::Article.respond_to?(:enable_output_filters)
|
|
259
|
+
count = 0
|
|
260
|
+
num_loops.times {
|
|
261
|
+
count = range_from
|
|
262
|
+
r = Lore::Article.find(:all).with(Lore::Article.id.in(range_from..range_to)).each { |a|
|
|
263
|
+
# raise ::Exception.new("ID ERROR: #{a.id.inspect} != #{count.inspect}") if a.id != count
|
|
264
|
+
count += 1
|
|
265
|
+
valid = true
|
|
266
|
+
valid = valid && a.tags.is_a?(Array)
|
|
267
|
+
valid = valid && a.id.is_a?(Fixnum)
|
|
268
|
+
# raise ::Exception.new("TYPE ERROR") unless valid
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
test.report("lore shortcut unfiltered") {
|
|
273
|
+
id_error = false
|
|
274
|
+
Lore.disable_cache
|
|
275
|
+
Lore::Article.disable_output_filters if Lore::Article.respond_to?(:disable_output_filters)
|
|
276
|
+
count = 0
|
|
277
|
+
num_loops.times {
|
|
278
|
+
count = range_from
|
|
279
|
+
r = Lore::Article.all_with(Lore::Article.id.in(range_from..range_to)).each { |a|
|
|
280
|
+
# raise ::Exception.new("ID ERROR: #{a.id.inspect} != #{count.inspect}") if a.id != count
|
|
281
|
+
count += 1
|
|
282
|
+
valid = true
|
|
283
|
+
# raise ::Exception.new("TYPE ERROR") unless valid
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
test.report("sequel") {
|
|
288
|
+
id_error = false
|
|
289
|
+
count = 0
|
|
290
|
+
num_loops.times {
|
|
291
|
+
count = range_from
|
|
292
|
+
DB[:articles].inner_join(:contents, :id => :content_id).filter( :articles__id => (range_from..range_to)).each { |a|
|
|
293
|
+
# raise ::Exception.new("ID ERROR: #{a.id.inspect} != #{count.inspect}") if a.id != count
|
|
294
|
+
count += 1
|
|
295
|
+
valid = true
|
|
296
|
+
# tags = a[:tags][1..-2].split(',')
|
|
297
|
+
# id = a[:id].to_i
|
|
298
|
+
# raise ::Exception.new("TYPE ERROR") unless valid
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
test.report("activerecord") {
|
|
303
|
+
id_error = false
|
|
304
|
+
count = 0
|
|
305
|
+
num_loops.times {
|
|
306
|
+
count = range_from
|
|
307
|
+
for a in AR::Article.find(:all, :include => :content, :conditions => "id between #{range_from} AND #{range_to}") do
|
|
308
|
+
# raise ::Exception.new("ID ERROR: #{a.id.inspect} != #{count.inspect}") if a.id != count
|
|
309
|
+
count += 1
|
|
310
|
+
valid = true
|
|
311
|
+
valid = valid && a.tags.is_a?(Array)
|
|
312
|
+
valid = valid && a.id.is_a?(Fixnum)
|
|
313
|
+
# raise ::Exception.new("TYPE ERROR") unless valid
|
|
314
|
+
end
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
test.report('lore using cache') {
|
|
318
|
+
id_error = false
|
|
319
|
+
Lore.enable_cache
|
|
320
|
+
Lore::Article.disable_output_filters if Lore::Article.respond_to?(:disable_output_filters)
|
|
321
|
+
count = 0
|
|
322
|
+
num_loops.times {
|
|
323
|
+
count = range_from
|
|
324
|
+
Lore::Article.find(100).with(Lore::Article.id.in(range_from..range_to)).each { |a|
|
|
325
|
+
# raise ::Exception.new("ID ERROR: #{a.id.inspect} != #{count.inspect}") if a.id != count
|
|
326
|
+
count += 1
|
|
327
|
+
valid = true
|
|
328
|
+
valid = valid && a.tags.is_a?(Array)
|
|
329
|
+
valid = valid && a.id.is_a?(Fixnum)
|
|
330
|
+
# raise ::Exception.new("TYPE ERROR") unless valid
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
test.report("lore prepared") {
|
|
335
|
+
id_error = false
|
|
336
|
+
Lore.disable_cache
|
|
337
|
+
count = 0
|
|
338
|
+
num_loops.times {
|
|
339
|
+
count = range_from
|
|
340
|
+
Lore::Article.id_in_range(range_from,range_to).each { |a|
|
|
341
|
+
# raise ::Exception.new("ID ERROR: #{a.id.inspect} != #{count.inspect}") if a.id != count
|
|
342
|
+
count += 1
|
|
343
|
+
valid = true
|
|
344
|
+
valid = valid && a.tags.is_a?(Array)
|
|
345
|
+
valid = valid && a.id.is_a?(Fixnum)
|
|
346
|
+
# raise ::Exception.new("TYPE ERROR") unless valid
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
|