استخدام المعلمات في استعلامات مستكشف البيانات

تُعدّ المعاملات (Parameters) أداة قوية يمكن استخدامها في استعلامات Data Explorer على Discourse. تتيح المعاملات تنفيذ استعلامات أكثر ديناميكية وتخصيصاً، فبدلاً من تثبيت القيم داخل استعلاماتك، يمكنك إعلان متغيرات ستطلب إدخال قيمتها عند تشغيل الاستعلام.

إعلان معامل

لإعلان معامل، يمكنك استخدام الصياغة التالية:

-- [params]
-- int :parameter_name = 10

سيبدأ قسم المعاملات في الاستعلام دائماً بـ -- [params]، يليه نوع كل معامل في سطر جديد، حيث يتم استبدال parameter_name باسم المعامل الذي تريده.

سيؤدي هذا إلى إنشاء حقل يمكنك من خلاله إدخال قيم مختلفة في كل مرة تشغّل فيها الاستعلام.

أنواع المعاملات

عند إعلان المعاملات في استعلامات Data Explorer الخاصة بك، يمكنك تحديد أنواع مختلفة من المدخلات. فيما يلي أنواع المعاملات المتاحة ووصفها:

المعاملات الرقمية

  • int: يعرض حقل إدخال رقمي، ويصبح قيمة رقمية. int مقصور على الأرقام ذات 32 بت.
  • bigint: مشابه لـ int، لكنه يمكن أن يكون أكبر.
  • double: يسمح بالقيم العشرية.

سيتم التحقق من صحة المعاملات الرقمية على الواجهة الأمامية.

معاملات النصوص

  • string: مربع نص حر، ويصبح قيمة نصية.

معاملات القوائم

  • int_list: إدخال أرقام صحيحة مفصولة بفواصل، وتصبح أرقاماً صحيحة مفصولة بفواصل في الاستعلام.
  • string_list: مشابه لـ int_list، ولكن للنصوص.

معاملات المعرّفات المحددة

  • post_id: إدخال رقمي؛ يضمن وجود المنشور المحدد على المنتدى قبل تشغيل الاستعلام.
  • topic_id: مشابه لـ post_id، ولكن للمواضيع.
  • badge_id: يضمن وجود الشارة المحددة.

معاملات القيم المنطقية (Boolean)

  • boolean: يعرض مربع اختيار.
  • null boolean: يعرض قائمة منسدلة، مما يسمح بإدخال فارغ.

معاملات الوقت

  • time: يعرض حقل اختيار الوقت.
  • date: يعرض حقل اختيار التاريخ.
  • datetime: يعرض حقل إدخال يتضمن كل من التاريخ والوقت.

معاملات المحددات (Selectors)

  • user_id: يعرض صندوق محدد مستخدم Discourse، ويصبح المعرّف الرقمي للمستخدم.
  • user_list: مشابه لـ user_id، لكنه يسمح بعدة مستخدمين، ويصبح قائمة بالمعرّفات الرقمية للمستخدمين مفصولة بفواصل.
  • group_id: مشابه لـ user_id، ولكن للمجموعات.
  • group_list: مشابه لـ user_list، ولكن للمجموعات.
  • category_id: مشابه لـ user_id، ولكن للفئات.

المعاملات الداخلية

  • current_user_id: لا توجد واجهة إدخال؛ يضبط المتغير تلقائياً على معرّف المستخدم الذي يشغّل الاستعلام.

استخدام معاملات القوائم

عند استخدام معاملات القوائم (int_list، string_list، user_list)، يجب توخي الحذر الخاص لتجنب أخطاء الصياغة. فيما يلي مثال على استخدام معامل قائمة بشكل صحيح:

-- [params]
-- user_list :the_user_ids
SELECT SUM(length(bio_raw))
FROM user_profiles
WHERE user_id IN (:the_user_ids)

معاملات فارغة (Null)

يمكنك أيضاً السماح بإدخال فارغ عن طريق إضافة بادئة null لنوع المعامل. هذا يعني أنه ليس من الضروري تقديم قيمة لهذا المعامل عند تشغيل الاستعلام.

إليك بعض الأمثلة على كيفية إعلان مثل هذه المعاملات:

-- [params]
-- null int :null_int
-- null boolean :null_boolean
-- null string :null_string
-- null current_user_id :me

في SQL أعلاه، null_int و null_boolean و null_string هي معاملات يمكن تركها فارغة عند تشغيل الاستعلام.

