Páginas

terça-feira, 18 de dezembro de 2012

SQL*Loader

É possível utilizar os utilitários  Export e Import do Oracle para extrair ou importar grandes quantidades de dados de um banco de dados Oracle, respectivamente. Entretanto, esses utilitários sofriam da limitação de serem ferramentas cliente/servidor.

A versão 10g do Oracle introduziu o recurso de Data Pump. Funcionalmente falando, os resultados obtidos são os mesmos dos “velhos” Export e Import, entretando, as suas implementações são completamente diferentes, pois os processos do Data Pump rodam d

Tanto os utilitários Export, Import e Data Pump leêm e escrevem arquivos em formato proprietário do Oracle. Mas o que fazer quando se quer fazer um upload de grandes quantidades de dados gerados a partir de um outro sistema que não o Oracle? Nestes casos, podemos utilizar o SQL*Loader.

O SQL*Loader utiliza um arquivo de input onde são localizados os dados que serão carregados no banco de dados, um arquivo de controle (controlfile) utilizado para definir a forma de interpretar o conteúdo do arquivo de input e um arquivo de erro, no qual serão registradas as falhas e o

O controlfile nada mais é que um arquivo de texto que diz ao SQL*Loader como processar os arquivos de input. Os formatos que o SQL*Loader é capaz de entender são o de registro fixo, registro variável e o de registro de stream.

  • Os formatos de registro fixo são os mais simples e os que possuem processamento mais rápido. No exemplo abaixo cada linha de dados possui uma extensão fixa que termina com o caractere de retorno carriage return). Dentro das linhas, é utilizado algum caractere como delimitador dos campos. O controlfile deste exemplo lerá o arquivo fixed.dat, realizará o parsing em linhas de 15 bytes, dividirá as linhas em 2 campos e as inserirá nas colunas “first” e “last” da tabela “names”.
Controlfile:
load data
infile ‘fixed.dat’ “fix 15”
into table names
fields terminated by ‘,’
(first, last)

Arquivo de input (fixed.dat)
Ricardo,Wandre
Luiz,Carlossss
Thiago,Gottiii
  • Os registros variáveis possuem uma entrada no início de cada linha para informar sua extensão. A extensão dessa entrada deve ser incluída no controlfile. Repare que no exemplo abaixo do arquivo de input, cada linha apresenta um número de 3 dígitos, de acordo com o que foi especificado no controlfile.
Controlfile:
load data
infile ‘names.dat’ “var 3”
into table names
fields terminated by ‘,’
(first, last)

Arquivo de input (names.dat)
015Ricardo,Wandre
012Luiz,Carlos
013Thiago,Gotti
  • No formato de registro de stream nenhuma informação sobre a extensão das linhas é fornecido ao SQL*Loader. O controlfile e o arquivo de input podem ser vistos abaixo. Repare que neste controlfile o caracter ‘\n’ é utilizado para especificar onde termina uma linha.
Controlfile:
load data
infile ‘names.dat’ “str ‘\n’”
into table names
fields terminated by ‘,’
(first, last)

Arquivo de input (names.dat)
Ricardo,Wandre
Luiz,Carlos
Thiago,Gotti

Com relação à velocidade de processamento temos que o formato de registro fixo é mais rápido que o de registro variável que, por sua vez, é mais rápido que o de registro de streams.

A linha de comando necessária para executar o SQL*Loader é:

sqlldr userid=<nome_administrador>/<senha> control=<arquivo_de_controle.ctl>

Obs: Ao contrário do Data Pump o SQL*Loader não é um utilitário que roda no servidor, mas sim um processo de usuário que estabelece uma sessão com a instância e no banco de dados é executado através de um processo servidor normal.

quarta-feira, 5 de dezembro de 2012

[Linux] Ver andamento de uma cópia (cp) com o comando watch

O comando cp pode ser utilizado para copiar dados entre pastas do linux.
Muitas vezes é bom saber o andamento, para quem sabe, fazer uma pausa para o café.
Por isso, um comando essencial é o watch.
O comando watch repete um comando linux a cada 2 seg (isso pode ser alterado, veja o man do watch - man watch).

Suponha que vc fez uma cópia recursica do diretório X para o diretório Y, ou seja, todos os arquivos da pasta X vão ser copiados para a pasta Y:
  • cp -R /caminho/X /caminho/Y &
A cópia é iniciada, porém, vc não sabe o quanto de dados que já foram transferidos.

Para saber isso, basta entrar no diretório Y
  • cd /caminho/Y
E executar o comando:
  • watch du -ks .
  • Na linha de cima, não esqueça de colocar o último ponto após o -ks
