لینک کوتاه مطلب : https://hsgar.com/?p=6864

معادل سازی رشته های یونیکد عجیب است

در اصل HyPer یک مدل بسیار ساده برای رشته ها داشت: ما مطمئن شدیم که همه رشته ها معتبر هستند UTF-8، اما در غیر این صورت واقعاً به ذاتی یونیکد اهمیت نمی داد. و این در واقع یک مدل کاملا منطقی است برای اکثر برنامه ها. معمولاً ما به هیچ وجه به ساختار رشته دقیق اهمیت نمی دهیم، و در مکان های معدودی که به آن اهمیت می دهیم (به عنوان مثال، strpos و substr)، ما مقداری منطق اضافی برای مدیریت صحیح UTF-8 اضافه می کنیم.

همه چیز خوب بود تا اینکه کاربران شروع به شکایت از سفارشات مرتب کردند. هنگام مرتب سازی ساده UTF-8، ما بر اساس مقدار نقطه کد مرتب می کنیم، که اغلب خوب است اما همیشه آن چیزی نیست که کاربران می خواهند. بنابراین ما پشتیبانی را برای گردآوری ها:

select * from foo order by x collate "de_DE";

و اینجاست که زندگی شروع به جالب شدن می کند. عبارت جمع‌آوری می‌تواند به صراحت در هر مکانی از پرس و جو داده شود، همانطور که در بالا نشان داده شده است، یا اضافه شود ایجاد جدول بیانیه، ارائه یک ترکیب پیش فرض برای یک ستون. بنابراین اساساً هر مقداری که در یک دستور SQL مرتب یا مقایسه می‌شود، می‌تواند یک ترکیب مرتبط داشته باشد.

در ابتدا من ساده لوحانه فکر می کردم که این فقط بر عملیات مقایسه تأثیر می گذارد، مانند تماس strcoll بجای strcmp، اما متاسفانه زندگی بسیار پیچیده تر است. اول، الگوریتم ترکیب یونیکد کاملاً دخیل است، ترجمه دنباله ورودی به دنباله ای از وزن های 3 (یا 4) قبل از مقایسه، و دوم، برخی از سیستم های پایگاه داده دیوانه به طور پیش فرض جمع بندی های حساس به حروف کوچک و بزرگ، و برخی از کاربران واقعاً این رفتار را می خواهند.

چرا عدم حساسیت به حروف کوچک و بزرگ دیوانه کننده است؟ زیرا به معناشناسی عجیبی می انجامد. اول از همه، کل مکانیسم وزن دهی یونیکد عجیب است. برخی از عجیب بودن را می توان با استفاده پنهان کرد آی سی یو، اما هنوز نتایج عجیبی دریافت می کنید. به عنوان مثال دو رشته زیر را در نظر بگیرید (\u یک فرار یونیکد است):

abc
abc\u007F

واضح است که آنها متفاوت هستند، درست است؟ خوب، اگر شما بپرسید نسخه نمایشی مجموعه ICU آنها نیستند، آنها برابر در نظر گرفته می شوند. دلیل آن ورود در میز DUCET، که برای 007F می گوید

007F  ; [.0000.0000.0000] # DELETE (in ISO 6429)
 

پس برای مقایسه باید این شخصیت را نادیده گرفت. و نقاط کد دیگری وجود دارد که برای مقایسه ساده مرتبط هستند، اما نه برای ترکیب‌بندی‌های بی‌حساس و غیره. بسیار سرگرم کننده است، به ویژه اگر می‌خواهید الگوریتم‌های مبتنی بر هش را پیاده‌سازی کنید.

اما جدا از مشکلات فنی، آیا واقعاً این همان چیزی است که کاربران می خواهند؟ آیا کاربران انتظار دارند که این دو رشته با هم برابر باشند، درست همانطور که ظاهراً انتظار دارند «abc» و «äbc» در ترکیب‌بندی بدون لهجه با هم برابر باشند؟ و در مورد پرس و جوها چطور؟ به عنوان مثال در نظر بگیرید

select x,count(*)
from (values('abc'),('ABC'),('äbc')) s(x)
group by x collate "de_DE_ci_ai";

که گروه را با حروف بزرگ و بدون لهجه اجرا می کنند، به این معنی که هر سه رشته با هم برابر هستند. نتیجه آن چیست؟ abc 3؟ ABC 3؟ äbc 3؟
هر سه پاسخ معتبر خواهند بود، زیرا این سه با توجه به ترکیب انتخابی “برابر” هستند. و نتیجه ممکن است حتی غیر قطعی باشد، اگر پرس و جو در سراسر رشته ها موازی شود و اولین مقدار برنده شود.

آیا کاربران واقعاً این را می خواهند؟ خب، ظاهراً این کار را می‌کنند، حداقل به من گفته شده است، و برخی از سیستم‌ها حتی به طور پیش‌فرض رفتار حساس به حروف کوچک و بزرگ دارند. اما به نظرم عجیب است، معنایی این پرسش‌ها می‌تواند کاملاً گیج‌کننده باشد.

لینک منبع

ارسال یک پاسخ

آدرس ایمیل شما منتشر نخواهد شد.