imparcial 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. data/History.txt +2 -5
  2. data/Manifest.txt +79 -5
  3. data/README.txt +71 -7
  4. data/Rakefile +1 -1
  5. data/lib/imparcial/driver/abstract/expression/column.rb +313 -0
  6. data/lib/imparcial/driver/abstract/expression/constraint.rb +149 -0
  7. data/lib/imparcial/driver/abstract/expression/delete.rb +88 -0
  8. data/lib/imparcial/driver/abstract/expression/index.rb +206 -0
  9. data/lib/imparcial/driver/abstract/expression/insert.rb +49 -0
  10. data/lib/imparcial/driver/abstract/expression/lock.rb +11 -0
  11. data/lib/imparcial/driver/abstract/expression/record.rb +41 -0
  12. data/lib/imparcial/driver/abstract/expression/select.rb +38 -0
  13. data/lib/imparcial/driver/abstract/expression/sequence.rb +260 -0
  14. data/lib/imparcial/driver/abstract/expression/statement.rb +128 -0
  15. data/lib/imparcial/driver/abstract/expression/table.rb +416 -0
  16. data/lib/imparcial/driver/abstract/expression/transaction.rb +143 -0
  17. data/lib/imparcial/driver/abstract/expression/update.rb +50 -0
  18. data/lib/imparcial/driver/abstract/expression.rb +23 -0
  19. data/lib/imparcial/driver/abstract/result.rb +95 -0
  20. data/lib/imparcial/driver/abstract/sql/column.rb +103 -0
  21. data/lib/imparcial/driver/abstract/sql/constraint.rb +42 -0
  22. data/lib/imparcial/driver/abstract/sql/delete.rb +22 -0
  23. data/lib/imparcial/driver/abstract/sql/index.rb +45 -0
  24. data/lib/imparcial/driver/abstract/sql/insert.rb +63 -0
  25. data/lib/imparcial/driver/abstract/sql/record.rb +19 -0
  26. data/lib/imparcial/driver/abstract/sql/select.rb +101 -0
  27. data/lib/imparcial/driver/abstract/sql/sequence.rb +55 -0
  28. data/lib/imparcial/driver/abstract/sql/table.rb +42 -0
  29. data/lib/imparcial/driver/abstract/sql/transaction.rb +43 -0
  30. data/lib/imparcial/driver/abstract/sql/update.rb +29 -0
  31. data/lib/imparcial/driver/abstract/sql.rb +21 -0
  32. data/lib/imparcial/driver/abstract/typemap.rb +168 -0
  33. data/lib/imparcial/driver/abstract/util.rb +53 -0
  34. data/lib/imparcial/driver/abstract.rb +255 -0
  35. data/lib/imparcial/driver/mysql/expression/table.rb +17 -0
  36. data/lib/imparcial/driver/mysql/expression.rb +11 -0
  37. data/lib/imparcial/driver/mysql/result.rb +33 -0
  38. data/lib/imparcial/driver/mysql/sql/column.rb +59 -0
  39. data/lib/imparcial/driver/mysql/sql/constraint.rb +39 -0
  40. data/lib/imparcial/driver/mysql/sql/index.rb +42 -0
  41. data/lib/imparcial/driver/mysql/sql/sequence.rb +39 -0
  42. data/lib/imparcial/driver/mysql/sql/table.rb +67 -0
  43. data/lib/imparcial/driver/mysql/sql.rb +15 -0
  44. data/lib/imparcial/driver/mysql/typemap.rb +13 -0
  45. data/lib/imparcial/driver/mysql/util.rb +13 -0
  46. data/lib/imparcial/driver/mysql.rb +49 -0
  47. data/lib/imparcial/driver/postgre/expression.rb +32 -0
  48. data/lib/imparcial/driver/postgre/result.rb +35 -0
  49. data/lib/imparcial/driver/postgre/sql/column.rb +53 -0
  50. data/lib/imparcial/driver/postgre/sql/constraint.rb +37 -0
  51. data/lib/imparcial/driver/postgre/sql/index.rb +53 -0
  52. data/lib/imparcial/driver/postgre/sql/sequence.rb +30 -0
  53. data/lib/imparcial/driver/postgre/sql/table.rb +46 -0
  54. data/lib/imparcial/driver/postgre/sql.rb +15 -0
  55. data/lib/imparcial/driver/postgre/typemap.rb +36 -0
  56. data/lib/imparcial/driver/postgre/util.rb +19 -0
  57. data/lib/imparcial/driver/postgre.rb +43 -0
  58. data/lib/imparcial/driver.rb +1 -0
  59. data/lib/imparcial/exception.rb +71 -0
  60. data/lib/imparcial/extension.rb +90 -0
  61. data/lib/imparcial/initializer.rb +30 -0
  62. data/lib/imparcial.rb +1 -1
  63. data/test/unit/base/common/tc_quote.rb +30 -0
  64. data/test/unit/base/expression/tc_column.rb +84 -0
  65. data/test/unit/base/expression/tc_constraint.rb +39 -0
  66. data/test/unit/base/expression/tc_delete.rb +51 -0
  67. data/test/unit/base/expression/tc_index.rb +43 -0
  68. data/test/unit/base/expression/tc_insert.rb +44 -0
  69. data/test/unit/base/expression/tc_select.rb +142 -0
  70. data/test/unit/base/expression/tc_sequence.rb +48 -0
  71. data/test/unit/base/expression/tc_table.rb +68 -0
  72. data/test/unit/base/expression/tc_table_diff.rb +41 -0
  73. data/test/unit/base/expression/tc_transaction.rb +46 -0
  74. data/test/unit/base/expression/tc_update.rb +29 -0
  75. data/test/unit/base/statement/tc_conditions.rb +84 -0
  76. data/test/unit/base/statement/tc_limit.rb +25 -0
  77. data/test/unit/base/statement/tc_order.rb +25 -0
  78. data/test/unit/helper.rb +64 -0
  79. data/test/unit/mysql/tc_sequence.rb +41 -0
  80. metadata +102 -10
