PostgreSQL – Foreign Data Wrapper: Importação de Schema

agosto 22, 2018

Para quem usa o recurso de FDW (Foreign Data Wrapper) muitas vezes precisamos ter acesso a diversas tabelas numa base externa.
O recurso de importar schemas resolve tal questão com facilidade.

Os comandos a seguir são feitos no psql:

Criação da base que acessará outra:

CREATE DATABASE db_acessa;

Criação da base a ser acessada:

CREATE DATABASE db_acessado;

Acessando a base a ser acessada:

\c db_acessado

Criação de um schema:

CREATE SCHEMA sc_acessado;

Criação de tabelas no schema criado:

CREATE TABLE sc_acessado.tb_acessado1(
    id serial primary key,
    campo int);

CREATE TABLE sc_acessado.tb_acessado2(
    id serial primary key,
    campo int);

CREATE TABLE sc_acessado.tb_acessado3(
    id serial primary key,
    campo int);

Acessando a base que acessará outra:

\c db_acessa

Criação de schema:

CREATE SCHEMA sc_acessa;

Habilitar o FDW do Postgres na base corrente:

CREATE EXTENSION postgres_fdw;

Criação do objeto server:

CREATE SERVER srv_acessado
    FOREIGN DATA WRAPPER postgres_fdw
    OPTIONS (host 'localhost',
             dbname 'db_acessado',
             port '5432');

Criação de mapeamento de usuário:

CREATE USER MAPPING FOR postgres
    SERVER srv_acessado
    OPTIONS (user 'postgres', password '123');

Importar o schema sc_acessado da outra base:

IMPORT FOREIGN SCHEMA sc_acessado
    FROM SERVER srv_acessado
    INTO sc_acessa;

Verifidando no psql as tabelas estrangeiras que foram importadas do schema escolhido:

\dE sc_acessa.*
List of relations
  Schema   | Name         | Type          | Owner
-----------+--------------+---------------+----------
 sc_acessa | tb_acessado1 | foreign table | postgres
 sc_acessa | tb_acessado2 | foreign table | postgres
 sc_acessa | tb_acessado3 | foreign table | postgres

Apagando as tabelas estrangeiras:

DROP FOREIGN TABLE
    sc_acessa.tb_acessado1,
    sc_acessa.tb_acessado2,
    sc_acessa.tb_acessado3;

Agora em vez de importarmos todas as tabelas, vamos importar tabelas específicas:

IMPORT FOREIGN SCHEMA sc_acessado
    LIMIT TO (tb_acessado1, tb_acessado2)
    FROM SERVER srv_acessado INTO sc_acessa;

Verifidando no psql as tabelas estrangeiras que foram importadas do schema escolhido:

\dE sc_acessa.*
List of relations
  Schema   | Name         | Type          | Owner
-----------+--------------+---------------+----------
sc_acessa  | tb_acessado1 | foreign table | postgres
sc_acessa  | tb_acessado2 | foreign table | postgres
Anúncios

Argumentos Parciais em Python

julho 19, 2017
partial(func, *args, **keywords)

partial é uma classe do módulo functools, cuja instância é uma função com parâmetros parciais.

Mas como assim?

Imagine uma função por exemplo que tenha 2 parâmetros.
E então você deseja utilizá-la com um desses parâmetros com um valor fixo.
Uma saída mais trabalhosa seria reescrever a funçao dessa forma:

def nova_funcao(x):
    returns funcao_original(x, 10)

 

Como um exemplo prático, a função int para retornar o valor de um inteiro, na base decimal, cuja entrada é um número binário:

int('101', base=2)
 5

 

Vamos fazer de uma forma mais amigável importando a classe partial:

from functools import partial

 

Nossa função modificada será a partir da função int, cujo parâmetro “base” será fixado com o valor 2:

bin2int = partial(int, base=2)

 

Utilizando a nova função para um teste simples:

bin2int('111')
7

 

Para um próximo caso prático vamos construir função que retorne a multiplicação entre dois números:

def fc_foo(x: int, y: int) -> int:
    'Retorna a multiplicação de dois números'
    return x * y

 

Criação de uma lista:

lista = [10, 20, 30, 40]

 

Criação de outra lista, mas vazia:

lista2 = []

Agora imagine que por um motivo qualquer essa nova função precisa ter seu valor de “y” fixado com o valor 7 para ser usado em map…
A tentação de fazer isto é grande:

for i in map(fc_foo(y=7), lista):
    lista2.append(i)
TypeError: fc_foo() missing 1 required positional argument: 'x'

Ops…
Não force a barra 😛

 

Vamos fazer certo agora:

partial_foo = partial(fc_foo, y=7)

 

Com um dos parâmetros com valor fixo vamos fazer um teste:

partial_foo(2)
14

 

E por fim, o loop com map:

for i in map(partial_foo, lista):
    lista2.append(i)

Imprimindo os valores gerados:

print(lista2)
[70, 140, 210, 280]

No último exemplo pudemos ver a função que multiplicava dois números tendo um deles fixados em 7.
Na função map que leva um dos parâmetros com o nome da função tivemos que dar um jeito para que recebesse somente um parâmetro.

Para quem programa em Python, vão ter outros casos em que isso será útil.
Você não vai precisar escrever uma nova função 😉

Diagrama de Fluxo de Django

abril 26, 2017

django

Debug em Python

agosto 14, 2015

Onde foi que eu errei???

Muitas vezes nos perguntamos isso na vida sobre algo que não deu certo. Em programação é um recurso muito útil que nos permite visualizar cada passo da aplicação.
Ou seja, conforme os resultados apresentados verificamos se é o comportamento desejado ou não.
Em Python utilizamos o módulo pdb para esse fim.
Vejamos um simples exemplo cujo arquivo foi nomeado como “teste.py”:

import pdb
pdb.set_trace()

for i in xrange(10):
    print(i ** 3)

Ao executarmos:

$ python teste.py
 > /tmp/teste.py(4)()
 -> for i in xrange(10):
 (Pdb) n
 > /tmp/teste.py(5)()
 -> print(i ** 3)
 (Pdb) n
 0
 > /tmp/teste.py(4)()
 -> for i in xrange(10):
 (Pdb) n
 > /tmp/teste.py(5)()
 -> print(i ** 3)
 (Pdb) n
 1
 > /tmp/teste.py(4)()
 -> for i in xrange(10):
 (Pdb) n
 > /tmp/teste.py(5)()
 -> print(i ** 3)
 (Pdb) n
 8
 > /tmp/teste.py(4)()
 -> for i in xrange(10):
 (Pdb) help
Documented commands (type help ):
 ========================================
 EOF bt cont enable jump pp run unt
 a c continue exit l q s until
 alias cl d h list quit step up
 args clear debug help n r tbreak w
 b commands disable ignore next restart u whatis
 break condition down j p return unalias where
Miscellaneous help topics:
 ==========================
 exec pdb
Undocumented commands:
 ======================
 retval rv
(Pdb)

Isso faz com que entremos em uma espécie de prompt interativo cujo comando mais dado no exemplo foi o “n” de next, para seguir o próximo passo.
O comando help exibe todos os outros comandos possíveis.
Em trechos como:

 > /tmp/teste.py(4)()
-> for i in xrange(10):


> /tmp/teste.py(5)()
-> print(i ** 3)

Respectivamente mostram que está sendo executada as linhas 4 e 5 do arquivo de código-fonte. E claro, em seguida a linha de código que está sendo executada (->).
Para maiores informações sobre os possíveis comandos do pdb do prompt “(Pdb)”
acesse:

https://docs.python.org/2/library/pdb.html

Objetos com Atributos Dinâmicos em Python

fevereiro 27, 2012

python-logo

A dica apresentada neste pequeno artigo é algo bem simples, mas que pode ser bastante útil.
A idéia é ter a possibilidade de criar objetos com atributos dinâmicos (como diz o título).
Na hora que um objeto é instanciado é possível declarar além de atributos que já existam,
conforme a estrutura classe, também outros atributos podem ser declarados com seu valor.

Vejamos primeiro um exemplo simples:

Criação da classe Carro:

class Carro(object):
    marca = ''
    modelo = ''

Criação de um objeto da classe Carro:

c1 = Carro()

Vejamos agora o dicionário de atributos com seus respectivos valores:

print(c1.__dict__)

{}

O atributo especial __dict__, em um objeto, é um dicionário que é usado para guardar atributos e seus respectivos valores.
O dicionário em questão apresentou um conjunto vazio.
Agora vamos preencher os atributos:

c1.marca = 'Porsche'
c1.modelo = '911'
print(c1.__dict__)

{‘modelo’: ‘911’, ‘marca’: ‘Porsche’}

Com os atributos preenchidos com valores agora o dicionário não está mais vazio.
Python é tão flexível que nos permite até criar um atributo “on the fly”:

c1.ano = 1993
print(c1.__dict__)

{‘ano’: 1993, ‘modelo’: ‘911’, ‘marca’: ‘Porsche’}

E que tal se pudermos no momento da criação do objeto, além de poder atribuir valores
aos atributos existentes, também criar atributos que não existem na classe?

