user_query 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. data/ChangeLog +4 -0
  2. data/README +45 -0
  3. data/Rakefile +359 -0
  4. data/Releases +6 -0
  5. data/TODO +0 -0
  6. data/examples/userqueryex/HOWTO.txt +5 -0
  7. data/examples/userqueryex/README +183 -0
  8. data/examples/userqueryex/Rakefile +10 -0
  9. data/examples/userqueryex/WHAT.txt +16 -0
  10. data/examples/userqueryex/app/controllers/application.rb +4 -0
  11. data/examples/userqueryex/app/controllers/entries_controller.rb +68 -0
  12. data/examples/userqueryex/app/helpers/application_helper.rb +3 -0
  13. data/examples/userqueryex/app/helpers/entries_helper.rb +2 -0
  14. data/examples/userqueryex/app/models/entry.rb +8 -0
  15. data/examples/userqueryex/app/views/entries/_form.rhtml +20 -0
  16. data/examples/userqueryex/app/views/entries/edit.rhtml +9 -0
  17. data/examples/userqueryex/app/views/entries/list.rhtml +75 -0
  18. data/examples/userqueryex/app/views/entries/new.rhtml +8 -0
  19. data/examples/userqueryex/app/views/entries/show.rhtml +8 -0
  20. data/examples/userqueryex/app/views/layouts/entries.rhtml +13 -0
  21. data/examples/userqueryex/config/boot.rb +44 -0
  22. data/examples/userqueryex/config/database.yml +36 -0
  23. data/examples/userqueryex/config/environment.rb +54 -0
  24. data/examples/userqueryex/config/environments/development.rb +21 -0
  25. data/examples/userqueryex/config/environments/production.rb +18 -0
  26. data/examples/userqueryex/config/environments/test.rb +19 -0
  27. data/examples/userqueryex/config/routes.rb +22 -0
  28. data/examples/userqueryex/db/migrate/001_entry_migration.rb +16 -0
  29. data/examples/userqueryex/db/schema.rb +15 -0
  30. data/examples/userqueryex/doc/README_FOR_APP +2 -0
  31. data/examples/userqueryex/public/404.html +8 -0
  32. data/examples/userqueryex/public/500.html +8 -0
  33. data/examples/userqueryex/public/dispatch.cgi +10 -0
  34. data/examples/userqueryex/public/dispatch.fcgi +24 -0
  35. data/examples/userqueryex/public/dispatch.rb +10 -0
  36. data/examples/userqueryex/public/favicon.ico +0 -0
  37. data/examples/userqueryex/public/images/rails.png +0 -0
  38. data/examples/userqueryex/public/javascripts/application.js +2 -0
  39. data/examples/userqueryex/public/javascripts/controls.js +815 -0
  40. data/examples/userqueryex/public/javascripts/dragdrop.js +913 -0
  41. data/examples/userqueryex/public/javascripts/effects.js +958 -0
  42. data/examples/userqueryex/public/javascripts/prototype.js +2006 -0
  43. data/examples/userqueryex/public/robots.txt +1 -0
  44. data/examples/userqueryex/public/stylesheets/scaffold.css +74 -0
  45. data/examples/userqueryex/script/about +3 -0
  46. data/examples/userqueryex/script/breakpointer +3 -0
  47. data/examples/userqueryex/script/console +3 -0
  48. data/examples/userqueryex/script/destroy +3 -0
  49. data/examples/userqueryex/script/generate +3 -0
  50. data/examples/userqueryex/script/performance/benchmarker +3 -0
  51. data/examples/userqueryex/script/performance/profiler +3 -0
  52. data/examples/userqueryex/script/plugin +3 -0
  53. data/examples/userqueryex/script/process/reaper +3 -0
  54. data/examples/userqueryex/script/process/spawner +3 -0
  55. data/examples/userqueryex/script/runner +3 -0
  56. data/examples/userqueryex/script/server +3 -0
  57. data/examples/userqueryex/test/fixtures/entries.yml +5 -0
  58. data/examples/userqueryex/test/functional/entries_controller_test.rb +88 -0
  59. data/examples/userqueryex/test/test_helper.rb +28 -0
  60. data/examples/userqueryex/test/unit/entry_test.rb +10 -0
  61. data/lib/user_query.rb +10 -0
  62. data/lib/user_query/generator.rb +219 -0
  63. data/lib/user_query/parameters.rb +93 -0
  64. data/lib/user_query/parser.rb +762 -0
  65. data/lib/user_query/schema.rb +159 -0
  66. data/lib/user_query/user_query_version.rb +6 -0
  67. data/test/parser_test.rb +539 -0
  68. data/test/schema_test.rb +142 -0
  69. metadata +148 -0
