@@ -449,20 +449,28 @@ def ask(cond):
449449 self .assertTrue (any ("stopped early" in n for n in esp .dialect .notes ))
450450
451451 def test_left_right_rung (self ):
452- # SUBSTR/SUBSTRING/MID blocked but LEFT+RIGHT present -> RIGHT(LEFT(x,p),1)
452+ # SUBSTR/SUBSTRING/MID blocked but LEFT+RIGHT present -> RIGHT(LEFT(x,p),1).
453+ # LEFT/RIGHT are reserved JOIN keywords in SQLite; some builds reject LEFT(/RIGHT(
454+ # as function calls (syntax error, keyword) rather than invoking a same-named UDF,
455+ # so register the shims under non-keyword names and translate the engine's LEFT(/
456+ # RIGHT( onto them (the same rewrite the disguised-dialect oracles use). Keeps the
457+ # test portable across SQLite builds while still exercising the real left_right rung.
453458 con = sqlite3 .connect (":memory:" )
454459 con .execute ("CREATE TABLE t7 (v TEXT)" )
455460 con .execute ("INSERT INTO t7 VALUES ('Zagreb-42')" )
456461 con .commit ()
457- con .create_function ("LEFT " , 2 , lambda s , n : (s or "" )[:max (n , 0 )])
458- con .create_function ("RIGHT " , 2 , lambda s , n : (s or "" )[len (s or "" ) - n :] if n > 0 else "" )
462+ con .create_function ("esp_left " , 2 , lambda s , n : (s or "" )[:max (n , 0 )])
463+ con .create_function ("esp_right " , 2 , lambda s , n : (s or "" )[len (s or "" ) - n :] if n > 0 else "" )
459464 blk = re .compile (r"(?i)\b(SUBSTR|SUBSTRING|SUBSTRC|MID)\s*\(" )
465+ rwLeft = re .compile (r"(?i)\bLEFT\s*\(" )
466+ rwRight = re .compile (r"(?i)\bRIGHT\s*\(" )
460467
461468 def ask (cond ):
462469 if blk .search (cond ):
463470 return False
471+ sql = rwRight .sub ("esp_right(" , rwLeft .sub ("esp_left(" , cond ))
464472 try :
465- return con .execute ("SELECT CASE WHEN (%s) THEN 1 ELSE 0 END" % cond ).fetchone ()[0 ] == 1
473+ return con .execute ("SELECT CASE WHEN (%s) THEN 1 ELSE 0 END" % sql ).fetchone ()[0 ] == 1
466474 except sqlite3 .DatabaseError :
467475 return False
468476 esp = Esperanto (ask )
0 commit comments