Skip to content

Instantly share code, notes, and snippets.

@ololobus
Last active October 20, 2016 16:18
Show Gist options
  • Save ololobus/0c6cd5d98a6e57a501a2f3ffc96ccda3 to your computer and use it in GitHub Desktop.
Save ololobus/0c6cd5d98a6e57a501a2f3ffc96ccda3 to your computer and use it in GitHub Desktop.

Задачи от Postgres Professional

[1]

select * from post 
inner join friend on friend.friend_usr_id = post.usr_id
where friend.usr_id = $1
order by post.added desc
limit 10;

[2]

Выполнить: python -c '()(())()())'

Если SyntaxError: invalid syntax, то баланс не выполняется, если что-то другое (например, TypeError: 'tuple' object is not callable), то все нормально.

[3]

exists - выполняет подзапрос до первой найденной записи, поэтому если поискать бульдозериста-женщину или нянечку-мужчину, то запрос свалится в seq scan, пока не пройдет всю таблицу до конца и ничего не найдет.

Решить можно с помощью индекса по этим полям, но нет смысла хранить в индексе все записи. Нужно исключить наиболее частые, то есть создать частичный индекс с условием "НЕ бульдозерист-мужчина или нянечка-женщина":

CREATE INDEX employee_occupation_idx ON employee (occupation, sex)
WHERE NOT (...);

[4]

Чтобы определить, нужно позапускать параллельные транзакции без коммита и посмотреть в это время в другой сессии на pg_locks + pg_class.

В итоге Накладывается RowShareLock на таблицу parent + row-level блокировка RowExclusiveLock на строку parent, на которую ссылается новый child.

[5]

На Repeatable Read. Но, кажется, что если перевод денег сделан правильно, то проверку баланса можно понизить до Read Committed, так как здесь запросы на debit/credit идут в одном стейтменте и, соотвественно, на одном снэпшоте.

[6]

Если не учитывать отсутствие ;, то у меня запрос выполняется и результат тот, что описан в задании. Можно, наверное, придраться, что инсерт и апдейт потенциально выполняются в одной транзакции. Что есть ограничения на таблицу, так как если в ней есть другие записи, то обновляется только одна. Вообще запрос выглядит крайне странно :)

[7]

Нужно возвращать новое значение (return new;) внутри функции, если все нормально:

create or replace function check_uniq() returns trigger as
$code$
begin
  if exists (select * from tbl t where t.col=new.col) then
    raise exception 'Unique violation';
  end if;
  
  return new;
end;
$code$
language plpgsql;

Ну и не забыть создать сам триггер на инсерт и апдейт:

create trigger uniq_check before insert or update on tbl
for each row execute procedure check_uniq();

[8]

NOTICE: ER000

В документации написано, что следует избегать кодов с тремя нулями на конце, так как это коды категорий:

It is recommended that you avoid throwing error codes that end in three zeroes, 
because these are category codes and can only be trapped by trapping the whole category.

Если заменить ER000 на, например, ER003, то выводится ER001, что интуитивно можно было ожидать.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment