একটি টেবিলের মধ্যে একটি সূত্র সঞ্চয় করুন এবং একটি ফাংশনে সূত্রটি ব্যবহার করুন


10

আমার একটি পোস্টগ্রিসকিউএল 9.1 ডাটাবেস রয়েছে যেখানে এর কিছু অংশ এজেন্ট কমিশন পরিচালনা করে। প্রতিটি এজেন্টের তার নিজস্ব হিসাবের সূত্র রয়েছে যে তারা কত কমিশন পাবে। প্রতিটি এজেন্টকে যে পরিমাণ কমিশন পাওয়া উচিত তা তৈরি করার জন্য আমার একটি ফাংশন রয়েছে তবে এজেন্টের সংখ্যা বাড়ার সাথে সাথে এটি ব্যবহার করা অসম্ভব হয়ে উঠছে। আমি কিছু দীর্ঘ ক্ষেত্রে স্টেটমেন্ট এবং পুনরাবৃত্তি কোড করতে বাধ্য হই, যা আমার ফাংশনটিকে খুব বড় করে তুলেছে।

সমস্ত সূত্রে ধ্রুবক পরিবর্তনশীল রয়েছে:

d .. দিনগুলি সে মাসে কাজ করেছিল
r .. নতুন নোড দ্বারা সঞ্চিত
l .. আনুগত্য স্কোর
s .. সাবজেন্ট কমিশন
খ .. বেস হার
i .. আয় হয়েছে

সূত্রটি এমন কিছু হতে পারে:

d*b+(l*4+r)+(i/d)+s

প্রতিটি এজেন্ট এইচআর অধিদপ্তরের সাথে অর্থ প্রদানের সূত্রটি নিয়ে আলোচনা করে। সুতরাং আমি সূত্রটি এজেন্ট টেবিলের মধ্যে সংরক্ষণ করতে পারি তারপরে একটি ছোট ফাংশনের মতো থাকতে হবে যা কেবল টেবিল থেকে সূত্রটি পেয়ে যায় এবং এটির সাথে অনুবাদ করে পরিমাণ এবং পরিমাণ গণনা করে?

উত্তর:


6

প্রস্তুত করা

আপনার সূত্রগুলি দেখতে এইরকম:

d*b+(l*4+r)+(i/d)+s

আমি ভেরিয়েবলগুলি $nস্বরলিপি সহ প্রতিস্থাপন করব যাতে সেগুলি সরাসরি plpgsql এ মানগুলির সাথে প্রতিস্থাপন করা যায় EXECUTE(নীচে দেখুন):

$1*$5+($3*4+$2)+($6/$1)+$4

আপনি আপনার মূল সূত্রগুলি অতিরিক্তভাবে (মানব চোখের জন্য) সঞ্চয় করতে পারেন বা এই রূপটি গতিশীলভাবে একটি এক্সপ্রেশন দিয়ে তৈরি করতে পারেন:

SELECT regexp_replace(regexp_replace(regexp_replace(
       regexp_replace(regexp_replace(regexp_replace(
      'd*b+(l*4+r)+(i/d)+s'
      , '\md\M', '$1', 'g')
      , '\mr\M', '$2', 'g')
      , '\ml\M', '$3', 'g')
      , '\ms\M', '$4', 'g')
      , '\mb\M', '$5', 'g')
      , '\mi\M', '$6', 'g');

কেবল নিশ্চিত করুন, আপনার অনুবাদটি দুর্দান্ত। Regexp এক্সপ্রেশন জন্য কিছু ব্যাখ্যা :

\ এম .. শব্দের শুরুতে কেবল মিল হয়
\ এম .. কেবল একটি শব্দের শেষে মেলে

চতুর্থ প্যারামিটার 'g'.. বিশ্বব্যাপী প্রতিস্থাপন করুন

কোর ফাংশন

CREATE OR REPLACE FUNCTION f_calc(
    d int         --  days worked that month
   ,r int         --  new nodes accuired
   ,l int         --  loyalty score
   ,s numeric     --  subagent commission
   ,b numeric     --  base rate
   ,i numeric     --  revenue gained
   ,formula text
   ,OUT result numeric
)  RETURNS numeric AS
$func$
BEGIN    
   EXECUTE 'SELECT '|| formula
   INTO   result
   USING  $1, $2, $3, $4, $5, $6;                                          
END
$func$ LANGUAGE plpgsql SECURITY DEFINER IMMUTABLE; 

কল করুন:

SELECT f_calc(1, 2, 3, 4.1, 5.2, 6.3, '$1*$5+($3*4+$2)+($6/$1)+$4');

রিটার্নস:

29.6000000000000000

