পোস্টগ্রিসএসকিউএল 9.6 কলামটি ড্রপিং এবং সিটিই সহ এসকিউএল ফাংশনগুলিতে পার্শ্ব-প্রতিক্রিয়া


15

যদি আমার কাছে 3 টি কলামযুক্ত একটি টেবিল থাকে - এ, বি এবং ডি বলুন - এবং আমাকে একটি নতুন প্রবর্তন করতে হয়েছিল - ডি এর বর্তমান অবস্থান প্রতিস্থাপন করতে সি বলুন আমি নিম্নলিখিত পদ্ধতিটি ব্যবহার করব:

  1. সি এবং ডি 2 হিসাবে 2 টি নতুন কলাম প্রবর্তন করুন।
  2. ডি 2 এর বিষয়বস্তু অনুলিপি করুন।
  3. ডি মুছুন
  4. ডি 2 থেকে ডি নাম পরিবর্তন করুন D.

নতুন আদেশটি হবে এ, বি, সি এবং ডি be

আমি ভেবেছিলাম এটি একটি বৈধ অনুশীলন হিসাবে (এখনও অবধি) এটি কোনও সমস্যা তৈরি করে নি।

যাইহোক, আজ আমি একটি সমস্যার মুখোমুখি হয়েছি যখন একই টেবিলে একটি বিবৃতি বহন করে এমন একটি ফাংশন নিম্নলিখিত ত্রুটিটি ফিরে পেয়েছিল:

table row type and query-specified row type do not match

এবং নিম্নলিখিত বিবরণ:

Query provides a value for a dropped column at ordinal position 13

আমি পোস্টগ্রেএসকিউএল পুনরায় চালু করার চেষ্টা করেছি VACUUM FULLএবং শেষ পর্যন্ত এখানে এবং এখানে প্রস্তাবিত ফাংশনটি মুছে ফেলা এবং পুনরায় তৈরি করার চেষ্টা করেছি তবে এই সমাধানগুলি কার্যকর হয়নি (এক্ষেত্রে যে কোনও সিস্টেমের টেবিলটি পরিবর্তিত হয়েছে এমন পরিস্থিতি মোকাবিলা করার চেষ্টা করে)।

খুব ছোট একটি ডাটাবেসের সাথে কাজ করার বিলাসিতা থাকা আমি এটিকে রপ্তানি করেছি, এটি মুছে ফেলেছি এবং এটি আবার আমদানি করেছি এবং এটি আমার ফাংশনটির সাথে সমস্যাটি স্থির করেছে


আমি এই বিষয়টি সম্পর্কে সচেতন ছিলাম যে এখানে সিস্টেমের সারণীগুলি (হাত দিয়ে নোংরা হওয়া pg_attributeইত্যাদি) সংশোধন করে কলামগুলির প্রাকৃতিক শৃঙ্খলা নিয়ে গণ্ডগোল করা উচিত নয় :

পোস্টগ্রিসে কলামগুলির প্রাকৃতিক ক্রম পরিবর্তন করা সম্ভব?

আমার ফাংশনটিতে ফেলে দেওয়া ত্রুটিটি বিচার করে আমি এখন বুঝতে পারি যে আমার পদ্ধতির সাথে কলামগুলির ক্রম স্থানান্তরিত করাও একটি নং। আমি কী করছি সেটাও ভুল কেন কেউ হালকাভাবে আলোকিত করতে পারে?


পোস্টগ্রিজ সংস্করণটি 9.6.0।

ফাংশনটি এখানে:

CREATE OR REPLACE FUNCTION "public"."__post_users" ("facebookid" text, "useremail" text, "username" text) RETURNS TABLE (authentication_code text, id integer, key text, stripe_id text) AS '

-- First, select the user:
WITH select_user AS
(SELECT
users.id
FROM
users
WHERE
useremail = users.email),

-- Second, update the user (if user exists):
update_user AS
(UPDATE
users
SET
authentication_code = GEN_RANDOM_UUID(),
authentication_date = current_timestamp,
facebook_id = facebookid
WHERE EXISTS (SELECT * FROM select_user)
AND
useremail = users.email
RETURNING
users.authentication_code,
users.id,
users.key,
users.stripe_id),

-- Third, insert the user (if user does not exist):
insert_user AS
(INSERT INTO
users (authentication_code, authentication_date, email, key, name, facebook_id)
SELECT
GEN_RANDOM_UUID(),
current_timestamp,
useremail,
GEN_RANDOM_UUID(),
COALESCE(username, SUBSTRING(useremail FROM ''([^@]+)'')),
facebookid
WHERE NOT EXISTS (SELECT * FROM select_user)
RETURNING
users.authentication_code,
users.id,
users.key,
users.stripe_id)

