normalizePostgreSQLCheckConstraint normalizes PostgreSQL check constraint expressions for comparison
(expression string)
| 2270 | |
| 2271 | // normalizePostgreSQLCheckConstraint normalizes PostgreSQL check constraint expressions for comparison |
| 2272 | func normalizePostgreSQLCheckConstraint(expression string) string { |
| 2273 | // Based on the test output, we need to normalize: |
| 2274 | // Sync: (order_date >= (CURRENT_DATE - '1 year'::interval)) |
| 2275 | // Parser: order_date >= CURRENT_DATE - INTERVAL '1 year' |
| 2276 | // Both should normalize to the same canonical form |
| 2277 | |
| 2278 | expression = strings.TrimSpace(expression) |
| 2279 | |
| 2280 | // Step 1: Remove outer parentheses |
| 2281 | for strings.HasPrefix(expression, "(") && strings.HasSuffix(expression, ")") { |
| 2282 | // Only remove if they are balanced and wrapping the entire expression |
| 2283 | inner := expression[1 : len(expression)-1] |
| 2284 | parenCount := 0 |
| 2285 | canRemove := true |
| 2286 | for _, ch := range inner { |
| 2287 | if ch == '(' { |
| 2288 | parenCount++ |
| 2289 | } else if ch == ')' { |
| 2290 | parenCount-- |
| 2291 | if parenCount < 0 { |
| 2292 | canRemove = false |
| 2293 | break |
| 2294 | } |
| 2295 | } |
| 2296 | } |
| 2297 | if canRemove && parenCount == 0 { |
| 2298 | expression = inner |
| 2299 | } else { |
| 2300 | break |
| 2301 | } |
| 2302 | } |
| 2303 | |
| 2304 | // Step 2: Normalize interval syntax |
| 2305 | // Convert ::interval to INTERVAL prefix |
| 2306 | expression = strings.ReplaceAll(expression, "'::interval", "'") |
| 2307 | |
| 2308 | // Step 3: Standardize to INTERVAL syntax |
| 2309 | if strings.Contains(expression, "CURRENT_DATE") && strings.Contains(expression, "'") && !strings.Contains(expression, "INTERVAL") { |
| 2310 | // Add INTERVAL prefix where needed |
| 2311 | expression = strings.ReplaceAll(expression, "CURRENT_DATE - '", "CURRENT_DATE - INTERVAL '") |
| 2312 | expression = strings.ReplaceAll(expression, "CURRENT_DATE + '", "CURRENT_DATE + INTERVAL '") |
| 2313 | } |
| 2314 | |
| 2315 | // Step 4: Remove extra parentheses around date arithmetic |
| 2316 | expression = strings.ReplaceAll(expression, "(CURRENT_DATE - INTERVAL", "CURRENT_DATE - INTERVAL") |
| 2317 | expression = strings.ReplaceAll(expression, "(CURRENT_DATE + INTERVAL", "CURRENT_DATE + INTERVAL") |
| 2318 | |
| 2319 | // Step 5: Clean up trailing parentheses after year' |
| 2320 | if strings.Contains(expression, "year'") && strings.Contains(expression, "INTERVAL") { |
| 2321 | expression = strings.ReplaceAll(expression, "year')", "year'") |
| 2322 | } |
| 2323 | |
| 2324 | // Step 6: Normalize timestamp literals and type casts |
| 2325 | // '2020-01-01 00:00:00'::timestamp without time zone -> '2020-01-01'::timestamp |
| 2326 | expression = strings.ReplaceAll(expression, " 00:00:00'::timestamp without time zone", "'::timestamp") |
| 2327 | |
| 2328 | // Step 7: Normalize numeric type casts |
| 2329 | // >= 0::numeric -> >= 0 |
no outgoing calls
no test coverage detected