PL / pgSQL में मैन्युअल रूप से उठाए गए अपवाद के लिए अपवाद संदर्भ कैसे प्राप्त करें?


11

Postgres में, हमें इस कोड का उपयोग करके अपवादों का "स्टैक ट्रेस" मिलता है:

EXCEPTION WHEN others THEN
    GET STACKED DIAGNOSTICS v_error_stack = PG_EXCEPTION_CONTEXT;

यह "प्राकृतिक" अपवादों के लिए ठीक काम करता है, लेकिन अगर हम एक अपवाद का उपयोग करते हैं

RAISE EXCEPTION 'This is an error!';

... तो कोई स्टैक ट्रेस नहीं है। एक मेलिंग सूची प्रविष्टि के अनुसार , यह जानबूझकर हो सकता है, हालांकि मैं अपने जीवन के लिए यह पता नहीं लगा सकता कि क्यों। यह मुझे उपयोग करने के अलावा एक अपवाद फेंकने के लिए एक और तरीका जानने की इच्छा रखता है RAISE। क्या मुझे कुछ स्पष्ट याद आ रहा है? क्या किसी को इसके लिए एक चाल है? क्या ऐसा कोई अपवाद है जिसे मैं फेंकने के लिए पोस्टग्रैस प्राप्त कर सकता हूं जिसमें मेरे चयन की एक स्ट्रिंग होगी, ताकि मुझे त्रुटि संदेश में न केवल मेरी स्ट्रिंग मिल जाए, बल्कि पूर्ण स्टैक ट्रेस भी हो जाए?

यहाँ एक पूर्ण उदाहरण है:

CREATE OR REPLACE FUNCTION error_test() RETURNS json AS $$
DECLARE
    v_error_stack text;
BEGIN

    -- Comment this out to see how a "normal" exception will give you the stack trace
    RAISE EXCEPTION 'This exception will not get a stack trace';

    -- This will give a divide by zero error, complete with stack trace
    SELECT 1/0;

-- In case of any exception, wrap it in error object and send it back as json
EXCEPTION WHEN others THEN

    -- If the exception we're catching is one that Postgres threw,
    -- like a divide by zero error, then this will get the full
    -- stack trace of the place where the exception was thrown.
    -- However, since we are catching an exception we raised manually
    -- using RAISE EXCEPTION, there is no context/stack trace!
    GET STACKED DIAGNOSTICS v_error_stack = PG_EXCEPTION_CONTEXT;

    RAISE WARNING 'The stack trace of the error is: "%"', v_error_stack;

    return to_json(v_error_stack);
END;
$$ LANGUAGE plpgsql;

यहां एक सरल उदाहरण दिखाना एक अच्छा विचार हो सकता है।
क्रेग रिंगर

अच्छी बात @CraigRinger। किया हुआ!
तय्ये

यह स्व-निहित नहीं है। क्या है error_info? एक कस्टम प्रकार की तरह दिखता है।
क्रेग रिंगर

क्षमा करें - सोचा था कि आप सिर्फ सामान्य संदर्भ चाहते थे। मैंने बाहरी सामान हटा दिया है।
तय्ये

जवाबों:


9

यह व्यवहार डिज़ाइन द्वारा प्रतीत होता है।

में src/pl/plpgsql/src/pl_exec.cत्रुटि संदर्भ कॉलबैक स्पष्ट रूप से जाँच करता है देखने के लिए अगर यह एक PL / pgSQL के संदर्भ में कहा जाता है की जा रही RAISEबयान और, यदि हां, त्रुटि संदर्भ उत्सर्जक स्किप:

/*
 * error context callback to let us supply a call-stack traceback
 */
