2025, Oct 18 03:31

T‑SQL से Databricks SQL: TOP को LIMIT में बदलते समय sqlparse टोकनाइज़ेशन की समस्या और समाधान

यह गाइड बताता है कि sqlparse टोकनाइज़ेशन के कारण T‑SQL का TOP कीवर्ड क्यों छूट जाता है और Databricks SQL में उसे LIMIT में सुरक्षित रूप से कैसे बदलें, कोड के साथ।

T‑SQL को Databricks SQL में बदलना अक्सर सीधा लगता है, जब तक कि टोकनाइज़ेशन बीच में बाधा नहीं बनता। एक सामान्य रोड़ा TOP क्लॉज़ है: जिस टोकनाइज़र पर आप निर्भर हैं, वह इसे कीवर्ड नहीं मानता, इसलिए आपका कंट्रोल‑फ्लो कभी भी ट्रांसफ़ॉर्मेशन वाले मार्ग में नहीं जाता। अगर आपका लॉजिक केवल कॉमन कीवर्ड मिलने पर ही शॉर्ट‑सर्किट करता है, तो आप TOP को LIMIT में बदलने के बजाय अनजाने में मूल क्वेरी ही लौटा सकते हैं।

समस्या की रूपरेखा

विचार यह है कि SQL को पार्स किया जाए, टोकनों को फ्लैटन किया जाए, और फिर केवल तब आगे बढ़ा जाए जब कोई कम‑प्रचलित कीवर्ड दिखे। अगर सब कुछ “कॉमन” लगता है, तो कोड इनपुट को बिना छेड़छाड़ लौटाकर परिवर्तन टाल देता है। व्यवहार में, इससे TOP को सँभालना रुक जाता है, क्योंकि टोकनाइज़र उसे कीवर्ड के तौर पर पहचान ही नहीं पाता।

ast_unit = sqlparse.parse(input_sql)[0]
stream = TokenList(ast_unit.tokens).flatten()

shared_kw = ["SELECT","FROM","DISTINCT","WHERE","GROUP BY","ORDER BY","AS","JOIN","VALUES","INSERT INTO","UPDATE","DELETE FROM","SET","COUNT","AVG","MIN","MAX","SUM"]
passthrough = True
for piece in stream:
if piece.ttype == Keyword:
if piece.value.upper() not in shared_kw:
passthrough = False
break
if passthrough:
return input_sql

उम्मीद यह रहती है कि अगला कदम TOP को LIMIT में बदलना होगा। लेकिन गार्ड कभी ट्रिगर नहीं होता, इसलिए फ़ंक्शन फिसलकर मूल क्वेरी ही लौटा देता है।

मूल कारण

sqlparse.token.Keyword DDL और DML के कीवर्ड पहचानता है, पर DQL नहीं। नतीजतन, TOP को बिल्कुल भी Keyword टैग नहीं मिलता, इसलिए आपकी allowlist के मुकाबले वाली जाँच कभी चलती ही नहीं। परिणाम सूक्ष्म है: लूप को कोई “कम‑आम कीवर्ड” दिखाई नहीं देता, ब्रेक सेट नहीं होता, और कोड समय से पहले लौट आता है।

उपाय और संशोधित कोड

टोकनाइज़र की Keyword कवरेज के बाहर आने वाले कॉन्स्ट्रक्ट मिलने पर भी पाइपलाइन आगे बढ़े, यह सुनिश्चित करने के लिए कच्चे SQL पर TOP और आपके लिए महत्त्वपूर्ण अन्य संकेतकों (जैसे @ कैरेक्टर) की स्पष्ट जाँच जोड़ें।

ast_unit = sqlparse.parse(input_sql)[0]
stream = TokenList(ast_unit.tokens).flatten()

shared_kw = ["SELECT","FROM","DISTINCT","WHERE","GROUP BY","ORDER BY","AS","JOIN","VALUES","INSERT INTO","UPDATE","DELETE FROM","SET","COUNT","AVG","MIN","MAX","SUM"]
passthrough = True

for chunk in input_sql:
if "TOP" in chunk or "@" in chunk:
passthrough = False

if passthrough:
for piece in stream:
if piece.ttype == Keyword:
if piece.value.upper() not in shared_kw:
passthrough = False
break

if passthrough:
return input_sql

# passthrough False होने पर परिवर्तन के चरण जारी रखें (उदा., TOP -> LIMIT को हैंडल करना)

इस तरह यह सुनिश्चित होता है कि TOP वाली क्वेरियाँ ज्यों‑की‑त्यों वापस नहीं लौटेंगी, और बाद की लॉजिक नियत अनुसार TOP को LIMIT से बदल सकेगी। संदर्भ के लिए, sqlparse.token.Keyword द्वारा पहचाने जाने वाले शब्द, फ़ंक्शंस और कैरेक्टर की सूची यहाँ उपलब्ध है: https://github.com/andialbrecht/sqlparse/blob/master/sqlparse/keywords.py.

यह क्यों अहम है

स्वचालित SQL माइग्रेशन टूलिंग बनाते समय आपका कंट्रोल‑फ्लो अक्सर टोकन क्लास और कीवर्ड डिटेक्शन पर टिका होता है। अगर टोकनाइज़र कुछ श्रेणियाँ बाहर रख दे, तो आपका टूल बिना शोर किए अहम री‑राइट्स छोड़ सकता है। टोकनाइज़र किन चीज़ों को सच‑मुच Keyword का लेबल देता है, यह समझना ग़लत मान्यताओं और टूटी हुई ट्रांसफ़ॉर्मेशन पाथ से बचाता है।

व्यावहारिक निष्कर्ष

पहला, बिज़नेस नियम बाँधने से पहले यह जाँच लें कि आपका टोकनाइज़र वास्तव में क्या निकाल रहा है। जरूरत पड़े तो जिन कॉन्स्ट्रक्ट्स को पकड़ना अनिवार्य है, उनके लिए टोकन‑आधारित जाँच के साथ साधारण स्ट्रिंग स्कैन भी जोड़ें। दूसरा, जब व्यवहार उम्मीद से अलग हो, तो रनटाइम में क्या हो रहा है यह देखने के लिए प्रिंट डिबगिंग से वैल्यूज़ और एक्जीक्यूशन पाथ ट्रेस करें और पुष्टि करें कि टोकन पहचाना भी जा रहा है या नहीं।

संक्षेप में, इस सेटअप में TOP Keyword के रूप में नहीं दिखेगा, इसलिए उसे स्पष्ट रूप से गार्ड करें और बाकी पाइपलाइन को LIMIT में रूपांतरण करने दें। अपनी allowlist सटीक रखें, टोकनाइज़र की सीमाएँ जानें, और ट्रांसफ़ॉर्मेशन लॉजिक को स्केल करने से पहले हल्की‑फुल्की डायग्नॉस्टिक्स से सत्यापन करें।

यह लेख StackOverflow के प्रश्न पर आधारित है, जिसे SAMIBOIII ने पूछा था, और उसी उपयोगकर्ता SAMIBOIII के उत्तर पर।