প্রধান পয়েন্ট

  • ফাংশনটি 6 মান পরামিতি এবং formula text7 তম হিসাবে নেয় । আমি সূত্রটি শেষ রেখেছি, সুতরাং আমরা $1 .. $6পরিবর্তে ব্যবহার করতে পারি $2 .. $7। কেবল পঠনযোগ্যতার খাতিরে।
    আমি মান হিসাবে মান হিসাবে ডেটা টাইপ নিযুক্ত। যথাযথ ধরণের (বেসিক স্যানিটি চেক বাস্তবায়নের জন্য) বরাদ্দ করুন বা সেগুলি কেবল তৈরি করুন numeric:

  • USINGধারাটি সহ গতিশীল সম্পাদনের জন্য মানগুলিতে পাস করুন । এটি পিছনে পিছনে ingালাই এড়ানো এবং সবকিছুকে সহজ, নিরাপদ এবং দ্রুত করে তোলে।

  • আমি একটি OUTপ্যারামিটার ব্যবহার করি কারণ এটি আরও মার্জিত এবং আরও কম সংক্ষিপ্ততর সিনট্যাক্স তৈরি করে। একটি চূড়ান্ত RETURNপ্রয়োজন হয় না, আউট প্যারামিটার (গুলি) এর মান স্বয়ংক্রিয়ভাবে ফিরে আসে।

  • ম্যানুয়ালটিতে @ ক্রিস দ্বারা সুরক্ষা সম্পর্কিত বক্তৃতা এবং " সিকিউরিটি ডিফাইনার ফাংশনগুলি নিরাপদে লেখা" অধ্যায়টি বিবেচনা করুন । আমার ডিজাইনে, ইনজেকশনটির একক পয়েন্ট হ'ল সূত্রটি।

  • কলটি আরও সহজ করার জন্য আপনি কিছু পরামিতিগুলির জন্য ডিফল্ট ব্যবহার করতে পারেন ।


5

সুরক্ষা বিবেচনার বিষয়ে দয়া করে এটি সাবধানে পড়ুন। মূলত আপনি আপনার কার্যগুলিতে স্বেচ্ছাসেবী এসকিউএল ইনজেক্ট করার চেষ্টা করছেন। ফলস্বরূপ আপনার অত্যন্ত সীমাবদ্ধ অনুমতি সহ কোনও ব্যবহারকারীর অধীনে এই রান করা দরকার।

  1. একটি ব্যবহারকারী তৈরি করুন এবং এটি থেকে সমস্ত অনুমতি প্রত্যাহার করুন। আপনি যেমন করেন তেমন ডিবিতে জনসাধারণকে অনুমতি প্রদান করবেন না।

  2. ভাবটি মূল্যায়ন করতে একটি ফাংশন তৈরি করুন, এটি তৈরি করুন security definerএবং সেই সীমাবদ্ধ ব্যবহারকারীর মালিককে পরিবর্তন করুন ter

  3. এক্সপ্রেশনটি প্রসেস করুন এবং তারপরে এটিকে উপরে তৈরি করা ইওল () ফাংশনে সরিয়ে দিন। আপনার যদি প্রয়োজন হয় তবে আপনি অন্য ফাংশনে এটি করতে পারেন,

আবার নোট করুন, এটিতে গুরুতর সুরক্ষা জড়িত রয়েছে।

সম্পাদনা করুন: সংক্ষিপ্ত নমুনা কোড (স্বাক্ষরিত তবে ডক্স অনুসরণ করলে আপনাকে সেখানে পাওয়া উচিত):

CREATE OR REPLACE FUNCTION eval_numeric(text) returns numeric language plpgsql security definer immutable as
$$
declare retval numeric;
begin

execute $e$ SELECT ($1)::numeric$e$ into retval;
return retval;
end;
$$;

ALTER FUNCTION eval_numeric OWNER TO jailed_user;

CREATE OR REPLACE FUNCTION foo(expression text, a numeric, b numeric) returns numeric language sql immutable as $$
select eval(regexp_replace(regexp_replace($1, 'a', $2, 'g'), 'b', '$3', 'g'));
$$; -- can be security invoker, but eval needs to be jailed.

"এটিকে সুরক্ষা নিশ্চিত করুন" সত্যিই বিভ্রান্তিকর, আপনি কি ব্যাখ্যা করতে পারেন?
jcolebrand

1
PostgreSQL এর দুটি সুরক্ষা মোড রয়েছে যা কোনও ফাংশন চলতে পারে। সিকিউরিটি ইনভোকার ডিফল্ট। সিকিউরিটি ডিফাইনারের অর্থ "ফাংশনের মালিকের সুরক্ষা প্রসঙ্গে" চালানো "সাজানো যেমন * নিক্সের SETUID বিটের মতো। কোনও ক্রিয়াকলাপকে সুরক্ষার সুনির্দিষ্ট করে তুলতে আপনি এটি ফাংশন ঘোষণায় ( CREATE FUNCTION foo(text) returns text IMMUTABLE LANGUAGE SQL SECURITY DEFINER AS $$...) বা এটি করতে পারেনALTER FUNCTION foo(text) SECURITY DEFINER
ক্রিস ট্র্যাভার্স