Isso vai fazer com que o comando du seja executado (disk usage), exibindo quantos kbytes já foram copiados (ks);

É isso.

domingo, 28 de outubro de 2012

[C++] Lista de argumentos com tamanho variável


Nem todas as linguagens de programação permitem criar sub-rotinas com o número variável de parâmetros.  Entretanto, C/C++ permitem a criação deste tipo de sub-rotina. Para isso, utiliza-se reticências (...) em um protótipo de uma função que pode receber um número variável de argumentos não importando seus tipos. Deve-se notar que as reticências devem ser colocadas no final da lista de argumentos. Macros e definições do cabeçalho de argumentos variáveis <cstdarg> são utilizados para se obter os recursos necessários para a construção deste tipo de função.

A função soma desenvolvida utiliza todas as definições de macros do cabeçalho <cstdarg>. O objeto lista, do tipo va_list, é utilizado pelas macros va_start, va_arg e va_end para processar a lista de argumentos da função soma.

Macros:
  • va_list: tipo utilizado para armazenar informações para as macros va_arg e va_end. É necessário declarar um objeto do tipo va_list para acessar os argumentos de uma lista de argumentos de tamanho variável.
  • va_start: macro chamada antes que seja possível acessar os argumentos da lista de tamanho variável. Esta macro inicializa o objeto declaro com va_list.
  • va_arg: esta macro é expandida para uma expressão de valor e tipo do próximo argumento da lista. Sempre que invocada, esta macro irá modificar o objeto declarado com va_list para que seja apontado para o próximo objeto da lista.
  • va_end: utilizada para facilitar o retorno de uma função cuja a lista de argumentos tenha sido referenciada por va_start.

Exemplo:


#include <iostream>
#include <cstdarg>

using std::cout;
using std::endl;

int soma(int, ...);

int main(int argc, char** argv) {

        int x = 1, y = 2, z = 3;

cout << "x = " << x << endl;
cout << "y = " << y << endl;
cout << "z = " << z << endl;

cout << "A soma de x e y é: " << soma(2, x, y) << endl;
cout << "A soma de x, y e z é: " << soma(3, x, y, z) << endl;

return 0;
}

int soma(int i, ...) {

int total = 0;
va_list lista;

va_start(lista, i);

for (int j = 1; j <= i; j++)
total += va_arg(lista, int);

va_end(lista);

return total;
}

Resultado:
x = 1
y = 2
z = 3
A soma de x e y é: 3
A soma de x, y e z é: 6

É isso, divirtam-se.

segunda-feira, 15 de outubro de 2012

[Android] Adicionando botões dinamicamente na tela da aplicação.


Estava eu estudando um pouco de android (comecei a brincar disso esses dias) e queria colocar objetos diferentes na tela do meu aplicativo dependendo da ação realizada pelo usuário.

A ideia era que se o usuário pressionasse o botão 1 alguns objetos aparecessem na tela, mas se o botão 2 fosse pressionado, outros objetos aparecessem.

Fiquei lendo alguns tutoriais pra descobrir uma forma de fazer isso, mas não encontrei a resposta em um único lugar, por esta razão, depois de ler vários tutoriais e descobrir como fazer resolvi escrever este post.

A minha ideia foi criar dois frames, no primeiro frame haveriam 2 botões (botão 1 e botão 2 - bem criativo). Se o botão 1 fosse pressionado, apareceriam os botões 3 e 4 no frame 2. Caso fosse pressionado o botão 2, os botões 5, 6 e 7 apareceriam no frame 2.

Vejam, assim como foi feito com botões, poderiam ter sido utilizados outros objetos. É que fazer com botões era mais fácil e num precisava de muita criatividade, por isso optei por essa opção. (Na verdade, eu nem acho que tinha uma opção, mas isso não é assunto pra esse blog).

Pois bem, pra montar meu super projetinho foi utilizado o eclipse INDIGO (Xupa JUNO).

Inicialmente eu criei um projetinho android no eclipse com os seguintes passos:

File -> New -> Android Application Project

Tela New Android Application:

Application Name = BotoesInterativos
Project Name = BotoesInterativos
Package Name = com.example.botoesinterativos
Build SDK = Android 4.1 (API16)
Minimum Required SDK = API8: Android 2.2 (Froyo)

Clicar NEXT

Tela Create Activity:

Selecionar o checkbox 'Create Activity'
Selecionar a opção BlankActivity

Clicar NEXT

Tela New Blank Activity

Activity Name = MainActivity
Layout_name = activity_main
Navigation Type = None
Title = MainActivity

