কীভাবে শর্তাধীনভাবে একটি পিএসকিএল স্ক্রিপ্ট বন্ধ করা যায় (একটি ভেরিয়েবল মানের উপর ভিত্তি করে)?


10

আসুন নীচের উদাহরণটি বিবেচনা করুন (একটি পিএসকিএল স্ক্রিপ্টের শুরু থেকে):

\c :db_to_run_on

TRUNCATE the_most_important_table;
-- tried to avoid similarities to anything that exists out there

এখন যদি এটি কমান্ড দ্বারা এটি চালানো হয়

psql [connection details] -v db_to_run_on=\'dev_database\'

তাহলে এটি কেবল চালায় এবং ব্যবহারকারী খুশি হন। কিন্তু যদি তিনি (গুলি) নির্দিষ্ট করার সিদ্ধান্ত নেন -v db_to_run_on=production_database? (আসুন ধরে নিই যে এটি ঘটতে পারে, ঠিক যেমন লোকেরা rm -rf / # don't try this at home!!!দারুণভাবে চালায় run ) আশা করি সেই টেবিলটির একটি নতুন ব্যাকআপ রয়েছে ...

সুতরাং প্রশ্ন উঠেছে: স্ক্রিপ্টে পাস হওয়া ভেরিয়েবলগুলি কীভাবে পরীক্ষা করবেন এবং তাদের মানের উপর ভিত্তি করে আরও প্রক্রিয়াজাতকরণ বন্ধ করবেন?

উত্তর:


13

একটি বিকল্প রয়েছে psqlযাতে ত্রুটিযুক্ত আদেশগুলি কার্যকর করা বন্ধ করে দেয়, এটি ON_ERROR_STOP। আমরা যদি কোনওভাবে কোনও ত্রুটি বাড়িয়ে তুলতে পারি তবে এটি আমাদের যা চায় তা করবে।

সমস্যাটি হ'ল আমাদের ভেরিয়েবলটি পরীক্ষা করতে হবে এবং কোনওভাবে ত্রুটি তৈরি করতে হবে। যেহেতু কেউ কন্ট্রোল স্ট্রাকচার psql(কারণ কোনও নেই) * ব্যবহার করতে পারে না , তাই আমার একমাত্র ধারণা ছিল এসকিউএল পরীক্ষার জন্য ব্যবহার করা। ভাল, শর্তাধীন ত্রুটি তৈরি করা এমন কিছু যা pl/pgsqlযথেষ্ট ভাল, তাই আমি একটি ফাংশন লিখেছিলাম যা একটি ত্রুটি তৈরি করবে। আমি এখন একটি সাধারণ CASEকাঠামো থেকে এই ফাংশনটি কল করতে পারি । একটি সহজ উদাহরণ:

-- let's assume for clarity that there is no function with this name in the database
CREATE OR REPLACE FUNCTION error_generator()
RETURNS boolean AS
$body$
BEGIN
    RAISE 'Meaningful error message here';
    RETURN FALSE; -- just for aesthetical purposes
END;
$body$
LANGUAGE plpgsql;

\set ON_ERROR_STOP on

BEGIN;

-- test for the variable value
-- notice that if :var is not set, it fails as well (with a syntax error)
SELECT CASE WHEN 1 = :var THEN error_generator() ELSE TRUE END;

INSERT INTO test_table (integer_value, text_value)
VALUES (:var, 'something');

COMMIT;

*: আপনি শেলের পরে \!এবং শর্তসাপেক্ষে যে কোনও শেল কমান্ড ব্যবহার করতে পারেন , তবে যেহেতু \!একটি নতুন শেল খোলে, সেখানে যে কোনও কিছু কার্যকর করার ফলে বর্তমানের পিএসকিএল স্ক্রিপ্টের কোনও প্রভাব নেই।


\set ON_ERROR_STOP on- সুন্দর!
এমএসসিওউজ

5

পোস্টগ্রিএসকিউএল 10

পোস্টগ্রিএসকিউএল 10 পিএসকিএল-এ শর্তযুক্ত করে। এটি আর কোনও সমস্যা নয় is

\if :db_to_run_on = 'dev_database'
  TRUNCATE the_most_important_table;
\endif

আমার ধারণা আপনিও এটি ব্যবহার করতে পারেন DO..

\if :db_to_run_on != 'dev_database'
do $$
  BEGIN
    RAISE 'Meaningful error message here';
  END;
$$ LANGUAGE plpgsql;
\endif

... আপনি পোস্টগ্র্রেএসকিউএল 10 চালিয়ে যাচ্ছেন তা আর সমস্যা নেই
স্টিভ বেনেট

1
@ স্টেভবেনেট এটি সম্পর্কে খুব পরিষ্কার। তবে আমি মনে করি এটি সম্পূর্ণ সত্য নয়। আপনার শুধুমাত্র 10 সংস্করণে পিএসকিএল প্রয়োজন, সার্ভার ব্যাকএন্ড নয়।
ইভান ক্যারল

ওহ, এটি আকর্ষণীয়। তবে হ্যাঁ, পুরানো সংস্করণগুলি খুব দীর্ঘ সময় ধরে থাকতে পারে।
স্টিভ বেনেট

আপনি \set ON_ERROR_STOP 1এবং তারপরে \if yes \endifপিএসকিএল সংস্করণ 10 বা ততোধিক প্রয়োজন হতে পারে। :) (পূর্ববর্তী সংস্করণগুলি \ifঅবৈধ হওয়ার বিষয়ে অভিযোগ করবে এবং তারপরে ছেড়ে দেবে))
ওয়াইল্ডকার্ড ২৩'১৮

1

আমার জন্য যা আমি খুব ভাল কাজ করেছি তা হ'ল এসকিউএল ফাইল তৈরি করতে একটি স্ক্রিপ্টিং ভাষা ব্যবহার করা যা আমি তারপরে পিএসকিএল-তে পাইপ করি, এরকম কিছু:

#!/usr/bin/env ruby

raise "Not a good database name: #{ARGV.first.inspect}" unless ARGV.first =~ /^(dev|test)/

puts "\\timing off"
puts "set client_min_messages='warning';"
puts
puts "TRUNCATE the_most_important_table;"
puts "-- more commands"

তারপরে, আমি ড্রাইভার স্ক্রিপ্ট থেকে এটি কল করেছি:

#!/bin/bash
/usr/bin/ruby generator ${1} | /usr/bin/psql --dbname=${1} --file=- --single-transaction

আমার ড্রাইভার স্ক্রিপ্টটি সাধারণত একটি রেক ফাইল হয় তবে আপনি ধারণাটি পাবেন।


2
হ্যাঁ ঠিক. আমি এটি পেয়েছি :) আমি আপনার ইনপুটটির প্রশংসা করার সময়, এটি হ'ল আমি এড়াতে চাই - একটি অতিরিক্ত স্তর ব্যবহার করে।
dezso

1

দেজোর উত্তরের আরও সংক্ষিপ্ত সংস্করণ:

CREATE OR REPLACE FUNCTION pg_temp.err(msg varchar) RETURNS boolean     
AS $$ BEGIN RAISE '%',msg; END; $$ LANGUAGE plpgsql;

এরপরে আপনি এটিকে কল করতে পারেন:

\set ON_ERROR_STOP on

SELECT CASE WHEN (
  SELECT COUNT(*) FROM mytable
) > 0 THEN pg_temp.err('Already loaded') END;
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.