Criação da classe Carro agora utilizando o método construtor (__init__()), o qual fará
o trabalho de associar ao objeto instanciado cada par chave / valor declarado:

class Carro(object):
    marca = ''
    modelo = ''
    
    # Metodo construtor
    def __init__(self, **kargs):
        for chave,valor in kargs.items():
            self.__dict__[chave] = valor
c1 = Carro(marca = 'Porsche', modelo = '911', cor = 'verde', ano = 1991)
print(c1.__dict__)

{‘ano’: 1991, ‘modelo’: ‘911’, ‘marca’: ‘Porsche’, ‘cor’: ‘verde’}

Os atributos “cor” e “ano” não existem na classe do objeto.
O método construtor tem em si um loop que busca a combinação chave / valor do parâmetro dinâmico “kargs”
para cada item encontrado e faz a vinculação dos valores às chaves, mesmo que essas chaves não existam como atributos na classe.

Em uma linha só, ao instanciar o objeto é possível definir vários atributos 🙂

AUTO INCREMENTO E PREENCHIMENTO COM ZEROS À ESQUERDA NO ORACLE

outubro 30, 2010

A Idéia

No MySQL há dois recursos muito interessantes que são o AUTO_INCREMENT e o ZEROFILL.
O AUTO_INCREMENT que como o próprio nome sugere, incrementa automaticamente a cada INSERT. Esse recurso também está disponível no PostgreSQL (serial) e no MS SQL Server (identity).
Já o ZEROFILL, preenche com zeros à esquerda. Algo do tipo: 27 -> 00027.

No Oracle

No Oracle essas coisas, lógico, também são possíveis. Mas darão um pouco mais de trabalho.
Vamos construir um exemplo em que, numa tabela de funcionarios há um campo chamado id_funcionario, o qual é a matrícula de um colaborador contendo 5 dígitos, e, em casos que o número de dígitos seja inferior a 5, será preenchido com zeros, por exemplo: 00352. E também esse número será incrementado a cada
INSERT para fazermos o “AUTO_INCREMENT”.

Criação da tabela

CREATE TABLE tb_funcionarios(
id_funcionario CHAR(5),
nome_funcionario VARCHAR(30),
CONSTRAINT pk_funcionario PRIMARY KEY (id_funcionario)
);

Até então nada de muito especial, talvez o fato do campo de identificação ser CHAR e não INT… A resposta pra isso é muito simples; ninguém soma matrículas 🙂

SEQUENCES – Criando uma sequência

São Objetos que armazenam sequências numéricas:

CREATE SEQUENCE sq_funcionario START WITH 1 INCREMENT BY 1 NOMAXVALUE;

Relacionando a Sequência com a Tabela através de um Gatilho

CREATE OR REPLACE TRIGGER tg_id_funcionario BEFORE INSERT ON tb_funcionarios
FOR EACH ROW
BEGIN
SELECT lpad(sq_funcionario.nextval,5,’0′) INTO :NEW.id_funcionario FROM DUAL;
END;

A Função lpad

No Oracle, qualquer consulta necessita de um “FROM” para poder funcionar, então foi usada a tabela DUAL (para maiores informações procure no SQL Reference por “Selecting from the DUAL Table”).
A função “lpad” no caso teve três parâmetros respectivamente: o número, quantidade de dígitos e caractere para preencher à esquerda. Veja um exemplo prático:

SELECT lpad(352,5,’0′) FROM DUAL;

Retornou: 00352

E por fim, vamos inserir algumas coisas na tabela para testar

INSERT INTO tb_funcionarios (nome_funcionario) VALUES (‘Chiquinho da Silva’);
INSERT INTO tb_funcionarios (nome_funcionario) VALUES (‘Astrogilda Santos’);
INSERT INTO tb_funcionarios (nome_funcionario) VALUES (‘Estroncio Veiga’);
INSERT INTO tb_funcionarios (nome_funcionario) VALUES (‘Wolframia Costa’);
INSERT INTO tb_funcionarios (nome_funcionario) VALUES (‘Teobaldo Castro’);
INSERT INTO tb_funcionarios (nome_funcionario) VALUES (‘Equinocia Tavares’);
INSERT INTO tb_funcionarios (nome_funcionario) VALUES (‘Gisevalda Almeida’);
INSERT INTO tb_funcionarios (nome_funcionario) VALUES (‘Gioconda Ramires’);
INSERT INTO tb_funcionarios (nome_funcionario) VALUES (‘Berília Rocha’);
INSERT INTO tb_funcionarios (nome_funcionario) VALUES (‘Adergildo Sales’);
INSERT INTO tb_funcionarios (nome_funcionario) VALUES (‘Criptonio Dias’);
INSERT INTO tb_funcionarios (nome_funcionario) VALUES (‘Rubidio Jose’);

