domingo, 18 de março de 2018

Criando uma API em C para usar com CFFI - PostgreSQL

Uma lib bem legal do Postgres é a libpq.

Instalação no Debian 7, 8 e 9:

sudo apt update && sudo apt install libpq-dev


Ela pode ser usada com C ou C++.

Pequeno exemplo em C:
Includes: libpq-fe.h, stdio.h, stdlib.h, locale.h.

#define URL_CONN "dbname=mydatabase host=xx.xx.xx.xx user=postgres password=secret" 

typedef struct { 
    int n_rows;
    int n_cols; 
    char ** col_names;   
    PGresult *result;    
    PGconn * conn;
} Pq_reasult;

void pq_execute_query(char * sql){  
    setlocale(LC_ALL, "");
    Pq_reasult * pq = (Pq_reasult *) malloc(sizeof(Pq_reasult));
    pq->conn = PQconnectdb(URL_CONN); 

    if (PQstatus(pq->conn) == CONNECTION_BAD) {
        puts("Falha ao conectar ao Posgres!");
        exit(0);
    }
    
    PGresult * res = PQexec(pq->conn, sql);
    pq->result = res;
    
    if (PQresultStatus(pq->result) != PGRES_TUPLES_OK) {
        puts("0 linhas retornadas!"); 
    }     
    pq->n_rows = PQntuples(pq->result);
    pq->n_cols = PQnfields(pq->result); 

    if(pq->result != NULL){
        int row, col;  
        char * arr_res[pq->n_rows][pq->n_cols]; 
        
        for (row = 0; row < pq->n_rows; row++) {
            for (col = 0; col < pq->n_cols; col++) { 
                arr_res[row][col] = PQgetvalue(pq->result, row, col);
            } 
        }

        printf("Retornadas %d colunas.\n", (size_t)sizeof(arr_res[0]) /sizeof(*arr_res[0]));
        printf("Retornadas %d linhas.\n", (size_t)sizeof(arr_res) /sizeof(*arr_res)); 
        
   
        char * arr[pq->n_cols];
        for (col = 0; col < pq->n_cols; col++) {
            arr[col] = PQfname(pq->result, col); 
        }
        pq->col_names = &arr[0]; 
        
        int c;
        for(c = 0; c < pq->n_cols; c++){
            printf("%s\t", pq->col_names[c]);            
        }
        puts("");
        puts("==========================");
        
        for (row = 0; row < pq->n_rows; row++) {
            for (col = 0; col < pq->n_cols; col++) {
                printf("%s\t", arr_res[row][col]);
            }
            puts("");
        }

        puts("==========================");
    }
    PQclear(pq->result);
    PQfinish(pq->conn);  
} 


int main(void) {             

    return (EXIT_SUCCESS);
}
 
Vamos dar o nome do arquivo .c de "pg_foo.c".
Para linkar, no terminal digite:
$ gcc -c pg_foo.c -I /usr/include/postgresql/ -Wall -fPIC



A opção "-Wall -fPIC" é para que a lib gerada seja dinâmica. Não tem como compilar ela de modo estático. Vamos compilar:
$ gcc -shared -o libpq_query.dll pg_foo.o -I /usr/include/postgresql/ -lpq

Funciona tanto no Windows com MinGW como no Linux.

Vamos consumir com CFFI para usar com PyPy.
Baixando o PyPy:
$ wget https://bitbucket.org/pypy/pypy/downloads/pypy2-v5.10.0-linux64.tar.bz2

Extraindo:
$ tar jxf ./pypy2-v5.10.0-linux64.tar.bz2 

Vamos jogar na opt:
$ sudo mv ./pypy2-v5.10.0-linux64 /opt/pypy





Adicionar o PyPy ao PATH, no /etc/profile inclua:
export PATH=/opt/pypy/bin:$PATH




De um source:
$ source /etc/profile




Instalar o pip no PyPy para simplificar as coisas:
$ cd /opt/pypy/bin/
$ curl -O https://bootstrap.pypa.io/get-pip.py
$ sudo pypy get-pip.py

Instalando o CFFI:
sudo pypy -m pip install cffi

E finalmente:

import cffi
 
ffi = cffi.FFI()
ffi.cdef("void pq_execute_query(char * sql);") 
C = ffi.dlopen("./libpq_query.dll")