Pronto, uma vez criado o projeto, iremos alterar o arquivo activity_main.xml que se encontra no diretório res/layout. Este arquivo tem o seguinte formato.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:id="@+id/frameLayout1"
        android:layout_marginLeft="10dp"
        android:layout_marginTop="10dp"
              android:background="#ABABAB">
   
            <Button
                     android:id="@+id/botao1"
                     android:layout_width="90dp"
                     android:layout_height="35dp"
                     android:text="Botão 1"
                     android:textSize="10sp"/>
            <Button
                     android:id="@+id/botao2"
                     android:layout_width="90dp"
                     android:layout_height="35dp"
                     android:text="Botão 2"
                     android:layout_toRightOf="@+id/botao1"
                     android:textSize="10sp"
                     android:layout_centerHorizontal="true"/>
       </RelativeLayout>
      
    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="50dp"
        android:layout_below="@+id/frameLayout1"
        android:id="@+id/frameLayout2"
        android:layout_marginTop="10dp"
        android:layout_marginLeft="10dp"
        android:background="#ABABAB">

              <TableLayout
            android:id="@+id/tableLayoutFrame2"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:scrollbars="horizontal"
            android:shrinkColumns="0">
           
              </TableLayout>
          
    </RelativeLayout>
</RelativeLayout>

Observe que foram utilizados 2 RelativeLayout. No primeiro, existem os botões 1 e 2, enquanto que no segundo existe um TableLayout que será utilizado para colocarmos os demais botões dinamicamente.

Em seguida, alteramos o arquivo MainActitivity.java para ficar da seguinte forma:

package com.example.botoesinterativos;

import android.os.Bundle;
import android.app.Activity;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.view.View;

public class MainActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
       
        final TableRow tr = new TableRow(this);
       
        //Botões para opção botão 1
        final Button botao3 = new Button(this);
        final Button botao4 = new Button(this);
       
        botao3.setText("Botão 3");
        botao4.setText("Botão 4");
       
        botao3.setTextSize(10);
        botao4.setTextSize(10);
       
        botao3.setWidth(135);
        botao4.setWidth(135);
       
        botao3.setMinimumHeight(30);
        botao4.setMinimumHeight(30);
       
        botao3.setHeight(35);
        botao4.setHeight(35);
       
        //Botões para opção botão 2
        final Button botao5 = new Button(this);
        final Button botao6 = new Button(this);
        final Button botao7 = new Button(this);
       
        botao5.setText("Botão 5");
        botao6.setText("Botão 6");
        botao7.setText("Botão 7");
       
        botao5.setTextSize(10);
        botao6.setTextSize(10);
        botao7.setTextSize(10);
       
        botao5.setWidth(135);
        botao6.setWidth(135);
        botao7.setWidth(135);
       
        botao5.setMinimumHeight(30);
        botao6.setMinimumHeight(30);
        botao7.setMinimumHeight(30);
       
        botao5.setHeight(35);
        botao6.setHeight(35);
        botao7.setHeight(35);
       
        final Button botao1 = (Button) findViewById(R.id.botao1);
        botao1.setOnClickListener(new View.OnClickListener() {
                    
                     public void onClick(View v) {
                          
                           //Obtém o TableLayout
                           TableLayout ll = (TableLayout) findViewById(R.id.tableLayoutFrame2);
                          
                           //Limpa as views criadas anteriormente
                           tr.removeAllViews();
                           ll.removeAllViews();
                          
                           //Adiciona os botões à tabela
                           tr.addView(botao3);
                           tr.addView(botao4);
                          
                           int lHeight = RelativeLayout.LayoutParams.FILL_PARENT;
                           int lWidth = RelativeLayout.LayoutParams.WRAP_CONTENT;

                           //Adiciona a tabela ao TableLayout
                           ll.addView(tr, new RelativeLayout.LayoutParams(lHeight, lWidth));
                     }
              });
       
        final Button botao2 = (Button) findViewById(R.id.botao2);
        botao2.setOnClickListener(new View.OnClickListener() {
                    
                     public void onClick(View v) {
                          
                           //Obtém o TableLayout
                           TableLayout ll = (TableLayout) findViewById(R.id.tableLayoutFrame2);
                          
                           //Limpa as views criadas anteriormente
                           tr.removeAllViews();
                           ll.removeAllViews();
                          
                           //Adiciona os botões à tabela
                           tr.addView(botao5);
                           tr.addView(botao6);
                           tr.addView(botao7);
                          
                           int lHeight = RelativeLayout.LayoutParams.FILL_PARENT;
                           int lWidth = RelativeLayout.LayoutParams.WRAP_CONTENT;

                           //Adiciona a tabela ao TableLayout
                           ll.addView(tr, new RelativeLayout.LayoutParams(lHeight, lWidth));
                     }
              });
       
    }   
}


Note que nesta classe é criado um objeto tr (TableRow). Cada objeto inserido neste TableRow será uma coluna da tabela. Em seguida, são criados os botões 3, 4, 5, 6 e 7. O próximo passo é criar os eventos que serão utilizados pelos botões 1 e 2 para que os botões 3, 4, 5, 6 e 7 possam aparecer na tela.

As figuras abaixo mostram como ficou a tela da aplicação. Na primeira figura, nenhum botão foi pressionado. Na segunda, o botão 1 foi pressionado e apareceram os botões 3 e 4. Na última figura, o botão 2 foi pressionado e apareceram os botões 5, 6 e 7.






Viram só, simples como a vida tem que ser.

[Linux] Acessando a wireless com criptografia WPA pelo terminal do Linux.

Uma boa ferramenta para ajudar na conexão wireless pelo terminal do Linux é o wpa_supplicant. Este utilitário ajuda a configurar a rede com criptografia WPA de um modo simples.


Para utilizá-lo é preciso criar (ou editar se já existir) um arquivo em /etc, chamado wpa_supplican.conf (/etc/wpa_supplican.conf); para isso, é necessário ser super usuário (sudo no ubuntu e afins e su no Slackware).

Abra o arquivo e adicone as linhas ao final do arquivo:

network={
        scan_ssid=0
        ssid="MyNetwork"
        psk="MyPass"
        proto=WPA RSN
        key_mgmt=WPA-PSK WPA-EAP
        pairwise=CCMP TKIP
        group=CCMP TKIP
}

Onde:
                    MyNetwork é o nome da rede em que vc quer acesso
                    MyPass é a chave utilizada para ter acesso à rede

Pronto; para conectar, basta executar no terminal:

wpa_suppliant -Dwext -iwlan0 -c /etc/wpa_suppliant.conf &

Para obter um endereço de rede (no caso de usar dhcp), execute:

dhcpcd -d wlan0

Lembre-se:
  • Estou assumindo que sua interface wireless está definida em wlan0
  • Certifique-se que a interface wlan0 está ativa. Para isso execute o comando ifconfig -a; deverá aparecer a interface wlan0. Caso nao veja a interface, ative-a com ifconfig wlan0 up e volte a executar os comandos acima.
 Ao final, deve-se obter alguma coisa do tipo:

wlan0     Link encap:Ethernet  HWaddr 00:02:72:9b:a7:e0 
          inet addr:192.168.1.107  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fe80::202:72ff:fe9b:a7e0/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:339700 errors:0 dropped:0 overruns:0 frame:0
          TX packets:208785 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:400332866 (400.3 MB)  TX bytes:27863221 (27.8 MB)



Quaquer dúvida, pergunte!

[Oracle] Estruturas de Armazenamento - Tablespaces e Arquivos de Dados

A forma de armazenamento em um banco de dados Oracle pode ser analisada pelo lado físico ou lógico. Analisando de forma física, os componentes de armazenamento são vistos como arquivos  de dados (nível do sistema operacional). Já o armazenamento lógico é a forma como o Oracle gerencia, de forma interna, os objetos que estão armazenados no banco de dados.

Considerando o modelo de armazenamento utilizado pelo Oracle, temos que:
  1. A base de dados deve ser formada por um ou mais tablespaces, sendo que todo tablespace deve pertencer a apenas um banco de dados.
  2. Todo tablespace é formado por um ou mais arquivos de dados e cada arquivo de dados pertence a somente um tablespace.
  3. O arquivo de dados é formado por um ou mais blocos do SO. Cada bloco do SO pode pertencer a apenas um arquivo de dados.
  4. O tablespace é formado por um segmento ou mais, sendo que o segmento deve existir em apenas um tablespace.
  5. Todo segmento é formado por extensões. Cada segmento pode existir em somente um tablespace.
  6. A extensão é formada de um ou mais blocos do Oracle. Cada um desses blocos pode pertencer a somente uma extensão.
  7. Cada extensão estã localizada em um arquivo de dados. Um espaço no arquivo de dados pode ser alocado na forma de uma ou várias extensões.
  8. Todo bloco do Oracle constitui de um ou mais blocos do SO.
O esquema descrito acima pode ser visto na seguinte figura:



Estruturas de Armazenamento Físicas

