ךופה ,הטוג ,ךופה

כל מי שאי פעם פיתח בישראל בסביבת Windows או web אפליקציה שקוראת נתונים מ-AS400, בוודאי נתקל בבעיה הבאה: כל עוד הטקסט מכיל רק עברית, או שאינו מכיל עברית כלל, הכל טוב. ברגע שיש שדה עם תוכן מעורב (גם עברית וגם אנגלית או ספרות או תווים מיוחדים) – הכל מתערבב.

במאמר זה אסביר למה זה קורה, ואיך פותרים את זה.

 

למה זה קורה?

AS400 היא מערכת ישנה.

כמה ישנה? היה לי הכבוד לעבוד בארגון שהיה בין הראשונים בארץ שהתחילו לעבוד עם AS400, אי שם בשנת 1988.

יבמ תכננה את מערכת ההפעלה שלה כך שהטקסט נשמר ב-DB כפי שהוא אמור להראות (המינוח המקצועי הוא Visual). כלומר, כדי לכתוב את הכתובת של המשרד שלנו – "הנשיא 21", הקלדנו הנשיא-רווח-אחת-שתיים. מעצבן, אבל פעם אחת נאלצנו להקליד הפוך, ובכל הדוחות והשאילתות הכתובת הוצגה בצורה תקינה.

ואז, בתחילת שנות ה-90, עברנו משימוש במסופים לשימוש במחשבים אישיים עם אמולציה, ומהר מאוד התקדמנו למע' הפעלה גרפיות (או בקיצור: Windows) והעברית התפוצצה לנו בפרצוף.

כי במיקרוסופט, בניגוד ל-יבמ, חשבו שההקלדה צריכה להיות טבעית ("הנשיא-רווח-שתיים-אחת") ומערכת ההפעלה צריכה לטפל בהצגה נכונה (המינוח המקצועי הוא Logical, והאמת שזה באמת יותר לוגי).

התוצאה היתה (וככה זה נשאר עד היום) – שב-AS400 העברית נשמרה ב-DB בצורה כזו, שכל עוד מריצים תכניות ב-"מסכים ירוקים" היא מוצגת נכון, אבל ברגע שמציגים אותה במערכת windows/web, היא מתהפכת.

לצורך ההמחשה, הכינותי מראש שני פריטים.

ככה הם נראים ב-AS400:

אבל כשאנחנו שולפים את הנתונים ב-SQL Server, העברית הפוכה:

לקריאה נוספת ומעמיקה יותר לחצו כאן.

 

ואיך פותרים את זה?

אוקיי, הבנו למה זה קורה. אפשר לפתור את זה עם פונקציית Reverse, לא?

אז זהו, שלא )-:

פונקציית Reverse הופכת את כל הטקסט בשדה, כולל את מה שאינו בעברית:

ל-יבמ יש כמובן פתרון לבעיה. הוא מסורבל יותר ולא תמיד עובד – בתלות בגירסת מערכת ההפעלה שלכם, לכן אמשיך בתאור הפתרון של מיקרוסופט, ואחריו, למי שמתעניין בהסטוריה, אתאר את הפתרון של יבמ.

לשמחתי, מיקרוסופט שחררה פתרון משובח:

 

מיום שגיליתי את הפתרון הזה – הוא היחיד שאני משתמש בו לשליפת שדות טקסט מה-AS400.

לפתרון הזה יש רק בעיה אחת קטנה (באמת קטנה): אם השדה המקורי הוא באורך 30 תווים, בפלט של השאילתא תקבלו שדה באורך 32 תווים (כי הוספתם תו בהתחלה ועוד אחד בסוף). אם אתם שולפים נתונים לטבלה קיימת ב-SQL Server, אל תשכחו להגדיל את שדות הטקסט ב-2 תווים.

אגב, ב-C# בתחביר מעט שונה.

במקום
nchar(8237) + field_name + nchar(8236)

כותבים
(char)8237 + field_name + (char)8236

וכמו שהבטחתי כמה משפטים על הפתרון של יבמ, אבל קודם, כמה מילים על CCSID…

מחשבי AS400 יוצאים מהמפעל מוגדרים לעבוד בשוק האמריקאי, אך יודעים לתמוך בכל שפה. התמיכה בשפות שונות נעשית ע"י הגדרה של CCSID (coded character set identifier) כאשר לכל שפה קוד משלה, ואנגלית ארה"ב היא 37.

אם ה-AS400 מוגדר עם CCSID=37, כל עוד אתם במחשב ה-AS400 שלכם הכל טוב, אך כאשר אתם מייצאים למכונה אחרת (אפילו AS400 אחר שמוגדר עם CCSID שונה) – האות א' נעלמת. אם לדייק, היא לא נעלמת, היא פשוט בלתי נראית.

אם תשנו את ה-CCSID של השדות, הקבצים או המערכת ל-424, כאשר תייצאו נתונים למערכת זרה שמוגדרת לעבוד בעברית, ה-א' תראה, ותשארו "רק" עם הבעיה של ההיפוך.

הפתרון של יבמ היה CCSID חדש, 62235, שעושה בדיוק את מה שעושים nchar(8237), nchar(8236), ואפילו טוב יותר, כי הוא לא מוסיף תווים לטקסט המקורי.

(אגב, חוץ מ-62235 יש גם 62211 ו-62245. כדי להעמיק יותר לחץ כאן).

אז למה אני פחות אוהב אותו?

  • כי הוא מסורבל. ככה נראה היפוך של שדה:
    select cast(itdesc as char(30) ccsid 62235)
  • כי הוא עובד רק מגירסא V4R4 של OS400. נכון שכבר אין הרבה מערכות עם מערכת הפעלה נמוכה יותר, אבל עדיין, אני מעדיף פתרון שלא תלוי במערכת ההפעלה אלא עובד בכל מצב.