user_query 0.1.0

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.
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