-- Finally, select the authentication code, ID, key and Stripe ID:
SELECT
*
FROM
update_user
UNION ALL
SELECT
*
FROM
insert_user' LANGUAGE "sql" COST 100 ROWS 1
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER

আমি উভয় কলামে পুনর্নবীকরণ / পুনঃনির্মাণ সম্পাদন করেছি facebook_idএবং stripe_id(এর আগে একটি নতুন কলাম যুক্ত করা হয়েছিল, এটিই নামকরণের কারণ, তবে এই ক্যোয়ারীর দ্বারা স্পর্শ করা হয়নি)।

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


কটাক্ষপাত আমি পোস্টগ্রি ডাটাবেস সারণিতে একটি কলাম অবস্থান কিভাবে পরিবর্তন করব? স্ট্যাক ওভারফ্লোতে এটি সহায়ক হতে পারে, যদিও তারা বেশিরভাগই আপনার কলামগুলি পুনরায় অর্ডার না করার পরামর্শ দেয়।
joanolo

উত্তর:


16

9.6 এবং 9.6.1 এ সম্ভাব্য বাগ

এটি সম্পূর্ণ আমার কাছে বাগের মতো দেখাচ্ছে ...

কেন হয় তা আমি জানি না, তবে আমি নিশ্চিত হতে পারি যে এটি ঘটেছিল। এটি সবচেয়ে সহজ পাওয়া সেটআপ যা সমস্যাটি পুনরুত্পাদন করে (সংস্করণ 9.6.0 এবং 9.6.1)।

CREATE TABLE users
(
    id SERIAL PRIMARY KEY,
    email TEXT NOT NULL,
    column_that_we_will_drop TEXT
) ;

-- Function that uses the previous table, and that has a CTE
CREATE OR REPLACE FUNCTION __post_users
    (_useremail text) 
RETURNS integer AS
$$
-- Need a CTE to produce the error. A 'constant' one suffices.
WITH something_even_if_useless(a) AS
(
    VALUES (1)
)
UPDATE
    users
SET
    id = id
WHERE 
    -- The CTE needs to be referenced, if the next
    -- condition were not in place, the problem is not reproduced
    EXISTS (SELECT * FROM something_even_if_useless)
    AND email = _useremail
RETURNING
    id
$$
LANGUAGE "sql" ;

এই সেটআপের পরে, পরবর্তী বিবৃতি ঠিক কাজ করে

SELECT * FROM __post_users('a@b.com');

এই মুহুর্তে, আমরা একটি কলাম ড্রপ করেছি:

ALTER TABLE users 
    DROP COLUMN column_that_we_will_drop ;

এই পরিবর্তনটি ত্রুটি উত্পন্ন করতে পরবর্তী বিবৃতি তৈরি করে

SELECT * FROM __post_users('a@b.com');

যা অ্যান্ডি দ্বারা উল্লিখিত হিসাবে একই:

ERROR: table row type and query-specified row type do not match
SQL state: 42804
Detail: Query provides a value for a dropped column at ordinal position 3.
Context: SQL function "__post_users" statement 1
    SELECT * FROM __post_users('a@b.com');

ফাংশনটি বাদ দেওয়া এবং পুনরুদ্ধার করা সমস্যার সমাধান করে না।
ভ্যাকুয়াম ফুল (টেবিল বা পুরো ডাটাবেস) সমস্যার সমাধান করে না।


বাগ রিপোর্ট যথাযথ পোস্টগ্র্যাস এসকিউএল মেলিং তালিকায় প্রেরণ করা হয়েছিল এবং আমাদের খুব দ্রুত প্রতিক্রিয়া ছিল :

আমি এটিকে হেড বা 9.6 টি শাখার টিপে পুনরুত্পাদন করতে পারি না। আমি বিশ্বাস করি এটি ইতিমধ্যে এই প্যাচ দ্বারা ঠিক করা হয়েছিল, যা 9.6.1 এর পরে কিছুটা পরে গেছে:

https://git.postgresql.org/gitweb/?p=postgresql.git&a=commitdiff&h=f4d865f22

তবে রিপোর্টের জন্য ধন্যবাদ!

শুভেচ্ছা, টম লেন


সংস্করণ 9.6.2

2017-03-06 এ, আমি নিশ্চিত করতে পারি যে 9.6.2 সংস্করণে আমি এই আচরণটি পুনরুত্পাদন করতে পারি না। অর্থাৎ, বাগটি এই রিলিজটিতে সংশোধন করা হয়েছে বলে মনে হয়।

হালনাগাদ