static void
plpgsql_exec_error_callback(void *arg)
{
        PLpgSQL_execstate *estate = (PLpgSQL_execstate *) arg;

        /* if we are doing RAISE, don't report its location */
        if (estate->err_text == raise_skip_msg)
                return;

मुझे ऐसा कोई विशेष संदर्भ नहीं मिल रहा है कि ऐसा क्यों है।

सर्वर में आंतरिक रूप से, संदर्भ स्टैक को संसाधित करके उत्पन्न किया जाता है error_context_stack, जो एक जंजीर कॉलबैक है जो किसी सूची में जानकारी को कॉल करता है जब कहा जाता है।

जब PL / PgSQL एक फ़ंक्शन में प्रवेश करता है, तो यह त्रुटि संदर्भ कॉलबैक स्टैक में एक आइटम जोड़ता है। जब यह एक फ़ंक्शन छोड़ता है तो यह उस स्टैक से एक आइटम निकालता है।

यदि PostgreSQL सर्वर की त्रुटि रिपोर्टिंग कार्य, जैसे ereportया elogकहे जाते हैं, तो यह त्रुटि संदर्भ कॉलबैक कहलाता है। लेकिन PL / PgSQL में अगर यह नोटिस करता है कि इसे RAISEइसके कॉलबैक से बुलाया जा रहा है तो जानबूझकर कुछ नहीं करें।

यह देखते हुए कि, PostgreSQL को पैच किए बिना आपको प्राप्त करने का कोई तरीका नहीं दिखता है। मैं pgsql- जनरल से मेल पोस्ट करने का सुझाव देता हूं कि RAISEत्रुटि संदर्भ अब क्यों नहीं प्रदान करता है कि PL / PgSQL को GET STACKED DIAGNOSTICSइसका उपयोग करना है।

(बीटीडब्लू, अपवाद संदर्भ इस तरह से स्टैक ट्रेस नहीं है। यह थोड़ा सा दिखता है क्योंकि पीएल / पीजीक्यूएल प्रत्येक फ़ंक्शन कॉल को स्टैक में जोड़ता है, लेकिन इसका उपयोग सर्वर में अन्य विवरणों के लिए भी किया जाता है।)


त्वरित और गहन उत्तर के लिए बहुत बहुत धन्यवाद क्रेग। यह मुझे अजीब लगता है, और निश्चित रूप से मेरी उम्मीदों का मुकाबला करता है। RAISEउस जाँच से इसकी उपयोगिता कम हो जाती है। मैं उन्हें लिखूंगा।
तैतई

@Taytay कृपया यहां अपने प्रश्न का लिंक शामिल करें, लेकिन सुनिश्चित करें कि आपका मेल पूरा हो गया है और लिंक का पालन किए बिना इसे समझा जा सकता है ; कई लोग लिंक-ओनली या लिंक-ज्यादातर पोस्ट्स को नजरअंदाज करते हैं। अगर आपको यहां अभिलेखों में अपनी पोस्ट का लिंक पॉप करने का मौका मिलता है, तो archives.postgresql.org के माध्यम से, जो बाद में अन्य लोगों की मदद करने के लिए वास्तव में भयानक होगा।
क्रेग रिंगर

धन्यवाद क्रेग। अच्छी सलाह। मैंने यहां एक धागा बनाया: postgresql.org/message-id/… अब, वे इस मुद्दे का एक अच्छा समाधान ढूंढ रहे हैं।
तैतई

6

आप इस प्रतिबंध के इर्द-गिर्द काम कर सकते हैं और एक और फ़ंक्शन को कॉल करके वांछित के रूप में plpgsql emit त्रुटि संदर्भ बना सकते हैं (चेतावनी, नोटिस, ...) आपके लिए त्रुटि।

मैंने इसके लिए कुछ साल पहले एक समाधान पोस्ट किया था - यहाँ मेरी पहली पोस्ट में dba.SE पर :

-- helper function to raise an exception with CONTEXT
CREATE OR REPLACE FUNCTION f_raise(_lvl text = 'EXCEPTION'
                                  ,_msg text = 'Default error msg.')
  RETURNS void AS
$func$
BEGIN
   CASE upper(_lvl)
      WHEN 'EXCEPTION' THEN RAISE EXCEPTION '%', _msg;
      WHEN 'WARNING'   THEN RAISE WARNING   '%', _msg;
      WHEN 'NOTICE'    THEN RAISE NOTICE    '%', _msg;
      WHEN 'DEBUG'     THEN RAISE DEBUG     '%', _msg;
      WHEN 'LOG'       THEN RAISE LOG       '%', _msg;
      WHEN 'INFO'      THEN RAISE INFO      '%', _msg;
      ELSE RAISE EXCEPTION 'f_raise(): unexpected raise-level: "%"', _lvl;
   END CASE;
END
$func$  LANGUAGE plpgsql STRICT;

विवरण:

मैंने अपने पोस्ट किए गए परीक्षण मामले को विस्तारित करने के लिए इसे पोस्टग्रेज 9.3 में काम करता है:

एसक्यूएल फिडल।


बहुत बहुत धन्यवाद इरविन! पर्याप्त रूप से, मैंने वास्तव में पोस्ट करने से पहले आपके समाधान के साथ प्रयोग किया था, लेकिन मैंने कुछ गलत किया होगा और मुझे वह संदर्भ नहीं मिला जिसकी मुझे उम्मीद थी। अब जब मैंने फ़िडल देखा है (मुझे दिखाने के लिए धन्यवाद), तो मैं इसे एक और शॉट दूंगा!
तैत्तिल

अच्छी तरह से किया; यह आवश्यक नहीं होना चाहिए, लेकिन ऐसा लगता है कि यह चाल चलेगा।
क्रेग रिंगर

@ क्रेगिंगर: चूंकि अपवाद होना चाहिए, ठीक है, अपवाद , न्यूनतम प्रदर्शन प्रभाव कोई फर्क नहीं पड़ता, या तो। हमारे पास इस तरह से सभी विकल्प हैं।
इरविन ब्रान्डेसटेटर

पूरी तरह से सहमत हूँ, मैं बस कुछ बिंदु पर दूर जाना चाहिए समाधान की जरूरत देखना चाहते हैं।
क्रेग रिंगर

@ क्रेगिंगर: सच। अगर जल्द ही ऐसा नहीं होने वाला है, तो हम मैनुअल में इस वर्कअराउंड का सुझाव दे सकते हैं ...
Erwin Brandstetter
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.