@@ -0,0 +1,50 @@
1
+ module Imparcial
2
+ module Driver
3
+ module AbstractExpression
4
+ module Update
5
+
6
+ private
7
+
8
+ def expected_options_for_updating
9
+
10
+ {:table_name => :required, :values => :required, :conditions => :required}
11
+
12
+ end
13
+
14
+ public
15
+
16
+ # === Description
17
+ # Update some records.
18
+ #
19
+ # === Usage
20
+ # abstract_adapter.update :table_name => 'person', :values => {:salary => 1500},
21
+ # :conditions => ['id = ?',10]
22
+ #
23
+ # === Options
24
+ # * :table_name
25
+ # * :values
26
+ # * :conditions
27
+ #
28
+ # === Returning
29
+ # nothing
30
+
31
+ def update ( options )
32
+
33
+ check_options expected_options_for_updating, options
34
+
35
+ sql = sql_for_updating( options )
36
+
37
+ logger.warn sql if @update_logging
38
+
39
+ query sql
40
+
41
+ rescue adapter_specific_exception => ex
42
+
43
+ raise UpdateError.new(ex.message)
44
+
45
+ end
46
+
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,23 @@
1
+ FileList[File.dirname(__FILE__) + '/expression/*.rb'].each do |f|
2
+ require f
3
+ end
4
+
5
+ module Imparcial
6
+ module Driver
7
+ module AbstractExpression
8
+ include Statement
9
+ include Sequence
10
+ include Column
11
+ include Table
12
+ include Constraint
13
+ include Insert
14
+ include Select
15
+ include Delete
16
+ include Update
17
+ include Record
18
+ include Lock
19
+ include Transaction
20
+ include Index
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,95 @@
1
+ module Imparcial
2
+ module Driver
3
+
4
+ # This class will serve as base for adapter specific result class.
5
+
6
+ class AbstractResult
7
+ attr_reader :specific
8
+
9
+ def initialize ( result_specific )
10
+
11
+ @specific = result_specific
12
+
13
+ end
14
+
15
+ # === Description
16
+ # get number of rows avaliable.
17
+
18
+ def rows
19
+
20
+ raise FeatureNotFound
21
+
22
+ end
23
+
24
+ # === Description
25
+ # fetch the result.
26
+
27
+ def fetch
28
+
29
+ raise FeatureNotFound
30
+
31
+ end
32
+
33
+ def fetch_in_array
34
+
35
+ array = []
36
+
37
+ fetch do |*rows|
38
+
39
+ array << rows
40
+
41
+ end
42
+
43
+ array
44
+
45
+ end
46
+
47
+ # === Description
48
+ # Fetch the first row. Ignoring others if avaliable.
49
+
50
+ def fetch_first_row
51
+
52
+ fetch do |*rows|
53
+ return *rows
54
+ end
55
+
56
+ end
57
+
58
+
59
+ end
60
+
61
+ # This class wraps a regular row.
62
+ # Usually, a row will only come with value.
63
+ # Instead, we can also keep the column name. So that, this class
64
+ # can keep track of column name and value.
65
+ #
66
+ # -------------------
67
+ # id | name | price <- column name
68
+ # 1 | apple | 0.99 <- column value
69
+ # 2 | lemon | 1.99 <- column value
70
+ # -------------------
71
+
72
+ class Row
73
+ include Imparcial::Driver::AbstractUtil
74
+
75
+ attr_accessor :name, :value
76
+ alias_method :column_name, :name
77
+ alias_method :column_value, :value
78
+
79
+ def initialize ( column_name, column_value )
80
+
81
+ @name = column_name
82
+ @value = unquote_value(column_value)
83
+
84
+ end
85
+
86
+ def to_s
87
+
88
+ @value
89
+
90
+ end
91
+
92
+ end
93
+
94
+ end
95
+ end
@@ -0,0 +1,103 @@
1
+ module Imparcial
2
+ module Driver
3
+ module AbstractSQL
4
+ module Column
5
+
6
+ private
7
+
8
+ # Generate SQL statement for getting columns information.
9
+ # We need name, type and size.
10
+
11
+ def sql_for_getting_columns_information ( options )
12
+
13
+ %{SELECT
14
+ column_name,
15
+ data_type,
16
+ character_maximum_length
17
+ FROM INFORMATION_SCHEMA.columns
18
+ WHERE table_name = #{quote_value(options[:table_name])}
19
+ }
20
+
21
+ end
22
+
23
+ # Generate SQL statement for getting column information.
24
+ # We need name, type and size. Quite similar to above, except,
25
+ # it's a more narrow SQL.
26
+
27
+ def sql_for_getting_column_information ( options )
28
+
29
+ %{SELECT
30
+ column_name,
31
+ data_type,
32
+ character_maximum_length
33
+ FROM INFORMATION_SCHEMA.columns
34
+ WHERE table_name = #{quote_value(options[:table_name])} AND
35
+ column_name = #{quote_value(options[:field_name])}
36
+ }
37
+
38
+ end
39
+
40
+ # Generate SQL statement for adding some columns.
41
+ # Alter table will do the job for us.
42
+
43
+ def sql_for_adding_columns ( options )
44
+
45
+ syntax = ''
46
+
47
+ syntax += 'ALTER TABLE ' + quote(options[:table_name]) + ' '
48
+
49
+ parse_fields options[:fields] do |field|
50
+
51
+ syntax += "ADD COLUMN " + field_to_column_sql(field) + ","
52
+
53
+ end
54
+
55
+ syntax.chop!
56
+
57
+ syntax
58
+
59
+ end
60
+
61
+ # Generate SQL statement for dropping some columns.
62
+ # Alter table will do the job for us.
63
+
64
+ def sql_for_dropping_columns ( options )
65
+
66
+ syntax = ''
67
+
68
+ syntax += 'ALTER TABLE ' + quote(options[:table_name]) + ' '
69
+
70
+ options[:fields].each do |field_name|
71
+
72
+ syntax += 'DROP ' + field_name + ','
73
+
74
+ end
75
+
76
+ syntax.chop!
77
+
78
+ syntax
79
+
80
+ end
81
+
82
+ # Generate SQL statement for renaming a column.
83
+ # Must be overriden.
84
+
85
+ def sql_for_renaming_column ( options )
86
+
87
+ raise FeatureNotFound
88
+
89
+ end
90
+
91
+ # Generate SQL statement for modifying a column.
92
+ # Must be overriden.
93
+
94
+ def sql_for_modifying_columns ( options )
95
+
96
+ raise FeatureNotFound
97
+
98
+ end
99
+
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,42 @@
1
+ module Imparcial
2
+ module Driver
3
+ module AbstractSQL
4
+ module Constraint
5
+
6
+ private
7
+
8
+ def sql_for_adding_primary_key ( options )
9
+
10
+ syntax = 'ALTER TABLE ' + quote(options[:table_name]) + ' '
11
+ syntax += 'ADD PRIMARY KEY ('
12
+
13
+ for field_name in options[:fields]
14
+
15
+ syntax += quote(field_name) + ','
16
+
17
+ end
18
+
19
+ syntax.chop!
20
+ syntax += ')'
21
+
22
+ syntax
23
+
24
+ end
25
+
26
+ def sql_for_adding_column ( options )
27
+
28
+ raise FeatureNotFound
29
+
30
+ end
31
+
32
+ def sql_for_adding_default_value ( options )
33
+
34
+ raise FeatureNotFound
35
+
36
+ end
37
+
38
+
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,22 @@
1
+ module Imparcial
2
+ module Driver
3
+ module AbstractSQL
4
+ module Delete
5
+
6
+ private
7
+
8
+ # SQL for generating the delete statement.
9
+
10
+ def sql_for_deleting ( options )
11
+
12
+ syntax = 'DELETE FROM ' + quote(options[:table_name])
13
+ syntax += parse_conditions options[:conditions] if options[:conditions]
14
+
15
+ syntax
16
+
17
+ end
18
+
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,45 @@
1
+ module Imparcial
2
+ module Driver
3
+ module AbstractSQL
4
+ module Index
5
+
6
+ private
7
+
8
+ # Generate SQL statement for creating an index.
9
+
10
+ def sql_for_creating_index ( options )
11
+
12
+ syntax = 'CREATE '
13
+ syntax += options[:index_type] + ' ' if options[:index_type]
14
+ syntax += 'INDEX '
15
+ syntax += options[:index_name] + ' '
16
+ syntax += 'ON ' + quote(options[:table_name])
17
+ syntax += '('
18
+ syntax += quote(options[:column_name])
19
+ syntax += ')'
20
+
21
+ syntax
22
+
23
+ end
24
+
25
+ # Generate SQL statement for dropping an index.
26
+
27
+ def sql_for_dropping_index ( options )
28
+
29
+ 'DROP INDEX ' + options[:index_name]
30
+
31
+ end
32
+
33
+ # Subclasses need to override this method.
34
+
35
+ def sql_for_getting_indexes
36
+
37
+ raise FeatureNotFound
38
+
39
+ end
40
+
41
+ end
42
+ end
43
+ end
44
+ end
45
+
@@ -0,0 +1,63 @@
1
+ module Imparcial
2
+ module Driver
3
+ module AbstractSQL
4
+ module Insert
5
+
6
+ private
7
+
8
+ # Some helpers for inserting method.
9
+ # Extract column names from a hash.
10
+
11
+ def column_names_for ( values )
12
+
13
+ column_names = []
14
+
15
+ values.each_key do |column_name|
16
+
17
+ column_names << quote(column_name)
18
+
19
+ end
20
+
21
+ column_names
22
+
23
+ end
24
+
25
+ # Extract column values from a hash.
26
+
27
+ def column_values_for ( values )
28
+
29
+ column_values = []
30
+
31
+ values.each_value do |column_value|
32
+
33
+ column_values << quote_value(column_value)
34
+
35
+ end
36
+
37
+ column_values
38
+
39
+ end
40
+
41
+ # Execute the SQL statement for inserting.
42
+
43
+ def sql_for_inserting ( options )
44
+
45
+ syntax = 'INSERT INTO ' + quote(options[:table_name])
46
+ syntax += '('
47
+
48
+ syntax += column_names_for(options[:values]).join(',')
49
+
50
+ syntax += ') VALUES ('
51
+
52
+ syntax += column_values_for(options[:values]).join(',')
53
+
54
+ syntax += ')'
55
+
56
+ syntax
57
+
58
+ end
59
+
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,19 @@
1
+ module Imparcial
2
+ module Driver
3
+ module AbstractSQL
4
+ module Record
5
+
6
+ private
7
+
8
+ # Execute SQL statement for couting records of a table.
9
+
10
+ def sql_for_couting_records ( options )
11
+
12
+ 'SELECT COUNT(*) FROM ' + quote(options[:table_name])
13
+
14
+ end
15
+
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,101 @@
1
+ module Imparcial
2
+ module Driver
3
+ module AbstractSQL
4
+ module Select
5
+
6
+ private
7
+
8
+ def get_key ( name, table_metadata )
9
+
10
+ key_name = ('key_for_' + name.to_s).to_sym
11
+ key = table_metadata[key_name]
12
+
13
+ unless key
14
+
15
+ msg = 'A key has not been defined at '+table_metadata[:name].to_s
16
+ raise SelectError.new(msg)
17
+
18
+ end
19
+
20
+ key
21
+
22
+ end
23
+
24
+ def get_relkind ( table )
25
+
26
+ table[:relkind].to_s.upcase!.gsub!('_', ' ')
27
+
28
+ end
29
+
30
+ def unroll_joins ( table_list, previous_table_metadata )
31
+
32
+ syntax = ''
33
+
34
+ # Array
35
+
36
+ table_list.each do |list|
37
+
38
+ for table_metadata, inner_table_list in list
39
+
40
+ rel = get_relkind table_metadata
41
+
42
+ syntax += ' ' + rel + ' ' + quote(table_metadata[:name]) + ' ON '
43
+
44
+ previous_key = get_key previous_table_metadata[:name], table_metadata
45
+ previous_id = quote(table_metadata[:name]) + '.' + previous_key
46
+
47
+ current_key = get_key table_metadata[:name], previous_table_metadata
48
+ current_id = quote(previous_table_metadata[:name]) + '.' + current_key
49
+
50
+ syntax += previous_id + ' = ' + current_id
51
+
52
+ next unless inner_table_list
53
+ next if inner_table_list.length == 0
54
+
55
+ syntax += unroll_joins inner_table_list, table_metadata
56
+
57
+ end
58
+
59
+ end
60
+
61
+ syntax
62
+
63
+ end
64
+
65
+ # Enable selection by column name.
66
+
67
+ def build_field_selection ( fields )
68
+
69
+ if fields
70
+
71
+ fields.join(',')
72
+
73
+ else
74
+
75
+ '*'
76
+
77
+ end
78
+
79
+ end
80
+
81
+ def sql_for_selecting ( options )
82
+
83
+ syntax = 'SELECT '
84
+ syntax += build_field_selection options[:fields]
85
+ syntax += ' FROM '
86
+
87
+ syntax += quote options[:joins] ? options[:joins][0].keys.first[:name] : options[:table_name]
88
+ syntax += unroll_joins options[:joins][0].values[0], options[:joins][0].keys.first if options[:joins]
89
+
90
+ syntax += parse_conditions options[:conditions]
91
+ syntax += parse_limit options[:limit]
92
+ syntax += parse_order options
93
+
94
+ syntax
95
+
96
+ end
97
+
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,55 @@
1
+ module Imparcial
2
+ module Driver
3
+ module AbstractSQL
4
+ module Sequence
5
+
6
+ private
7
+
8
+ # Generate SQL statement for creating a sequence.
9
+
10
+ def sql_for_creating_sequence ( options = {} )
11
+
12
+ syntax = 'CREATE SEQUENCE ' + quote(options[:sequence_name]) + ' '
13
+ syntax += 'START WITH ' + quote_value(options[:start_with]) + ' '
14
+ syntax += 'MINVALUE ' + quote_value(options[:min_value]) + ' '
15
+ syntax += 'MAXVALUE ' + quote_value(options[:max_value]) if options[:max_value]
16
+ syntax += 'INCREMENT BY ' + quote_value(options[:increment_by]) + ' '
17
+ syntax += options[:cycle] ? 'CYCLE ' : 'NO CYCLE '
18
+ syntax += 'CACHE ' + quote_value(options[:cache]) if options[:cache]
19
+
20
+ syntax
21
+
22
+ end
23
+
24
+ private
25
+
26
+ # Generate SQL statement for dropping a sequence.
27
+
28
+ def sql_for_dropping_sequence ( options = {} )
29
+
30
+ 'DROP SEQUENCE ' + quote(options[:sequence_name])
31
+
32
+ end
33
+
34
+ # Generate SQL statement for verifying sequences.
35
+ # Subclasses must override this method.
36
+
37
+ def sql_for_sequence_exists? ( options = {} )
38
+
39
+ raise FeatureNotFound
40
+
41
+ end
42
+
43
+ # Generate SQL statement for retrieving sequences.
44
+ # Subclasses must override this method.
45
+
46
+ def sql_for_getting_sequences
47
+
48
+ raise FeatureNotFound
49
+
50
+ end
51
+
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,42 @@
1
+ module Imparcial
2
+ module Driver
3
+ module AbstractSQL
4
+ module Table
5
+
6
+ private
7
+
8
+ # Generate SQL statement for dropping table.
9
+
10
+ def sql_for_dropping_table ( options )
11
+
12
+ 'DROP TABLE ' + quote( options[:table_name] )
13
+
14
+ end
15
+
16
+ # Generate SQL statement for creating table.
17
+
18
+ def sql_for_creating_table ( options )
19
+
20
+ columns = []
21
+
22
+ # Let's parse some columns in order to provide default options.
23
+
24
+ parse_fields options[:fields] do |field|
25
+
26
+ columns << field_to_column_sql(field)
27
+
28
+ end
29
+
30
+ syntax = 'CREATE TABLE ' + quote( options[:table_name] )
31
+ syntax += '('
32
+ syntax += columns.join(',')
33
+ syntax += ')'
34
+
35
+ syntax
36
+
37
+ end
38
+
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,43 @@
1
+ module Imparcial
2
+ module Driver
3
+ module AbstractSQL
4
+ module Transaction
5
+
6
+ private
7
+
8
+ # Generate SQL statement for initializing a transaction.
9
+
10
+ def sql_for_initializing_a_transaction
11
+
12
+ 'BEGIN'
13
+
14
+ end
15
+
16
+ # Generate SQL statement for terminating a transaction.
17
+
18
+ def sql_for_terminating_a_transaction
19
+
20
+ 'COMMIT'
21
+
22
+ end
23
+
24
+ # Generate SQL statement for rolling back a transaction.
25
+
26
+ def sql_for_rolling_back ( options )
27
+
28
+ options[:savepoint_name] == nil ? 'ROLLBACK' : 'ROLLBACK TO ' + options[:savepoint_name].to_s
29
+
30
+ end
31
+
32
+ # Generate SQL statement for placing a saving point.
33
+
34
+ def sql_for_saving_point ( options )
35
+
36
+ 'SAVEPOINT ' + options[:savepoint_name].to_s
37
+
38
+ end
39
+
40
+ end
41
+ end
42
+ end
43
+ end