@ জনার প্রতি মন্তব্য: "আমি নিশ্চিত করতে পারি যে বাগটি 9.6.1 এ উপস্থিত রয়েছে এবং এটি 9.6.2 এ স্থির করা হয়েছিল। ফিক্সটি পোস্টগ্রিজ রিলিজ ওয়েবসাইটেও তালিকাভুক্ত করা হয়েছে : ফিক্স উত্সাহী" ক্যোয়ারী একটি বাদ পড়া কলামের জন্য একটি মান সরবরাহ করে "এর সময় ত্রুটিগুলি বাদ দেওয়া কলাম সহ একটি টেবিলে অন্তর্ভুক্ত করুন বা আপডেট করুন "



4
আমি 9.6.0 ব্যবহার করছি এবং @ জ্যানোলো সঠিক, আমি তার পদ্ধতিটি দিয়ে বাগটি পুনরুত্পাদন করতে পারি। টম যদি এটি পুনরুত্পাদন করতে না পারে তবে এটি সম্ভবত এই নির্দিষ্ট সংস্করণটি সহ একটি বিচ্ছিন্ন বাগ ছিল (এবং 9.6.1 আমি ধরে নিই?)। উত্তরে উল্লিখিত হিসাবে, কোনও টেবিলের কলামটি ফেলে দেওয়ার সময় এবং সেই টেবিলকে প্রভাবিত করে সিটিই সহ একটি ফাংশন ব্যবহার করার সময় সমস্যাটি উপস্থিত হয় । সুতরাং, সমস্যাটি কেবল পুনঃক্রমের সাথে নয় এবং এটিই আমার প্রশ্নটি নিয়ে যাওয়ার চেষ্টা করছিলাম। এটি প্রতিফলিত করার জন্য আমি শিরোনাম সম্পাদনা করব।
অ্যান্ডি

আমি নিশ্চিত করতে পারি যে বাগটি 9.6.1 এ উপস্থিত রয়েছে এবং 9.6.2 এ স্থির হয়েছিল। ফিক্স এছাড়াও তালিকাভুক্ত করা হয় postgres মুক্তি ওয়েবসাইট : ফিক্স কৃত্রিম "QUERY একটি মান প্রদান করে একটি কলাম বাদ" একটি টেবিলের উপর ঢোকান বা আপডেট সময় ত্রুটি থাকা কোনো কলাম বাদ
জানা

0

আমি জানি আপনি সম্ভবত এটি আগে শুনেছেন, কিন্তু এটি একটি ভয়ঙ্কর ধারণা।

  • লজিকাল ক্রম শুধুমাত্র পছন্দসই জিনিসগুলিকে প্রভাবিত করে SELECT *
  • লজিকাল অর্ডারের প্রভাব উপস্থিতিতে সীমাবদ্ধ।

সুতরাং যদি কিছু বিবেচনা না করে তবে আপনাকে হতাশ করে না এবং আমরা স্বীকার করি যে আমরা কেবল সারি কাঠামো নিয়ে ফটোশপ খেলছি এবং প্রদর্শনকে কেন্দ্র করে আকাঙ্ক্ষা করি, আসুন আমরা আরও কিছু বিষয় ব্যাখ্যা করি।

  • লজিকাল ক্রম পোস্টগ্র্রেএসকিউএলে বিদ্যমান নেই
  • শারীরিক অর্ডারের আসল সুবিধা রয়েছে (টেবিল প্যাকিং)
  • পোস্টগ্রিএসকিউএল কোনও পরে শারীরিক অর্ডারের উপর আপনাকে কোনও নিয়ন্ত্রণ দেয় না CREATE TABLE(যদিও এটি অনেক বেশি অগ্রাধিকার হবে)

সুতরাং PostgreSQL একটি খারাপ প্রদর্শন স্তর display সর্বোপরি, ALTERসূক্ষ্মভাবে কাজ করার সময় আপনি ড্রাগনকে প্রলুব্ধ করবেন না। ALTER TABLEএবং ক্যাভেট উভয় বিভাগই এর উল্লেখ করে,