ওহ, সুতরাং নির্দিষ্ট পিজি লিনো। Gotcha।
কাঁদা

@ ক্রিসট্রেভারগুলি আমি একটি সূত্রের মূল্যায়ন করার জন্য কিছু নমুনা কোডের প্রত্যাশা করছিলাম অর্থাত a+bএকটি টেবিলের মধ্যে একটি পাঠ্য টাইপ কলামে সঞ্চিত আছে foo(a int, b int,formula text)তবে সূত্রটি যদি একটি + বি হয় তবে আমি কীভাবে ফাংশনটি পরিবর্তে একটি + বি করতে পারি? আমার সমস্ত সম্ভাব্য সূত্রের জন্য খুব দীর্ঘ ক্ষেত্রে বিবৃতি থাকতে হবে এবং সমস্ত বিভাগে কোডটি পুনরাবৃত্তি করতে হবে?
ইন্দাগো

1
@ ইন্দাগো, আমি মনে করি আপনি সুরক্ষা উদ্বেগের কারণে এটি দুটি স্তরে বিভক্ত করতে চান। প্রথমটি হ'ল একটি অন্তরঙ্গকরণ স্তর। এটি করার জন্য আপনি পোস্টগ্রিজ এসকিউএলে রেজিক্সগুলি ব্যবহার করতে পারেন। নিম্ন স্তরে, আপনি মূলত এটি জেলযুক্ত এসকিউএল ফাংশনে চালাচ্ছেন। আপনি যদি এটি করতে যাচ্ছেন তবে আপনাকে অবশ্যই সত্যিকারের দিকে খুব ঘনিষ্ঠ মনোযোগ দিতে হবে এবং আপনাকে ফিরে আসার মানগুলিতেও গভীর মনোযোগ দিতে হবে। আরও অনেক কিছু না জেনে সামোপল কোড সহ অনেক কিছু করা কঠিন তবে উত্তরটি সংশোধন করবে।
ক্রিস ট্র্যাভারস

2

কেবলমাত্র সূত্রটি সংরক্ষণ এবং তার সম্পাদন করার বিকল্প (যা ক্রিস হিসাবে উল্লেখ করা হয়েছে, সুরক্ষার সমস্যা রয়েছে ) নামক একটি পৃথক টেবিল formula_stepsথাকতে হবে যার মূলত ভেরিয়েবল এবং অপারেটর এবং সেগুলি চালানো হবে এমন ক্রম থাকবে। এটি কিছুটা বেশি কাজ হবে তবে এটি আরও সুরক্ষিত হবে। টেবিলটি দেখতে এমন হতে পারে:

formula_steps
-------------
  formula_step_id
  সূত্র_আইডি (এফকে, এজেন্টস টেবিল দ্বারা রেফারেন্স)
  INPUT_1
  INPUT_2
  অপারেটর (যদি আপনি সরাসরি অপারেটর প্রতীক সংরক্ষণ করতে না চান তবে অনুমোদিত অপারেটরগুলির একটি সারণির আইডিও হতে পারে)
  ক্রম

আর একটি বিকল্প গাণিতিক এক্সপ্রেশন মূল্যায়নের জন্য কিছু তৃতীয় পক্ষের গ্রন্থাগার / সরঞ্জাম ব্যবহার করা হবে। এটি আপনার ডাটাবেসকে এসকিউএল ইঞ্জেকশনের জন্য কম দুর্বল করে তুলবে, তবে এখন আপনি সম্ভাব্য সুরক্ষা সমস্যাগুলি কেবল আপনার বাহ্যিক সরঞ্জামে স্থানান্তরিত করেছেন (যা এখনও নিরাপদ হতে পারে)।


চূড়ান্ত বিকল্পটি হ'ল গাণিতিক অভিব্যক্তিগুলির মূল্যায়ন করে এমন একটি পদ্ধতি লিখতে (বা ডাউনলোড করা)। এই সমস্যার জন্য পরিচিত অ্যালগরিদম রয়েছে, সুতরাং অনলাইনে তথ্য খুঁজে পাওয়া শক্ত হওয়া উচিত নয়।


1
তৃতীয় বিকল্পের জন্য +1। যদি সমস্ত সম্ভাব্য ইনপুটগুলি জানা থাকে তবে হার্ড ইনডুটগুলির প্রত্যেকটির একটি নির্বাচন করুন এবং পাঠ্য হিসাবে সঞ্চিত সূত্রে তাদের (যদি এবং প্রয়োজন হিসাবে) প্রতিস্থাপন করেন তবে পাটিগণিতের মূল্যায়নের জন্য একটি লাইব্রেরি রুটিন ব্যবহার করুন। এসকিউএল ইঞ্জেকশন ঝুঁকি নিরসন।
জোয়েল ব্রাউন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.