C.pq_execute_query(b" SELECT * FROM conta_contabil LIMIT 20;")

Setup do Postgresql - Debian 9

Entre os melhores Sistemas de Gerenciamento de Banco de Dados (SGBDs) da atualidade estão:

Oracle: Porque é caro;
Microsoft SQL Server: Porque é barato;
SQLIte: Porque é leve, simplificado, self-contained e de domínio público;
MariaDB (MySQL): Porque é Software Livre;
PostgreSQL: Porque é Software Livre;

1 - Oracle:
Se você tem um sistema grande e complexo com algumas dezenas/centenas/milhares de usuários e precisa de um bom suporte técnico, que que o suporte seja prestado por uma empresa e precisa armazenas dados binários no SGBD (imagens, streaming, áudio, etc... - não faça isso a menos que tem um bom motivo...), então talvez use o Oracle, prepare seu bolso...

2 - SQL Server:
Se você se enquadra na situação 1, mas quer ter um custo menor, talvez use o SQL Server. A Microsoft gosta de você.

3 - SQLite:
Se você está em um cenário com bem poucos usuários, onde os acessos ao banco de dados quase nunca são simultâneos/concorrentes, ou o sistema tenha apenas 1 usuário, mesmo que o volume de dados seja de médio para grande, se você não for fazer muitas consultas complexas: esse "carinha" é a melhor opção pra você.

4 - MariaDB
Se você entende a filosofia de Software Livre e sabe o que significa o trabalho da Comunidade do Software Livre/Open Source, e está em um cenário multi-usuário, com transações concorrentes, mas precisa apenas armazenar e recuperar dados (CRUDs), tem profissonas na sua equipe que entendem isso e sabem buscar/oferecer ajuda: então o MariaDB (MySQL) te oferece uma performance melhor hoje (futuramente isso pode mudar).

5 - PostgreSQL
Se você tem uma situação semelhante à anterior, mas além de meramente armazenar dados, precisa gerar relatórios complexos, alguns com muitas JOINs/Sub-consultas, e precisa de um SGBD mais robusto, o PostgreSQL pode ser sua melhor escolha.

Recentemente me surgiu a necessidade de montar uma espécie de Data warehouse na empresa. Mas além de servir como armazém da dedos para geração de relatórios (alguns deles um pouco pesados), eu gostaria também de "aproveitar" essa instância de SGBD para alguns CRUDs, adivinha qual SQGB escolhi?

INSTALAÇÃO DO POSTGRES NO DEBIAN 9

$ sudo apt update && sudo apt install postgresql postgresql-common -y




Você também pode precisar desse (principalmente se for desenvolver em C ):


$ sudo apt install libpq-dev





Se quiser gerenciar o BD em modo gráfico:


$ sudo apt install pgadmin3

Mudando a senha do root

Digite:

$ sudo -u postgres psql


\password

Você deve ver algo assim (crie a senha, "\q" sai do console):

user@deb-ctb:~$ sudo -u postgres psql
psql (9.6.7)
Digite "help" para ajuda.

postgres=# \password
Digite nova senha:
Digite-a novamente:
postgres=# \q
user@deb-ctb:~$

Entramos no console do Postgres com o usuário padrão (postgres), e criamos senha dele.
Isso já deve te dar acesso em modo local ao PG Admin.
Você pode criar bases de dados, restaurar backups, etc.

Mas por padrão o Postgres não libera acesso remoto (em rede), você precisa configurar isso manualmente. Não precisa dizer que é por motivos de segurança.

Uma forma bem liberal e permissiva de fazer isso é aceitar conexões de qualquer lugar.
O ideal seria permitir somente os endereços dos clientes que você confia pra acessar a base remotamente... Se sua aplicação é Web e está em localhost (127.0.0.1) você nem precisa fazer isso, mas... por sua conta e risco (e sempre é):

Edite o arquivo pg_hba.conf:

$ sudo nano /etc/postgresql/9.6/main/pg_hba.conf

Encontre a seguinte linha:

# IPv4 local connections:
host    all          all          127.0.0.1/32         md5

E deixe assim:

# IPv4 local connections:
host    all          all          0.0.0.0/0            md5

No postgresql.conf (pasta /etc/postgresql/9.6/main/) vamos editar a seguinte linha:

#listen_addresses = 'localhost'    # what IP address(es) to listen on;


Descomente ela e deixe: '*' em vez de: 'localhost':

listen_addresses = '*'         # what IP address(es) to listen on;

E reinicie o BD:

user@deb-ctb:~$ sudo /etc/init.d/postgresql restart
[ ok ] Restarting postgresql (via systemctl): postgresql.service.
user@deb-ctb:~$

Pronto! A parte fácil já foi, agora é só usar.

quarta-feira, 28 de setembro de 2016

Criando "Pendrives" de boot no windows sem "programinha"

Por vários motivos, uma das coisas que eu não gosto é ficar instalando "programinhas" no Windows pra fazer as coisas. 

Se o software não for Livre ou Open Source, às vezes por mais que você preste atenção e desmarque 10 opções na instalação sempre vem um software adware ou outros verdadeiros vírus semelhantes junto com o app que você está instalando.

Muita gente não sabe, mas não precisa de programinha pra criar pendrive de boot.

Um pendrive configurado para boot via porta USB geralmente é usado quando você quer formatar o PC ou rodar um sistema operacional "Live", ou seja, um S.O que não precisa ser instalado na máquina para você eventualmente dar manutenção no Windows (por exemplo com o https://partedmagic.com)

Pra criar um pendrive de boot você pode usar um utilitário do Windows chamado diskpart.

Basta abrir o terminal e executar-lo:


Irá aparecer:


A seguir você deve selecionar o disco. Se tiver aquivos que você ainda vai usar nele faça backup (será FORMATADO):


Então selecione o disco (cuidado pra não selecionar o disco errado). Pelo tamanho do disco você consegue ver qual é o pendrive:


Limpe o disco:


Crie uma nova partição primária o formate com os comandos abaixo:

create partition primary
select partition 1
active
format fs=ntfs quick
assign
exit



O pendrive está pronto!
Se você vai gravar uma imagem ISO, do Windows 8 em diante você consegue "montar" o arquivo clicando com o botão direito. Daí ele irá aparecer no "meu computador" como se você um CD/DVD inserido no PC. 
Em versões antigas do Windows: descompacte com o 7zip (ou winrar pra quem gosta):



Depois é só copiar e colar os arquivos no pendrive.

Para você dar boot no pendrive, talvez só isso não baste, principalmente se você nunca fez isso nesse PC.
Então você deve dar uma olhada nas configurações da BIOS do seu PC (ou UEFI nos PCs mais modernos):

Terminal "Linux like" no Windows

Parece uma coisa boba mas sofri um pouco antes de achar isso.

Trata-se de você não ter que ver isso quando abre o terminal no Windows.



Nosso velho "amigo" é um pouco feioso né? Quem já usou Linux sabe que os terminais do Linux são bonitos e cheios de funcionalidades, e muitas vezes é bem mais fácil (para alguns) digitar um comando no terminal que ficar clicando aqui e ali e lá. 
O pior é quando você se vê obrigado a usar o windows já tendo usado Linux.

Felizmente, existem alguns terminais bem legais pra windows que vão ajudar bastante. São chamados de "emuladores de terminal", porque na prática não substituem o terminal do windows, só estendem as funcionalidades e escondem a cara feia dele.

O que gostei mais foi o Cmder. Vejamos um trecho traduzido do site oficial (http://cmder.net):

"Cmder é um pacote de software criado pela pura frustração sobre a falta de bons emuladores de console no Windows. É baseado em softwares incríveis, e temperado com o esquema de cores Monokai e um layout personalizado, com visual sexy desde o início."



Ele já vem com alguns comandos do Linux que você pode usar à vontade, como por exemplo o superte ao git e o ssh/scp. A única coisa que achei chatinha é o que eu considero um BUG: o comando history -c parece que não está funcionando. Mas você pode apagar as linhas do arquivo .history que fica dentro da pasta cmder\config que tem o mesmo efeito.
E como no Cmder você pode definir seus próprios comandos, você pode definir um comando personalizado para apagar o histórico: abra o arquivo "user-alses.cmd" que fica na pasta "config" e inclua a seguinte linha:

hc.=echo clear > %CMDER_ROOT%\config\.history

Feche e abra o Cmder.

Assim quando você digitar "hc." e der enter, os únicos comandos que ficarão são os comandos que você digitou na ultima sessão, antecedidos de "clear".

LAMP no Debian e distribuições baseadas

Um assunto já exaustivamente documentado em vários sites da internet é como instalar a pilha LAMP no Debian (Linux + Apache + MySql + PHP).

Acontece que acabam viajando na maionese e complicando uma coisa que é simples, falando coisas desnecessárias e não explicando todo que tem que explicar.

Se você só quer o LAMP instalado de forma padrão, basta como root executar no terminal:

apt-get update && apt-get install apache2 mysql-server php5 php5-dev php5-mysql php-pear phpmyadmin

Será exibido a lista de pacotes que serão instalados, confira e pressione y, ou s se você estiver usando o Debian em português.

Em seguida será solicitado que você defina a senha do MySql.
Não é obrigatório, porque depois você pode defini-la conforme vou explicar abaixo, mas é bom já definir uma senha agora. Informe a senha e confirme:




CONFIGURAÇÃO DO PHPMYADMIN

Irá aparecer a tela abaixo, selecione a primeira opção:



A seguir, se você definiu uma senha para o MySql será solicitada. Isso é para que o phpmyadmin possa fazer algumas configurações automáticas. Depois será solicitado a senha de administração do phpmyadmin, note que são senhas distintas.

Depois disso você poderá acessar o phpmyadmin pelo navegador conforme abaixo:




LIBERANDO ACESSO REMOTO


Por padrão o acesso remoto no MySql é restrito ao servidor local. Se você quer liberar o acesso na rede, para poder por exemplo acessar de um programa cliente ou de uma IDE faça o seguinte logado como root:
nano /etc/mysql/my.cnf


Econtre a linha "bind-address  =  127.0.0.1" e coloque um # (sharp) na frente dela, assim:

#bind-address  =  127.0.0.1

Agora faça loguin no MySql:

mysql -u root -p 

Depois de logado execute:

GRANT ALL ON *.* TO 'root'@'%' IDENTIFIED BY 'suasenha';
quit

Isso vai liberar direto ao MySql para todas a maquinas da rede. Você pode liberar o acesso por IP também colocando @'numero-do-ip', em vez de @'%', mas eu acho melhor você fazer esse controle de acesso via firewall, porque é mais fácil.
Mas enfim, reinicie o MySql e o acesso estará liberado:
invoke-rc.d mysql restart


COMO RESETAR/DEFINIR A SENHA DO MYSQL

Se por algum motivo você não informou na instalação a senha do ROOT do banco de dados MySql, ou esqueceu (acontece), até onde eu sei não é possível recuperar...Mas segue os passos para reseta-la, como root execute isso para PARAR o SGBD (testado no MySql 5):


sudo /etc/init.d/mysql stop

Agora inicie o MySql em modo de segurança:


sudo mysqld_safe --skip-grant-tables &

Depois faça loguin como root (como o MySql está executando em modo de segurança não será solicitado senha):


mysql -u root

 Agora basta resetar a senha:

use mysql;

update user set password=PASSWORD('a-nova-senha-vai-aqui') where User='root';

flush privileges;

quit

Agora reinicie o MySql e pronto:


sudo /etc/init.d/mysql stop 

sudo /etc/init.d/mysql start

Versões descontinuadas do Debain - apt

Uma dica rápida mas que pode ser útil se por algum motivo você precisar um dia instalar pacotes em uma versão descontinuada do Debian. Se você não sabe o que é Debian dê uma olhada aqui.

Considere por exemplo que você tem que instalar um pacote no Debian Squeeze (Debian versão 6).

Se você não sabe qual é a versão do seu Debian execute o comando "cat /etc/issue" ou "cat /etc/debian_version", deverá ver algo assim:

root@debian6:/home/oracle# cat /etc/issue
Debian GNU/Linux 6.0 \n \l

root@debian6:/home/oracle# cat /etc/debian_version 
6.0.10
root@debian6:/home/oracle# 

 
Mas voltando o assunto, se você está com o sources.list original e estiver com uma versão descontinuada do Debian, ao Executar:

apt-get update

Você receberá erros parecidos com esses no terminal:

Err http://ftp.br.debian.org squeeze/main Sources
  404  Not Found [IP: 200.236.31.3 80]
Err http://ftp.br.debian.org squeeze/main amd64 Packages
  404  Not Found [IP: 200.236.31.3 80]
W: Failed to fetch http://ftp.br.debian.org/debian/dists/squeeze/main/source/Sources.gz  404  Not Found [IP: 200.236.31.3 80]

W: Failed to fetch http://ftp.br.debian.org/debian/dists/squeeze/main/binary-amd64/Packages.gz  404  Not Found [IP: 200.236.31.3 80]

E: Some index files failed to download, they have been ignored, or old ones used instead.

Isso acontece porque a distribuição foi descontinuada e os pacotes foram movidos para outro lugar. Ao tentar atualizar a lista de pacotes o Debian não encontra os pacotes e mostra esses erros.

Para resolver isso altere seu arquivo sources.list que fica no diretório /etc/apt/ e deixe descomentadas apenas as seguintes linhas:

deb http://archive.debian.org/debian/ squeeze main non-free contrib
deb-src http://archive.debian.org/debian/ squeeze main non-free contrib

Salve o arquivo e como root execute novamente:

apt-get update

Se tudo deu certo a lista de pacotes foi atualizada com sucesso, e você deve ver uma saída +/- assim:


root@debian6:/home/oracle# apt-get update
Hit http://archive.debian.org squeeze Release.gpg
Ign http://archive.debian.org/debian/ squeeze/contrib Translation-en
Ign http://archive.debian.org/debian/ squeeze/contrib Translation-en_US
Ign http://archive.debian.org/debian/ squeeze/main Translation-en
Ign http://archive.debian.org/debian/ squeeze/main Translation-en_US
Ign http://archive.debian.org/debian/ squeeze/non-free Translation-en
Ign http://archive.debian.org/debian/ squeeze/non-free Translation-en_US
Hit http://archive.debian.org squeeze Release
Hit http://archive.debian.org squeeze/main Sources
Hit http://archive.debian.org squeeze/non-free Sources
Hit http://archive.debian.org squeeze/contrib Sources
Hit http://archive.debian.org squeeze/main amd64 Packages
Hit http://archive.debian.org squeeze/non-free amd64 Packages
Hit http://archive.debian.org squeeze/contrib amd64 Packages
Reading package lists... Done
root@debian6:/home/oracle# 

segunda-feira, 26 de setembro de 2016

LibreOfifce Calc como ferramenta de análise de cadência de vendas

Conforme já comentei em outros posts a maioria das pessoas ainda não gosta de usar o LibreOffice e preferem usar o Microsoft Office pirateado. Se você não sabe o que é LibreOffice dê uma olhada aqui.

Dependendo do uso que você faz do Office você não precisa dele, não precisa comprá-lo. 
É como usar um carro esportivo só para andar dentro da cidade sem nunca ir em uma pista de corrida. Além de gastar mais dinheiro você não usa nem metade do que o carro te oferece. Isso é desnecessário.

Hoje vamos resolver um problema moderado usando um aplicativo da suíte LibreOffice, o Calc, usando a formula de desvio padrão que ele oferece.

Imagine o seguinte cenário:

Você é o gerente de uma grande equipe de vendedores, e de repente você descobre que por algum motivo alguns vendedores não vendem durante alguns dias da semana, ou seja, estão concentrando o faturamento da empresa em apenas alguns dias sendo que poderiam "cadenciar" a venda, ou seja, buscar vender pelo menos um pouco todo dia.
Então você chama sua equipe de vendas e informa que devem vender todo dia.

No final da semana você pede que cada um informe a quantidade média de vendas por dia e obtêm os seguintes dados:



Aparentemente todos cumpriram com o combinado, mas intrigado você decide levantar os dados na contabilidade e descobre que na verdade as vendas ocorreram +/- dessa forma:



Olhando o relatório da contabilidade acima você percebe que em muitos dias não ouve vendas. Até parece que os vendedores mentiram, mas você faz uma conferência por amostragem das médias de vendas diárias e vê que elas "batem". Logo vê que não é possível determinar a cadência de vendas através da média.

Aqui temos apenas 6 vendedores só para não ficar uma imagem muito grande, mas imagine que sejam 200. Também note que no mundo real os vendedores irão vender quantidades de produtos diferentes entre si. Imagine também que alem dos dados da semana você gostaria também dos dados do mês inteiro.

E agora? Como descobrir rapidamente quais os vendedores não cumprem com o combinado? E até mesmo fazer um ranking dos melhores e dos piores com respeito à cadência de vendas? 
Simples: você pode calcular o desvio padrão do período por vendedor.

O QUE É DESVIO PADRÃO
Se já sabe o que é desvio padrão vá para a próxima parte.

Vejamos uma definição:

"Em Probabilidade e Estatística, o desvio padrão é a medida mais comum da dispersão estatística (representado pelo símbolo sigma, σ). Ele mostra o quanto de variação ou "dispersão" existe em relação à média (ou valor esperado). Um baixo desvio padrão indica que os dados tendem a estar próximos da média; um desvio padrão alto indica que os dados estão espalhados por uma gama de valores.

O desvio padrão define-se como a raiz quadrada da variância. É definido desta forma de maneira a dar-nos uma medida da dispersão que:

Seja um número não-negativo;
Use a mesma unidade de medida dos dados fornecidos inicialmente.

Faz-se uma distinção entre o desvio padrão σ (sigma) do total de uma população ou de uma variável aleatória, e o desvio padrão de um subconjunto em amostra." - fonte https://pt.wikipedia.org/wiki/Desvio_padr%C3%A3o

OK, li 2x e não entendi nada...

Rsrs, não se preocupe, vamos simplificar. 

Desconsidere a diferença entre "desvio padrão amostral x desvio padrão populacional", para esse exemplo os 2 servem, mesmo assim vamos usar o populacional. 

Se não entendeu nada até aqui, então entenda o seguinte:

Veja esse alvo de tiro usado por duas pessoas diferentes:


A que conclusão podemos chegar? - O cara da direita tem Mal de Parkinson e não mexa com o cara da esquerda! kkkk Sim, esta conclusão pode ser correta... mas o ponto não é esse!


Imagine que esse alvo é na verdade um plano cartesiano e a "mosca" do alvo representa uma média que estamos buscando atingir. No caso dos alvos seria a coordenada 0,0, e no caso das vendas que vimos acima seria 1 venda por dia, totalizando 6 vendas ao final da semana.

No alvo da esquerda os tiros mais próximos da média são como dados homogêneos, ou seja, a maioria tem valor bem próximo da coordenada 0,0 e portanto os valores são próximos entre si - homogêneos/próximos. Se calcularmos o desvio padrão disso ele será próximo de 0,0.

Já no alvo da direita, se os buracos de bala fossem coordenadas numéricas e calculássemos o desvio padrão, o número seria bem, mas bem maior mesmo que zero, mostrando que as coordenadas são como dados heterogêneos/dispersos em relação à média (lembre nesse exemplo a média é a mosca do alvo).


Então podemos dizer que: 

Dados homogêneos (dispersão menor) = desvio padrão menor.

Dados heterogêneos (dispersão maior) = desvio padrão maior.


Veja novamente:


Vejamos agora novamente a planilha de vendas, mas agora com uma coluna que calcula o desvio padrão das vendas de cada vendedor em relação aos dias úteis da semana:




Agora podemos ver claramente que o único vendedor do nosso exemplo que cumpriu a risca o combinado foi o "vendedor C", pois o cálculo do desvio padrão das vendas dele foi igual a zero - ele acertou na mosca!
E em contraste com ele o "vendedor Z" não fez caso do combinado, ele ficou 4 dias da semana sem vender nada e só fez vendas Sexta e sábado, podemos ver que o desvio padrão dele é o maior de todos!
Nessa planilha também podemos aplicar filtros e classificar os dados pela coluna do desvio padrão do menor para a maior, para facilitar a análise dos dados:


Conforme eu disse no início do post, muitas funções de cálculo que estão disponíveis no M$ Office, também estão no LibreOffice, e o uso delas é simples em ambos, com pequenas diferenças entre si, mas basta se acostumar com o funcionamento do LibreOffice.

Criando uma API em C para usar com CFFI - PostgreSQL

Uma lib bem legal do Postgres é a libpq . Instalação no Debian 7, 8 e 9: sudo apt update && sudo apt install libpq-dev Ela po...