কিছু ডিডিএল কমান্ড, বর্তমানে কেবল TRUNCATEএবং এর সারণী-পুনর্লিখন ফর্মগুলি ALTER TABLE, এমভিসিসি-নিরাপদ নয়। এর অর্থ হ'ল ছাঁটাই বা পুনর্লিখন সম্পাদনের পরে, টেবিলটি সমবর্তী লেনদেনে ফাঁকা প্রদর্শিত হবে, যদি তারা ডিডিএল কমান্ড প্রতিশ্রুতি দেওয়ার আগে নেওয়া একটি স্ন্যাপশট ব্যবহার করে। এটি কেবলমাত্র এমন লেনদেনের জন্য সমস্যা হবে যা ডিডিএল কমান্ড শুরুর আগে প্রশ্নে সারণীতে অ্যাক্সেস পায়নি - এটির যে কোনও লেনদেন কমপক্ষে একটি অ্যাক্সেস শেয়ারের টেবিল লক ধরে রাখে, যা লেনদেন শেষ না হওয়া অবধি ডিডিএল কমান্ডকে অবরুদ্ধ করে রাখে। সুতরাং এই কমান্ডগুলি লক্ষ্য টেবিলের ধারাবাহিক প্রশ্নের জন্য টেবিলের বিষয়বস্তুগুলিতে কোনও আপাত অসঙ্গতি সৃষ্টি করবে না, তবে তারা লক্ষ্য টেবিলের উপকরণ এবং ডাটাবেসের অন্যান্য টেবিলের মধ্যে দৃশ্যমান অসঙ্গতি সৃষ্টি করতে পারে।

এবং, যদি এটি যথেষ্ট না হয় এবং আপনি এখনও ভান করতে চান যে এটি একটি ভাল ধারণা বরং একটি ভয়ঙ্কর ধারণা। তারপরে এটি চেষ্টা করুন,

  1. সাথে টেবিলটি ফেলে দিন pg_dump -t
  2. ডাম্পগুলিতে হাতে কলামগুলি পুনরায় অর্ডার করুন।
  3. জিনিসগুলি একটি TEMP সারণিতে লোড করুন।
  4. BEGIN একটি লেনদেন
  5. DROP পুরানো টেবিল পুরোপুরি,
  6. RENAME প্রোড টেবিলে টেম্প টেবিল।
  7. COMMIT

যদি এগুলি সব অতিরিক্ত মনে হয় তবে মনে রাখবেন যে ডাটাবেসে সারিগুলি আপডেট করার জন্য সারিগুলি পুনর্লিখনের প্রয়োজন (ধরে নিবেন তারা টাস্ট নয় You're সারি। যদি আমি ছিল এই কাজের করতে হবে, যে কিভাবে আমি এটা করতে চাই।

তবে, এই সমস্তই সাধারণত কথা বলছে। আপনার ফলাফল কেউ পুনরুত্পাদন করেনি।

আপনি একটি পরীক্ষা-কেস দিয়েছেন যা আমরা চালাতে পারি না

ERROR:  column users.authentication_code does not exist
LINE 24: users.authentication_code,

এবং, আপনি যে সঠিক সংস্করণে আছেন তা আমাদের জানাননি


পুরো ব্যাখ্যাটির জন্য আপনাকে ধন্যবাদ, নির্দিষ্ট সংস্করণ অন্তর্ভুক্ত করার জন্য আমি প্রশ্নটি সম্পাদনা করেছি।
অ্যান্ডি

4
বাগটি 9.6.0 সংস্করণে পুনরায় উত্পাদনযোগ্য
ypercubeᵀᴹ

0

আমি ব্যাক আপ এবং আমার ডাটাবেস পুনরুদ্ধার করে এই বাগটি পেয়েছিলাম।

হেরোকুর জন্য পদক্ষেপ

  • রক্ষণাবেক্ষণ মোড চালু করুন: heroku maintenance:on
  • ব্যাকআপ ডাটাবেস: heroku pg:backups:capture
  • ডাটাবেস পুনরুদ্ধার: heroku pg:backups:restore
  • অ্যাপ্লিকেশন পুনরায় চালু করুন: heroku restart
  • রক্ষণাবেক্ষণ মোডটি বন্ধ করুন: heroku maintenance:off

0

আমি এই বাগ মধ্যে দৌড়ে। যারা তাদের ডিবি পুরোপুরি ব্যাকআপ / পুনরুদ্ধার করতে চান না তাদের জন্য। জেনে রাখুন যে কেবল টেবিলের অনুলিপি কার্যকর হয়। যদিও কোনও টেবিলটি অনুলিপি করার কোনও "যাদুকরী" উপায় নেই। আমি এটি ব্যবহার করে করেছি:

SELECT * INTO mytable_copy FROM mytable;
ALTER TABLE mytable RENAME TO mytable_backup; -- just in case. you never know
ALTER TABLE mytable_copy RENAME TO mytable;

এর পরে, আপনাকে এখনও নিজের সূচি, বিদেশী কী এবং ডিফল্ট ম্যানুয়ালি পুনরায় তৈরি করতে হবে। এই জাতীয় টেবিলটি পুনরায় তৈরি করার ফলে বাগটি অদৃশ্য হয়ে যায়।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.