@@ -0,0 +1 @@
1
+ # See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file
@@ -0,0 +1,74 @@
1
+ body { background-color: #fff; color: #333; }
2
+
3
+ body, p, ol, ul, td {
4
+ font-family: verdana, arial, helvetica, sans-serif;
5
+ font-size: 13px;
6
+ line-height: 18px;
7
+ }
8
+
9
+ pre {
10
+ background-color: #eee;
11
+ padding: 10px;
12
+ font-size: 11px;
13
+ }
14
+
15
+ a { color: #000; }
16
+ a:visited { color: #666; }
17
+ a:hover { color: #fff; background-color:#000; }
18
+
19
+ .fieldWithErrors {
20
+ padding: 2px;
21
+ background-color: red;
22
+ display: table;
23
+ }
24
+
25
+ #errorExplanation {
26
+ width: 400px;
27
+ border: 2px solid red;
28
+ padding: 7px;
29
+ padding-bottom: 12px;
30
+ margin-bottom: 20px;
31
+ background-color: #f0f0f0;
32
+ }
33
+
34
+ #errorExplanation h2 {
35
+ text-align: left;
36
+ font-weight: bold;
37
+ padding: 5px 5px 5px 15px;
38
+ font-size: 12px;
39
+ margin: -7px;
40
+ background-color: #c00;
41
+ color: #fff;
42
+ }
43
+
44
+ #errorExplanation p {
45
+ color: #333;
46
+ margin-bottom: 0;
47
+ padding: 5px;
48
+ }
49
+
50
+ #errorExplanation ul li {
51
+ font-size: 12px;
52
+ list-style: square;
53
+ }
54
+
55
+ div.uploadStatus {
56
+ margin: 5px;
57
+ }
58
+
59
+ div.progressBar {
60
+ margin: 5px;
61
+ }
62
+
63
+ div.progressBar div.border {
64
+ background-color: #fff;
65
+ border: 1px solid grey;
66
+ width: 100%;
67
+ }
68
+
69
+ div.progressBar div.background {
70
+ background-color: #333;
71
+ height: 18px;
72
+ width: 0%;
73
+ }
74
+
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require File.dirname(__FILE__) + '/../config/boot'
3
+ require 'commands/about'
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require File.dirname(__FILE__) + '/../config/boot'
3
+ require 'commands/breakpointer'
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require File.dirname(__FILE__) + '/../config/boot'
3
+ require 'commands/console'
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require File.dirname(__FILE__) + '/../config/boot'
3
+ require 'commands/destroy'
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require File.dirname(__FILE__) + '/../config/boot'
3
+ require 'commands/generate'
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require File.dirname(__FILE__) + '/../../config/boot'
3
+ require 'commands/performance/benchmarker'
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require File.dirname(__FILE__) + '/../../config/boot'
3
+ require 'commands/performance/profiler'
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require File.dirname(__FILE__) + '/../config/boot'
3
+ require 'commands/plugin'
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require File.dirname(__FILE__) + '/../../config/boot'
3
+ require 'commands/process/reaper'
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require File.dirname(__FILE__) + '/../../config/boot'
3
+ require 'commands/process/spawner'
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require File.dirname(__FILE__) + '/../config/boot'
3
+ require 'commands/runner'
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require File.dirname(__FILE__) + '/../config/boot'
3
+ require 'commands/server'
@@ -0,0 +1,5 @@
1
+ # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
2
+ first:
3
+ id: 1
4
+ another:
5
+ id: 2
@@ -0,0 +1,88 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+ require 'entries_controller'
3
+
4
+ # Re-raise errors caught by the controller.
5
+ class EntriesController; def rescue_action(e) raise e end; end
6
+
7
+ class EntriesControllerTest < Test::Unit::TestCase
8
+ fixtures :entries
9
+
10
+ def setup
11
+ @controller = EntriesController.new
12
+ @request = ActionController::TestRequest.new
13
+ @response = ActionController::TestResponse.new
14
+ end
15
+
16
+ def test_index
17
+ get :index
18
+ assert_response :success
19
+ assert_template 'list'
20
+ end
21
+
22
+ def test_list
23
+ get :list
24
+
25
+ assert_response :success
26
+ assert_template 'list'
27
+
28
+ assert_not_nil assigns(:entries)
29
+ end
30
+
31
+ def test_show
32
+ get :show, :id => 1
33
+
34
+ assert_response :success
35
+ assert_template 'show'
36
+
37
+ assert_not_nil assigns(:entry)
38
+ assert assigns(:entry).valid?
39
+ end
40
+
41
+ def test_new
42
+ get :new
43
+
44
+ assert_response :success
45
+ assert_template 'new'
46
+
47
+ assert_not_nil assigns(:entry)
48
+ end
49
+
50
+ def test_create
51
+ num_entries = Entry.count
52
+
53
+ post :create, :entry => {}
54
+
55
+ assert_response :redirect
56
+ assert_redirected_to :action => 'list'
57
+
58
+ assert_equal num_entries + 1, Entry.count
59
+ end
60
+
61
+ def test_edit
62
+ get :edit, :id => 1
63
+
64
+ assert_response :success
65
+ assert_template 'edit'
66
+
67
+ assert_not_nil assigns(:entry)
68
+ assert assigns(:entry).valid?
69
+ end
70
+
71
+ def test_update
72
+ post :update, :id => 1
73
+ assert_response :redirect
74
+ assert_redirected_to :action => 'show', :id => 1
75
+ end
76
+
77
+ def test_destroy
78
+ assert_not_nil Entry.find(1)
79
+
80
+ post :destroy, :id => 1
81
+ assert_response :redirect
82
+ assert_redirected_to :action => 'list'
83
+
84
+ assert_raise(ActiveRecord::RecordNotFound) {
85
+ Entry.find(1)
86
+ }
87
+ end
88
+ end
@@ -0,0 +1,28 @@
1
+ ENV["RAILS_ENV"] = "test"
2
+ require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
3
+ require 'test_help'
4
+
5
+ class Test::Unit::TestCase
6
+ # Transactional fixtures accelerate your tests by wrapping each test method
7
+ # in a transaction that's rolled back on completion. This ensures that the
8
+ # test database remains unchanged so your fixtures don't have to be reloaded
9
+ # between every test method. Fewer database queries means faster tests.
10
+ #
11
+ # Read Mike Clark's excellent walkthrough at
12
+ # http://clarkware.com/cgi/blosxom/2005/10/24#Rails10FastTesting
13
+ #
14
+ # Every Active Record database supports transactions except MyISAM tables
15
+ # in MySQL. Turn off transactional fixtures in this case; however, if you
16
+ # don't care one way or the other, switching from MyISAM to InnoDB tables
17
+ # is recommended.
18
+ self.use_transactional_fixtures = true
19
+
20
+ # Instantiated fixtures are slow, but give you @david where otherwise you
21
+ # would need people(:david). If you don't want to migrate your existing
22
+ # test cases which use the @david style and don't mind the speed hit (each
23
+ # instantiated fixtures translates to a database query per test method),
24
+ # then set this back to true.
25
+ self.use_instantiated_fixtures = false
26
+
27
+ # Add more helper methods to be used by all tests here...
28
+ end
@@ -0,0 +1,10 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class EntryTest < Test::Unit::TestCase
4
+ fixtures :entries
5
+
6
+ # Replace this with your real tests.
7
+ def test_truth
8
+ assert true
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+
2
+ $:.unshift(File.dirname(__FILE__)) unless
3
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
4
+
5
+ require 'user_query/user_query_version.rb'
6
+ require 'user_query/parameters.rb'
7
+ require 'user_query/parser.rb'
8
+ require 'user_query/generator.rb'
9
+ require 'user_query/schema.rb'
10
+
@@ -0,0 +1,219 @@
1
+ module UserQuery
2
+
3
+ class Generator
4
+ class Error < Exception; end
5
+
6
+ # Inputs
7
+ attr_accessor :type
8
+ attr_accessor :values_inline
9
+ attr_accessor :target
10
+ attr_accessor :verbose
11
+
12
+ # Outputs
13
+ attr_accessor :expr
14
+ attr_accessor :values
15
+
16
+ def initialize(*opts)
17
+ self.target = '<<TARGET>>'
18
+ self.values_inline = true
19
+ self.type = :string
20
+ opts = Hash[*opts]
21
+ opts.each{|k, v| self.send("#{k}=", v)}
22
+ end
23
+
24
+ def sql(expr)
25
+ @values = [ ]
26
+ @expr = ''
27
+
28
+ return nil if expr.nil?
29
+
30
+ emit_sql(expr)
31
+
32
+ @expr
33
+ end
34
+
35
+ private
36
+
37
+ @@empty_hash = { }
38
+ @@empty_hash.freeze
39
+
40
+ @@OP_2_SQL = {
41
+ true => {
42
+ :not => 'NOT',
43
+ :and => 'AND',
44
+ :or => 'OR',
45
+ :lt => '<',
46
+ :gt => '>',
47
+ :le => '<=',
48
+ :ge => '>=',
49
+ :eq => '=',
50
+ :ne => '<>'
51
+ },
52
+ :null => {
53
+ :eq => 'IS',
54
+ :ne => 'IS NOT'
55
+ }
56
+ }
57
+
58
+ def op_to_sql(type, expr = nil)
59
+ #if true || @verbose
60
+ # $stderr.puts "opt_to_sql(#{type.inspect}, #{expr.inspect}) => "
61
+ #end
62
+
63
+ expr = expr && expr[0]
64
+ sql = nil
65
+ sql ||= (@@OP_2_SQL[expr] || @@empty_hash)[type] if expr
66
+ sql ||= (@@OP_2_SQL[true])[type]
67
+ raise Error, "Unknown operator #{type.inspect}" unless sql
68
+
69
+ #if @verbose
70
+ # $stderr.puts "#{sql.inspect} "
71
+ #end
72
+
73
+ sql
74
+ end
75
+
76
+ def emit_sql(expr)
77
+ case type = expr && expr[0]
78
+ when :not
79
+ emit("#{op_to_sql(type)} (")
80
+ emit_sql(expr[1])
81
+ emit(")")
82
+
83
+ when :and, :or
84
+ emit("(")
85
+ emit_sql(expr[1])
86
+ emit(" #{op_to_sql(type)} ")
87
+ emit_sql(expr[2])
88
+ emit(")")
89
+
90
+ when :lt, :gt, :le, :ge, :eq, :ne
91
+ emit("(")
92
+ emit(target)
93
+ emit(" #{op_to_sql(type, expr[1])} ")
94
+ emit_sql_value(expr[1])
95
+ emit(")")
96
+
97
+ when :between
98
+ emit("((")
99
+ emit(target)
100
+ emit(" >= ")
101
+ emit_sql_value(expr[1])
102
+ emit(") #{op_to_sql(:and)} (")
103
+ emit(target)
104
+ emit(" <= ")
105
+ emit_sql_value(expr[2])
106
+ emit("))")
107
+
108
+ when :range
109
+ emit("((")
110
+ emit(target)
111
+ emit(" >= ")
112
+ emit_sql_value(expr[1])
113
+ emit(") #{op_to_sql(:and)} (")
114
+ emit(target)
115
+ emit(" < ")
116
+ emit_sql_value(expr[2])
117
+ emit("))")
118
+
119
+ when :like
120
+ emit("(")
121
+ emit(target)
122
+ emit(" LIKE ")
123
+ expr_1 = expr[1]
124
+ expr_1 = [ :string, expr_1[1], expr_1[1] ]
125
+ expr_1[1] = expr_1[1].gsub(/[%_\\]/){|x| "\\#{x}"} # Escape '%' and '_' in query
126
+ expr_1[1] = '%' + expr_1[1] + '%'
127
+ # $stderr.puts "LIKE #{expr_1[1]}"
128
+ expr_1[2] = expr_1[1]
129
+ emit_sql_value(expr_1, :no_internal_escape)
130
+ emit(")")
131
+
132
+ else
133
+ emit("(")
134
+ emit(target)
135
+ emit(" #{op_to_sql(:eq, expr)} ")
136
+ emit_sql_value(expr)
137
+ emit(")")
138
+ end
139
+ end
140
+
141
+ def to_string(value)
142
+ to_simple(value)[0].to_s
143
+ end
144
+
145
+ def emit_sql_value(value, *options)
146
+ value, type = to_simple(value)
147
+
148
+ if values_inline
149
+ case type
150
+ when :null
151
+ value = sql_quote(value)
152
+ when :number, :boolean
153
+ value = value.to_s
154
+ else
155
+ value = sql_quote(value, *options)
156
+ end
157
+
158
+ emit(value)
159
+ else
160
+ emit('?')
161
+ @values << value
162
+ end
163
+ end
164
+
165
+ def to_simple(value)
166
+ case type = value && value[0]
167
+ when :null
168
+ value = nil
169
+
170
+ when :string, :word, :number
171
+ value = value[2]
172
+
173
+ when :boolean
174
+ value = value[2] ? 1 : 0 # MySQL tinyint(1)
175
+
176
+ when :money
177
+ type = :number
178
+ value = value[2].rep
179
+
180
+ # MySQL-specific timedate formats!?!
181
+ when :year
182
+ value = "#{'%04d' % value[2]}-01-01 00:00:00"
183
+
184
+ when :month
185
+ value = "#{'%04d' % value[2]}-#{'%02d' % value[3]}-01 00:00:00"
186
+
187
+ when :day
188
+ value = "#{'%04d' % value[2]}-#{'%02d' % value[3]}-#{'%02d' % value[4]} 00:00:00"
189
+
190
+ when :hour
191
+ value = "#{'%04d' % value[2]}-#{'%02d' % value[3]}-#{'%02d' % value[4]} #{'%02d' % value[5]}:00:00"
192
+
193
+ when :minute
194
+ value = "#{'%04d' % value[2]}-#{'%02d' % value[3]}-#{'%02d' % value[4]} #{'%02d' % value[5]}:#{'%02d' % value[6]}:00"
195
+ when :second
196
+ value = "#{'%04d' % value[2]}-#{'%02d' % value[3]}-#{'%02d' % value[4]} #{'%02d' % value[5]}:#{'%02d' % value[6]}:#{'%02d' % value[7]}"
197
+
198
+ else
199
+ raise Error, "Unknown value type #{value.inspect}"
200
+ end
201
+
202
+ [ value, type ]
203
+ end
204
+
205
+ def sql_quote(value, no_internal_escape = false)
206
+ return 'NULL' if value.nil?
207
+ "'" + (no_internal_escape ?
208
+ value.to_s.gsub(/(['])/){|x| "\\#{x}"} :
209
+ value.to_s.gsub(/(['\\])/){|x| "\\#{x}"}) +
210
+ "'"
211
+ end
212
+
213
+ def emit(raw)
214
+ @expr << raw
215
+ end
216
+
217
+ end
218
+
219
+ end # module