Obs.: Nomes fictícios, qualquer semelhança com a realidade é mera coincidência 🙂

O resultado

SELECT * FROM tb_funcionarios;

Conclusão

O resultado final foi obtido através de relacionamento entre objetos, no qual um gatilho (TRIGGER) é acionado quando um INSERT é feito na tabela e
faz com que o valor inserido para o campo “id_funcionario” seja automaticamente incrementado, pegando o próximo número da sequência e o preenchendo com zeros à esquerda.

Configuração Manual do Ambiente JDK no Ubuntu + Plugin Java para Mozilla

julho 16, 2010

Um pequeno tutorial para ajudar a configurar o ambiente Java para programação de forma mais flexível, sem depender do apt-get. Além de configurar o plugin Java para navegadores como Firefox, Google Chrome, Opera, Konqueror, etc…

De início, temos que baixar o JDK no site:

http://java.sun.com/products/archive/index.html

Passos do site:

JDK/JRE – 6 -> [ Escolha a última versão ] -> Go

Download JDK -> Plataform: [ “Linux x64” para sistemas de 64 bits e “Linux” para 32 ] -> Continue
jdk-[versão].bin (não pode ser rpm.bin!) -> Salve em /tmp

Configurações e comandos

Abra um terminal e dê os comandos:

cd /tmp

chmod +x jdk-*.bin # Torna o arquivo executavel

./jdk-[versão].bin # Roda o executável

[ Pressione “q” a não ser que queira ler todo o texto 🙂 ] -> [ Escreva “yes” (sem as aspas) ] -> <Enter>

mv jdk1* jdk # Deixa um nome mais amigavel

sudo mv jdk /opt/ # Move o diretorio jdk para /opt

Para sistemas de 64 bits:

# Cria um link para o plugin Java para Mozilla

sudo ln -s /opt/jdk/jre/lib/amd64/libnpjp2.so /usr/lib/mozilla/plugins/

Para sistemas de 32 bits:

# Cria um link para o plugin Java para Mozilla

sudo ln -s /opt/jdk/jre/lib/i386/libnpjp2.so /usr/lib/mozilla/plugins/

Edite o arquivo /etc/bash.bashrc e adicione as seguintes linhas:

export JAVA_HOME=/opt/jdk
export JRE_HOME=/opt/jdk/jre
export CLASSPATH=.:/opt/jdk/jre/lib
export PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin

Se for programar apenas em modo texto, no shell (haja coragem!!!), basta executar:

source /etc/bash.bashrc

Ou então para poder usufruir plenamente, simplesmente encerre a sessão na qual seu usuário está logado e entre novamente.

Pode ser que ao instalar via apt-get algum programa que necessite do jdk ele venha instalar automaticamente coisas como openjdk, icedtea que mais atrapalham do que ajudam. Então será preciso remover esses pacotes (indesejados) com o comando apt-get –purge remove nome_do_pacote. Uma boa maneira para se verificar se existem tais pacotes é fazendo uma busca com o comando:

dpkg -l | egrep “(jdk|java|icedtea)”

Se for o caso, desinstale o que não interessar para evitar conflitos com a instalação manual.

Agora o ambiente está pronto! É só começar a programar!

🙂

PostgreSQL com “ZEROFILL” e “AUTO_INCREMENT”

março 20, 2010

Este artigo é dirigido especialmente àqueles que vêm do MySQL para o Postgres.
Dois recursos interessantes que existem no MySQL, o ZEROFILL (preenchimento com zeros à esquerda) e o  AUTO_INCREMENT (incremento automático).

Como fazer o AUTO_INCREMENT no PostgreSQL

O recurso de auto incremento no Postgres é feito através de SEQUENCES (sequências), que é um tipo de objeto que armazena sequências.
Em um exemplo mais simples criamos a tabela sem criar a SEQUENCE explicitamente. A palavra chave SERIAL, na verdade é o tipo INTEGER e faz com que uma sequência seja criada implicitamente para o campo:

CREATE TABLE tb_teste(
id SERIAL PRIMARY KEY
);

Dentre as mensagens exibidas após o comando acima, destaca-se:

NOTICE: CREATE TABLE will create implicit sequence “tb_teste_id_seq” for serial column “tb_teste.id”

Vejamos a descrição da tabela:

\d tb_teste

Table “public.tb_teste”
column | Type    | Modifiers
——–+———+——————————————————-
id          | integer  | not null default nextval(‘tb_teste_id_seq’::regclass)
Indexes:
“tb_teste_pkey” PRIMARY KEY, btree (id)

