imparcial 0.0.4 → 0.0.5

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