real_data_tests 0.3.3 → 0.3.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -0
- data/lib/real_data_tests/rspec_helper.rb +88 -4
- data/lib/real_data_tests/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 35d81ac18056a163df010e92d75c5bd36896836d070f8c74041048ab98918cdf
|
4
|
+
data.tar.gz: 50d5df4a36a88f58b6dbc76494db155bc68b5b9ca1cf8cbd45b22a4bd8cd6166
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fb2bf7729c1b3a0c86a073924b8c50b0a2005885d93acb7bdd419f12db87e858801222235c6a1c437144b53f57b9375ee56e76c467e6b1d4e643a403131153c9
|
7
|
+
data.tar.gz: ff37ab1ab9d6c2b33efb657905bb682c4d99cd22a7533e8b19db95d9949f11e621f0d750fbb829f8d61c377faa64d008c66bcdd703a072fae349d4d80c369ab2
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,21 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.3.5] - 2025-01-14
|
4
|
+
### Fixed
|
5
|
+
- Enhanced SQL statement handling in native loader
|
6
|
+
- Added proper UUID value quoting in VALUES clauses
|
7
|
+
- Fixed string value formatting in SQL statements
|
8
|
+
- Improved error reporting with detailed SQL statement context
|
9
|
+
- Added robust SQL statement cleaning and normalization
|
10
|
+
|
11
|
+
## [0.3.4] - 2025-01-14
|
12
|
+
### Added
|
13
|
+
- Alternative native SQL loading method for CI environments
|
14
|
+
- Added `load_real_test_data_native` method that doesn't rely on system commands
|
15
|
+
- Works in restricted environments like GitHub Actions
|
16
|
+
- Uses ActiveRecord's native connection for SQL execution
|
17
|
+
- Maintains same transaction and foreign key handling behavior
|
18
|
+
|
3
19
|
## [0.3.3] - 2025-01-14
|
4
20
|
### Fixed
|
5
21
|
- Improved circular dependency handling in PgDumpGenerator for self-referential associations
|
@@ -3,16 +3,13 @@ module RealDataTests
|
|
3
3
|
def load_real_test_data(name)
|
4
4
|
dump_path = File.join(RealDataTests.configuration.dump_path, "#{name}.sql")
|
5
5
|
raise Error, "Test data file not found: #{dump_path}" unless File.exist?(dump_path)
|
6
|
-
|
7
6
|
ActiveRecord::Base.transaction do
|
8
7
|
# Disable foreign key checks
|
9
8
|
ActiveRecord::Base.connection.execute('SET session_replication_role = replica;')
|
10
|
-
|
11
9
|
begin
|
12
10
|
# Load the SQL dump quietly
|
13
11
|
result = system("psql #{connection_options} -q < #{dump_path}")
|
14
12
|
raise Error, "Failed to load test data: #{dump_path}" unless result
|
15
|
-
|
16
13
|
ensure
|
17
14
|
# Re-enable foreign key checks
|
18
15
|
ActiveRecord::Base.connection.execute('SET session_replication_role = DEFAULT;')
|
@@ -20,6 +17,43 @@ module RealDataTests
|
|
20
17
|
end
|
21
18
|
end
|
22
19
|
|
20
|
+
# New method that doesn't rely on system commands
|
21
|
+
def load_real_test_data_native(name)
|
22
|
+
dump_path = File.join(RealDataTests.configuration.dump_path, "#{name}.sql")
|
23
|
+
raise Error, "Test data file not found: #{dump_path}" unless File.exist?(dump_path)
|
24
|
+
|
25
|
+
ActiveRecord::Base.transaction do
|
26
|
+
connection = ActiveRecord::Base.connection
|
27
|
+
|
28
|
+
# Disable foreign key checks
|
29
|
+
connection.execute('SET session_replication_role = replica;')
|
30
|
+
|
31
|
+
begin
|
32
|
+
# Read the SQL file content
|
33
|
+
sql_content = File.read(dump_path)
|
34
|
+
|
35
|
+
# Split the file into individual statements
|
36
|
+
statements = split_sql_statements(sql_content)
|
37
|
+
|
38
|
+
# Execute each statement
|
39
|
+
statements.each do |statement|
|
40
|
+
next if statement.strip.empty?
|
41
|
+
begin
|
42
|
+
# Clean up any formatting issues that might cause syntax errors
|
43
|
+
cleaned_statement = clean_sql_statement(statement)
|
44
|
+
connection.execute(cleaned_statement)
|
45
|
+
rescue ActiveRecord::StatementInvalid => e
|
46
|
+
# Provide detailed error information
|
47
|
+
raise Error, "Failed to execute SQL statement: #{e.message}\nStatement: #{cleaned_statement}"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
ensure
|
51
|
+
# Re-enable foreign key checks
|
52
|
+
connection.execute('SET session_replication_role = DEFAULT;')
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
23
57
|
private
|
24
58
|
|
25
59
|
def connection_options
|
@@ -28,7 +62,6 @@ module RealDataTests
|
|
28
62
|
else
|
29
63
|
ActiveRecord::Base.connection_config
|
30
64
|
end
|
31
|
-
|
32
65
|
options = []
|
33
66
|
options << "-h #{config[:host]}" if config[:host]
|
34
67
|
options << "-p #{config[:port]}" if config[:port]
|
@@ -37,5 +70,56 @@ module RealDataTests
|
|
37
70
|
options << "-q"
|
38
71
|
options.join(" ")
|
39
72
|
end
|
73
|
+
|
74
|
+
def split_sql_statements(sql)
|
75
|
+
statements = []
|
76
|
+
current_statement = ''
|
77
|
+
in_string = false
|
78
|
+
escaped = false
|
79
|
+
|
80
|
+
sql.each_char do |char|
|
81
|
+
case char
|
82
|
+
when '\\'
|
83
|
+
escaped = !escaped
|
84
|
+
when "'"
|
85
|
+
in_string = !in_string unless escaped
|
86
|
+
escaped = false
|
87
|
+
when ';'
|
88
|
+
if !in_string
|
89
|
+
statements << current_statement.strip
|
90
|
+
current_statement = ''
|
91
|
+
else
|
92
|
+
current_statement << char
|
93
|
+
end
|
94
|
+
else
|
95
|
+
escaped = false
|
96
|
+
current_statement << char
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Add the last statement if it doesn't end with a semicolon
|
101
|
+
statements << current_statement.strip if current_statement.strip.length > 0
|
102
|
+
|
103
|
+
statements
|
104
|
+
end
|
105
|
+
|
106
|
+
def clean_sql_statement(statement)
|
107
|
+
# Handle VALUES clause formatting
|
108
|
+
if statement.include?('VALUES')
|
109
|
+
# Split into pre-VALUES and VALUES parts
|
110
|
+
parts = statement.split(/VALUES\s*\(/i, 2)
|
111
|
+
if parts.length == 2
|
112
|
+
# Properly quote UUIDs and strings in the VALUES part
|
113
|
+
values_part = parts[1]
|
114
|
+
values_part = values_part.gsub(/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?=[,\s)])/i, "'\\1'")
|
115
|
+
# Quote unquoted string values
|
116
|
+
values_part = values_part.gsub(/,\s*([^',\s][^,\s]*)(?=[,\s)])/, ", '\\1'")
|
117
|
+
# Reassemble the statement
|
118
|
+
statement = parts[0] + 'VALUES (' + values_part
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
statement
|
123
|
+
end
|
40
124
|
end
|
41
125
|
end
|