এটি প্রজেক্টের নরমালাইজেশনের একটি বাগ , একটি অ-নিরস্তকরণমূলক ক্রিয়াকলাপের সাথে কেস এক্সপ্রেশনটির ভিতরে সাব-কোয়েরি ব্যবহার করে উদ্ভাসিত।
ব্যাখ্যা করার জন্য, আমাদের সামনে দুটি জিনিস নোট করতে হবে:
- এসকিউএল সার্ভার সরাসরি সাবকিউরিগুলি চালাতে পারে না, তাই এগুলি সর্বদা তালিকাভুক্ত বা কোনও প্রয়োগে রূপান্তরিত হয় ।
- এর শব্দার্থবিজ্ঞানগুলি
CASE
এমন যে একটি ধারাটি THEN
যদি WHEN
সত্যটি ফিরে আসে তবেই একটি অভিব্যক্তিটি মূল্যায়ন করা উচিত ।
সমস্যাযুক্ত ক্ষেত্রে প্রবর্তিত (তুচ্ছ) সাব-কোয়েরি ফলস্বরূপ একটি প্রয়োগ অপারেটর (নেস্টেড লুপস যোগ দেয়) ফলাফল। দ্বিতীয় প্রয়োজনীয়তা পূরণের জন্য, এসকিউএল সার্ভার প্রাথমিকভাবে dbo.test6(1) + dbo.test6(2)
প্রয়োগের অভ্যন্তরীণ দিকে প্রকাশ করে:
[Expr1000] = Scalar Operator([dbo].[test6]((1))+[dbo].[test6]((2)))
... যোগদানের উপর CASE
একটি পাস- থ্রোক দ্বারা সম্মানিত শব্দার্থবিজ্ঞানের সাথে:
[@i]=(1) OR [@i]=(2) OR IsFalseOrNull [@i]=(3)
লুপটির অভ্যন্তরীণ দিকটি কেবল তখনই মূল্যায়ন করা হয় যদি পাস-থ্রু শর্তটি মিথ্যা (অর্থ @i = 3
) এর কাছে মূল্যায়ন করে । এটি এখন পর্যন্ত সব ঠিক আছে। কম্পিউট স্কালে নিম্নলিখিত নেস্টেড loops যোগদানের এছাড়াও সম্মান CASE
সঠিকভাবে শব্দার্থবিদ্যা:
[Expr1001] = Scalar Operator(CASE WHEN [@i]=(1) THEN (1) ELSE CASE WHEN [@i]=(2) THEN (2) ELSE CASE WHEN [@i]=(3) THEN [Expr1000] ELSE NULL END END END)
সমস্যাটি হ'ল ক্যোয়ারী সংকলনের প্রকল্পের স্বাভাবিককরণের স্তরটি Expr1000
এটি নিরবিচ্ছিন্নভাবে দেখে এবং নির্ধারণ করে যে এটি নিরাপদ হবে ( বর্ণনাকারী: এটি নয় ) এটিকে লুপের বাইরে নিয়ে যেতে হবে:
[Expr1000] = Scalar Operator([dbo].[test6]((1))+[dbo].[test6]((2)))
এটি পাস- থ্রো প্রিডিকেট দ্বারা প্রয়োগ করা শব্দার্থবিধি ভেঙে দেয়, সুতরাং ফাংশনটি কখন হওয়া উচিত নয় তা মূল্যায়ন করা হয় এবং অসীম লুপ ফলাফল হয়।
আপনার এই বাগটি রিপোর্ট করা উচিত। একটি কর্মসংস্থান হ'ল অভিব্যক্তিটিকে এর সাথে সম্পর্কিত করে (যেমন @i
অভিব্যক্তিতে অন্তর্ভুক্ত করে) প্রয়োগের বাইরে সরিয়ে নেওয়া রোধ করা তবে এটি অবশ্যই একটি হ্যাক। প্রকল্পের সাধারণীকরণকে অক্ষম করার একটি উপায় আছে, তবে আমাকে এটি সর্বজনীনভাবে ভাগ না করার জন্য আগেই জিজ্ঞাসা করা হয়েছিল, তাই আমি তা করব না।
স্কেলার ফাংশনটি ইনলাইন করা অবস্থায় এসকিউএল সার্ভার 2019-এ এই সমস্যাটি দেখা দেয় না , কারণ ইনলাইনিং লজিকগুলি পার্সড ট্রিটিতে সরাসরি পরিচালনা করে (প্রকল্পের স্বাভাবিককরণের আগে ভাল)। প্রশ্নটিতে সরল যুক্তি অনার্সিং-এ অন্তর্নিহিত যুক্তি দ্বারা সহজ করা যেতে পারে:
[Expr1019] = (Scalar Operator((1)))
[Expr1045] = Scalar Operator(CONVERT_IMPLICIT(int,CONVERT_IMPLICIT(int,[Expr1019],0)+(2),0))
... যা ফেরত 3।
মূল সমস্যাটি চিত্রিত করার আরেকটি উপায় হ'ল:
-- Not schema bound to make it non-det
CREATE OR ALTER FUNCTION dbo.Error()
RETURNS integer
-- WITH INLINE = OFF -- SQL Server 2019 only
AS
BEGIN
RETURN 1/0;
END;
GO
DECLARE @i integer = 1;
SELECT
CASE
WHEN @i = 1 THEN 1
WHEN @i = 2 THEN 2
WHEN @i = 3 THEN (SELECT dbo.Error()) -- 'subquery'
ELSE NULL
END;
২০০৮ R2 থেকে 2019 সিটিপি 3.0 পর্যন্ত সমস্ত সংস্করণের সর্বশেষতম বিল্ডগুলিতে পুনরুত্পাদন করে।
মার্টিন স্মিথের দেওয়া আরও একটি উদাহরণ (কোনও স্কেলারের কাজ ছাড়াই) :
SELECT IIF(@@TRANCOUNT >= 0, 1, (SELECT CRYPT_GEN_RANDOM(4)/ 0))
এটিতে প্রয়োজনীয় সমস্ত মূল উপাদান রয়েছে:
CASE
(অভ্যন্তরীণভাবে হিসাবে বাস্তবায়িত ScaOp_IIF
)
- একটি অ-বিবাদী ফাংশন (
CRYPT_GEN_RANDOM
)
- শাখায় একটি সাবকোয়ারি যা কার্যকর করা উচিত নয় (
(SELECT ...)
)
* কঠোরভাবে, উপরোক্ত রূপান্তরটি এখনও সঠিক হতে পারে যদি মূল্যায়ন Expr1000
সঠিকভাবে পিছিয়ে দেওয়া হয়, কারণ এটি কেবল নিরাপদ নির্মাণ দ্বারা রেফারেন্স করা হয়:
[Expr1002] = Scalar Operator(CASE WHEN [@i]=(1) THEN (1) ELSE CASE WHEN [@i]=(2) THEN (2) ELSE CASE WHEN [@i]=(3) THEN [Expr1000] ELSE NULL END END END)
... তবে এর জন্য একটি অভ্যন্তরীণ ফোর্সআর্ডার পতাকা প্রয়োজন (কোয়েরি ইঙ্গিত নয়), যা সেটও করা হয়নি। যে কোনও ক্ষেত্রে, প্রকল্পের নরমালাইজেশন দ্বারা প্রয়োগ করা যুক্তির বাস্তবায়নটি ভুল বা অসম্পূর্ণ।
এসকিউএল সার্ভারের জন্য অ্যাজুরে প্রতিক্রিয়া সাইটে বাগ রিপোর্ট ।