Lược đồ tạm thời trên mỗi kết nối?


8

Tôi đang cố gắng di chuyển các bài kiểm tra đơn vị của mình từ H2 sang Postgresql.

Hiện tại, H2 cung cấp cho tôi một lược đồ trong bộ nhớ sao cho mỗi kết nối ánh xạ tới một lược đồ duy nhất, tạo các bảng, chạy thử nghiệm và loại bỏ lược đồ. Việc tạo và hủy lược đồ được xử lý tự động bởi H2.

Các bài kiểm tra đơn vị chạy đồng thời.

Cách tốt nhất để làm điều này trong Postgresql là gì? Đặc biệt,

  1. Làm cách nào để có được một lược đồ duy nhất cho mỗi kết nối?
    • Khung thử nghiệm có nên tạo tên duy nhất hoặc có cơ chế tích hợp sẵn để thực hiện việc này không?
  2. Làm thế nào để tôi đảm bảo rằng lược đồ bị hủy khi kết nối bị hủy?
    • Tôi không muốn kết thúc với các lược đồ lơ lửng khi các bài kiểm tra đơn vị bị giết.
  3. Cách tiếp cận nào sẽ mang lại hiệu suất cao nhất?
    • Tôi cần tạo / thả hàng chục lược đồ mỗi giây.

CẬP NHẬT : Tôi đã tìm thấy một câu trả lời liên quan ở đây nhưng không thể bỏ lược đồ trong trường hợp quá trình chạy thử nghiệm đơn vị bị giết.

Câu trả lời:


13

pg_temp là một bí danh cho lược đồ tạm thời của phiên hiện tại.

Nếu bạn làm một SET search_path TO pg_temptrước khi chạy thử nghiệm thì tất cả chỉ nên hoạt động (miễn là không có gì tham chiếu một lược đồ rõ ràng).

Nếu bạn hoàn toàn không muốn thay đổi tập lệnh của mình, thì hãy đặt search_pathcho người dùng các bài kiểm tra đăng nhập là:

> ALTER ROLE testuser SET search_path = pg_temp;

Sau đó, mọi thứ mà người dùng tạo sẽ nằm trong pg_temp trừ khi được chỉ định rõ ràng.

Đây là một ví dụ từ psql, hiển thị lược đồ thực tế (cho kết nối này) mà bí danh giải quyết thành:

> SET search_path TO pg_temp;
SET
> create table test();
CREATE TABLE
> \dt test
          List of relations
  Schema   | Name | Type  |  Owner
-----------+------+-------+----------
 pg_temp_4 | test | table | postgres
(1 row)

Và, như bạn mong đợi, lược đồ đó khác với mọi kết nối đồng thời và sẽ biến mất sau khi kết nối được đóng lại.

Lưu ý rằng điều này cũng hoạt động cho các hàm, mặc dù bạn sẽ phải tham chiếu rõ ràng lược đồ pg_temp khi gọi chúng.


Nhưng pg_templà một lược đồ duy nhất phải không? Vì vậy, khi tôi chạy thử nghiệm đơn vị đồng thời, chúng sẽ không ghi đè lên bảng / dữ liệu của nhau chứ?
Gili

1
Không. Đó là bí danh cho lược đồ tạm thời của phiên hiện tại. Tôi sẽ cập nhật câu trả lời với một ví dụ.
hbn

Hãy nhớ rằng nếu bạn chỉ đóng và mở một kết nối, bạn cũng có thể kết thúc với cùng một lược đồ tạm thời, nhưng nó sẽ bị xóa. Mở 2 đồng thời để xem những cái khác nhau được phân bổ. Bạn không thể thấy lược đồ tạm thời của phiên khác trừ khi bạn là siêu người dùng.
hbn

Chắc chắn tôi đã thấy một bình luận từ bạn hỏi về khi nào nên thiết lập điều này. Dù sao - nó được đặt mỗi phiên nếu bạn chỉ làm một SET search_path; sử dụng SET LOCAL search_pathđể đặt cho mỗi giao diện con hoặc nếu bạn muốn, bạn có thể đặt ở cấp độ người dùng với ALTER USER mytestuser SET search_path = 'pg_temp'hoặc ở cấp cơ sở dữ liệu vớiALTER DATABASE mytestdb SET search_path = 'pg_temp'
hbn

Vì tò mò, có cách nào để thực hiện công việc này cho các hàm mà không có tham chiếu lược đồ rõ ràng không? Hoặc điều này là không thể cho pg_templược đồ?
Gili

3

Bạn có thể lấy tên của lược đồ tạm thời hiện tại (sau khi tạo bảng tạm thời đầu tiên) như được trình bày trong liên kết bạn đã thêm:

SELECT nspname
FROM   pg_namespace
WHERE  oid = pg_my_temp_schema();

