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,42 @@
1
+ module Imparcial
2
+ module Driver
3
+ module MysqlSQL
4
+ module Index
5
+
6
+ private
7
+
8
+ def sql_for_dropping_index ( options )
9
+
10
+ %{DROP INDEX #{options[:index_name]} ON
11
+ #{quote(options[:table_name])}
12
+ }
13
+
14
+ end
15
+
16
+ # Generate SQL statement for verifying if a given index exists.
17
+
18
+ def sql_for_index_exists? ( options )
19
+
20
+ %{SELECT 1 FROM INFORMATION_SCHEMA.statistics
21
+ WHERE table_schema != "mysql" AND
22
+ table_name = #{quote_value(options[:table_name])} AND
23
+ INDEX_NAME = #{quote_value(options[:index_name])}
24
+ }
25
+
26
+ end
27
+
28
+ def sql_for_getting_indexes ( options )
29
+
30
+ %{SELECT table_name AS 'table', column_name AS 'column',\
31
+ index_name AS 'index' FROM INFORMATION_SCHEMA.statistics\
32
+ WHERE table_schema != 'mysql'
33
+ AND table_name = #{quote_value(options[:table_name])}
34
+ }
35
+
36
+ end
37
+
38
+
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,39 @@
1
+ module Imparcial
2
+ module Driver
3
+ module MysqlSQL
4
+
5
+ # Mysql doesn't support sequences.
6
+ # We have to disable all them.
7
+
8
+ module Sequence
9
+
10
+ private
11
+
12
+ def sql_for_creating_sequence ( options )
13
+
14
+ raise FeatureNotFound
15
+
16
+ end
17
+
18
+ def sql_for_dropping_sequence ( options )
19
+
20
+ raise FeatureNotFound
21
+
22
+ end
23
+
24
+ def sql_for_sequence_exists? ( options )
25
+
26
+ raise FeatureNotFound
27
+
28
+ end
29
+
30
+ def sql_for_retrieving_sequences
31
+
32
+ raise FeatureNotFound
33
+
34
+ end
35
+
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,67 @@
1
+ module Imparcial
2
+ module Driver
3
+ module MysqlSQL
4
+ module Table
5
+
6
+ private
7
+
8
+ def sql_for_creating_table ( options = {} )
9
+
10
+ syntax = super
11
+
12
+ syntax += 'ENGINE = '
13
+
14
+ # If any engine has not been specified, we make INNODB as default.
15
+
16
+ if options[:engine]
17
+
18
+ syntax += options[:engine].to_s
19
+
20
+ else
21
+
22
+ syntax += 'INNODB'
23
+
24
+ end
25
+
26
+ syntax
27
+
28
+ end
29
+
30
+ private
31
+
32
+ # Generate SQL statement for retrieving tables.
33
+
34
+ def sql_for_getting_tables
35
+
36
+ 'SHOW TABLES'
37
+
38
+ end
39
+
40
+ # Generate SQL statement for retrieving columns.
41
+ =begin
42
+ def sql_for_retrieving_columns ( options = {} )
43
+
44
+ %{
45
+ SELECT
46
+ A.column_name, A.data_type, A.character_maximum_length as size,
47
+ (A.is_nullable = 'YES') as allow_null,
48
+ (A.column_name = B.column_name) as pk,
49
+ A.column_default,
50
+ A.extra = 'auto_increment' as auto_inc,
51
+ A.column_name in (
52
+ SELECT s.COLUMN_NAME FROM INFORMATION_SCHEMA.statistics s
53
+ WHERE s.COLUMN_NAME = A.column_name
54
+ ) as indexed
55
+
56
+ FROM information_schema.columns A
57
+ LEFT JOIN information_schema.key_column_usage B ON A.table_name = B.table_name
58
+ WHERE A.table_name = #{quote_value(options[:table_name])}
59
+
60
+ }
61
+
62
+ end
63
+ =end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,15 @@
1
+ FileList[File.dirname(__FILE__) + '/sql/*.rb'].each do |f|
2
+ require f
3
+ end
4
+
5
+ module Imparcial
6
+ module Driver
7
+ module MysqlSQL
8
+ include Table
9
+ include Sequence
10
+ include Index
11
+ include Constraint
12
+ include Column
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,13 @@
1
+ module Imparcial
2
+ module Driver
3
+ module MysqlTypemap
4
+
5
+ def sql_types
6
+
7
+ super.dup.merge!('INT' => :integer)
8
+
9
+ end
10
+
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module Imparcial
2
+ module Driver
3
+ module MysqlUtil
4
+
5
+ def quote ( val )
6
+
7
+ "`#{val}`"
8
+
9
+ end
10
+
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,49 @@
1
+ require 'mysql'
2
+
3
+ require 'imparcial/driver/mysql/util'
4
+ require 'imparcial/driver/mysql/result'
5
+ require 'imparcial/driver/mysql/typemap'
6
+ require 'imparcial/driver/mysql/sql'
7
+ require 'imparcial/driver/mysql/expression'
8
+
9
+ module Imparcial
10
+ module Driver
11
+ class MysqlAdapter < AbstractAdapter
12
+
13
+ include MysqlUtil
14
+ include MysqlTypemap
15
+ include MysqlSQL
16
+ include MysqlExpression
17
+
18
+ def adapter_specific_exception
19
+
20
+ Mysql::Error
21
+
22
+ end
23
+
24
+ def connect
25
+
26
+ @conn = Mysql.real_connect @host, @username, @password, @database, @port, @socket
27
+
28
+ rescue adapter_specific_exception => ex
29
+
30
+ raise AdapterConnectionError.new(ex.message)
31
+
32
+ end
33
+
34
+ def query ( sql )
35
+
36
+ result = conn.query sql
37
+ @result = MysqlResult.new result
38
+
39
+ end
40
+
41
+ def last_insert_id
42
+
43
+ conn.last_insert_id
44
+
45
+ end
46
+
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,32 @@
1
+ FileList[File.dirname(__FILE__) + '/expression/*.rb'].each do |f|
2
+ require f
3
+ end
4
+
5
+ module Imparcial
6
+ module Driver
7
+ module PostgreExpression
8
+
9
+ def insert ( options = {} )
10
+
11
+ super options
12
+
13
+ begin
14
+
15
+ seq_name = 'seq_' + options[:table_name].to_s + '_id'
16
+ id = conn.query "SELECT currval('#{seq_name}')"
17
+
18
+ @last_insert_id = id[0][0].to_i
19
+
20
+ rescue adapter_specific_exception; end
21
+
22
+ end
23
+
24
+ def last_insert_id
25
+
26
+ @last_insert_id
27
+
28
+ end
29
+
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,35 @@
1
+ module Imparcial
2
+ module Driver
3
+ class PostgreResult < AbstractResult
4
+
5
+ def rows
6
+
7
+ @specific.result.length
8
+
9
+ end
10
+
11
+ def fetch
12
+
13
+ fields = @specific.fields
14
+ rows = @specific.result
15
+
16
+ rows.each do |row|
17
+
18
+ v = []
19
+
20
+ row.each_with_index do |value, index|
21
+
22
+ v << Row.new(fields[index], value)
23
+
24
+ end
25
+
26
+ yield(*v)
27
+
28
+ end
29
+
30
+
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,53 @@
1
+ module Imparcial
2
+ module Driver
3
+ module PostgreSQL
4
+ module Column
5
+
6
+ private
7
+
8
+ def sql_for_renaming_column ( options )
9
+
10
+ syntax = ''
11
+
12
+ syntax += 'ALTER TABLE ' + quote(options[:table_name]) + ' '
13
+
14
+ options[:field].each do |old_name, new_name|
15
+
16
+ syntax += "RENAME COLUMN #{old_name} TO #{new_name}"
17
+
18
+ end
19
+
20
+ logger.warn(syntax) if @table_logging
21
+
22
+ syntax
23
+
24
+ end
25
+
26
+ def sql_for_modifying_columns ( options )
27
+
28
+ syntax = ''
29
+
30
+ syntax += 'ALTER TABLE ' + quote(options[:table_name]) + ' '
31
+
32
+ options[:fields].each do |field|
33
+
34
+ column = field_to_column field
35
+
36
+ syntax += "ALTER COLUMN #{column[:name]} TYPE #{column[:type]}"
37
+ syntax += "(#{column[:size]})" if column[:size]
38
+ syntax += ","
39
+
40
+ end
41
+
42
+ syntax.chop!
43
+
44
+ logger.warn(syntax) if @table_logging
45
+
46
+ syntax
47
+
48
+ end
49
+
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,37 @@
1
+ module Imparcial
2
+ module Driver
3
+ module PostgreSQL
4
+ module Constraint
5
+
6
+ private
7
+
8
+ def sql_for_adding_auto_increment ( options )
9
+
10
+ seq_name = 'seq_' + options[:table_name].to_s + '_' + options[:field].to_s
11
+ drop_sequence_if_necessary :sequence_name => seq_name
12
+ create_sequence :sequence_name => seq_name
13
+ sql_for_adding_default_value :table_name => options[:table_name], :fields => {options[:field] => "nextval('#{seq_name}')"}
14
+
15
+ end
16
+
17
+ def sql_for_adding_default_value ( options )
18
+
19
+ syntax = 'ALTER TABLE ' + quote(options[:table_name]) + ' '
20
+
21
+ for field, value in options[:fields]
22
+
23
+ value = quote_value(value) if not value.to_s.match('nextval')
24
+ syntax += "ALTER COLUMN #{quote(field)} SET DEFAULT #{value},"
25
+
26
+ end
27
+
28
+ syntax.chop!
29
+
30
+ syntax
31
+
32
+ end
33
+
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,53 @@
1
+ module Imparcial
2
+ module Driver
3
+ module PostgreSQL
4
+ module Index
5
+
6
+ private
7
+
8
+ # Generate SQL statement for verifying if a given index exists.
9
+
10
+ def sql_for_index_exists? ( options )
11
+
12
+ %{SELECT
13
+ c2.relname as "table",
14
+ (select attname from pg_attribute where attrelid = i.indexrelid AND attnum > 0) as "column" ,
15
+ c.relname as "index"
16
+ FROM pg_class c
17
+ JOIN pg_roles r ON r.oid = c.relowner
18
+ LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
19
+ LEFT JOIN pg_index i ON i.indexrelid = c.oid
20
+ LEFT JOIN pg_class c2 ON i.indrelid = c2.oid
21
+ WHERE c.relkind = 'i'
22
+ AND n.nspname NOT IN ('pg_catalog', 'pg_toast') AND
23
+ c2.relname = #{quote_value(options[:table_name])} AND
24
+ c.relname = #{quote_value(options[:index_name])}
25
+ }
26
+
27
+ end
28
+
29
+ # Generate SQL statement for retrieving all indexes.
30
+
31
+ def sql_for_getting_indexes ( options )
32
+
33
+ %{SELECT
34
+ c2.relname as "table",
35
+ (select attname from pg_attribute where attrelid = i.indexrelid AND attnum > 0) as "column" ,
36
+ c.relname as "index"
37
+ FROM pg_class c
38
+ JOIN pg_roles r ON r.oid = c.relowner
39
+ LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
40
+ LEFT JOIN pg_index i ON i.indexrelid = c.oid
41
+ LEFT JOIN pg_class c2 ON i.indrelid = c2.oid
42
+ WHERE c.relkind = 'i'
43
+ AND n.nspname NOT IN ('pg_catalog', 'pg_toast') AND
44
+ c2.relname = #{quote_value(options[:table_name])}
45
+ }
46
+
47
+ end
48
+
49
+
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,30 @@
1
+ module Imparcial
2
+ module Driver
3
+ module PostgreSQL
4
+ module Sequence
5
+
6
+ private
7
+
8
+ def sql_for_sequence_exists? ( options )
9
+
10
+ %{
11
+ SELECT 1 FROM pg_class WHERE relkind = 'S' AND
12
+ relname = #{quote_value(options[:sequence_name])}
13
+ }
14
+
15
+ end
16
+
17
+ # Generate SQL statement for retrieving sequences.
18
+
19
+ def sql_for_getting_sequences
20
+
21
+ %{
22
+ SELECT relname FROM pg_class WHERE relkind = 'S'
23
+ }
24
+
25
+ end
26
+
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,46 @@
1
+ module Imparcial
2
+ module Driver
3
+ module PostgreSQL
4
+ module Table
5
+
6
+ private
7
+
8
+ # Generate SQL statement for retrieving tables.
9
+
10
+ def sql_for_getting_tables
11
+
12
+ %{
13
+ SELECT table_name FROM information_schema.tables
14
+ WHERE table_schema = 'public'
15
+ }
16
+
17
+ end
18
+
19
+ # Generate SQL statement for retrieving columns.
20
+ =begin
21
+ def sql_for_retrieving_columns ( options )
22
+
23
+ %{
24
+ SELECT
25
+ A.column_name, A.data_type, A.character_maximum_length,
26
+ (A.is_nullable = 'YES') as allow_null,
27
+ (A.column_name = B.column_name) as pk,
28
+ A.column_default,
29
+ A.column_default LIKE 'nextval%' as auto_inc,
30
+ A.column_name in (SELECT sa.attname from pg_class sc
31
+ JOIN pg_index si ON sc.oid = si.indexrelid
32
+ JOIN pg_class sc2 ON sc2.oid = si.indrelid
33
+ JOIN pg_attribute sa ON sc.oid = sa.attrelid
34
+ WHERE sc2.relname = #{quote_value(options[:table_name])} AND sa.attname = A.column_name
35
+ ) as column_indexed
36
+ FROM information_schema.columns A
37
+ LEFT JOIN information_schema.key_column_usage B ON A.table_name = B.table_name
38
+ WHERE A.table_name = #{quote_value(options[:table_name])};
39
+ }
40
+
41
+ end
42
+ =end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,15 @@
1
+ FileList[File.dirname(__FILE__) + '/sql/*.rb'].each do |f|
2
+ require f
3
+ end
4
+
5
+ module Imparcial
6
+ module Driver
7
+ module PostgreSQL
8
+ include Table
9
+ include Sequence
10
+ include Index
11
+ include Constraint
12
+ include Column
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,36 @@
1
+ module Imparcial
2
+ module Driver
3
+ module PostgreTypemap
4
+
5
+ def regular_types
6
+
7
+ super.dup.merge!(:datetime => 'TIMESTAMP')
8
+
9
+ end
10
+
11
+ def sql_types
12
+
13
+ super.dup.merge!('CHARACTER VARYING' => :string,
14
+ 'DOUBLE PRECISION' => :float)
15
+
16
+ end
17
+
18
+ private
19
+
20
+ # Due to nextval, we have to format the default value
21
+
22
+ def parse_column ( column )
23
+
24
+ super
25
+
26
+ if column[:default_value]
27
+
28
+ column[:default_value].gsub!(/::.*/,'')
29
+
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,19 @@
1
+ module Imparcial
2
+ module Driver
3
+ module PostgreUtil
4
+
5
+ def quote_value ( val )
6
+
7
+ conn.class.quote val
8
+
9
+ end
10
+
11
+ def quote ( val )
12
+
13
+ "\"#{val}\""
14
+
15
+ end
16
+
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,43 @@
1
+ require 'postgres'
2
+
3
+ require 'imparcial/driver/postgre/util'
4
+ require 'imparcial/driver/postgre/result'
5
+ require 'imparcial/driver/postgre/typemap'
6
+ require 'imparcial/driver/postgre/sql'
7
+ require 'imparcial/driver/postgre/expression'
8
+
9
+ module Imparcial
10
+ module Driver
11
+ class PostgreAdapter < AbstractAdapter
12
+
13
+ include PostgreUtil
14
+ include PostgreTypemap
15
+ include PostgreSQL
16
+ include PostgreExpression
17
+
18
+ def adapter_specific_exception
19
+
20
+ PGError
21
+
22
+ end
23
+
24
+ def connect
25
+
26
+ @conn = PGconn.connect @host, @port, '', '', @database, @username, @password
27
+
28
+ rescue adapter_specific_exception => ex
29
+
30
+ raise AdapterConnectionError.new(ex.message)
31
+
32
+ end
33
+
34
+ def query ( sql )
35
+
36
+ result = conn.exec sql
37
+ @result = PostgreResult.new result
38
+
39
+ end
40
+
41
+ end
42
+ end
43
+ end
@@ -0,0 +1 @@
1
+ require 'imparcial/driver/abstract'