SlideShare uma empresa Scribd logo
1 de 79
Baixar para ler offline
FALANDO "POSTGRÊS"
DICKSON S. GUEDES
21 PYTHONFLORIPA MEETUP
Created: 2017-08-07 seg 20:30
BEGIN TRANSACTION;
Por que estamos aqui hoje?
AVISO IMPORTANTE
Esta palestra conterá cenas fortes de assassinato às boas
práticas de códigos.
Também conterá códigos que provocarão os mais diferentes
estímulos musculares em sua face. `(leia-se "sua face" mesmo,
e não "seu feice")
Existe o risco de que alguns paradigmas seus sejam
quebrados.
Você pode querer começar a se retirar… tudo bem…
EMACS ROCKS!
Esta palestra é totalmente escrita e apresentada utilizando o
editor de texto Emacs com org-mode `(leia-se "não vai ter
memes")
e este talvez seja o primeiro paradigma a ser quebrado…
Além de uma tela preta e apresentação em texto você verá
códigos em Python e em SQL sendo reproduzidos aqui dentro
mesmo…
PS: ainda dá tempo de sair…
SEM MEMES?
VAMOS ENTÃO COMEÇAR?
A language that doesn't affect the way you think about
programming, is not worth knowing. - Alan Perlis
Então vamos conhecer um pouco mais das relações entre o
Python e o Elefante?
LICENÇA
PYTHON
GPL Compatível
POSTGRESQL
PostgreSQL License
PADRÕES
PEP
1-8: Guidelines, Code Style, …
20: The Zen of Python
248: Database API Spec v1.0
249: Database API Spec v2.0
257: Docstring
SQL (ISO/IEC)
92: CLI, PSM, DATETIME, UNION, …,
INFORMATION_SCHEMA, CAST, …
1999: MED, OLB, JRT, GROUP BY, ROLLUP, WITH
RECURSIVE
2003: XML, Window Functions, SEQUENCES, MERGE*
2006: XML, XQuery
2008: TRUNCATE, Partitioned JOIN
2011: Temporal
2016: JSON, Row Pattern Matching
DOCUMENTAÇÃO
https://www.postgresql.org/docs/
https://www.postgresql.org/docs/current/static/index.html
https://www.postgresql.org/docs/9.6/static/index.html
https://www.postgresql.org/docs/9.5/static/index.html
OO
respirem …
EXTENSIBILIDADE
ESTENDENDO PYTHON
Python
import spam
status = spam.system("ls -l")
C
#include <Python.h>
static PyObject *
spam_system(PyObject *self, PyObject *args)
{
const char *command;
int sts;
if (!PyArg_ParseTuple(args, "s", &command))
return NULL;
sts = system(command);
return Py_BuildValue("i", sts);
}
ESTENDENDO POSTGRESQL
VIA CATÁLOGO
# 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
FUNÇÕES, OPERADORES, TIPOS E DOMÍNIOS
Criando um dominio de dados para CPF e um operador
unário que o valida:
BEGIN;
DROP SCHEMA IF EXISTS teste CASCADE;
CREATE SCHEMA teste;
SET search_path TO teste;
CREATE OR REPLACE FUNCTION cpf_valido(numeric)
RETURNS BOOLEAN
LANGUAGE SQL
COST 10
IMMUTABLE STRICT
AS
$_$
with
cpf as (
select $1 as numero
),
cpf_formatado as (
select lpad(cpf.numero::text,11,'0') as numero
from cpf
),
matriz as (
select regexp_split_to_table( cpf_formatado.numero, E's*' ) as valor
from cpf_formatado
),
digitos_por_posicao_1 as (
select row_number() over () as posicao, valor::int
from matriz
),
digitos_por_posicao_2 as (
select posicao - 1 as posicao, valor
from digitos_por_posicao_1
),
digito_1 as (
select sum(posicao*valor) as soma,
sum(posicao*valor) % 11 as resto
from digitos_por_posicao_1 where posicao<=9
),
digito_2 as (
select sum(posicao*valor) as soma,
sum(posicao*valor) % 11 as resto
from digitos_por_posicao_2 where posicao<=9
),
cpf_esperado as (
select array_to_string(array_agg(valor),'')::numeric as numero
from
(
select valor from digitos_por_posicao_1 where posicao <=9
union all
select resto from digito_1
union all
select resto from digito_2
) as foo
)
select distinct cpf.numero = cpf_esperado.numero
from cpf, cpf_esperado;
$_$;
CREATE OPERATOR #? (
LEFTARG = numeric,
PROCEDURE = cpf_valido
);
CREATE DOMAIN cpf AS numeric CHECK ( cpf_valido(VALUE) );
COMMIT;
E agora testar para ver como funciona…
SET search_path TO teste;
DROP TABLE IF EXISTS teste.pessoa;
SELECT cpf_valido(59328253241);
SELECT 59328253241 #? AS cpf_valido;
SELECT 37821042773 #? AS cpf_valido;
SELECT 91416742433 #? AS cpf_valido;
SELECT 91416000433 #? AS cpf_valido;
SELECT 37821042003 #? AS cpf_valido;
SELECT NOT 37821042003 #? AS cpf_valido;
SELECT NOT 91416000433 #? AS cpf_valido;
CREATE TABLE teste.pessoa (
nro_cpf cpf
);
INSERT INTO teste.pessoa VALUES(88229346798);
INSERT INTO teste.pessoa VALUES(45476684425);
E se eu tentar inserir CPF INVALIDO!?
INSERT INTO pessoa VALUES(45076684425);
INSERT INTO pessoa VALUES(81249396798);
VIA C
#include "postgres.h"
#include <string.h>
#include "fmgr.h"
#include "utils/geo_decls.h"
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
PG_FUNCTION_INFO_V1(makepoint);
Datum
makepoint(PG_FUNCTION_ARGS)
{
/* Here, the pass-by-reference nature of Point is not hidden. */
Point *pointx = PG_GETARG_POINT_P(0);
Point *pointy = PG_GETARG_POINT_P(1);
Point *new_point = (Point *) palloc(sizeof(Point));
new_point->x = pointx->x;
new_point->y = pointy->y;
PG_RETURN_POINT_P(new_point);
}
E para o SQL reconhecer esta função, preciso criá-la em meu
banco.
CREATE FUNCTION makepoint(point, point) RETURNS point
AS 'DIRECTORY/funcs', 'makepoint'
LANGUAGE C STRICT;
VIA LINGUAGEM_DO_SEU_CORACAO
Criar a linguagem utilizando extensão:
create extension if not exists plpython2u;
create or replace function array_transpose(a float[])
returns float[]
language plpython2u
as $$
import numpy as np
return np.array(a).transpose()
$$;
E usar ela no SQL:
select array_transpose(array[1.0, 2.0, 4.5]);
Mas com algumas limitações, as vezes:
select array_transpose(array[ array[1.0, 2.0], array[4.5, 7.8]]);
ERRO: não pode converter matriz
multidimensional para lista python detalhe:
pl/python só suporta matrizes
unidimensionais. contexto: função pl/python
"array_transpose"/
REPOSITÓRIO DE EXTENSÕES
PYPI
pip search …
pip install …
…
PGXN CLIENT
pgxn search …
pgxn install …
…
INTEROPERABILIDADE
LIBPQ
async non-block
stream (controle de uxo)
text/binary
noti cações assíncronas (LISTEN/NOTIFY)
COPY (trasferência de dados)
PSYCOPG2
Exemplo básico de execução:
import psycopg2
dbconn = psycopg2.connect(host="/var/run/postgresql", dbname="guedes")
cursor = dbconn.cursor()
cursor.execute("""
SELECT relname
FROM pg_class
WHERE relkind='r'
""")
for row in cursor.fetchall():
print("Tabela: {}".format(row[0]))
cursor.close()
dbconn.close()
implementado em C, como wrapper da libpq
noti cações
COPY
…
criação de tipo personalizados
equivalencia de tipos Python vs PostgreSQL
from psycopg2.extensions import adapt, register_adapter, AsIs
class Point(object):
def __init__(self, x, y):
self.x = x
self.y = y
def adapt_point(point):
x = adapt(point.x).getquoted()
y = adapt(point.y).getquoted()
return AsIs("'(%s, %s)'" % (x, y))
register_adapter(Point, adapt_point)
cur.execute("INSERT INTO atable (apoint) VALUES (%s)",
(Point(1.23, 4.56),))
INSERT INTO atable (apoint) VALUES ('(1.23, 4.56)');
Um outro exemplo é o tipo
CURIOSIDADE
A biblioteca psycopg2 e o cliente de linha de comando pgxn
são de autoria de Daniele Varrazzo
:|
respirem …
"O POSTGRÊS"
Costumamos falar em "um código Pythônico"… mas e com
SQL?
O ANINHADOR FRENÉTICO
PROBLEMA
SELECT ...,
CASE WHEN sobrenome IS NULL
THEN nome
WHEN sobrenome IS NOT NULL
THEN sobrenome || ',' || nome
END
FROM ...
SOLUÇÃO
Dai você vai lá e mostra como faz…
SELECT ...,
COALESCE(sobrenome || ',', '') || nome
FROM ...
O ANINHADOR FRENÉTICO II
PROBLEMA
SELECT ...,
CASE WHEN COALESCE(endereco, '') <> ''
THEN CASE WHEN COALESCE(
COALESCE(endereco, '') ||
' ' ||
COALESCE(bairro, '')
) <> ' '
THEN endereco ||' '|| bairro
ELSE COALESCE(cidade, '')
END
ELSE COALESCE(cidade,'SEM CIDADE')
END
FROM ...
LEFT JOIN ...
LEFT JOIN ...
POSSÍVEL SOLUÇÃO
SELECT ...,
COALESCE(endereco ||' '|| bairro, cidade, 'SEM CIDADE'),
FROM ...
LEFT JOIN ...
LEFT JOIN ...
OPA! TRÊS PARÂMETROS?
SELECT ...,
COALESCE(endereco ||' '|| bairro, cidade, 'SEM CIDADE'),
^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^ ^^^^^^^^^^
FROM ...
LEFT JOIN ...
LEFT JOIN ...
QUAL É O RESULTADO DISTO?
SELECT ...,
COALESCE(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'SEM VALOR'),
COALESCE(NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'SEM VALOR'),
COALESCE(NULL, NULL, NULL, NULL, NULL, NULL, 'SEM VALOR'),
COALESCE(NULL, NULL, NULL, NULL, NULL, 'SEM VALOR'),
COALESCE(NULL, NULL, NULL, NULL, 'SEM VALOR'),
COALESCE(NULL, NULL, NULL, 'SEM VALOR'),
COALESCE(NULL, NULL, 'SEM VALOR'),
COALESCE(NULL, 'SEM VALOR'),
...
FROM ...
COMO ISSO É POSSÍVEL?
???
???
VARIADIC + SYNTAX SUGAR
CREATE OR REPLACE FUNCTION menor_de_todos(VARIADIC valores numeric[])
RETURNS numeric AS
$$
SELECT min($1[valor])
FROM generate_subscripts($1, 1) as g(valor);
$$
LANGUAGE SQL;
SELECT menor_de_todos(10, 11, 12, 30, -20, -30) as menor;
/*
menor
--------
-30
(1 row)
*/
Parâmetros! Não é para passar um ARRAY não!
SELECT menor_de_todos(ARRAY[10, 11, 12, 30, -20, -30]) as menor;
^^^^^^
`-- assim da ruim
CONHEÇA BEM AS FERRAMENTAS QUE VOCÊ USA
O POSTGRES TEM UM TYPO JSON E UM TIPO JSONB, SABIA?
E suporte índices!
{
"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" }
]
}
AS FUNÇÕES DE AGREGAÇÃO DO POSTGRES SÃO COMO MAP-
REDUCE
https://www.postgresql.org/docs/current/static/xaggr.html
AS VEZES TEM FUNÇÕES QUE VOCÊ NEM IMAGINA
SELECT make_date(2017, 7, 7);
O EXPLORADOR DO DESCONHECIDO
NONE VS NULL
Qual é o resultado desta expressão em Python?
print(None + 1)
E qual é o resultado desta expressão no PostgreSQL?
SELECT NULL + 1 as resultado;
NULL E A ARITIMÉTICA
t
SELECT NULL = NULL;
SELECT NULL > NULL;
SELECT NULL < NULL;
O QUE É NULL?
t
SELECT NULL IS NULL; => true
SELECT NULL IS DISTINCT FROM NULL; => false
SELECT NULL IS NOT DISTINCT FROM NULL; => true
SELECT 1 IS NULL; => false
SELECT 1 IS DISTINCT FROM NULL; => true
SELECT 1 IS NOT DISTINCT FROM NULL; => false
TESTE DE ATENÇÃO!
LEMBRAM DA FUNÇÃO MENOR_DE_TODOS?
SELECT menor_de_todos(10, 11, 12, 30, -20, -30) as menor;
E SE EU PASSAR NULL?
SELECT menor_de_todos(10, 11, 12, NULL, -20, -30) as menor;
EXPLICAÇÃO
menor_de_todos(...) usa a função min(...) que é
uma função de agregação e funções de agregação ignoram
NULL.
O FABRICADOR DE REGISTROS
UM REGISTRO TAMBÉM É CHAMADO DE TUPLA!
SELECT ROW(10, 'JOAO', 1500.50);
DOIS REGISTROS SENDO COMPARADOS!
SELECT ROW(10, 'JOAO', 1500.50) = ROW(10, 'JOAO', 1500.50); => true
SELECT ROW(10, 'JOAO', 1500.50) > ROW(9, 'PEDRO', 500.50); => true
SELECT ROW(1, 'MARIA', 1000.10) > ROW(1, 'MARIA', 1000.11); => false
SELECT ROW(100, 'JOANA', 10.60) < ROW(100, 'JOANA', NULL); => ?????
NULL!
Sim, o resultado é NULL, porque o resultado é desconhecido.
:/
respirem …
LEMBRA O INSERT?
INSERT INTO ... VALUES (1, 'JOAO', 1500.10);
PENSA NO VALUES!
/* INSERT INTO ... */
VALUES (1, 'JOAO', 1500.10); -- FUNCIONA!
VALUES É UM COMANDO SOZINHO!
INSERT INTO ... SELECT codigo, nome, valor FROM tabela_temporaria;
INSERT INTO ... VALUES (1, 'JOAO', 1500.10);
VALUES
(1, '...', 1500.10),
(2, '...', 500.00),
(3, '...', 100.00),
(4, '...', 50.50),
(5, '...', 3500.00)
;
SELECT * FROM (
VALUES
(1, '...', 1500.10),
(2, '...', 500.00),
(3, '...', 100.00),
(4, '...', 50.50),
(5, '...', 3500.00)
) AS foo WHERE column3 > 100; -- quais registros aparecem?
PARA O INFINITO, E ALÉM
SIM, TUDO ISSO É POSSÍVEL
SELECT '+Infinity'::float > 999999999999999999999
9999999999999999999999999999999999999999999999999
9999999999999999999999999999999999999999999999999
9999999999999999999999999999999999999999999999999
9999999999999999999999999999999999999999999999999
9999999999999999999999999999999999999999999999999
999999999999999999999999999999999999999999; => true
SELECT '-Infinity'::float < 999999999999999999999
9999999999999999999999999999999999999999999999999
9999999999999999999999999999999999999999999999999
9999999999999999999999999999999999999999999999999
9999999999999999999999999999999999999999999999999
9999999999999999999999999999999999999999999999999
999999999999999999999999999999999999999999; => true
INFINITO PARA DATAS, TAMBÉM, CLARO!
SELECT 'Infinity'::date > current_date; => true
INSERT INTO elemento(nome, validade) VALUES ('uranio', 'Infinity');
isto é um date _.^^^^^^^^
SELECT 'today'::interval = current_date; => true
SELECT 'yesterday'::date = 'today'::date - interval '1 day'; => true
SELECT 'tomorroy'::date = 'today'::date + interval '1 day'; => true
SELECT current_date + 'allballs'::time; => '2015-09-18 00:00:00'
E TUDO PODE SER RESCRITO COMO …
SELECT date 'Infinity' > current_date; => true
INSERT INTO elemento(nome, validade) VALUES ('uranio', 'Infinity');
isto é um date _.^^^^^^^^
SELECT interval 'today' = current_date; => true
SELECT date 'yesterday' = date 'today' - interval '1 day'; => true
SELECT date 'tomorroy' = date 'today' + interval '1 day'; => true
SELECT current_date + time 'allballs'; => '2015-09-18 00:00:00'
NANANANANANANAN
SELECT 'NaN'::numeric + 1; => 'NaN'
LATERAL JOIN
SELECT conta, ultimo_movimento.valor
FROM movimento m
LATERAL (SELECT valor
FROM movimento _m
WHERE _m.conta = m.conta
AND _m.data < m.data
ORDER BY data DESC
LIMIT 1) as ultimo_movimento
WHERE m.data = current_date
AND m.conta = 1214124;
VAMOS VOLTAR UM POUCO PARA O PYTHON?
antes… só mais uma coisinha ….
:)
respirem …
FDW - FOREIGN DATA WRAPPERS
le_fdw
postgres_fdw
mysql_fdw
mongo_fdw
multicorn
FDW - UM EXEMPLO NATIVO
Exemplo do postgres_fdw, ou seja, um Postgres
conversando com outro…
CREATE EXTENSION postgres_fdw;
CREATE SERVER servidor_de_consultas
FOREIGN DATA WRAPPER postgres_fdw
OPTIONS (host '10.100.1.1', dbname 'filial_sul', port '5432');
CREATE USER MAPPING FOR CURRENT_USER
SERVER servidor_de_consultas
OPTIONS (user '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)
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 MULTICORN
SHOW ME THE CODE!!
–> Telegram FDW
CONCLUSÕES
Saiba o quanto você sabe
Saiba o quanto você ainda não sabe
Saiba que jamais saberás tudo mas seja curioso
Leia e se questione: "Será que …?"
Ensine o que aprendeu e …
:D
inspirem …

Mais conteúdo relacionado

Mais procurados

Introdução ao Smarty
Introdução ao SmartyIntrodução ao Smarty
Introdução ao SmartyNelson Gomes
 
Conceitos e técnicas de programação aula 3
Conceitos e técnicas de programação aula 3Conceitos e técnicas de programação aula 3
Conceitos e técnicas de programação aula 3Robson Ferreira
 
Maratona Windows Phone 7
Maratona Windows Phone 7Maratona Windows Phone 7
Maratona Windows Phone 7Felipe Pimentel
 
Pseudocódigo ou Portugol (Lógica de Programação)
Pseudocódigo ou Portugol (Lógica de Programação)Pseudocódigo ou Portugol (Lógica de Programação)
Pseudocódigo ou Portugol (Lógica de Programação)Gercélia Ramos
 
Videoulas de algoritmos e lógica de programação
Videoulas de algoritmos e lógica de programaçãoVideoulas de algoritmos e lógica de programação
Videoulas de algoritmos e lógica de programaçãoaldoirjava
 
Curso Java #01 - Introdução
Curso Java #01 - IntroduçãoCurso Java #01 - Introdução
Curso Java #01 - IntroduçãoRenato Sousa
 
Programacao orientada-a-objetos-java
Programacao orientada-a-objetos-javaProgramacao orientada-a-objetos-java
Programacao orientada-a-objetos-javaRenato Sousa
 
Aprender Javascript e jQuery (UFCD
Aprender Javascript e jQuery (UFCDAprender Javascript e jQuery (UFCD
Aprender Javascript e jQuery (UFCDAfonso Gomes
 
Qcon SP 2012, 5 (ou mais) coisas que você gostaria de saber sobre o iOS e o O...
Qcon SP 2012, 5 (ou mais) coisas que você gostaria de saber sobre o iOS e o O...Qcon SP 2012, 5 (ou mais) coisas que você gostaria de saber sobre o iOS e o O...
Qcon SP 2012, 5 (ou mais) coisas que você gostaria de saber sobre o iOS e o O...Ricardo Valeriano
 
Qualidade de código - a qualidade que faz a diferença
Qualidade de código - a qualidade que faz a diferençaQualidade de código - a qualidade que faz a diferença
Qualidade de código - a qualidade que faz a diferençaCaelum
 
Algoritmos e Visualg parte 1
Algoritmos e Visualg   parte 1Algoritmos e Visualg   parte 1
Algoritmos e Visualg parte 1Marcio Pinto
 
Desenvolvendo com Silverlight para WP7 Mango [Update]
Desenvolvendo com Silverlight para WP7 Mango [Update]Desenvolvendo com Silverlight para WP7 Mango [Update]
Desenvolvendo com Silverlight para WP7 Mango [Update]Felipe Pimentel
 

Mais procurados (19)

Introdução ao Smarty
Introdução ao SmartyIntrodução ao Smarty
Introdução ao Smarty
 
Conceitos e técnicas de programação aula 3
Conceitos e técnicas de programação aula 3Conceitos e técnicas de programação aula 3
Conceitos e técnicas de programação aula 3
 
Maratona Windows Phone 7
Maratona Windows Phone 7Maratona Windows Phone 7
Maratona Windows Phone 7
 
Pseudocódigo ou Portugol (Lógica de Programação)
Pseudocódigo ou Portugol (Lógica de Programação)Pseudocódigo ou Portugol (Lógica de Programação)
Pseudocódigo ou Portugol (Lógica de Programação)
 
Manual básico de conversão de pseudocódigo para C#
Manual básico de conversão de pseudocódigo para C#Manual básico de conversão de pseudocódigo para C#
Manual básico de conversão de pseudocódigo para C#
 
Videoulas de algoritmos e lógica de programação
Videoulas de algoritmos e lógica de programaçãoVideoulas de algoritmos e lógica de programação
Videoulas de algoritmos e lógica de programação
 
Curso Java #01 - Introdução
Curso Java #01 - IntroduçãoCurso Java #01 - Introdução
Curso Java #01 - Introdução
 
Programacao orientada-a-objetos-java
Programacao orientada-a-objetos-javaProgramacao orientada-a-objetos-java
Programacao orientada-a-objetos-java
 
Apostila visualgv25
Apostila visualgv25Apostila visualgv25
Apostila visualgv25
 
Aprender Javascript e jQuery (UFCD
Aprender Javascript e jQuery (UFCDAprender Javascript e jQuery (UFCD
Aprender Javascript e jQuery (UFCD
 
Qcon SP 2012, 5 (ou mais) coisas que você gostaria de saber sobre o iOS e o O...
Qcon SP 2012, 5 (ou mais) coisas que você gostaria de saber sobre o iOS e o O...Qcon SP 2012, 5 (ou mais) coisas que você gostaria de saber sobre o iOS e o O...
Qcon SP 2012, 5 (ou mais) coisas que você gostaria de saber sobre o iOS e o O...
 
Qualidade de código - a qualidade que faz a diferença
Qualidade de código - a qualidade que faz a diferençaQualidade de código - a qualidade que faz a diferença
Qualidade de código - a qualidade que faz a diferença
 
Aula 3
Aula 3Aula 3
Aula 3
 
Aula 02 - Curso PHP e MySQL
Aula 02 - Curso PHP e MySQLAula 02 - Curso PHP e MySQL
Aula 02 - Curso PHP e MySQL
 
Algoritmos e Visualg parte 1
Algoritmos e Visualg   parte 1Algoritmos e Visualg   parte 1
Algoritmos e Visualg parte 1
 
Desenvolvendo com Silverlight para WP7 Mango [Update]
Desenvolvendo com Silverlight para WP7 Mango [Update]Desenvolvendo com Silverlight para WP7 Mango [Update]
Desenvolvendo com Silverlight para WP7 Mango [Update]
 
Aula 01 - Curso PHP e MySQL
Aula 01 - Curso PHP e MySQLAula 01 - Curso PHP e MySQL
Aula 01 - Curso PHP e MySQL
 
ARDUINO PRIMEIROS PASSOS
ARDUINO  PRIMEIROS PASSOSARDUINO  PRIMEIROS PASSOS
ARDUINO PRIMEIROS PASSOS
 
Boas Práticas em jQuery
Boas Práticas em jQueryBoas Práticas em jQuery
Boas Práticas em jQuery
 

Semelhante a Falando "Postgrês"

Introdução ao Desenvolvimento WEB com Ruby on Rails
Introdução ao Desenvolvimento WEB com Ruby on RailsIntrodução ao Desenvolvimento WEB com Ruby on Rails
Introdução ao Desenvolvimento WEB com Ruby on RailsJulio Betta
 
TDC2016 Boas Práticas SQL em Banco Relacional para Desenvolvedores
TDC2016 Boas Práticas SQL em Banco Relacional para DesenvolvedoresTDC2016 Boas Práticas SQL em Banco Relacional para Desenvolvedores
TDC2016 Boas Práticas SQL em Banco Relacional para DesenvolvedoresFernando Franquini
 
Removendo o cheiro ruim do seu código - SoLiSC 2011
Removendo o cheiro ruim do seu código - SoLiSC 2011Removendo o cheiro ruim do seu código - SoLiSC 2011
Removendo o cheiro ruim do seu código - SoLiSC 2011Luís Cobucci
 
Removendo o cheiro ruim do seu código - PHPSC Conf 2011
Removendo o cheiro ruim do seu código - PHPSC Conf 2011Removendo o cheiro ruim do seu código - PHPSC Conf 2011
Removendo o cheiro ruim do seu código - PHPSC Conf 2011Luís Cobucci
 
Algoritmos e Estrutura de Dados - Aula 03
Algoritmos e Estrutura de Dados - Aula 03Algoritmos e Estrutura de Dados - Aula 03
Algoritmos e Estrutura de Dados - Aula 03thomasdacosta
 
Apresentando o EcmaScript 6
Apresentando o EcmaScript 6Apresentando o EcmaScript 6
Apresentando o EcmaScript 6Giovanni Bassi
 
Desafio de Robótica - Católica de Santa Catarina - Joinville
Desafio de Robótica - Católica de Santa Catarina - JoinvilleDesafio de Robótica - Católica de Santa Catarina - Joinville
Desafio de Robótica - Católica de Santa Catarina - JoinvilleNatã Barbosa
 
Relato Sobre a Migração de uma Aplicação Legada para Rails
Relato Sobre a Migração de uma Aplicação Legada para RailsRelato Sobre a Migração de uma Aplicação Legada para Rails
Relato Sobre a Migração de uma Aplicação Legada para RailsCássio Marques
 
Programando Melhor - Flisol
Programando Melhor - FlisolProgramando Melhor - Flisol
Programando Melhor - FlisolLeonn Leite
 
Estripando o Elefante - (Trabalhando com extensões no PostgreSQL)
Estripando o Elefante - (Trabalhando com extensões no PostgreSQL)Estripando o Elefante - (Trabalhando com extensões no PostgreSQL)
Estripando o Elefante - (Trabalhando com extensões no PostgreSQL)Dickson S. Guedes
 
Ganhando tempo automatizando com SQL
Ganhando tempo automatizando com SQLGanhando tempo automatizando com SQL
Ganhando tempo automatizando com SQLDickson S. Guedes
 
Aula 12 funcoes - Programação 1
Aula 12 funcoes - Programação 1Aula 12 funcoes - Programação 1
Aula 12 funcoes - Programação 1Isaac Barros
 
Refatoração de código com Capitão Nascimento versão completa
Refatoração de código com Capitão Nascimento versão completaRefatoração de código com Capitão Nascimento versão completa
Refatoração de código com Capitão Nascimento versão completaEduardo Bregaida
 
Curso de PostgreSQL: Um pouco Além dos Comandos
Curso de PostgreSQL: Um pouco Além dos ComandosCurso de PostgreSQL: Um pouco Além dos Comandos
Curso de PostgreSQL: Um pouco Além dos ComandosMarcos Thomaz
 
Shell Script - Aula 02
Shell Script - Aula 02Shell Script - Aula 02
Shell Script - Aula 02Olival Paulino
 

Semelhante a Falando "Postgrês" (20)

Introdução ao Desenvolvimento WEB com Ruby on Rails
Introdução ao Desenvolvimento WEB com Ruby on RailsIntrodução ao Desenvolvimento WEB com Ruby on Rails
Introdução ao Desenvolvimento WEB com Ruby on Rails
 
TDC2016 Boas Práticas SQL em Banco Relacional para Desenvolvedores
TDC2016 Boas Práticas SQL em Banco Relacional para DesenvolvedoresTDC2016 Boas Práticas SQL em Banco Relacional para Desenvolvedores
TDC2016 Boas Práticas SQL em Banco Relacional para Desenvolvedores
 
Aula1
Aula1Aula1
Aula1
 
Removendo o cheiro ruim do seu código - SoLiSC 2011
Removendo o cheiro ruim do seu código - SoLiSC 2011Removendo o cheiro ruim do seu código - SoLiSC 2011
Removendo o cheiro ruim do seu código - SoLiSC 2011
 
Tdc2010 web
Tdc2010 webTdc2010 web
Tdc2010 web
 
Removendo o cheiro ruim do seu código - PHPSC Conf 2011
Removendo o cheiro ruim do seu código - PHPSC Conf 2011Removendo o cheiro ruim do seu código - PHPSC Conf 2011
Removendo o cheiro ruim do seu código - PHPSC Conf 2011
 
Algoritmos e Estrutura de Dados - Aula 03
Algoritmos e Estrutura de Dados - Aula 03Algoritmos e Estrutura de Dados - Aula 03
Algoritmos e Estrutura de Dados - Aula 03
 
JavaScript - A Linguagem
JavaScript - A LinguagemJavaScript - A Linguagem
JavaScript - A Linguagem
 
Minicurso Ruby on Rails
Minicurso Ruby on RailsMinicurso Ruby on Rails
Minicurso Ruby on Rails
 
04_Introducao_JavaScript.pdf
04_Introducao_JavaScript.pdf04_Introducao_JavaScript.pdf
04_Introducao_JavaScript.pdf
 
Apresentando o EcmaScript 6
Apresentando o EcmaScript 6Apresentando o EcmaScript 6
Apresentando o EcmaScript 6
 
Desafio de Robótica - Católica de Santa Catarina - Joinville
Desafio de Robótica - Católica de Santa Catarina - JoinvilleDesafio de Robótica - Católica de Santa Catarina - Joinville
Desafio de Robótica - Católica de Santa Catarina - Joinville
 
Relato Sobre a Migração de uma Aplicação Legada para Rails
Relato Sobre a Migração de uma Aplicação Legada para RailsRelato Sobre a Migração de uma Aplicação Legada para Rails
Relato Sobre a Migração de uma Aplicação Legada para Rails
 
Programando Melhor - Flisol
Programando Melhor - FlisolProgramando Melhor - Flisol
Programando Melhor - Flisol
 
Estripando o Elefante - (Trabalhando com extensões no PostgreSQL)
Estripando o Elefante - (Trabalhando com extensões no PostgreSQL)Estripando o Elefante - (Trabalhando com extensões no PostgreSQL)
Estripando o Elefante - (Trabalhando com extensões no PostgreSQL)
 
Ganhando tempo automatizando com SQL
Ganhando tempo automatizando com SQLGanhando tempo automatizando com SQL
Ganhando tempo automatizando com SQL
 
Aula 12 funcoes - Programação 1
Aula 12 funcoes - Programação 1Aula 12 funcoes - Programação 1
Aula 12 funcoes - Programação 1
 
Refatoração de código com Capitão Nascimento versão completa
Refatoração de código com Capitão Nascimento versão completaRefatoração de código com Capitão Nascimento versão completa
Refatoração de código com Capitão Nascimento versão completa
 
Curso de PostgreSQL: Um pouco Além dos Comandos
Curso de PostgreSQL: Um pouco Além dos ComandosCurso de PostgreSQL: Um pouco Além dos Comandos
Curso de PostgreSQL: Um pouco Além dos Comandos
 
Shell Script - Aula 02
Shell Script - Aula 02Shell Script - Aula 02
Shell Script - Aula 02
 

Mais de Dickson S. Guedes

O mínimo necessário que você precisa conhecer sobre computação quântica
O mínimo necessário que você precisa conhecer sobre computação quânticaO mínimo necessário que você precisa conhecer sobre computação quântica
O mínimo necessário que você precisa conhecer sobre computação quânticaDickson S. Guedes
 
Porque aprender várias linguagens me tornou um DBA (e desenvolvedor) melhor
Porque aprender várias linguagens me tornou um DBA (e desenvolvedor) melhorPorque aprender várias linguagens me tornou um DBA (e desenvolvedor) melhor
Porque aprender várias linguagens me tornou um DBA (e desenvolvedor) melhorDickson S. Guedes
 
Pattern matching - O que é? Onde vive? Do que se alimenta? Como se reproduz?
Pattern matching - O que é? Onde vive? Do que se alimenta? Como se reproduz?Pattern matching - O que é? Onde vive? Do que se alimenta? Como se reproduz?
Pattern matching - O que é? Onde vive? Do que se alimenta? Como se reproduz?Dickson S. Guedes
 
Primeiros passos machine learning PostgreSQL
Primeiros passos machine learning PostgreSQLPrimeiros passos machine learning PostgreSQL
Primeiros passos machine learning PostgreSQLDickson S. Guedes
 
Dicas de sobrevivência de um DBA sem mouse
Dicas de sobrevivência de um DBA sem mouseDicas de sobrevivência de um DBA sem mouse
Dicas de sobrevivência de um DBA sem mouseDickson S. Guedes
 
Curiosidades que você (talvez) não sabia e se sabia vale a pena lembrar
Curiosidades que você (talvez) não sabia e se sabia vale a pena lembrarCuriosidades que você (talvez) não sabia e se sabia vale a pena lembrar
Curiosidades que você (talvez) não sabia e se sabia vale a pena lembrarDickson S. Guedes
 
Como encontrar uma agulha num palheiro de logs
Como encontrar uma agulha num palheiro de logsComo encontrar uma agulha num palheiro de logs
Como encontrar uma agulha num palheiro de logsDickson S. Guedes
 
Como encontrar uma agulha no palheiro de logs do PostgreSQL
Como encontrar uma agulha no palheiro de logs do PostgreSQLComo encontrar uma agulha no palheiro de logs do PostgreSQL
Como encontrar uma agulha no palheiro de logs do PostgreSQLDickson S. Guedes
 
Gerenciando múltiplas versões do PostgreSQL com pgvm
Gerenciando múltiplas versões do PostgreSQL com pgvmGerenciando múltiplas versões do PostgreSQL com pgvm
Gerenciando múltiplas versões do PostgreSQL com pgvmDickson S. Guedes
 
PGXN - Como distribuir suas extensões com o PostgreSQL
PGXN - Como distribuir suas extensões com o PostgreSQLPGXN - Como distribuir suas extensões com o PostgreSQL
PGXN - Como distribuir suas extensões com o PostgreSQLDickson S. Guedes
 
Plante uma árvore, escreva um livro, tenha um filho e contribua com software ...
Plante uma árvore, escreva um livro, tenha um filho e contribua com software ...Plante uma árvore, escreva um livro, tenha um filho e contribua com software ...
Plante uma árvore, escreva um livro, tenha um filho e contribua com software ...Dickson S. Guedes
 
Conhecendo Postgresql.- ENECOMP 2009
Conhecendo Postgresql.- ENECOMP 2009Conhecendo Postgresql.- ENECOMP 2009
Conhecendo Postgresql.- ENECOMP 2009Dickson S. Guedes
 
Minicurso Postgresql - Enecomp 2009
Minicurso Postgresql - Enecomp 2009Minicurso Postgresql - Enecomp 2009
Minicurso Postgresql - Enecomp 2009Dickson S. Guedes
 
Testes unitarios no PostgreSQL com pgTAP
Testes unitarios no PostgreSQL com pgTAPTestes unitarios no PostgreSQL com pgTAP
Testes unitarios no PostgreSQL com pgTAPDickson S. Guedes
 
pgScript: um Elefante de barriga cheia
pgScript: um Elefante de barriga cheiapgScript: um Elefante de barriga cheia
pgScript: um Elefante de barriga cheiaDickson S. Guedes
 
Replicacao Sincrona "Nao existe almoco gratis!"
Replicacao Sincrona "Nao existe almoco gratis!"Replicacao Sincrona "Nao existe almoco gratis!"
Replicacao Sincrona "Nao existe almoco gratis!"Dickson S. Guedes
 

Mais de Dickson S. Guedes (20)

O mínimo necessário que você precisa conhecer sobre computação quântica
O mínimo necessário que você precisa conhecer sobre computação quânticaO mínimo necessário que você precisa conhecer sobre computação quântica
O mínimo necessário que você precisa conhecer sobre computação quântica
 
Porque aprender várias linguagens me tornou um DBA (e desenvolvedor) melhor
Porque aprender várias linguagens me tornou um DBA (e desenvolvedor) melhorPorque aprender várias linguagens me tornou um DBA (e desenvolvedor) melhor
Porque aprender várias linguagens me tornou um DBA (e desenvolvedor) melhor
 
Pattern matching - O que é? Onde vive? Do que se alimenta? Como se reproduz?
Pattern matching - O que é? Onde vive? Do que se alimenta? Como se reproduz?Pattern matching - O que é? Onde vive? Do que se alimenta? Como se reproduz?
Pattern matching - O que é? Onde vive? Do que se alimenta? Como se reproduz?
 
Primeiros passos machine learning PostgreSQL
Primeiros passos machine learning PostgreSQLPrimeiros passos machine learning PostgreSQL
Primeiros passos machine learning PostgreSQL
 
Dicas de sobrevivência de um DBA sem mouse
Dicas de sobrevivência de um DBA sem mouseDicas de sobrevivência de um DBA sem mouse
Dicas de sobrevivência de um DBA sem mouse
 
Destistificando o EXPLAIN
Destistificando o EXPLAIN Destistificando o EXPLAIN
Destistificando o EXPLAIN
 
Se meu elefante falasse
Se meu elefante falasseSe meu elefante falasse
Se meu elefante falasse
 
Curiosidades que você (talvez) não sabia e se sabia vale a pena lembrar
Curiosidades que você (talvez) não sabia e se sabia vale a pena lembrarCuriosidades que você (talvez) não sabia e se sabia vale a pena lembrar
Curiosidades que você (talvez) não sabia e se sabia vale a pena lembrar
 
O Elefante Poliglota
O Elefante PoliglotaO Elefante Poliglota
O Elefante Poliglota
 
Como encontrar uma agulha num palheiro de logs
Como encontrar uma agulha num palheiro de logsComo encontrar uma agulha num palheiro de logs
Como encontrar uma agulha num palheiro de logs
 
Como encontrar uma agulha no palheiro de logs do PostgreSQL
Como encontrar uma agulha no palheiro de logs do PostgreSQLComo encontrar uma agulha no palheiro de logs do PostgreSQL
Como encontrar uma agulha no palheiro de logs do PostgreSQL
 
Gerenciando múltiplas versões do PostgreSQL com pgvm
Gerenciando múltiplas versões do PostgreSQL com pgvmGerenciando múltiplas versões do PostgreSQL com pgvm
Gerenciando múltiplas versões do PostgreSQL com pgvm
 
PGXN - Como distribuir suas extensões com o PostgreSQL
PGXN - Como distribuir suas extensões com o PostgreSQLPGXN - Como distribuir suas extensões com o PostgreSQL
PGXN - Como distribuir suas extensões com o PostgreSQL
 
Pgxn.pgday
Pgxn.pgdayPgxn.pgday
Pgxn.pgday
 
Plante uma árvore, escreva um livro, tenha um filho e contribua com software ...
Plante uma árvore, escreva um livro, tenha um filho e contribua com software ...Plante uma árvore, escreva um livro, tenha um filho e contribua com software ...
Plante uma árvore, escreva um livro, tenha um filho e contribua com software ...
 
Conhecendo Postgresql.- ENECOMP 2009
Conhecendo Postgresql.- ENECOMP 2009Conhecendo Postgresql.- ENECOMP 2009
Conhecendo Postgresql.- ENECOMP 2009
 
Minicurso Postgresql - Enecomp 2009
Minicurso Postgresql - Enecomp 2009Minicurso Postgresql - Enecomp 2009
Minicurso Postgresql - Enecomp 2009
 
Testes unitarios no PostgreSQL com pgTAP
Testes unitarios no PostgreSQL com pgTAPTestes unitarios no PostgreSQL com pgTAP
Testes unitarios no PostgreSQL com pgTAP
 
pgScript: um Elefante de barriga cheia
pgScript: um Elefante de barriga cheiapgScript: um Elefante de barriga cheia
pgScript: um Elefante de barriga cheia
 
Replicacao Sincrona "Nao existe almoco gratis!"
Replicacao Sincrona "Nao existe almoco gratis!"Replicacao Sincrona "Nao existe almoco gratis!"
Replicacao Sincrona "Nao existe almoco gratis!"
 

Falando "Postgrês"

  • 1. FALANDO "POSTGRÊS" DICKSON S. GUEDES 21 PYTHONFLORIPA MEETUP Created: 2017-08-07 seg 20:30
  • 2. BEGIN TRANSACTION; Por que estamos aqui hoje?
  • 3. AVISO IMPORTANTE Esta palestra conterá cenas fortes de assassinato às boas práticas de códigos. Também conterá códigos que provocarão os mais diferentes estímulos musculares em sua face. `(leia-se "sua face" mesmo, e não "seu feice") Existe o risco de que alguns paradigmas seus sejam quebrados. Você pode querer começar a se retirar… tudo bem…
  • 4. EMACS ROCKS! Esta palestra é totalmente escrita e apresentada utilizando o editor de texto Emacs com org-mode `(leia-se "não vai ter memes") e este talvez seja o primeiro paradigma a ser quebrado… Além de uma tela preta e apresentação em texto você verá códigos em Python e em SQL sendo reproduzidos aqui dentro mesmo… PS: ainda dá tempo de sair…
  • 6. VAMOS ENTÃO COMEÇAR? A language that doesn't affect the way you think about programming, is not worth knowing. - Alan Perlis Então vamos conhecer um pouco mais das relações entre o Python e o Elefante?
  • 11. PEP 1-8: Guidelines, Code Style, … 20: The Zen of Python 248: Database API Spec v1.0 249: Database API Spec v2.0 257: Docstring
  • 12. SQL (ISO/IEC) 92: CLI, PSM, DATETIME, UNION, …, INFORMATION_SCHEMA, CAST, … 1999: MED, OLB, JRT, GROUP BY, ROLLUP, WITH RECURSIVE 2003: XML, Window Functions, SEQUENCES, MERGE* 2006: XML, XQuery 2008: TRUNCATE, Partitioned JOIN 2011: Temporal 2016: JSON, Row Pattern Matching
  • 16. ESTENDENDO PYTHON Python import spam status = spam.system("ls -l") C #include <Python.h> static PyObject * spam_system(PyObject *self, PyObject *args) { const char *command; int sts; if (!PyArg_ParseTuple(args, "s", &command)) return NULL; sts = system(command); return Py_BuildValue("i", sts); }
  • 18. VIA CATÁLOGO # 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
  • 19. FUNÇÕES, OPERADORES, TIPOS E DOMÍNIOS Criando um dominio de dados para CPF e um operador unário que o valida: BEGIN; DROP SCHEMA IF EXISTS teste CASCADE; CREATE SCHEMA teste; SET search_path TO teste; CREATE OR REPLACE FUNCTION cpf_valido(numeric) RETURNS BOOLEAN LANGUAGE SQL COST 10 IMMUTABLE STRICT AS $_$ with cpf as ( select $1 as numero ), cpf_formatado as ( select lpad(cpf.numero::text,11,'0') as numero from cpf ), matriz as ( select regexp_split_to_table( cpf_formatado.numero, E's*' ) as valor from cpf_formatado ), digitos_por_posicao_1 as ( select row_number() over () as posicao, valor::int
  • 20. from matriz ), digitos_por_posicao_2 as ( select posicao - 1 as posicao, valor from digitos_por_posicao_1 ), digito_1 as ( select sum(posicao*valor) as soma, sum(posicao*valor) % 11 as resto from digitos_por_posicao_1 where posicao<=9 ), digito_2 as ( select sum(posicao*valor) as soma, sum(posicao*valor) % 11 as resto from digitos_por_posicao_2 where posicao<=9 ), cpf_esperado as ( select array_to_string(array_agg(valor),'')::numeric as numero from ( select valor from digitos_por_posicao_1 where posicao <=9 union all select resto from digito_1 union all select resto from digito_2 ) as foo ) select distinct cpf.numero = cpf_esperado.numero from cpf, cpf_esperado; $_$; CREATE OPERATOR #? ( LEFTARG = numeric, PROCEDURE = cpf_valido
  • 21. ); CREATE DOMAIN cpf AS numeric CHECK ( cpf_valido(VALUE) ); COMMIT; E agora testar para ver como funciona… SET search_path TO teste; DROP TABLE IF EXISTS teste.pessoa; SELECT cpf_valido(59328253241); SELECT 59328253241 #? AS cpf_valido; SELECT 37821042773 #? AS cpf_valido; SELECT 91416742433 #? AS cpf_valido; SELECT 91416000433 #? AS cpf_valido; SELECT 37821042003 #? AS cpf_valido; SELECT NOT 37821042003 #? AS cpf_valido; SELECT NOT 91416000433 #? AS cpf_valido; CREATE TABLE teste.pessoa ( nro_cpf cpf ); INSERT INTO teste.pessoa VALUES(88229346798); INSERT INTO teste.pessoa VALUES(45476684425); E se eu tentar inserir CPF INVALIDO!? INSERT INTO pessoa VALUES(45076684425); INSERT INTO pessoa VALUES(81249396798);
  • 22. VIA C #include "postgres.h" #include <string.h> #include "fmgr.h" #include "utils/geo_decls.h" #ifdef PG_MODULE_MAGIC PG_MODULE_MAGIC; #endif PG_FUNCTION_INFO_V1(makepoint); Datum makepoint(PG_FUNCTION_ARGS) { /* Here, the pass-by-reference nature of Point is not hidden. */ Point *pointx = PG_GETARG_POINT_P(0); Point *pointy = PG_GETARG_POINT_P(1); Point *new_point = (Point *) palloc(sizeof(Point)); new_point->x = pointx->x; new_point->y = pointy->y; PG_RETURN_POINT_P(new_point); } E para o SQL reconhecer esta função, preciso criá-la em meu banco. CREATE FUNCTION makepoint(point, point) RETURNS point AS 'DIRECTORY/funcs', 'makepoint' LANGUAGE C STRICT;
  • 23. VIA LINGUAGEM_DO_SEU_CORACAO Criar a linguagem utilizando extensão: create extension if not exists plpython2u; create or replace function array_transpose(a float[]) returns float[] language plpython2u as $$ import numpy as np return np.array(a).transpose() $$; E usar ela no SQL: select array_transpose(array[1.0, 2.0, 4.5]); Mas com algumas limitações, as vezes: select array_transpose(array[ array[1.0, 2.0], array[4.5, 7.8]]);
  • 24. ERRO: não pode converter matriz multidimensional para lista python detalhe: pl/python só suporta matrizes unidimensionais. contexto: função pl/python "array_transpose"/
  • 26. PYPI pip search … pip install … …
  • 27. PGXN CLIENT pgxn search … pgxn install … …
  • 29. LIBPQ async non-block stream (controle de uxo) text/binary noti cações assíncronas (LISTEN/NOTIFY) COPY (trasferência de dados)
  • 30. PSYCOPG2 Exemplo básico de execução: import psycopg2 dbconn = psycopg2.connect(host="/var/run/postgresql", dbname="guedes") cursor = dbconn.cursor() cursor.execute(""" SELECT relname FROM pg_class WHERE relkind='r' """) for row in cursor.fetchall(): print("Tabela: {}".format(row[0])) cursor.close() dbconn.close()
  • 31. implementado em C, como wrapper da libpq noti cações COPY … criação de tipo personalizados equivalencia de tipos Python vs PostgreSQL from psycopg2.extensions import adapt, register_adapter, AsIs class Point(object): def __init__(self, x, y): self.x = x self.y = y def adapt_point(point): x = adapt(point.x).getquoted() y = adapt(point.y).getquoted() return AsIs("'(%s, %s)'" % (x, y)) register_adapter(Point, adapt_point) cur.execute("INSERT INTO atable (apoint) VALUES (%s)", (Point(1.23, 4.56),)) INSERT INTO atable (apoint) VALUES ('(1.23, 4.56)');
  • 32. Um outro exemplo é o tipo CURIOSIDADE A biblioteca psycopg2 e o cliente de linha de comando pgxn são de autoria de Daniele Varrazzo
  • 34. "O POSTGRÊS" Costumamos falar em "um código Pythônico"… mas e com SQL?
  • 36. PROBLEMA SELECT ..., CASE WHEN sobrenome IS NULL THEN nome WHEN sobrenome IS NOT NULL THEN sobrenome || ',' || nome END FROM ...
  • 37. SOLUÇÃO Dai você vai lá e mostra como faz… SELECT ..., COALESCE(sobrenome || ',', '') || nome FROM ...
  • 39. PROBLEMA SELECT ..., CASE WHEN COALESCE(endereco, '') <> '' THEN CASE WHEN COALESCE( COALESCE(endereco, '') || ' ' || COALESCE(bairro, '') ) <> ' ' THEN endereco ||' '|| bairro ELSE COALESCE(cidade, '') END ELSE COALESCE(cidade,'SEM CIDADE') END FROM ... LEFT JOIN ... LEFT JOIN ...
  • 40. POSSÍVEL SOLUÇÃO SELECT ..., COALESCE(endereco ||' '|| bairro, cidade, 'SEM CIDADE'), FROM ... LEFT JOIN ... LEFT JOIN ...
  • 41. OPA! TRÊS PARÂMETROS? SELECT ..., COALESCE(endereco ||' '|| bairro, cidade, 'SEM CIDADE'), ^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^ ^^^^^^^^^^ FROM ... LEFT JOIN ... LEFT JOIN ...
  • 42. QUAL É O RESULTADO DISTO? SELECT ..., COALESCE(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'SEM VALOR'), COALESCE(NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'SEM VALOR'), COALESCE(NULL, NULL, NULL, NULL, NULL, NULL, 'SEM VALOR'), COALESCE(NULL, NULL, NULL, NULL, NULL, 'SEM VALOR'), COALESCE(NULL, NULL, NULL, NULL, 'SEM VALOR'), COALESCE(NULL, NULL, NULL, 'SEM VALOR'), COALESCE(NULL, NULL, 'SEM VALOR'), COALESCE(NULL, 'SEM VALOR'), ... FROM ...
  • 43. COMO ISSO É POSSÍVEL?
  • 44. ???
  • 45. ??? VARIADIC + SYNTAX SUGAR CREATE OR REPLACE FUNCTION menor_de_todos(VARIADIC valores numeric[]) RETURNS numeric AS $$ SELECT min($1[valor]) FROM generate_subscripts($1, 1) as g(valor); $$ LANGUAGE SQL; SELECT menor_de_todos(10, 11, 12, 30, -20, -30) as menor; /* menor -------- -30 (1 row) */ Parâmetros! Não é para passar um ARRAY não! SELECT menor_de_todos(ARRAY[10, 11, 12, 30, -20, -30]) as menor; ^^^^^^ `-- assim da ruim
  • 46. CONHEÇA BEM AS FERRAMENTAS QUE VOCÊ USA
  • 47. O POSTGRES TEM UM TYPO JSON E UM TIPO JSONB, SABIA? E suporte índices! { "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" } ] }
  • 48. AS FUNÇÕES DE AGREGAÇÃO DO POSTGRES SÃO COMO MAP- REDUCE https://www.postgresql.org/docs/current/static/xaggr.html
  • 49. AS VEZES TEM FUNÇÕES QUE VOCÊ NEM IMAGINA SELECT make_date(2017, 7, 7);
  • 50. O EXPLORADOR DO DESCONHECIDO
  • 51. NONE VS NULL Qual é o resultado desta expressão em Python? print(None + 1) E qual é o resultado desta expressão no PostgreSQL? SELECT NULL + 1 as resultado;
  • 52. NULL E A ARITIMÉTICA t SELECT NULL = NULL; SELECT NULL > NULL; SELECT NULL < NULL;
  • 53. O QUE É NULL? t SELECT NULL IS NULL; => true SELECT NULL IS DISTINCT FROM NULL; => false SELECT NULL IS NOT DISTINCT FROM NULL; => true SELECT 1 IS NULL; => false SELECT 1 IS DISTINCT FROM NULL; => true SELECT 1 IS NOT DISTINCT FROM NULL; => false
  • 55. LEMBRAM DA FUNÇÃO MENOR_DE_TODOS? SELECT menor_de_todos(10, 11, 12, 30, -20, -30) as menor;
  • 56. E SE EU PASSAR NULL? SELECT menor_de_todos(10, 11, 12, NULL, -20, -30) as menor;
  • 57. EXPLICAÇÃO menor_de_todos(...) usa a função min(...) que é uma função de agregação e funções de agregação ignoram NULL.
  • 58. O FABRICADOR DE REGISTROS
  • 59. UM REGISTRO TAMBÉM É CHAMADO DE TUPLA! SELECT ROW(10, 'JOAO', 1500.50);
  • 60. DOIS REGISTROS SENDO COMPARADOS! SELECT ROW(10, 'JOAO', 1500.50) = ROW(10, 'JOAO', 1500.50); => true SELECT ROW(10, 'JOAO', 1500.50) > ROW(9, 'PEDRO', 500.50); => true SELECT ROW(1, 'MARIA', 1000.10) > ROW(1, 'MARIA', 1000.11); => false SELECT ROW(100, 'JOANA', 10.60) < ROW(100, 'JOANA', NULL); => ?????
  • 61. NULL! Sim, o resultado é NULL, porque o resultado é desconhecido.
  • 63. LEMBRA O INSERT? INSERT INTO ... VALUES (1, 'JOAO', 1500.10);
  • 64. PENSA NO VALUES! /* INSERT INTO ... */ VALUES (1, 'JOAO', 1500.10); -- FUNCIONA!
  • 65. VALUES É UM COMANDO SOZINHO! INSERT INTO ... SELECT codigo, nome, valor FROM tabela_temporaria; INSERT INTO ... VALUES (1, 'JOAO', 1500.10); VALUES (1, '...', 1500.10), (2, '...', 500.00), (3, '...', 100.00), (4, '...', 50.50), (5, '...', 3500.00) ; SELECT * FROM ( VALUES (1, '...', 1500.10), (2, '...', 500.00), (3, '...', 100.00), (4, '...', 50.50), (5, '...', 3500.00) ) AS foo WHERE column3 > 100; -- quais registros aparecem?
  • 66. PARA O INFINITO, E ALÉM
  • 67. SIM, TUDO ISSO É POSSÍVEL SELECT '+Infinity'::float > 999999999999999999999 9999999999999999999999999999999999999999999999999 9999999999999999999999999999999999999999999999999 9999999999999999999999999999999999999999999999999 9999999999999999999999999999999999999999999999999 9999999999999999999999999999999999999999999999999 999999999999999999999999999999999999999999; => true SELECT '-Infinity'::float < 999999999999999999999 9999999999999999999999999999999999999999999999999 9999999999999999999999999999999999999999999999999 9999999999999999999999999999999999999999999999999 9999999999999999999999999999999999999999999999999 9999999999999999999999999999999999999999999999999 999999999999999999999999999999999999999999; => true
  • 68. INFINITO PARA DATAS, TAMBÉM, CLARO! SELECT 'Infinity'::date > current_date; => true INSERT INTO elemento(nome, validade) VALUES ('uranio', 'Infinity'); isto é um date _.^^^^^^^^ SELECT 'today'::interval = current_date; => true SELECT 'yesterday'::date = 'today'::date - interval '1 day'; => true SELECT 'tomorroy'::date = 'today'::date + interval '1 day'; => true SELECT current_date + 'allballs'::time; => '2015-09-18 00:00:00'
  • 69. E TUDO PODE SER RESCRITO COMO … SELECT date 'Infinity' > current_date; => true INSERT INTO elemento(nome, validade) VALUES ('uranio', 'Infinity'); isto é um date _.^^^^^^^^ SELECT interval 'today' = current_date; => true SELECT date 'yesterday' = date 'today' - interval '1 day'; => true SELECT date 'tomorroy' = date 'today' + interval '1 day'; => true SELECT current_date + time 'allballs'; => '2015-09-18 00:00:00'
  • 71. LATERAL JOIN SELECT conta, ultimo_movimento.valor FROM movimento m LATERAL (SELECT valor FROM movimento _m WHERE _m.conta = m.conta AND _m.data < m.data ORDER BY data DESC LIMIT 1) as ultimo_movimento WHERE m.data = current_date AND m.conta = 1214124;
  • 72. VAMOS VOLTAR UM POUCO PARA O PYTHON? antes… só mais uma coisinha ….
  • 74. FDW - FOREIGN DATA WRAPPERS le_fdw postgres_fdw mysql_fdw mongo_fdw multicorn
  • 75. FDW - UM EXEMPLO NATIVO Exemplo do postgres_fdw, ou seja, um Postgres conversando com outro… CREATE EXTENSION postgres_fdw; CREATE SERVER servidor_de_consultas FOREIGN DATA WRAPPER postgres_fdw OPTIONS (host '10.100.1.1', dbname 'filial_sul', port '5432'); CREATE USER MAPPING FOR CURRENT_USER SERVER servidor_de_consultas OPTIONS (user '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) Output: cpf, nome Remote SQL: SELECT cpf, nome
  • 76. FROM recursos_humanos.tb_funcionarios WHERE ((cpf = 1234567891::numeric)) Planning time: 0.061 ms Execution time: 105.232 ms (5 registros)
  • 77. FDW - UM EXEMPLO MULTICORN SHOW ME THE CODE!! –> Telegram FDW
  • 78. CONCLUSÕES Saiba o quanto você sabe Saiba o quanto você ainda não sabe Saiba que jamais saberás tudo mas seja curioso Leia e se questione: "Será que …?" Ensine o que aprendeu e …