لنرَ كيف يمكن استخدام هذه الأنواع من المعاملات في استعلام:

-- [params]
-- null int :post_id
-- null string :username
SELECT *
FROM users
WHERE (id = :post_id OR :post_id IS NULL)
AND (username = :username OR :username IS NULL)

في هذا الاستعلام، إذا لم يتم تقديم post_id أو username (أي تم تركها كـ null)، سيتجاهل الاستعلام تلك الجزء من جملة WHERE. هذا يسمح باستعلامات أكثر مرونة حيث تكون بعض الشروط اختيارية.

التحقق من الواجهة الأمامية

سيتم التحقق من معظم أنواع المعاملات على الواجهة الأمامية. وتشمل هذه التحقيقات المدخلات المطلوبة غير المعبأة، الإدخال الرقمي غير الصالح، الفئات أو المجموعات غير الموجودة، أوقات غير صالحة، إلخ. بالنسبة للإدخال غير الصالح، سيتم عرض سبب الخطأ في النموذج، وسيتم رفض عملية تشغيل الاستعلام.

اختيار الأنواع واستخدام التحويل (Casts)

بشكل عام، يجب أن تعمل المعاملات “بشكل صحيح” في استعلاماتك. للحالات الأكثر تقدماً، قد تحتاج إلى إضافة تحويل صريح ::type.

على سبيل المثال، للفواصل الزمنية (intervals)، تحتاج إلى إعلان معامل نصي وتحويله إلى interval. يمكن أن تتضمن القيم وحدات، مثل 2 day أو 3 hours:

-- [params]
-- string :lookback = 2 day

SELECT id AS topic_id, created_at
FROM topics
WHERE created_at >= NOW() - :lookback::interval

تحتاج بعض الدوال أيضاً إلى أنواع حجة صريحة:

round(amount::numeric, :decimal_places::integer)
date_trunc('day', :start_date::timestamp)

أمثلة إضافية

إليك بعض الأمثلة الإضافية لإعلان أنواع مختلفة من المعاملات:

-- [params]
-- int             :int = 3
-- bigint          :bigint = 12345678912345
-- boolean         :boolean
-- null boolean    :boolean_three = #null
-- string          :string = little bunny foo foo
-- date            :date = 14 jul 2015
-- time            :time = 5:02 pm
-- datetime        :datetime = 14 jul 2015 5:02 pm
-- double          :double = 3.1415
-- string          :inet = 127.0.0.1/8
-- user_id         :user_id = system
-- post_id         :post_id = http://localhost:3000/t/adsfdsfajadsdafdsds-sf-awerjkldfdwe/21/1?u=system
-- topic_id        :topic_id = /t/-/21
-- int_list        :int_list = 1,2,3
-- string_list     :string_list = a,b,c
-- category_id     :category_id = meta
-- group_id        :group_id = admins
-- user_list       :mul_users = system,discobot
-- current_user_id :me 

مواضيع أخرى في هذه السلسلة

هذه أدلة رائعة، شكراً لنشرها @SaraDev :slight_smile: :hugs:

@AlexDev
هل يمكن أن يكون اسم حقل في عبارة WHERE معلمة؟ شكرًا
أو هل يمكن أن تكون عبارة SQL بأكملها معلمة لتمريرها من نقطة نهاية REST /admin/plugin/explorer/queries/id/run

تنبيه: لا يمكنك استخدام الأرقام في أسماء المعلمات الخاصة بك، على سبيل المثال “foo123” ستفشل.

-- [params]
-- string       :foo123 = a

SELECT :foo123

يؤدي إلى

PG::SyntaxError: ERROR:  syntax error at or near ":"
LINE 10: SELECT :foo123
                ^

لقد حاولت إجراء استدعاء POST لنقطة النهاية run مع معلمات في حمولة JSON كما يلي:

payload = {
    "params": {
        "request_post_id": "45"
    },
    "explain": False
}

لقد قمت بالهندسة العكسية للحمولة من علامة تبويب أدوات المطور في Chrome.
بطريقة ما، ما زلت أتلقى خطأ 500 في الخادم.

هل يمكن لأحد أن يساعدني من فضلك؟

إعلان خدمة عامة: تمت إضافة هذا مؤخرًا بواسطة

طلب ميزة: هل سيكون من الممكن إضافة tag_group كنوع معلمة (parameter type) يقوم بحقن (inject) معرّف العدد الصحيح (integer ID) لمجموعة العلامات المحددة؟