עבודה עם ריבוי תוצאות MySQL מתוך Asterisk
-
בס"ד
אני יודע שאין פה יותר מידי מתכנתים שמתעסקים עמוק ב-DialPlan של אסטריסק,
אבל אני באמצע פרויקט עם שעון חול שאוזל, אז אמרתי אנסה את מזלי...אני ניגש למסד MySQL ישירות מתוך ה DialPlan של אסטריסק באמצעות הפקודה MySQL.
הביצוע של השאילתות שליפה / הוספה / עדכון עובד בסדר גמור*.*אבל, כאשר אני מבצע שאילתת שליפה שאמורה להחזיר יותר מתוצאה אחת,
לדוגמא: שליפה של כל המוצרים שמשוייכים לקטגוריה X,
המאפיין "Fetch" שמכניס את התוצאות למשתנים - מכניס רק את ההתאמה (השורה) הראשונה,
ואם אני חוזר שוב על ה "Fetch" הוא מכניס רק את השניה וכן הלאה,
עד ההתאמה האחרונה, ואז חזרה נוספת על ה "Fetch" תוציא שגיאה.השאלה שלי,
איך אני יכול לדעת כמה תוצאות אמורות להיות,
ובעיקר, איך אני מנווט בין התוצאות קדימה ואחורה או "תופס" התאמה ספציפית (לדוגמא, 4).אני מבין שאפשר לבצע עבודה שחורה של קוד - ולכתוב שאילתות לכל דבר:
למשל, שאילתה מקדימה שתיתן את סכום התוצאות הצפוי, ולשמור במשתנה נפרד.
או לדוגמא, לקרוא את ה-id של התוצאה הנוכחית, ובעקבותיו שאילתא חדשה שתחפש מיהו ה id שלפניו / אחריו, ואז להריץ שאילתא חדשה על ה id החדש לראות אם הוא עומד בתנאים המבוקשים.
אבל ברור שזה לא תכל'ס.האם מישהו יודע על דרך נורמלית לטייל בין ההתאמות שהתקבלו?
תודה רבה!!!
-
יש פה איזה תכנון שלא הכי מריח לי, אבל נתחיל בזה שfetch קורא ישר מהזרם שמגיע מהDB ולכן לא שייך בו אחורה, וגם כדאי "לגמור איתו" כמה שיותר מהר כדי לנקות את הקונקשיין.
בשביל לטייל אחורה על כרחך אתה צריך לשים את התוצאות במערך, שכל שלב אתה מוסיך איבר, עד לשלב בו הfetch מחזיר null.
איך עושים מערך ואיך מנווטים בו בחיה הזו? אין לי מושג ואני נורא מעריך את מתכנתי העל שמבינים את שפת החרטומים הזו. -
@איש-אחד זה dialplan קלאסי?
למה שלא תשתמש בphpagi הרבה הרבה יותר הגיוני ופשוט.דוגמא:
https://www.voip-info.org/asterisk-simple-php-lookup-mysql-database-to-set-callerid-name/עוד דוגמא
#!/usr/bin/env php <?php //echo "run"; set_time_limit(30); require('phpagi.php'); error_reporting(E_ALL); $agi = new AGI(); $agi->answer(); $cid = $agi->parse_callerid(); //$agi->say_number("$cid"); // speaks the number 1234 fwrite(STDOUT, "NOOP $cid "); fflush($agi); $ani = $agi->request['agi_callerid']; $agi->noop("My CalleID: <<<<<<<=".$ani); $agi->say_digits("1234") // fwrite(STDOUT, "SAY DIGITS 5551212 '125#'"); // fflush($agi); //saynumber("1234"); // $agi->text2wav('Goodbye'); //$agi->stream_file('vm-isunavail.gsm'); //$agi->say_number("0548486354"); // speaks the number 1234 $agi->hangup(); ?>
מאז ש"גיליתי" אותו אני עובד רק איתו.
השיחה פשוט מפנה לAGI ומשם הכל פשוט. כולל תנאים סוויצשים וכל מה שזז...
זה PHP קלאסי.אם אתה צריך עזרה בזה אז תכתוב כאן
עריכה: @איש-אחד סורי שעד שלחצתי "שלח" הספקת לכתוב את המגילה...
זה היה כתוב כבר ממזמן. רק שכחתי ללחוץ שלח... -
@dovid
תודה על התשובה!כמו שציינת בעצמך, אכן, כל תכונה מינימלית שנתמכת בשפת החרטומים הזו - זה נס,
ולצפות לתמיכה במערכים בשפה הזו, זה כנראה ישאר משאלת לב...מה גם, שלפעמים אני רוצה שאילתא גדולה, למשל, שישמיע את כל ה"מוצרים" (שורות בטבלה) אחד אחרי השני.
ולהעתיק את כל הדטהבייס קומפלט לתוך המערך - נראה לי לא יותר מידי פרקטי.עלה לי עכשיו רעיון, ואשמח לשמוע עליו ביקורת - אם מגיע לו כזאת,
כשאני כותב שאילתא, להוסיף לה LIMIT 0,2, דהיינו שישלוף עד 2 התאמות, ויתחיל מההתאמה הראשונה,
כשהערך 0 שממנו מתחילים לקבל את ההתאמות, יתקבל מתוך משתנה.
לאחר ביצוע השאילתא אני עושה סיבוב ראשון של ה "Fetch" כרגיל ומקבל את כל הערכים,
ואז אני עושה עוד סיבוב אחד של "Fetch" - רק בשביל לוודא שהוא לא NULL (דהיינו, שקיימות התאמות נוספות).
במידה ואכן קיימות התאמות נוספות,
כשאבקש לזוז קדימה / אחורה - אעדכן בהתאם את המשתנה שממנו ה LIMIT מתחיל להחזיר תוצאות,
ופשוט אבצע את השאילתא שוב, כשהפעם ה LIMIT מתחיל לשלוף את 2 ההתאמות מ -1 במקום מ - 0, וכן הלאה.מה אתם אומרים?
-
הרעיון שלך יעבוד אבל הוא קרוע מבחינת ביצועים, כבר עדיף את העבודה השחורה שרצית להימנע ממנה (שאילתה מקוננת, שהעליונה תופסת ID בתנאי ש(שאילתה-בת בודקת את זו שקטן ממנו) וכדומה). אישית אני לא חושב שזו עבודה שחורה, אבל זה ממש לא נח לחיות אם כאלה סיבוכים.
שים לב שבדוגמה הרשמית שלהם יש לולאה, כזו:
exten => 888,n(fetchrow),MYSQL(Fetch foundRow ${resultid} number) ; fetch row exten => 888,n,GotoIf($[“${foundRow}” = “1”]?done) ; leave loop if no row found exten => 888,n,NoOp(${number}) exten => 888,n,Goto(fetchrow) ; continue loop if row found exten => 888,n(done),MYSQL(Clear ${resultid})
בעיקרון כל שפת תכנות בעולם נראית בlow level ככה, אז גם אתה עם קצת ראש יכול להפיק מזה הכל.
למשל במקרה שלך תוכל לשים כל פעם את התוצאה של השורה הקודמת במשתנה בשם previusrow ולבדוק אותו. -
@dovid
בחישוב ביצועים אני לא מבין בכלל, תודה שהמלצת על דרך יותר טובה!
ו @clickone , תודה רבה גם על העזרה כאן וגם "מאחורי הקלעים"!אגב, בדוגמא שציטטת (@dovid),
היא רק ממחישה את הבעייה שלי - חוסר יכולת בניווט קדימה אחורה.
מה שקורה שם, זה בשורה הראשונה ה Fetch שומר את התוצאה במשתנה בשם number,
בשורה השלישית הוא רושם אותו בפלט של האסטריסק (ובקבצי הלוג),
ובשורה הרביעית הוא מחזיר בלופ לשורה הראשונה שבתורה דורסת את number בלי שום נקיפות מצפון... -
@איש-אחד אמר בעבודה עם ריבוי תוצאות MySQL מתוך Asterisk:
אגב, בדוגמא שציטטת (@dovid),
היא רק ממחישה את הבעייה שלי - חוסר יכולת בניווט קדימה אחורה.
מה שקורה שם, זה בשורה הראשונה ה Fetch שומר את התוצאה במשתנה בשם number,
בשורה השלישית הוא רושם אותו בפלט של האסטריסק (ובקבצי הלוג),
ובשורה הרביעית הוא מחזיר בלופ לשורה הראשונה שבתורה דורסת את number בלי שום נקיפות מצפון...אולי אני לא מרוכז, אבל לדעתי אם יש לך לולאה, ויש לך אפשרות לשמור משתנה, אין שום צורך ב"ניווט אחורה".
תן ציור תיאורטי שזה לא אפשרי. -
@dovid
נניח יש לי מערכת מכירות טלפונית עם כמות מוצרים לא קבועה,
ואני רוצה לאפשר למתקשר פשוט לשמוע את כל המוצרים לפי סדר.אני נותן שאילתא של SELECT * FROM table,
כל הטבלה קומפלט נכנסת לתוך משתנה בשם result נניח,
ואז ה Fetch עושה Parse רק לשורה הראשונה ומפריד את העמודות לתוך משתנים, לדוגמא: שם מוצר, קוד, מחיר וכדו'.
אני משמיע למתקשר את תכולת המשתנים שהתקבלה.
זהו הוא שמע. עכשיו הוא בוחר נניח ב: "למעבר למוצר הבא, הקישו X". מה אני עושה איתו?
אז למעשה, אם אני חוזר שוב פעם על אותה פעולת Fetch בדיוק בלי שום שינוי -
הוא ידרוס את הערכים הקודמים של שורה 1 ששמורים במשתנים, ובמקומם יכניס את הערכים של שורה 2.
טוב. המתקשר שמע את גם את שורה 2.
אבל הפעם המתקשר החליט לאתגר אותי ובחר ב: "לחזרה למוצר הקודם, הקישו X".
מה אני עושה איתו עכשיו? -
@איש-אחד
אם זה המקרה זה לוגיקה של דפדפוף אלא דפדוף לשם דיפדוף. לזה אין לי פתרון.אגב, ההבנה שלך שfetch סה"כ מפרסר רשומה מresult שגויה לדעתי.
בresult אין את הטבלה רק buffer - כלומר גוש הנתונים הבא. אם למשל אתה מתשאל 20,000 שורות
אתה יכול לראות שבזכות הfetch (שזה נקרא בכלל השפות forward-only cursor) הזיכרון ייראה בדיוק אותו דבר כמו עם אלף שורות.
מאותה סיבה גם אסור לסגור את הקונקשיין בטרם יתבצע הfetch האחרון. -
מעניין לעניין באותו עניין,
מה באמת כדאי - לגבי סגירת קונקשן,
כשלמעשה לאורך כל השיחה אני מבצע שאילתות,
כל תזוזה בין מוצרים / הזמנת מוצרים - אמורה לכאורה לבצע גישה לדטהבייס.
כמובן שאת ניקוי ה "result" אני חייב לבצע לפני כל ביצוע שאילתא חדשה.
אבל לגבי סגירת הקונקשן, טכנית אני יכול להגדיר שהכיבוי שלו יתבצע רק בעת ניתוק השיחה.האם עדיף לאמץ נוהל קבוע לעשות ניקוי result וסגירת קונקשן מיד בסיום כל שאילתא,
או שסגירת ופתיחת קונקשנים כל הזמן - יאטו את הביצועים כשאין בזה צורך של ממש?תודה רבה!