poliglotaadjetivo e substantivo de dois gêneros
1. que ou aquele que sabe ou fala muitas línguas.2. que está escrito em muitas línguas; poliglótico.3. diz-se da ave que é capaz de imitar muitos sons e
arremedar outras aves.
ATENÇÃO: esta palestra é umaviagem!
vamos começar com umahipótese
seria possível transformar umservidor Postgres em um
servidor WEB?
ahn?! que esse careca tafalando?
vamos começar a viagem…
no mundo "dos computadô"
o dado nu e crú
[ entrada ] -> [ processamento ] -> [ saida ]
continuo processo de transformação dedados
no mundo "das Internet"
Browser
Apache, Rails, Django, JBoss,Cowboy, Phoenix, Node.js
Javascript
JSON
Javascript Object Notation{ "nome": "Joao", "endereco" : { "cep": "88000-00", "rua": "Das Saudades", "nro": 453, "bairro": "Centro" }, "dependentes": [ { "nome": "Maria", "parentesco": "esposa" }, { "nome": "Mario", "parentesco": "filho" }, { "nome": "Marina", "parentesco": "filha" } ]}
ecoandovar pessoa = { "nome": "Joao", "endereco" : { "cep": "88000-00", "rua": "Das Saudades", "nro": 453, "bairro": "Centro" }, "dependentes": [ { "nome": "Maria", "parentesco": "esposa" }, { "nome": "Mario", "parentesco": "filho" }, { "nome": "Marina", "parentesco": "filha" } ]}
console.log(pessoa.nome); => "Joao" console.log(pessoa["dependentes"][0]["nome"]); => "Maria"
Voltando ao Javascript
callbackvar audita = function(objeto) { console.log(objeto.nome + " foi inserido!");}
var pessoa = new Pessoa();
pessoa.on('after-save', audita);
pessoa = { "nome": "Joao", ... }pessoa.save();
=> Joao foi inserido!
alguem lembra?
Websockets
pub/sub
o movimento deJavascriptização
Node.js
respirem …
no mundo do Postgres
a extensibilidade que liberta
Postgres não é apenas umSGDB
é uma plataforma dedesenvolvimento de aplicações
o catalogo# \dt pg_catalog. List of relations Schema | Name | Type | Owner ------------+-------------------------+-------+---------- pg_catalog | pg_aggregate | table | postgres ... pg_catalog | pg_class | table | postgres ... pg_catalog | pg_database | table | postgres pg_catalog | pg_foreign_data_wrapper | table | postgres pg_catalog | pg_foreign_server | table | postgres pg_catalog | pg_foreign_table | table | postgres pg_catalog | pg_index | table | postgres ... pg_catalog | pg_language | table | postgres ... pg_catalog | pg_operator | table | postgres ... pg_catalog | pg_type | table | postgres pg_catalog | pg_user_mapping | table | postgres
operadores (pg_operator)+-/*o seu mais novo operador pode estar aqui…
tipos (pg_type)integernumerictext…jsonjsonbo seu tipo pode estar aqui também
linguagens (pg_language)plpgsqlplperlplpythonplv8 - javascripta sua linguagem pode estar aqui também
respirem …
plv8
plv8 - Javascript no Postgres
vamos usar o mesmo exemplo doJavascript
DO LANGUAGE plv8 $$var pessoa = { "nome": "Joao", "endereco" : { "cep": "88000-00", "rua": "Das Saudades", "nro": 453, "bairro": "Centro" }, "dependentes": [ { "nome": "Maria", "parentesco": "esposa" }, { "nome": "Mario", "parentesco": "filho" }, { "nome": "Marina", "parentesco": "filha" } ]}
plv8.elog(NOTICE, pessoa.nome);plv8.elog(NOTICE, pessoa["dependentes"][0]["nome"]);$$;
FDW - foreign data wrappers(pg_foreign_data_wrapper)
file_fdwpostgres_fdwmysql_fdwmongo_fdwmulticornque tal o seu aqui também?
FDW - um exemplo nativoCREATE EXTENSION postgres_fdw;
CREATE SERVER servidor_de_consultas FOREIGN DATA WRAPPER postgres_fdw OPTIONS (host '192.168.1.1', dbname 'banco', port '5432');
CREATE USER MAPPING FOR CURRENT_USERSERVER servidor_de_consultas OPTIONS (user 'usuario_consulta', password 'consulta');
CREATE FOREIGN TABLE pessoas (cpf numeric, nome varchar) SERVER servidor_de_consultas OPTIONS ( schema_name 'recursos_humanos', table_name 'tb_funcionarios');
EXPLAIN (ANALYZE,VERBOSE, BUFFERS) SELECT * FROM pessoas WHERE cpf = 1234567891; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------ Foreign Scan on public.pessoas (cost=100.00..118.06 rows=3 width=104) (actual time=46.039..46.040 rows=1 loops=1) Output: cpf, nome Remote SQL: SELECT cpf, nome FROM recursos_humanos.tb_funcionarios WHERE ((cpf = 1234567891::numeric)) Planning time: 0.061 ms Execution time: 105.232 ms(5 registros)
FDW - um exemplo multicornhttp://multicorn.org/implementing-an-fdw/
BGW - background workers
BGW - uma visão geralexecuta junto com o postgresmorre junto com o postgresmas também pode ser dinamicoé um daemono poder esta nas mãos de seu criadorvocê tem que escreve-lo em C
BGW - um exemplopostmaster|-̀- autovacuum|-̀- checkpointer|-̀- bgwriter|-̀- matador_de_conexoes_ociosas|-̀- analisador_da_saude_do_banco...
background worker como umaporta de entrada
BGW é em C, ou seja …
Mas você pode inicia-lo utilizando umafunção do banco
--
SELECT net_http_server(8000);
e um novo BGW iniciapostmaster|-̀- autovacuum|-̀- checkpointer|-̀- bgwriter|-̀- matador_de_conexoes_ociosas|-̀- analisador_da_saude_do_banco|-̀- net_http_server...
LISTEN/NOTIFY
LISTEN SESSAO A SESSAO B
psql -d banco | psql -d banco |> LISTEN usuario_logou; | > ...
LISTEN SESSAO A SESSAO B
psql -d banco | psql -d banco |> LISTEN usuario_logou; | > ...> LISTEN usuario_logou; | > ... | > INSERT INTO login (current_timestamp, 'JOSE');... o cara coxilou por uns minutos ... |
LISTEN SESSAO A SESSAO B
psql -d banco | psql -d banco |> LISTEN usuario_logou; | > ...> LISTEN usuario_logou; | > ... | > INSERT INTO login (current_timestamp, 'JOSE');... o cara coxilou por uns minutos ... | | > NOTIFY usuario_logou, 'JOSE'; |
LISTEN SESSAO A SESSAO B
psql -d banco | psql -d banco |> LISTEN usuario_logou; | > ...> LISTEN usuario_logou; | > ... | > INSERT INTO login (current_timestamp, 'JOSE');... o cara coxilou por uns minutos ... | | > NOTIFY usuario_logou, 'JOSE';> LISTEN usuario_logou; | |
LISTEN SESSAO A SESSAO B
psql -d banco | psql -d banco |> LISTEN usuario_logou; | > ...> LISTEN usuario_logou; | > ... | > INSERT INTO login (current_timestamp, 'JOSE');... o cara coxilou por uns minutos ... | | > NOTIFY usuario_logou, 'JOSE';> LISTEN usuario_logou; | |Notificação assíncrona "usuario_logou" com |mensagem "JOSE" recebida do processo do |servidor com PID 25439. |
a contrib tcntest=# create table tcndatatest-# (test(# a int not null,test(# b date not null,test(# c text,test(# primary key (a, b)test(# );CREATE TABLEtest=# create trigger tcndata_tcn_triggertest-# after insert or update or delete on tcndatatest-# for each row execute procedure triggered_change_notification();CREATE TRIGGER
vendo o resultado da tcntest=# listen tcn;LISTENtest=# insert into tcndata values (1, date '2012-12-22', 'one'),test-# (1, date '2012-12-23', 'another'),test-# (2, date '2012-12-23', 'two');INSERT 0 3Asynchronous notification "tcn" with payload ""tcndata",I,"a"='1',"b"='2012-12-22'" received from server process with PID 22770.Asynchronous notification "tcn" with payload ""tcndata",I,"a"='1',"b"='2012-12-23'" received from server process with PID 22770.Asynchronous notification "tcn" with payload ""tcndata",I,"a"='2',"b"='2012-12-23'" received from server process with PID 22770.test=# update tcndata set c = 'uno' where a = 1;UPDATE 2Asynchronous notification "tcn" with payload ""tcndata",U,"a"='1',"b"='2012-12-22'" received from server process with PID 22770.Asynchronous notification "tcn" with payload ""tcndata",U,"a"='1',"b"='2012-12-23'" received from server process with PID 22770.test=# delete from tcndata where a = 1 and b = date '2012-12-22';DELETE 1Asynchronous notification "tcn" with payload ""tcndata",D,"a"='1',"b"='2012-12-22'" received from server process with PID 22770.
respirem …
finalizando …
(quase)
hipoteticamente pensando …
como poderia ser um servidor web noPostgres?
iniciando a aplicaçãoCREATE SCHEMA todo_list;
CREATE TABLE todo_list.itens( conteudo jsonb );
CREATE INDEX ix_itens_id ON todo_list.itens USING GIN ((conteudo->'id'));
SELECT pg_web_app_start('todo_list', 8000);
guedes@betelgeuse ~$curl -X PUT http://ip.servidor:8000/item/ -d '{ "id": 1, "descricao": "compartilhar conhecimento"}'{ "response": "created" }
curl -X GET http://ip.servidor:8000/item/1{ "id": 1, "descricao": "compartilhar conhecimento"}
curl -X DELETE http://ip.servidor:8000/item/1{ "response": "deleted" }
curl -X GET http://ip.servidor:8000/item/1
qual é a magica dopg_web_app_start('todo_list', 8000) ?
todo_list.app()CREATE FUNCTION todo_list.app() RETURNS jsonb LANGUAGE plv8 AS $$var TodoListApp = PgWebApp();
TodoListApp.get('/', function(req, res) { res.send('<html> .... </html>');});
TodoListApp.get('/item/:id', function(req, res) { plv8.execute('SELECT * FROM todo_list.itens WHERE id = $1', [ req.params.id ]);});
TodoListApp.put('/item', function(req, res) { plv8.execute('INSERT INTO todo_list.itens VALUES ($1)', [ req.body ]);});
TodoListApp.post('/item', function(req, res) { plv8.execute('UPDATE todo_list.itens SET conteudo = $1 WHERE id = $2', [ req.body, req.params.id ]);});
TodoListApp.delete('/item', function(req, res) { plv8.execute('DELETE FROM todo_list.itens WHERE id = $1', [ req.params.id ]);});
TodoListApp.on('usuario_logado', function(payload) { plv8.elog(NOTICE, 'O usuario ' + payload + ' logou!');});
RETURN TodoListApp;$$;
é como se eu publicasse meuesquema todo_list na porta
8000
mas …
você pode esquecer tudo isto …
e dar uma olhada no pg_rest
no fim das contas você vaiperceber que ..
não há limites para o que vocêpode fazer com o Postgres …
e que não há limite para a suaimaginação …
mas tenha a certeza de que ocaminho seja divertido
compartilhem conhecimento
inspirem
e é isso, obrigado! :)Conferencia Brasileira de PostgreSQL
18 a 20 de Novembro
email: [email protected]: twitter:
http://pgbr.postgresql.org.br/
http://github.com/guedeshttp://twitter.com/guediz