Como podemos ver, não existe “mágica” e sim LÓGICA! 🙂 -> Se quiser um auto incremento, tem que ter uma sequência, a qual é o valor padrão do campo ao qual está associada, nem que seja criada implicitamente.

Criação de uma Sequência

Incrementa com razão = 1 (lembre-se das aulas de progressão aritimética ;)), valor mínimo = 0, valor máximo = 99999:

CREATE SEQUENCE sq_exemplo INCREMENT 1 MINVALUE 0 MAXVALUE 99999;

Enfim, o ZEROFILL

Criação da Tabela

CREATE TABLE tb_exemplo(

id CHAR(5) DEFAULT lpad(nextval(‘sq_exemplo’)::CHAR(5),5,’0′) PRIMARY KEY
);

Repare que desta vez houve a mensagem de criação de sequência implícita. Isso porque a mesma foi criada explicitamente.

E onde está o EFEITO ESPECIAL?

1 – A restrição DEFAULT, que atribui um valor padrão ao campo;
2 – A função nextval que retorna o próximo valor da sequência, sua sintaxe é: nextval(‘nome_da_sequence’);
3 – A função lpad que recebe aqui três parâmetros: text, integer e text.
No primeiro parâmetro, nextval(‘sq_exemplo’)::CHAR(5), como a função nextval retorna um integer, foi preciso converter para um formato texto, que no caso foi CHAR(5).
No segundo parâmetro, 5 é o tamanho máximo da string que será preenchida com zeros à esquerda.
E no terceiro parâmetro, ‘0’, é o caractere que será usado para preencher à esquerda caso de a string (primeiro parâmetro) for menor que o tamanho máximo (segundo parâmetro).

Teste e Conclusão

INSERT INTO tb_exemplo VALUES (DEFAULT),(DEFAULT),(DEFAULT),(DEFAULT),(DEFAULT);

O comando acima é um INSERT múltiplo na tabela que só tem um campo e que o mesmo possui um valor padrão (DEFAULT) e esse valor é o próximo numero da sequência, com preenchimento de zeros à esquerda.

Agora vejamos o resultado:

SELECT * from tb_exemplo ;

id
——-
00000
00001
00002
00003
00004
00005
(6 rows)

Vale a pena repetir os testes para ver  os valores inseridos.

Enfim, confie no poder do grande elefante e tome suas rédeas para dominá-lo XD.

Concedendo ou Revogando Privilégios em Colunas

dezembro 15, 2009

Antes da versão 8.4 só era possível fazer o controle de acesso de forma mais granular a uma tabela criando uma view especificando as colunas permitidas.

Agora pode dar ou tirar privilégios da seguinte forma:

GRANT SELECT (coluna1,coluna2,…) ON tabela TO role;

Para o exemplo prático a criação de role:

CREATE ROLE limitado LOGIN NOSUPERUSER;

Só terá acesso às colunas campoX e campoY, sendo de somente leitura da tabela tb_exemplo:

GRANT SELECT (campoX,campoY) ON tb_exemplo TO limitado;

De forma análoga será revogado (retirado) o acesso à coluna “campoX”:

REVOKE SELECT (campoX) ON tb_exemplo FROM limitado;

PostgreSQL – Função Replace: Corrigindo Inserções Equivocadas

dezembro 4, 2009

Imaginemos uma situação em que uma pessoa encarregada de cadastrar nomes de pessoas em um banco de dados. E que essa pessoa por algum motivo acabava confundindo os sobrenomes “dos Santos” e “da Silva”.

No exemplo, o cadastro das pessoas que constam como “da Silva”, na verdade o sobrenome é “dos Santos”. Como corrigir isso??? Fazer um UPDATE em cada linha? Há uma maneira simples, rápida e eficiente para isso:

–Criação da Tabela de exemplo:

CREATE TEMP TABLE tb1(

nome varchar(25)

);

–Inserção dos valores (equivocadamente):

INSERT INTO tb1 VALUES (‘Genésio Silva’),

(‘Estrobaldo da Silva’),

(‘Aventina Silva’),

(‘Eloécio da Silva’);

–Arrumando o erro:

UPDATE tb1 SET nome = replace(nome,’da Silva’,’dos Santos’);

–Verificando o resultado:

SELECT * from tb1 ;

nome

———————–

Genésio Silva

Estrobaldo dos Santos

Aventina Silva

Eloécio dos Santos

(4 rows)

Como pode se constatar apenas as ocorrências da string “da Silva” e não “Silva” foram alteradas para o novo valor.