मैं यह कैसे निर्धारित कर सकता हूं कि PLPGSQL के साथ मौजूदा search_path में कोई तालिका मौजूद है?


10

मैं एक एप्लिकेशन के लिए एक सेटअप स्क्रिप्ट लिख रहा हूं जो किसी अन्य एप्लिकेशन के लिए एक ऐडऑन है, इसलिए मैं यह जांचना चाहता हूं कि क्या अन्य एप्लिकेशन के लिए टेबल मौजूद हैं। यदि नहीं, तो मैं उपयोगकर्ता को एक उपयोगी त्रुटि देना चाहता हूं। हालाँकि, मुझे नहीं पता कि स्कीमा क्या तालिकाओं को धारण करेगा।

DO LANGUAGE plpgsql $$
BEGIN
    PERFORM 1
    FROM
        pg_catalog.pg_class c
        JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
    WHERE
        n.nspname = current_setting('search_path')
        AND c.relname = 'foo'
        AND c.relkind = 'r'; -- not sure if I actually need this or not...

    IF NOT FOUND THEN
        RAISE 'This application depends on tables created by another application';
    END IF;
END;
$$;

हालाँकि, डिफ़ॉल्ट रूप से current_setting('search_path')एक TEXT देता है "$user",public, जो बहुत उपयोगी नहीं है।

केवल एक चीज जो मैं सोच सकता हूं, वह है टेबल से चयन करने की कोशिश करना और अपवाद को पकड़ना। यह काम करेगा, लेकिन मुझे नहीं लगता कि यह बहुत ही सुरुचिपूर्ण है और मैंने पढ़ा है कि इसका उपयोग करना महंगा है (हालांकि शायद इस परिदृश्य में यह ठीक होगा क्योंकि मैं केवल इसे एक बार चला रहा हूं?)।

जवाबों:


18

जल्दी और गन्दी

Postgres में 9.4+ का उपयोग करें

SELECT to_regclass('foo');

यदि खोजकर्ता को खोज पथ में नहीं मिला है तो NULL लौटाता है।
पोस्टग्रैज में 9.3 या पुराने कास्ट काregclass उपयोग करें :

SELECT 'foo'::regclass;

यह एक अपवाद उठाता है , अगर ऑब्जेक्ट नहीं मिला है!

यदि 'foo'पाया जाता है, तो oidउसके textप्रतिनिधित्व में लौटा दिया जाता है । यह सिर्फ टेबल का नाम है, वर्तमान खोज पथ के अनुसार स्कीमा-योग्य और जहां आवश्यक हो, दोहरे-उद्धृत।

यदि ऑब्जेक्ट नहीं मिला है, तो आप सुनिश्चित कर सकते हैं कि यह खोज पथ में कहीं भी मौजूद नहीं है - या स्कीमा-योग्य नाम ( schema.foo) के लिए बिल्कुल भी नहीं ।

यदि यह पाया जाता है कि दो कमियाँ हैं :

  1. खोज में खोज_पथ के निहित स्कीमा शामिल हैं , अर्थात् pg_catalogऔरpg_temp । लेकिन आप अपने उद्देश्य के लिए अस्थायी और सिस्टम तालिकाओं को बाहर करना चाह सकते हैं। (?)

  2. regclassसिस्टम कैटलॉग में सभी ऑब्जेक्ट्स के लिए काम करने के लिए एक कास्ट pg_class: इंडेक्स, व्यूज, सीक्वेंस आदि। न सिर्फ टेबल। आप विशेष रूप से एक नियमित तालिका की तलाश में हैं। हालाँकि, आपको शायद इसी नाम की अन्य वस्तुओं से भी समस्या होगी। विवरण:

धीमा और पक्का

हम आपकी क्वेरी पर वापस आ गए हैं, लेकिन उपयोग नहीं करते हैं current_setting('search_path'), जो नंगे सेटिंग को लौटाता है। समर्पित सिस्टम सूचना फ़ंक्शन का उपयोग करें current_schemas()। प्रति प्रलेखन:

current_schemas(boolean) name[]
खोज पथ में स्कीमा के नाम, वैकल्पिक रूप से निहित स्कीमा सहित

"$user"खोज पथ में स्मार्ट तरीके से हल किया गया है। यदि कोई स्कीमा SESSION_USERमौजूद नहीं है, तो स्कीमा को शुरू करने के लिए वापस नहीं किया जाता है। इसके अलावा, आप वास्तव में क्या चाहते हैं, इसके आधार पर, आप इसके अलावा स्कीमा ( pg_catalogऔर संभवतः pg_temp) आउटपुट निकाल सकते हैं - लेकिन मुझे लगता है कि आप उन मामलों को हाथ में नहीं लेना चाहते हैं, इसलिए उपयोग करें:

DO 
$do$
BEGIN
   IF EXISTS (
      SELECT  -- list can be empty
      FROM   pg_catalog.pg_class c
      JOIN   pg_catalog.pg_namespace n ON n.oid = c.relnamespace
      WHERE  n.nspname = ANY(current_schemas(FALSE))
      AND    n.nspname NOT LIKE 'pg_%'  -- exclude system schemas!
      AND    c.relname = 'foo'
      AND    c.relkind = 'r')           -- you probably need this
   THEN
      RAISE 'This application depends on tables created by another application';
   END IF;
END
$do$;

एसक्यूएल फिडल , अंतिमDOविवरणको छोड़कर सभी को प्रदर्शित करता है।
एसक्यूएल फेल्ड (JDBC) में DOसमाप्ति वर्णों वाले कथनों की समस्या है ।


1

आप कॉन्फ़िगरेशन मान को एक सरणी में बदल सकते हैं और $userवर्तमान उपयोगकर्ता नाम के साथ बदल सकते हैं। तब सरणी का उपयोग उस स्थिति में किया जा सकता है:

where n.nspname = any(string_to_array(replace(current_setting('search_path'), '$user', current_user), ','))

0
./sshi.sh vb20deployment controller <<'HERE'
export PGPASSWORD="postgres"
cd logu/postgresql/bin
row=1
tableArray=(table1 table2 table3 table4 table5 table6)

for (( x=0 ; x<=5 ; x++)) ; do        

./psql.bin --port=5432 --username=postgres --host=hostname.rds.amazonaws.com --dbname=mydb -c "SELECT * FROM information_schema.tables WHERE '${tableArray[$x]}' = table_name" | while read -a Record ; do
  row=$((row + 1))
  if [[ $row -gt 3 ]]; then

     echo ${Record[4]}

   fi
done

done


HERE
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.