Допустим надо проверить, что поле входит в какое-то множество. Очевидно, что надо использовать конструкцию типа
field IN (1, 2, 3, ...)
Но что если это множество пустое. Как его указать?
field IN (???)
one flew east one flew west one flew over the cuckoo's nest
field IN (1, 2, 3, ...)
field IN (???)
ALTER TABLE table_name SET SCHEMA new_schema;
ALTER FUCNTION function_name SET SCHEMA new_schema;
-- и т.д.
IF TG_OP = 'DELETE' THEN
RENAME OLD TO myrow;
ELSE
RENAME NEW TO myrow;
END IF;
-- Далее работаем с myrow не задумываясь о типе триггера
SELECT
contype, -- тип ограничения (PK/FK)
attname -- имя атрибута
FROM pg_constraint
JOIN pg_attribute ON
attrelid = conrelid AND
attnum = any(conkey)
WHERE
contype in ('p', 'f') AND
conrelid = 'yourtablename'::regclass::oid
ORDER BY 1, attnum;
Добавлены строковые функции: concat(), concat_ws(), left(), right()
и reverse().
Pavel Stehule, проверено мной.
(while [ $(ps -p 10708 ho pid) ]; do sleep 5; done; echo -e "\a") &
Распознавание функциональной зависимости от первичных ключей. Это позволяет
колонкам не присутствовать в GROUP BY, если там присутствует первичный ключ.
В дальнейшем нам стоит также разрешить функциональную зависимость от UNIQUE
ограничений при условии, что колонка помечена как NOT NULL, но это будет ждать пока
NOT NULL ограничения не будут представлены в pg_constraint, т.к. нам будут нужны
pg_constraint OID-ы для всех условий, где будет разрешаться функциональная
зависимость.
Peter Eisentraut, проверено Alex Hunsaker и Tom Lane
SELECT field_a, field_b, count(*)
FROM TABLE
GROUP BY field_a
Снижает уровни блокировок CREATE TRIGGER и некоторых действий ALTER TABLE,
CREATE RULE. Убирает прописанные на прямую в коде режимы блокировок, используемые во
множестве команд изменения DDL, позволяя более легко менять уровни блокировок в
будущем. Реализован начальный анализ DDL подкомманд, так что многие уровни блокировок
теперь будут ShareUpdateExclusiveLock или ShareRowExclusiveLock, позволяя конкретным
коммандам не блокировать чтение/запись. Это первое изменение из числа запланированных
в этом направлении; будет нужна дополнительная документация когда весь проект
завершится.
SELECT table_name
FROM information_schema.columns
WHERE column_name = 'put_column_name_here';
CREATE TABLE IF NOT EXISTS.
Reviewed by Bernd Helmle.
$ create table if not exists tesit (x text);
CREATE TABLE
$ create table if not exists tesit (x text);
NOTICE: relation "tesit" already exists, skipping
CREATE TABLE
WITH t AS ( -- Эта часть Model.
SELECT quote_ident(datname) AS d
FROM pg_database WHERE NOT datistemplate
)
SELECT
'pg_dump -U postgres -Fc --file=' || d || -- Эта часть View.
to_char(now(),'_YYYYMMDD') ||
'.pgbackup' || ' '|| d
FROM t;
psql -Atqf backup.sql | sh
Добавляет команду \conninfo в psql, показывающую информацию о текущем соединении.
David Christensen. Проверено Steve Singer. Некоторые изменения от меня.
Значение standard_conforming_strings по умолчанию теперь on.
Это изменение должно быть доведено до сведения разработчиков драйверов и в
замечаниях к релизу должно быть указанным как не совместимое с предыдущими
релизами.
$ SELECT 'guns \'n roses';
?COLUMN?
---------------
guns 'n roses
(1 row)
;; Dired Mode extra features
(load "dired-x.el")
(setq dired-omit-files
(concat dired-omit-files "\\|^\\..+$"))
(dired-omit-mode 1)
Как передать NEW из правила в хранимую функцию?
Есть много представлений, в которых в базу записывается, например, адрес. И это везде происходит одинаково. Хочется вынести этот процесс в отдельную процедуру.
SELECT
c.relname, -- отношение
count(*) AS pages, -- количество страниц
-- использование страниц
sum((usagecount = 0)::int4) as "0",
sum((usagecount = 1)::int4) as "1",
sum((usagecount = 2)::int4) as "2",
sum((usagecount = 3)::int4) as "3",
sum((usagecount = 4)::int4) as "4",
sum((usagecount = 5)::int4) as "5"
FROM
pg_buffercache b
INNER JOIN pg_class c ON
b.relfilenode = c.relfilenode AND
b.reldatabase IN (
0, (SELECT oid FROM pg_database WHERE datname = current_database())
)
GROUP BY c.relname
ORDER BY 2 DESC
LIMIT 10;
postgres=# SELECT * FROM pg_settings WHERE name = 'mysql_compatible';
-[ RECORD 1 ]----------------------------------------------------------------
name | mysql_compatible
setting | ON
unit |
category | Version AND Platform Compatibility / Other Platforms AND Clients
short_desc | Enable MySQL Emulation Layer
extra_desc |
context | backend
vartype | bool
source | DEFAULT
min_val |
max_val |
SELECT xact_start < query_start
FROM pg_stat_activity
WHERE procpid = pg_backend_pid();
SELECT
granted, -- удерживает (t)/ожидает (f)
count(1) AS locks, -- ^^^ количество блокировок
pid, -- pid
now() - xact_start AS xact_age, -- длительность транзакции
now() - query_start AS query_age, -- длительность запроса
current_query -- текущий запрос
FROM
pg_locks AS l
LEFT JOIN pg_stat_activity AS a ON
pid = procpid
GROUP BY 1, 3, 4, 5, 6
ORDER BY 1 DESC, 2 DESC
-- ORDER BY 4 DESC
LIMIT 100;
Добавляет опцию EXPLAIN (BUFFERS) для отображения статистики
использования буферов.
Патч также убирает эту статистику из вывода track_counts, т.к. EXPLAIN
(или глобальная статистика) теперь считается лучшим местом для такой
информации.
Itagaki Takahiro, проверено Euler Taveira de Oliveira.
Поддержка ORDER BY в агрегатных функциях, наконец-то не хак-решение того в каком порядке значения будут агрегироваться. На ряду с этим снимается ограничение использования DISTINCT в агрегатах с одним и только одним аргументом.
Возможно стоит упомянуть о изменении в поведении: ранее agg(DISTINCT x) всегда выкидывала null-значения. Теперь это происходит только тогда, когда transition-функция агрегата реализует это ограничение. Иначе null-значения обрабатываются так, как обычно делает DISTINCT, т.е. возвращается одна копия.
Andrew Gierth, проверено Hitoshi Harada
Устанавливает язык PL/pgSQL по умолчанию.
SELECT
waiting, -- ждёт?
now() - xact_start AS xact_age, -- длительность транзакции
now() - query_start AS queru_age, -- длительность запроса
procpid, -- pid
current_query -- запрос
FROM
pg_stat_activity
WHERE xact_start IS NOT NULL
ORDER BY 1 DESC, 2 DESC;
Поддержка основанного на перезаписи полного вакуума как
VACUUM FULL. Традиционный VACUUM FULL был переименован в VACUUM
FULL INPLACE. Также добавлена опция -i, --inplace в vacuumdb для
FULL INPLACE ваккума.
Т.к. новый VACUUM FULL использует инфраструктуру от CLUSTER, мы
не можем использовать его для системных таблиц. VACUUM FULL для
них прозрачно преобразуется в VACUUM FULL INPLACE.
Itagaki Takahiro, проверено Jeff Davis и Simon Riggs.
Добавляет Потоковую репликацию (Streaming replication).
Включает два новых вида процессов postmaster-а - walsender и walreceiver. Walreceiver отвечает за соединение с главным сервером и передачу WALL данных на диск, в то время как walsender работает на главном сервере и передаёт клиенту WAL данные с диска.
Документация всё ещё нуждается в доработке, но основа уже есть. Возможно мы позже вынесем секцию касающуюся репликации в отдельную главу, также как и секцию о репликации на основе файлов. Это будет в отдельном патче, чтобы было понятно что добавлено/изменено. Этот патч также добавляет новую секцию в главу о FE/BE протоколе, касающуюся walsender/walreceivxer
Подняли версию каталога из-за двух новых функций pg_last_xlog_receive_location() и pg_last_xlog_replay_location() для мониторинга прогресса репликации.
Fujii Masao, с дополнительными правками от меня
(load "~/.emacs.d/sql.el")
;; Minor modes
(add-hook 'sql-mode-hook 'whitespace-mode)
;; 4 spaces instead of tab
(add-hook 'sql-mode-hook
'(lambda ()
(setq indent-tabs-mode nil
tab-width 4
indent-line-function 'insert-tab)
(define-key sql-mode-map (kbd "C-j")
'(lambda()
(interactive)
(delete-horizontal-space t)
(newline)
(indent-relative-maybe)))))
indent-line-function 'insert-tab
(define-key sql-mode-map (kbd "C-j")
'(lambda()
(interactive)
(delete-horizontal-space t)
(newline)
(indent-relative-maybe)))))
Добавлены pg_table_size() и pg_indexes_size() более удобные надстройки над функцией pg_relation_size().
Bernd Helmle, проверил Greg Smith
;; In psql turn off pager usage and adjust prompts
(setq sql-postgres-options '("-P" "pager=off"
"-v" "PROMPT1=%n@%m:%> %~%R%#\n"
"-v" "PROMPT2="
"-v" "PROMPT3="))
(load "~/.emacs.d/postgresql.el")
Добавляет агрегатные функции string_agg. Версия с одним аргументом конкатенирует входные значения в строку, с двумя аргументами то же самое, но ещё добавляет разделитель между элементами.
Патч от Pavel Stehule, проверен David E. Wheeler и мной.
Расширение набора опций фреймов поддерживаемых window функциями.
Патч позволяет фреймам начинаться с текушей строки (CURRENT ROW) (в режиме либо RANGE либо ROW), и также добавляет поддержку ROWS n PRECEDING и ROWS n FOLLOWING для начальной и конечной точек. (PRECEDING/FOLLOWING для RANGE ещё не готово - граматика работает, но это всё что пока есть)
Hitoshi Harada, проверено Pavel Stehule
SELECT indexdef
FROM pg_indexes
WHERE indexdef ~ 'USING (gist|gin)';
CREATE OR REPLACE FUNCTION raise_notice(text)
RETURNS void AS
$BODY$
BEGIN
RAISE NOTICE '%', $1;
RETURN;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE
COST 1;
psql -1 -v ON_ERROR_STOP=1 -f script.psql
SELECT oid AS dboid
FROM pg_database
WHERE datname = 'database1';
SELECT relfilenode AS tfile
FROM pg_class
WHERE relname = 'table1';
SELECT i.relfilenode AS ifile, i.relname
FROM
pg_class c
JOIN pg_index x
ON x.indrelid = c.oid
JOIN pg_class i
ON i.oid = x.indexrelid
WHERE c.relname = 'table1';
<path_to_pg_data>/base/<dboid>/<tfile>
<path_to_pg_data>/base/<dboid>/<ifile>
// Ветки и листья, чекбоксы
/* В попытках разобраться в этом коде, я повесть написал сию. Однако, не поэт
я, а сплошное горе, и повесть получилась из кусков... */
makeTree = function(treeData) {
// И тут сказал Шекспир: "мне кажется - сие не есть листок бумаги
// белоснежный А4, а папка езмь в которой он лежит"...
var leaf = false;
// ...но вот мы видим, что бездетной матери подобна папка та, печален ее
// рок - исписанной ей быть, как может быть исписан лишь листок...
if (!treeData.child) leaf = true;
// ...и чисел магия не может ум пленить, как возвышают над землей поэтов
// строфы...
// (кстати, а почему бы не treeData.id.toString?)
if (treeData.id == 0) treeData.id = '0';
// ...ВНЕЗАПНО объявил король поход, взять обязал он воинов благородных
// честь и имя (id, name), бумаги пачку A4 (leaf:leaf), в ножнах
// меч (checked:false)...
var node, obj = {id:treeData.id, text:treeData.name, leaf:leaf, checked:false};
// ...и вот стоит отряд на поле как следует в военном деле: там во главе
// король, за ним придворные, бояре, рядовых толпа, холопов массы...
node = new Ext.tree.TreeNode(obj);
// И тут король окликнул "Кто мне верен, из тех, кто близко ко двору?"
if (treeData.child) {
// и собралась вокруг него толпа, что лобызать готова стопы короля...
for (var i = 0; i < treeData.child.length; i++) {
node.appendChild(
// Подобным образом так поступил из них и каждый.
// Так стал отряд подобен видом дереву тем, кто смотрит с высоты
// полета птиц...
makeTree(treeData.child[i])
);
}
}
return node;
}
gray@gray ~ $ python
Python 2.6.4 (r264:75706, Dec 22 2009, 17:55:44)
[GCC 4.3.4] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> m = [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
>>> map(lambda *l: list(l), *m)
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> m = [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
>>> map(lambda *l: list(l), *m)
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
>>>
>>> m = [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
>>> zip(*m)
[(1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12)]
>>>
SELECT
schemaname AS sch, -- схема
relname AS tab, -- таблица
pg_size_pretty(pg_relation_size(relid)) AS tsize, -- размер
n_tup_upd + n_tup_ins + n_tup_del AS wr, -- операций записи
seq_scan + idx_scan AS re, -- всего чтений
n_tup_ins AS i, n_tup_upd AS u, n_tup_del AS d -- I/U/D
FROM
pg_stat_user_tables
WHERE schemaname NOT IN ('pgq')
ORDER BY
n_tup_upd + n_tup_ins + n_tup_del DESC
LIMIT 40;
SELECT
schemaname AS sch, -- схема
relname AS tab, -- таблица
pg_size_pretty(pg_relation_size(relid)) AS tsize, -- размер
seq_scan AS ss, -- последовательных чтений
idx_scan AS is, -- индексных чтений
seq_scan + idx_scan AS re, -- всего чтений
n_tup_upd + n_tup_ins + n_tup_del AS wr, -- операций записи
n_tup_ins AS i, n_tup_upd AS u, n_tup_del AS d -- I/U/D
FROM
pg_stat_user_tables
-- WHERE pg_relation_size(relid) > 1 * 1024 * 1024 -- ограничение по размеру
ORDER BY
length(seq_scan::text) DESC,
pg_relation_size(relid) DESC
LIMIT 40;
SELECT
idstat.schemaname AS sch, -- схема
idstat.relname AS tab, -- таблица
indexrelname AS idx, -- индекс
idstat.idx_scan AS iis, -- число сканирований по этому индексу
pg_size_pretty(pg_relation_size(indexrelid)) AS isize, -- размер индекса
tabstat.idx_scan AS tis, -- индексных чтений по таблице
tabstat.seq_scan AS tss, -- последовательных чтений по таблице
tabstat.seq_scan + tabstat.idx_scan AS tre, -- чтений по таблице
n_tup_upd + n_tup_ins + n_tup_del AS twr, -- операций записи
pg_size_pretty(pg_relation_size(idstat.relid)) AS tsize -- размер таблицы
FROM
pg_stat_user_indexes AS idstat
JOIN pg_indexes ON
indexrelname = indexname AND
idstat.schemaname = pg_indexes.schemaname
JOIN pg_stat_user_tables AS tabstat ON
idstat.relid = tabstat.relid
WHERE
indexdef !~* 'unique'
ORDER BY
idstat.idx_scan,
pg_relation_size(indexrelid) DESC
LIMIT 20;
main = do
...
spawn myXxkbBar
...
myXxkbBar = "xxkb" -- configuration in ~/.xxkbrc
-- Do not leave useless conky, dzen and xxkb after restart
((modm, xK_q), spawn "killall conky dzen2 xxkb; xmonad --recompile; xmonad --restart"),
myManageHook = composeAll [
resource =? "XXkb" --> doIgnore
]
XXkb.group.base: 1
XXkb.group.alt: 2
XXkb.mainwindow.appicon: yes
XXkb.mainwindow.geometry: 15x15+1265+0
XXkb.mainwindow.xpm.1: en15.xpm
XXkb.mainwindow.xpm.2: ru15.xpm
XXkb.button.enable: no
XXkb.controls.add_when_start: no
XXkb.controls.add_when_change: yes
XXkb.controls.focusout: yes
XXkb.controls.mainwindow_delete: no
SELECT pg_stat_reset();