Nhưng kế hoạch hiện tại của bạn vẫn sẽ không có nhiều ý nghĩa. Để tạo các bảng trong lược đồ tạm thời hiện tại, chỉ cần tạo các bảng tạm thời. Đó là tất cả. Theo mặc định, search_pathđược xác định để các bảng tạm thời được hiển thị đầu tiên. Người ta không bao giờ cần các bảng tạm thời đủ điều kiện lược đồ. Bạn không bao giờ phải trực tiếp giải quyết lược đồ tạm thời hiện tại theo bất kỳ cách nào - đó là một chi tiết triển khai.


Đồng ý rằng đó là một hack, nhưng nó có thể đơn giản hơn đáng kể so với mã tạo tham số để cho phép các bảng tạm thời được tạo.
hbn

Điểm hay, ngoại trừ như @hbn đã đề cập, tôi muốn kiểm tra đơn vị và mã sản xuất để chạy cùng một tập lệnh SQL. Cái trước nên chạy với một lược đồ tạm thời trong khi cái sau thì không.
Gili

@hbn, vì tò mò, mã tạo tham số sẽ trông như thế nào? Tôi đang sử dụng flywaydb.org và nó chỉ thực thi các tệp SQL đơn giản (không có biến). Tôi có lẽ không muốn đi theo con đường này. Tôi chỉ tò mò những gì liên quan.
Gili

Tôi chưa bao giờ sử dụng flywaydb. Ở mức độ cơ bản, bạn có thể sử dụng một số ngôn ngữ tạo khuôn mẫu văn bản (ví dụ Jinja2 trong Python) để xử lý trước các tập lệnh tạo của bạn, tùy ý thêm "tạm thời" khi bạn tạo bảng. Nếu bạn rõ ràng đang tạo các hàm, việc hack lược đồ get-the-tạm thời có lẽ là không thể tránh khỏi (theo như tôi biết), bạn không thể trực tiếp tạo một hàm tạm thời.
hbn

@hbn , If you're explicitly sequences ...: Tôi nghĩ bình luận cuối cùng của bạn có lỗi đánh máy. Bạn có ý gì để nói giữa explicitlysequences?
Gili

1

Làm bài kiểm tra của bạn liên quan đến giao dịch? DDL là giao dịch trong PostgreSQL, vì vậy nếu bạn tạo lược đồ và bảng của mình, sau đó chạy thử nghiệm, tất cả trong một giao dịch sau đó được khôi phục, lược đồ không bao giờ thực sự được cam kết và hiển thị cho các phiên khác.

Bạn vẫn cần sử dụng một tên có lẽ là duy nhất cho lược đồ của mình (có thể bao gồm tên máy chủ và PID), CREATE SCHEMAsẽ thất bại ngay lập tức nếu một lược đồ có tên giống hệt đã tồn tại và sẽ chặn nếu một phiên khác đã tạo một lược đồ có tên giống hệt trong một giao dịch không được cam kết.

Một cách khác có thể chỉ là sử dụng các bảng tạm thời, nếu bạn có thể sửa đổi các tập lệnh tạo cơ sở dữ liệu của mình để làm điều đó.


Thủ thuật hay, nhưng nó sẽ không hoạt động trong trường hợp của tôi vì một thử nghiệm duy nhất hoạt động trên nhiều giao dịch. Mỗi phương thức kiểm tra là một máy khách web thực hiện nhiều giao dịch phía máy chủ. Ví dụ, nó tạo, truy vấn và xóa người dùng. Mỗi cuộc gọi là một yêu cầu HTTP riêng và chạy trong giao dịch riêng của mình.
Gili

Đủ công bằng, cách tiếp cận của tôi rất hạn chế.
hbn

@Gili: Lưu ý rằng kỹ thuật không bao giờ cam kết CREATE SCHEMAnày là kỹ thuật duy nhất có thể đảm bảo khiến chúng biến mất khi thử nghiệm đơn vị bị giết.
Daniel Vérité

0

Tôi chỉ có một ý tưởng.

Postgresql đảm bảo rằng một phiên không thể thấy các bảng tạm thời của người khác. Tôi đoán điều này có nghĩa là khi bạn tạo một bảng tạm thời, nó sẽ tạo một lược đồ tạm thời. Vì vậy, có lẽ tôi có thể làm như sau:

  1. Tạo một bảng tạm thời (giả) và tra cứu lược đồ của nó.
  2. Sử dụng lược đồ này cho thử nghiệm (tạo các bảng, chạy thử nghiệm).
  3. Khi kết nối được đóng lại, Postgresql sẽ bỏ lược đồ.

Tôi không thích dựa vào chi tiết thực hiện, nhưng trong trường hợp này có vẻ khá an toàn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.