Chamamos de estrutura física aquilo que o sistema operacional “vê” quando “olha” para uma base de dados Oracle, pois trata-se de um conjunto de arquivos de dados. Também pode-se utilizar partições de um disco que não está sendo gerenciada pelo SO para armazenar os arquivos de dados, entretanto, isso introduz certa complexidade (e eu num manjo nada disso). Também é possível que o Oracle gerencie ele mesmo o armazenamento da estrutura física utilizando ASM (Automated Storage Management), nestes dois últimos casos o SO não está envolvido.

Arquivos de Dados Oracle

Quando um banco de dados é criado, também é criada uma série de arquivos para armazenar o dicionário de dados e os dados do tablespace SYSAUX, além de outros tablespaces que o DBA tenha resolvido criar. Estes arquivos de dados consistem de um cabeçalho que o identifica como parte de um banco de dados Oracle, de informações sobre a qual tablespace ele pertence e qual o último checkpoint realizado. O restante do arquivo é formado por extenões e espaço livre.

Blocos do Sistema Operacional

São a unidade mínima cuja a alocação é possível para o sistema de arquivos. Os seus tamanhos podem variar dependendo do sistema de arquivos, sendo que a maioria dos sistema permite configurar o tamanho dos blocos durante a formatação do disco. Por questão de desempenho é aconselhável manter o tamanho dos blocos do sistema operacional igual ao tamanho dos blocos Oracle. Obs: é possível criar tablespaces com tamanhos de blocos diferentes dentro do mesmo banco de dados.

Estruturas de Armazenamento Lógicas

A estrutura lógica é formada pelos tablespaces, segmentos e extensões. No banco de dados Oracle são necessários pelo menos 3 tablespaces (de preferência mais) considerando o Oracle 10g. Nas versões anteriores eram necessário apenas 1 tablespace.

Tablespaces

É a maior estrutura dentro de um banco de dados e todo banco de dados Oracle 10g precisa de pelo menos três tablespaces:
  • SYSTEM: Utilizado para armazenar o dicionário de dados além dos objetos do esquema SYS.
  • SYSAUX: Armazena os objetos que não são do usuário SYS, mas que são essenciais ao funcionamento do banco de dados. Este tablespace é utilizado, por exemplo, para armazenar estatísticas do banco de dados.
  • UNDO: É utilizado para armazenar as informações de UNDO. Essas informaçõe permitem que usuários leiam linhas de uma tabela, de forma consistente, enquanto elas  estejam sendo modificadas.
Quando um banco de dados é criado com o DBCA (Assistente de Configuração de Banco de Dados – sigla em inglês), além dos tablespaces acima, também são criados os tablespaces TEMP e USERS. Nota o tablespace de UNDO é criado com o nome UNDOTBS1.
  • TEMP: Utilizado para armazenar dados temporários do banco de dados, por exemplo, conteúdo de tabelas temporárias. Além disso, é utilizado como espaço para classificação de dados. Embora não seja um tablespace obrigatório, é altamente recomendado a sua criação.
  • USERS: É utilizado para armazenar os dados dos usuários. Este é o tablespace padrão que pode ser utilizado pelos usuários do banco de dados (exceto SYS e SYSTEM).
Os tablespaces podem ser classificados como SYSTEM ou não-SYSTEM: No Oracle 10g, apenas os tablespaces SYSTEM e SYSAUX são considerados tablespaces SYSTEM, os demais são não-SYSTEM.

Segmentos

Os segmentos são alocados dentro dos tablespaces. Um segmento nada mais é do que um objeto do banco de dados que requer armazenamento, por exemplo, um índice ou uma tabela. É permitido criar vários tipos diferentes de segmentos, sendo que a view DBA_SEGMENTS exibe todos os segmentos criados no banco.

SELECT DISTINCT segment_type FROM DBA_SEGMENTS;

Extensões

São formadas por blocos contíguos, podendo ser gerenciadas de forma automática ou manual. Quando é alocado espaço para criação de segmentos em um tablespace, é também alocada uma extensão de cada vez (o segmento é formado por uma ou mais extensões.) As extensões podem ser gerenciadas de forma local (recomendado) ou no dicionário de dados (existente por questão de compatibilidade com versões anteriores ao Oracle 10g).

Blocos do Banco de Dados

São as menores unidades de E/S do banco de dados. Isto significa que quando o banco precisa ler dados do disco, todo o bloco onde o dado está contido deve ser lido. A mesma coisa ocorre na escrita mesmo que uma única linha de um bloco tenha sido alterada. Nota: não é possível alterar o tamanho dos blocos de dados de um tablespace depois dele ter sido criado.