março 2010
março 2010
índice
Delphi
Delphi
Editorial
04
Espero que nesse mês todos
tenham recebido
muitos ovinhos do
coelhinho. Quem
não recebeu seja
um bom menino...
Banco de Dados
14
05
Utilizando componentes ABCr no
Delphi 2010
Autor: Antonio Spitaleri
Autor: Antonio Spitaleri
Banco de Dados
19
Indo mais além eplorando as
tabelas de sistema
Interbase/Firebird
Stored Procedures e Triggers no
MySQL
Autor: Felipe Santos
Autor: Bruno Alcarás
Dicas
- Dicas Delphi
10
Manipulando Streams no Delphi
2010
.NET
24
Novidades do Visual Studio 2010
Autor: Djonatas Tenfen
Desafio The Club
28
- Cruzada
30
Legenda
Iniciante
Intermediário
Avançado
março 2010
03
Bem-vindo
Espero que nesse mês todos tenham recebido muitos ovinhos do coelhinho.
Quem não recebeu seja um bom menino ou menina que no próximo ano ele
vem.
Aproveito para convidar nossos leitores a comparecerem ao “Microsoft
TechDay” que será realizado em Blumenau-SP no dia 24/04 e que tem com um
dos idealizadores nosso colunista Djonatas Tenfen. O The Club tem prazer em
apoiar essa iniciativa. Tenho certeza que será um grande evento. Saiba mais
acessando: www.mstechday.com
Av. Profº Celso Ferreira da Silva, 190
Jd. Europa - Avaré - SP - CEP 18.707-150
Informações: (14) 3732-1529
Suporte: (14) 3733-1588
Internet
http://www.theclub.com.br
Cadastro: [email protected]
Suporte: [email protected]
Informações: [email protected]
Skype Cadastro: theclub_cadastro
Skype Suporte: theclub_linha1
theclub_linha2
theclub_linha3
Nessa edição temos artigos pra todos os gostos.
Nosso consultor técnico Antonio Spitaleri Neto trabalha dobrado esse mês e
nos apresenta dois artigos. No primeiro, ”Manipulando Streams no Delphi 2010”,
ele fala sobre um recurso presente no Delphi desde o seu início, os Streams, e
que apesar de ser pouco utilizado nos dias de hoje, pode ser muito importante
para alguns pontos específicos dos nossos aplicativos. No segundo, ”Utilizando
os Componente ACBr com Impressoras Fiscais no Delphi 2010” ele fala sobre os
componentes Open Source ACBr que são uma verdadeira “mão na roda” para
nós desenvolvedores trabalharmos com ECF.
Iniciando as páginas dedicadas a Banco de Dados dessa edição, Felipe Santos
com seu artigo “Indo mais além, explorando as tabelas de sistema Interbase/
Firebird” nos mostra como trabalhar com as tabelas de sistema do Interbase/
Firebird visando uma melhor manutenção dos nossos Bancos de Dados.
Nosso consultor Jr. Bruno Alcarás neste mês nos trás o artigo “Stored Procedure
e Triggers no MySQL”, nos dando uma visão geral sobre esses ótimos recursos
que são mais conhecidos em Banco de Dados Firebird mas que também tem um
papel muito importante no desenvolvimento de um Banco MySQL.
Djonatas Tenfen no seu artigo “Novidades do Visual Studio 2010” nos apresenta
as principais novidades dessa nova versão do Visual Studio que foi oficialmente
lançado no dia 12/04.
www.twitter.com/theclubbr
Copyright The Club Megazine 2009
Diretor Técnico
Marcos César Silva
Diagramação e Arte
Vitor M. Rodrigues
Revisão
Tassiane Fileto
Colunistas
Antonio Spitaleri Neto
Bruno Alcarás
Djonatas Tenfen
Felipe Santos
Impressão e acabamento:
GRIL - Gráfica e Editora
Taquarituba-SP - Tel. (14) 3762-1345
Reprodução
A utilização, reprodução, apropriação, armazenamento em banco
de dados, sob qualquer forma ou meio, de textos, fotos e outras
criações intelectuais em cada publicação da revista “The Club
Megazine” são terminantemente proibidos sem autorização
escrita dos titulares dos direitos autorais.
Um grande abraço
Marcos César Silva - Editor Chefe
[email protected]
04
março 2010
Delphi é marca registrada da Borland International,
as demais marcas citadas são registradas
pelos seus respectivos proprietários.
Delphi
Manipulando Streams
no Delphi 2010
FileStream
Entre os vários recursos que existem
desde versões mais antigas do Delphi e ainda
assim são pouco explorados pelos desenvolvedores especializados na ferramenta,
sem dúvida um dos mais destacados são os
Streams. Streams são objetos que remetem
ao início dos tempos da programação, quando
a manipulação de dados era feita byte a byte.
Com o surgimento de novas tecnologias, a utilização dos Streams ficou restrita a situações
em que os mesmos são imprescindíveis.
Nesse artigo estarei abordando de forma
prática o uso dos Streams utilizando a versão
2010 do Delphi. Porém os exemplos funcionam em versões anteriores do Delphi com
pouca ou nenhuma modificação.
Mãos a obra!
Como o próprio nome já sugere, a classe TFileStream, descendente de TStream, manipula arquivos
em disco na forma de Streams. Em geral utilizamos
essa forma de Stream para manipular arquivos de
texto, mas a utilização da mesma para outros tipos
de arquivos é perfeitamente possível.
Inicie uma nova aplicação no Delphi e monte
o layout da mesma conforme a figura 1:
No Delphi existe uma classe base TStream e dela descendem as demais classes de
manipulação de Streams: TMemoryStream,
TFileStream, TBlobStream. Essas três classes
que citei são as mais importantes na manipulação de Streams em Delphi. Apesar de
possuírem diferenças entre si, a forma de
trabalhar com cada uma das três classes é
bem semelhante.
Figura 1
março 2010
05
O que faremos a seguir é carregar um arquivo
texto para um objeto FileStream e em seguida carregar esse Stream no objeto Memo para exibição
do mesmo.
cionado, iremos realizar a carga do mesmo para o
FileStream e exibir o conteúdo do mesmo no objeto
memo que inserimos na aplicação.
Segue o código:
Quando criamos um objeto FileStream no
construtor do mesmo temos de informar além do
caminho do arquivo o modo de abertura desse
arquivo. FileStream nos possibilita quatro formas
de abertura que são:
procedure TForm1.
btnexibirClick(Sender:
TObject);
var
Fmcreate- Caso o arquivo não exista, será
criado. Caso exista, será zerado e a escrita no
mesmo irá sobrescrever seu conteúdo atual;
sFilename:string;
oFileStream:TFileStream;
try
sFilename:=edtcaminho.
Text;
oFileStream:=TFileStream.
Fmopenreadwrite- Abre o arquivo para
leitura e escrita.
Create(sFilename,fmOpenRead);
memstream.Lines.
LoadFromStream(oFileStream);
finally
O primeiro passo será a busca do arquivo com
o OpenDialog, que será feita no evento OnClick do
botão “Carregar”.
end;
end;
btncarregarClick(Sender:
Salve as alterações e teste o aplicativo. Se
tudo correu bem, o resultado será semelhante ao
mostrado na figura 2:
TObject);
var
sFilename:string;
begin
if(OpenDialog1.Execute)
then
sFilename:=OpenDialog1.
FileName;
edtcaminho.
Text:=sFilename;
end;
Com o caminho do arquivo devidamente selemarço 2010
Embora não seja o mais recomendado, todos
os servidores de banco de dados utilizados com
o Delphi aceitam o armazenamento de dados na
forma binária através de campos Blob. Esse tipo de
campo em geral é utilizado para o armazenamento
de imagens no banco de dados, mas pode ser utilizado para armazenar vídeos, textos entre outros
dados de forma binária.
Para se trabalhar com campos Blob nos componentes DataSet existentes no Delphi, podemos
lançar mão de mais duas classes: TBlobStream,
para os componentes BDE, e TMemorystream
ou a própria classe TStream para demais tipos de
DataSets. Com essas classes poderão ser feitos o
envio e recuperação de dados a partir de campos
Blob. Lembrando que para o Stream independe
se o campo Blob contém um texto, uma imagem
ou outra forma de dado. Sua função é apenas
servir de veículo para envio e recuperação dessas
informações.
FreeAndNil(oFileStream);
Segue o código:
procedure TForm1.
Stream com imagens
begin
Fmopenread- Abre o arquivo apenas
para leitura;
Fmopenwrite- Abre o arquivo apenas
para escrita;
Veja a Figura 2.
Figura 2
Vamos a um exemplo prático com Blob em
combinação com outros dois objetos para carga
de imagens. No PageControl de nossa aplicação,
adicione uma nova página e coloque como caption
da mesma “Blobstream”. Em seguida adicione a
página um componente Clientdataset, alterando
seu nome para CdsBlob. Abra o FieldsEditor do
clientdataset e adicione campo Blob com o nome
de IMAGEM. Isso feito clique com o botão direito
sobre o clientdataset e clique em CreateDataSet.
Nesse exemplo estarei trabalhando com
o clientdataset apenas em memória, mas ele
poderia estar ligado a uma fonte de dados sem
problemas.
Com o clientdataset devidamente criado e
configurado, monte o restante do layout da página
conforme a figura 3.
Os outros dois objetos que estaremos utilizando são: TStream para a recuperação do conteúdo
do Blob após o mesmo ter sido carregado. E TJpegImage para armazenar a imagem proveniente do
campo Blob.
Veja a Figura 3.
Lembrando que o componente OpenDialog
não precisa ser criado novamente, será utilizado o
que já havíamos criado na primeira página.
Iremos selecionar o caminho de uma imagem
para em seguida enviá-lo para o Blobstream. Para
a seleção do arquivo, no evento OnClick do botão
“Selecionar” faça:
procedure TForm1.
SelecionarClick(Sender:
TObject);
begin
OpenDialog1.
Filter:=EmptyStr;
OpenDialog1.
Filter:=’Image Files|*.
jpg’;
Figura 3
procedure TForm1.SalvarClick(Sender: TObject);
var
sFilename:string;
oFilestream:TFileStream;
oMemorystream:TStream;
oImage:TJPEGImage;
begin
try
sFilename:=edtcaminhoimg.Text;
oFilestream:=TFileStream.
Create(sFilename,fmOpenRead);
oMemorystream:=TMemoryStream.Create;
oImage:=TJPEGImage.Create;
cdsblob.Open;
cdsblob.Append;
cdsblobIMAGEM.LoadFromStream(oFilestream);
cdsblob.Post;
oMemorystream:=cdsblob.CreateBlobStream(cdsbl
obIMAGEM,bmRead);
oImage.LoadFromStream(oMemorystream);
Image1.Picture.Assign(oImage);
finally
FreeAndNil(oFilestream);
FreeAndNil(oMemorystream);
FreeAndNil(oImage);
end;
Listagem 4
if(OpenDialog1.Execute)
then
edtcaminhoimg.
Text:=OpenDialog1.
seguida salvamos o caminho do arquivo de imagem
na Edit edtcaminho.
FileName;
end;
Alteramos o filtro do OpenDialog para que
apenas aceite imagens com a extensão jpeg e em
Como estamos trabalhando com imagens em
formato Jpeg devemos adicionar na uses da unit a
biblioteca Jpeg.
Iremos agora salvar essa imagem já selecio-
nada em um FileStream, salvá-la no campo blob
e depois recuperá-la com a técnica do blobstream
combinada com o Jpegimage.
Veja a codificação no evento OnClick do botão
“Salvar”:
Veja a listagem 4.
março 2010
07
Repare que o objeto TJpegImage apenas serve
de container provisório para receber a imagem
proveniente do campo Blob.
Com essa técnica podemos salvar e recuperar
imagens em qualquer DataSet que ofereça suporte
aos campos Blob.
Salve as alterações e teste o aplicativo. Um
exemplo de resultado pode ser visto na figura 4:
Veja a Figura 4.
Figura 4
Trabalhando com buffers
Quando trabalhamos com Streams é importante termos em mente que o conteúdo do Stream
irá ocupar uma certa quantidade de memória no
computador. Em algumas situações pode ser importante que tenhamos um controle mais preciso
desse espaço e de como ele será manipulado.
Esse maior controle pode ser conseguido com a
técnica de “bufferização”, que consiste em alocar
previamente um espaço de memória onde o buffer
irá trabalhar. Algo semelhante ao que é feio com
ponteiros em linguagens como C++.
Antes de passarmos a prática com buffers, é
importante destacar duas propriedades importantes de um Stream, que são: Size e Position.
Size retorna um inteiro com o tamanho ocupado pelo Stream, e Position também retorna um
inteiro com a posição atual do cursor de leitura do
Stream. Assim como os datasets, Streams também
possuem um cursor interno responsável pela leitura
dos dados.
Figura 5
Botão “Selecionar Arquivo”:
procedure TForm1.btnarqselecionarClick(Sender:
TObject);
begin
if(OpenDialog1.Execute)then
edtcaminhoarq.Text:=OpenDialog1.FileName;
Vamos a prática. Adicione uma nova página
ao PageControl da aplicação e monte seu layout
conforme a figura 5:
end;
Botão “Copiar”:
Veja a Figura 5.
Nesse exemplo iremos selecionar um arquivo
texto, carregá-lo para um FileStream, em seguida
copiá-lo para outro FileStream com a técnica da
bufferização e exibir seu conteúdo no Memo.
procedure TForm1.btncopiarClick(Sender: TObject);
var
oStreamin,
oStreamout:TFileStream;
aBufferstream:array[0..1023]of Byte;
08
março 2010
iByteRead:integer;
sFilename:string;
begin
try
ProgressBar1.Position:=0;
sFilename:=edtcaminhoarq.Text;
oStreamin:=TFileStream.
Create(sFilename,fmOpenRead);
oStreamout:=TFileStream.Create(‘temp.
txt’,fmCreate);
repeat
iByteRead:=oStreamin.
Read(aBufferstream,1024);
oStreamout.Write(abufferstream,iByteRead);
ProgressBar1.StepBy(1);
until(iByteRead=0);
finally
ProgressBar1.Position:=100;
FreeAndNil(oStreamin);
FreeAndNil(oStreamout);
Memo1.Lines.LoadFromFile(‘temp.txt’);
end;
end;
Veja o aplicativo em execução na Figura 6:
Veja a Figura 6.
Conclusão
Streams são um excelente recurso disponibilizado pelo Delphi quando necessitamos utilizar
técnicas avançadas de manipulação de arquivos
em disco sendo carregados em memória.
Espero que tenham gostado e até a próxima!
Figura 6
Sobre o autor
Antonio Spitaleri Neto
Consultor Técnico The Club.
[email protected]
março 2010
09
Utilizando os componentes
ACBr com Impressoras
Fiscais no Delphi 2010
No dia-a-dia do desenvolvimento voltado
para a área de automação comercial, uma
grande preocupação dos desenvolvedores
é a comunicação do aplicativo com as chamadas impressoras fiscais, conhecidas pela
sigla “ECF”. Para quem trabalha nesse ramo
a algum tempo, a solução mais simples e comumente utilizada eram as dll’s dos próprios
desenvolvedores da ECF utilizada.
Outro ponto importante a se destacar no
Acbr é o fato de utilizar muitos dos conceitos
da orientação a objetos. Conceitos esses
muito raramente utilizados quando se trata
de aplicativos e bibliotecas desenvolvidos
em Delphi. O fato de utilizar orientação a
objetos tornou o código do ACBr mais legível
e extensível e ao longo dos últimos anos várias
melhorias tem sido aplicadas ao projeto.
Recorrer a essas dll’s sem dúvida torna o
trabalho de se comunicar com as ECF’s mais
tranqüilo, porém apresenta um incoveniente:
E se o modelo e\ou fabricante da ECF for
trocada pelo cliente? Ou ainda se um cliente
novo utilizar um modelo de um fabricante
diferente? Para essas situações, se faz necessário readaptar o aplicativo para trabalhar
com o novo modelo\fabricante de ECF.
Nesse artigo, estarei mostrando como
podemos utilizar o ACBr para fazermos nosso
aplicativo se comunicar com uma impressora fiscal. Para os que não dispõem de uma
impressora fiscal para testes, é importante
ressaltar que o exemplo funciona com emuladores de ECF sem problemas.
O projeto ACBr vem de encontro a esse
problema. Esse conjunto de componentes e
rotinas totalmente Open Source e desenvolvido em Delphi, permite que a aplicação que
irá se comunicar com a ECF seja desenvolvida
apenas uma vez, e a troca de modelo ou
fabricante de componente deixa de ser um
problema.
No artigo não estarei mostrando a instalação dos componentes ACBr no Delphi 2010,
já que instruções para instalação acompanham o componente.
Também não será abordada no artigo
a instalação e configuração de emuladores
de ECF.
Iniciando a aplicação
Criaremos uma aplicação que irá realizar as
principais operações relacionadas às impressoras
fiscais, como por exemplo: Leitura X, Redução Z,
além é claro das operações de registro de itens
em uma venda.
Veja como ficará o layout principal da aplicação
na figura 1:
No alto e a esquerda da tela, temos dois
componentes ComboBox onde no primeiro iremos
colocar na propriedade Items uma lista com os
modelos suportados pelo Acbr. São eles:
ecfNenhum, ecfNaoFiscal, ecfBematech,
ecfSweda, ecfDaruma, ecfSchalter,
ecfMecaf, ecfYanco, ecfDataRegis,
ecfUrano, ecfICash, ecfQuattro, ecfFiscNET,
ecfEpson, ecfNCR, ecfSwedaSTX;
No segundo componente ComboBox, colocaremos uma lista com os nomes das portas COM
disponíveis no computador. No exemplo fiz a lista
com as portas COM1 até COM6.
Logo abaixo dos componentes ComboBox,
10
março 2010
temos uma série de 7 botões que utilizaremos para
efetuar as operações com a ECF. A função de cada
botão pode ser vista nos captions de cada botão.
No lado direito do formulário temos um
componente PageControl com duas páginas. Na
primeira colocamos um componente TMemo,
que será ligado ao componente ACBrEcf através
da propriedade MemoBobina deste último. Na
segunda página, colocamos um componente
TWebbrowser para exibirmos as informações da
bobina do ACBrECF.
Finalmente, na parte inferior do formulário,
pode ser visto o componente ACBrECF que será o
responsável pela interação de nosso aplicativo com
a impressora fiscal.
Foi inserido no formulário também um componente StatusBar para exibir o staus da impressora
fiscal.
Com o layout da aplicação pronto, iremos criar
as rotinas dos botões inseridos no formulário, com
execeção do botão “Vender Item” que codificaremos depois.
Seguem os códigos dos eventos OnClick dos
botões:
“Ativar ECF”:
procedure TForm1.
btnativarClick(Sender:
TObject);
begin
ACBrECF1.Modelo:=TAC
BrECFModelo(cmbmodelo.
ItemIndex);
ACBrECF1.
Porta:=cmbporta.
Items[cmbporta.ItemIndex];
ACBrECF1.TimeOut:=3000;
ACBrECF1.Ativar;
Application.
ProcessMessages;
if ACBrECF1.Ativo then
begin
btnativar.
Enabled:=false;
StatusBar1.
Panels[0].Text:=’ECF
Ativa’;
end;
end;
Figura 1
“Leitura X”:
procedure TForm1.
btnleituraxClick(Sender:
TObject);
begin
ACBrECF1.LeituraX;
end;
“Redução Z”:
procedure TForm1.
btnreducaozClick(Sender:
TObject);
begin
if(MessageDlg(‘Se for
emitida a Redução Z, a ECF
ficará inoperante até o
dia seguinte.Deseja Contin
uar?’,mtConfirmation,[mbYe
s,mbNo],0)=mrYes)then
ACBrECF1.
ReducaoZ(Now);
end;
“Abrir Cupom”:
procedure TForm1.
btnabrircupomClick(Sender:
TObject);
begin
ACBrECF1.AbreCupom;
StatusBar1.Panels[0].
Text:=’Cupom Aberto’;
end;
“Cancela Cupom”:
procedure TForm1.
btncancelacupomClick(Sender:
TObject);
begin
ACBrECF1.CancelaCupom;
StatusBar1.Panels[0].
Text:=’Livre’;
end;
“Desativar ECF”:
procedure TForm1.
btndesativarClick(Sender:
TObject);
begin
if ACBrECF1.Ativo then
ACBrECF1.Desativar;
if not ACBrECF1.Ativo
then
begin
btndesativar.
Enabled:=false;
btnativar.
Enabled:=true;
end;
end;
março 2010
11
Destaca-se nesse código a rotina da Redução
Z. Como se trata de uma operação que irá deixar
a ECF inoperante pelo restante do dia é altamente
recomendável que peçamos uma confirmação ao
usuário antes de efetuar a mesma.
Em seguida faremos a codificação para exibir
os dados da bobina da ECF no WebBrowser. O
componente ACBrECF irá enviar os dados para o
componente Memo apontado em sua propriedade
MemoBobina. O que precisamos fazer é salvar o
conteúdo do Memo em um arquivo .html e em
seguida exibi-lo no WebBrowser.
Segue o código. Ficará no evento OnChange
do componente Memo:
procedure TForm1.
membobinaChange(Sender:
TObject);
begin
membobina.Lines.
SaveToFile(‘bobina.html’);
Application.
ProcessMessages;
WebBrowser1.Navigate(‘file
:///’+ExtractFilePath(Appl
ication.ExeName)+’bobina.
html’);
end;
Repare que com a utilização do componente
ACBrECF, todas as operações envolvendo a ECF
ficam transparentes ao desenvolvedor. Basta dar
um comando através do componente para realizar
a operação. Essa sem dúvida é a grande vantagem
dessa suíte de componentes.
Teste o aplicativo e salve as alterações. Com
isso terminamos a primeira parte de nosso exemplo. A seguir mostrarei como registrar itens de uma
venda através do componente ACBrECF.
Operação de venda de itens
Adicione um novo formulário a aplicação e
monte o layout do mesmo conforme mostrado
na figura 2:
Veja a Figura 2.
12
março 2010
Figura 2
A função que utilizaremos para registrar a
venda do item e a função VendeItem do ACBrECF.
Essa função recebe os parâmetros necessários para
se efetuar uma venda na ECF. Essa função será
utilizada no botão “Vender Item”.
Não poderemos permitir a saída da tela sem
que a venda seja finalizada. Para isso, no botão
“Sair” utilizaremos as funções SubtotalizaCupom
e EfetuaPagamento. Essas funções irão encerrar
a venda e permitir que a ECF fique livre para uma
nova venda.
Referente ao pagamento, é importante ressaltar que as formas de pagamento precisam estar
cadastradas na impressora fiscal. Nesse exemplo,
estarei trabalhando com forma de pagamento em
dinheiro, representada pelo código 01, constante
da maioria das ECF’s.
Antes da codificação nesses botões, volte ao
formulário principal e no evento OnClick do botão
“Vender Item”, coloque o seguinte código:
procedure TForm1.
Button1Click(Sender:
TObject);
begin
try
frmvenderitem:=Tfrmvenderitem.
Create(Self);
frmvenderitem.
ShowModal;
finally
FreeAndNil(frmvenderitem);
end;
end;
Esse código irá chamar o formulário de venda
de itens.
Agora, segue a codificação dos eventos OnClick
dos botões do formulário de venda de itens:
Botão “Vender Item” :
procedure Tfrmvenderitem.
btnvenderitemClick(Sender:
TObject);
begin
if(Form1.ACBrECF1.
Ativo)and(Form1.ACBrECF1.
Estado=estVenda)then
begin
Form1.ACBrECF1.
VendeItem(edtcodigo.
Text,edtdescricao.
Text,edticms.Text,
StrToFloat(edtquantidade.T
ext),StrToFloat(edtvalorun
itario.Text),
StrToFloat(edtdesconto.
Text),edtunidade.Text);
end;
end;
Botão “Sair”:
procedure Tfrmvenderitem.
btnsairClick(Sender:
TObject);
var
sValorpagamento:string;
begin
if(MessageDlg(‘Deseja
finalizar a venda?’,mtConf
irmation,[mbYes,mbNo],0)=m
rYes)then
begin
Form1.ACBrECF1.
SubtotalizaCupom;
sValorpagamento:=In
putBox(‘ACBr’,’Informe o
valor pago’,’’);
Form1.ACBrECF1.Efetu
aPagamento(‘01’,StrToFloat
(sValorpagamento));
Form1.ACBrECF1.
FechaCupom(‘Obrigado Volte
Sempre!’);
Close;
end;
end;
Figura 3
O projeto ACBr, é totalmente open source,
podendo ser adquirido nos seguintes links:
Pagina principal ACBR
Veja o formulário com valores para teste na
figura 3:
Veja a Figura 3.
Após a venda dos itens e o pagamento, a ECF
ficará livre para uma nova venda.
Fique atento para os tipos de dados necessários nas passagens de parâmetros para as funções,
para evitar erros de conversão.
Além da venda de itens e principais leituras,
como a Leitura X e Redução Z, o ACBr, permite
também o completo gerenciamento da ECF, como
o cadastro de formas de pagamento e a emissão
de relatórios gerenciais.
Ao se trocar o modelo de ECF, nenhuma
alteração precisará ser feita no código, já que o
ACBrECF, envia os comandos de acordo com o
modelo de ECF configurada em sua propriedade
Modelo. Os modelos suportados são descritos no
ínicio desse artigo.
http://acbr.sourceforge.net/drupal/
Ferramenta de controle de versão
SVN no Windows (Tortoise):
h t t p : / / a c b r. s o u r c e f o r g e . n e t /
drupal/?q=node/37
Para instalar o componente NFe:
h t t p : / / a c b r. s o u r c e f o r g e . n e t /
drupal/?q=node/36
FAQ - ACBrNFe
h t t p : / / a c b r. s o u r c e f o r g e . n e t /
drupal/?q=node/38
Nesses links também se pode obter maiores
informações sobre os componentes.
Abraços e até a próxima.
Sobre o autor
Antonio Spitaleri Neto
Conclusão
Na área de automação comercial, o projeto
ACBr sem dúvida é uma grande ajuda quando precisamos operar com ECF’s, pois sua portabilidade
e extensibilidade garante um grande ganho de
desempenho no desenvolvimento.
Consultor Técnico The Club.
[email protected]
março 2010
13
INDO MAIS ALÉM
EXPLORANDO AS
TABELAS DE SISTEMA
INTERBASE/FIREBIRD
Olá pessoal,
Tem certos momentos em que quebramos a cabeça tentando montar fórmulas, queries, procedures e todo tipo de truques para
resolver determinadas situações em nossos
bancos de dados. Por exemplo: precisamos
realizar uma grande atualização em nosso
banco de dados, mas devido a toda integridade referencial que temos através de triggers,
um único Update dispararia centenas, milhares de outras ações que, provavelmente,
sairiam de nosso controle. Então uma saída
seria a desativação das triggers. Mas como
desativar todas as triggers de nosso banco?
Usando o comando Alter trigger tal_de_tal
inactive? Uma a uma? Pois é, um tanto quanto
complicado, não?
Ou mesmo essa outra situação: Temos
uma coluna em nossos bancos chamada
Tipo_Cliente que é validada por uma Check
Constraint determinando que os valores
possíveis são ‘F’ (Pessoa Física) e ‘J’ (Pessoa
14
março 2010
Jurídica). Quando nós criamos essa Constraint
não especificamos o nome da mesma. Então
o banco de dados cria um nome aleatório do
tipo CHECK$10. Agora precisamos alterar essa
validação, acrescentando um novo valor. Para
isso precisamos dropar a constraint e recria-la
novamente. Mas como dropar a constraint se
não sabemos o nome da mesma? Outra tarefa
difícil de cumprir.
Por isso nesse mês abordaremos um assunto diferente: o uso das tabelas de sistema
em bancos de dados InterBase/Firebird.
São tabelas que contém informações
extremamente úteis e que, se bem utilizadas
e manipuladas, podem nos ajudar a ir muito
mais além na administração e manutenção
de nossos bancos.
Na prática podemos realizar todo tipo de
comando DML (Data Manipulation Language)
sobre as tabelas de sistema, respeitando algumas restrições que o próprio banco de dados
impõe para manter a integridade interna.
Então vamos lá:
AS TABELAS DE SISTEMA
Assim como outros objetos internos, as tabelas
de sistema são todas aquelas cujo nome se iniciam
com os caracteres RDB$ ou, no caso do InterBase,
também TMP$. Essa nomenclatura é de uso exclusivo do banco de dados e não pode ser utilizado
na criação de novas tabelas pelo usuário. As TMP$
são tabelas temporárias de sistema, utilizadas no
recurso de monitoramento do banco de dados. Já
as RDB$ são as tabelas de sistema responsáveis
por guardar todo tipo de informação relativa,
principalmente, ao metadata do banco de dados,
à estrutura do banco.
Quando criamos um banco de dados, o sistema já cria automaticamente as tabelas RDB$.
São elas:
Veja a Tabela.
Tabela de Sistema
Funcionalidade
RDB$CHARACTER_SETS
Descreve todos os tipos de Character Sets disponíveis no banco de dados.
RDB$CHECK_CONSTRAINTS
Grava informações sobre todas as Constrainst do tipo Check presentes no banco de dados. Também armazena informações
sobre todas as Constraints das colunas marcadas como Not Null.
RDB$COLLATIONS
Descreve as regras das Collations permitidas para uso do banco de dados.
RDB$DATABASE
Salva informações sobre o banco de dados.
RDB$DEPENDENCIES
Armazena todos os tipos de dependência entre os objetos do sistema. Tabelas / Stored Procedures / Triggers, enfim. É
por aqui que o banco de dados valida se uma coluna pode ser alterada / excluída sem afetar outros objetos.
RDB$EXCEPTIONS
Descreve todas as exceções de erro geradas e utilizadas pelas Stored Procedures, inclusive as exceções criadas pelo
usuário.
RDB$FIELDS
Contém informações sobre as características de cada coluna e domínio do banco de dados. Informações sobre valores
default, not null, campos computados, enfim. Todas as colunas de todas as tabelas são referenciadas nessa tabela.
RDB$FIELD_DIMENSIONS
Descreve o tamanho de cada coluna.
RDB$FILES
Lista informações sobre todos os arquivos secundários do tipo shadow que estão em uso no banco de dados.
RDB$FILTERS
Contém informações sobre filtros de campos do tipo Blob.
RDB$FORMATS
Uma tabela interessante. Ela armazena informações sobre o versionamento de alterações realizadas nas tabelas do banco.
Todas as vezes que executamos um comando de Alter/Drop/Create Table essa tabela grava o número dessa alteração. E
isso que permite que uma aplicação possa acessar tabelas alteradas sem a necessidade de ser recompilada. O sistema
permite que sejam feitas até 255 alterações na estrutura de tabelas. Ao atingir esse limite, um backup e um restore do
banco precisa ser feito para zerar esse contador e permitir novas alterações.
RDB$FUNCTION_ARGUMENTS
Define atributos de funções utilizadas pelo banco de dados, inclusive as UDFs.
RDB$FUNCTIONS
Descreve as UDFs utilizadas pelo banco de dados.
RDB$GENERATORS
Contém informações sobre todas as Generators utilizadas pelo banco de dados.
RDB$INDEX_SEGMENTS
Uma tabela de sistema muito importante que grava informações sobre todas as colunas que são referenciadas em todos
os índices do banco de dados. Modificar manualmente essa tabela pode causar grandes corrupções!
RDB$INDICES
Descreve todos os índices criados no banco de dados. Cada índice dessa tabela deve ser suas respectivas referencias na
tabela RDB$INDEX_SEGMENTS.
RDB$LOG_FILES
Essa tabela não é mais utilizada nos bancos de dados InterBase/Firebird, mas permanece listada por legado.
RDB$PAGES
Uma tabela bem técnica, que grava informações sobre cada página de dados alocada do banco de dados. Qualquer tipo
de modificação manual nessa tabela irá corromper o mesmo.
RDB$PROCEDURE_PARAMETERS
Essa tabela grava informações sobre os parâmetros (input e output) usados em todas as Stored Procedures do banco
de dados.
RDB$PROCEDURES
Contém a descrição das Stored Procedures do banco de dados.
RDB$REF_CONSTRAINTS
Grava informações sobre as Constraints de Integridade Referencial usadas no banco (Primary e Foreing Keys).
RDB$RELATION_CONSTRAINTS
Aqui são listadas as relações entre as Constraints e de Integridade Referencial e as respectivas tabelas relacionadas.
RDB$RELATION_FIELDS
Descreve informações complementares sobre as colunas e domínios do banco de dados, bem como as relações entre
as colunas e as tabelas.
RDB$RELATIONS
Define algumas características de tabelas e Views.
RDB$ROLES
Listas todos os Roles criados no banco, bem como o usuário dono desse Role.
RDB$SECURITY_CLASSES
Define as listas de controle de acesso (ACLs) criadas no banco, bem como a relação dessas regras com os objetos do
sistema.
RDB$TRANSACTIONS
Grava informações sobre todas as transações multi-banco que estão em uso no sistema.
RDB$TRIGGER_MESSAGES
Contém informações sobre todas a mensagens de Triggers, bem como as Triggers relacionadas às mensagens.
RDB$TRIGGERS
Descreve todas as Triggers do banco de dados.
RDB$TYPES
Lista todos os tipos de dados e apelidos para os Character Sets e Collations usados no banco de dados.
RDB$USER_PRIVILEGES
Contém informações sobre o direito de acesso de cada usuário criado no banco de dados. Sempre que usamos os comandos Grant e Revoke, o sistema grava essas referências nessa tabela.
RDB$VIEW_RELATIONS
Aqui são listadas as relações entre as Views e suas respectivas tabelas.
março 2010
15
Também pode existir outras tabelas de sistema
de forma distinta entre o InterBase e o Firebird,
conforme a ODS (On Disk Structure) do banco
de dados.
VISUALIZANDO AS TABELAS DE SISTEMA
Para acessar e visualizar as tabelas de sistema
devemos:
1. Usando o utilitário de linha de comando
ISQL, executamos o comando:
Imagem 2
SQL> show system;
RDB$CHARACTER_SETS
RDB$CHECK_CONSTRAINTS
RDB$COLLATIONS
RDB$DATABASE
RDB$DEPENDENCIES
RDB$EXCEPTIONS
[...]
SQL>
2. Usando o utilitário gráfico IBConsole,
selecionamos no menu:
3. Usando o utilitário gráfico IBExpert,
marcamos na propriedade da conexão:
Veja a imagem 2.
MANIPULANDO AS TABELAS DE SISTEMA
Devemos sempre tomar cuidado antes de
assim proceder, mas vamos dar alguns exemplos
de comandos DML que podemos executar sobre
as tabelas de sistema.
Ampliando o tamanho de um campo Char/
Varchar:
Muitas vezes precisei ampliar o tamanho de
16
março 2010
uma coluna Char/Varchar. Por exemplo: Precisamos
ampliar a coluna NOME de 30 para 60 caracteres.
Mas como fazer de uma só vez em todas as tabelas
do banco de dados onde essa coluna existe? Manipulando as tabelas de sistema:
Update
rdb$fields
Set
rdb$field_length = 60
Where
rdb$field_name =
(select f.rdb$field_
source
from rdb$relation_
fields f
where f.rdb$field_name
= ‘NOME’)
Esse comando irá buscar todas as colunas descritas com o nome “NOME” e aumentar na tabela
que descreve os campos o Length dessa coluna
para 60 caracteres.
Ativando e Desativando Triggers:
Quando precisamos realizar uma atualização
em massa no banco de dados ou quando temos um
banco de dados vazio que precisa ser populado, podemos nos deparar com um problema: as Triggers.
Isso porque, muitas vezes usamos as Triggers para
realizar a integridade referencial de nossos bancos.
Ai quando vamos inserir um dado em determinada
tabela, a Trigger impede por não existir relação com
outra tabela principal, por exemplo. Precisamos
então rodar comandos do tipo Alter Trigger ... Inactive/Active. Mas como fazer isso de forma prática
quando temos centenas / milhares de Triggers?
Executando o comando DML abaixo:
UPDATE
RDB$TRIGGERS
SET
rdb$trigger_inactive = 1
WHERE
(rdb$system_flag = 0 or
rdb$system_flag IS NULL)
AND
rdb$trigger_name NOT LIKE
‘CHECK%’ AND
rdb$trigger_name NOT LIKE
‘RDB$%’
Esse comando irá desativar todas as Triggers
do banco de dados, com exceção das Triggers de
sistema e das Checks Constraints. Para reativar
novamente as mesmas, basta realizar o Update
novamente, ajustando o valor para “0” (Zero).
Apagando Checks Constraints sem
saber o nome:
Como no exemplo que demos na abertura do
nosso artigo, como podemos apagar todas as Checks Constraints relacionadas à uma determinada
coluna de nosso banco de dados, se não sabemos
o nome de nossa Check Constraint? Basta executar
o comando DML abaixo:
DELETE
FROM RDB$RELATION_
CONSTRAINTS A
Where
(Select count(*) from
RDB$CHECK_CONSTRAINTS B,
RDB$TRIGGERS C
where
(A.RDB$CONSTRAINT_TYPE =
‘CHECK’) and
(A.RDB$CONSTRAINT_
NAME = B.RDB$CONSTRAINT_
NAME) and
(B.RDB$TRIGGER_NAME =
C.RDB$TRIGGER_NAME) and
(C.RDB$TRIGGER_TYPE =
1) and
(A.RDB$RELATION_NAME
in
(SELECT
DISTINCT
r.rdb$relation_name
FROM rdb$check_
constraints C JOIN
rdb$relation_
constraints R
ON
(C.rdb$constraint_name =
R.rdb$constraint_name)
WHERE
C.rdb$trigger_
name IN
(SELECT
D.rdb$dependent_name
FROM
rdb$dependencies D
WHERE
D.rdb$field_
name = ‘TIPO_CLIENTE’ and
d.rdb$dependent_name like
‘CHECK%’))
)) > 0;
Club Megazine comentamos a respeito do uso das
UDFs. Segue um exemplo de uso de UDF contra
uma tabela de sistema:
Select F_UUID1MACMAC(F_
UUID1MAC()) from
rdb$database;
Esse comando executado a partir de qualquer computador cliente retornará o endereço
Mac Address do servidor do banco de dados. Isso
pode ser muito útil por exemplo para se criar uma
rotina de validação da aplicação para liberação de
licenças de uso.
de Tamanhos’
WHERE RDB$RELATION_NAME=’
T02P007LJ’;
UPDATE RDB$RELATIONS SET
RDB$DESCRIPTION=’Cadastro
de Cores’
WHERE RDB$RELATION_NAME=’
T03P007LJ’;
UPDATE RDB$RELATIONS SET
RDB$DESCRIPTION=’Tabelas de
Preco’
WHERE RDB$RELATION_NAME=’
T04P009LJ’;
UPDATE RDB$RELATIONS SET
RDB$DESCRIPTION=’Imagens de
Produtos’
WHERE RDB$RELATION_NAME=’
T05P015LP’;
Trabalhando com Descrições em
Tabelas:
Esse é outro ponto interessante. É muito
comum encontrar bancos de dados com centenas
de tabelas, mas onde o nome da tabela não identifica seu real propósito. Por exemplo: ao invés de
chamar uma tabela de cadastros de produto de
TABPRODUTOS, o nome da tabela é algo do tipo
T01P007LJ. Então novo desenvolvedor ou mesmo
um usuário mais experiente acaba ficando perdido
ao tentar encontrar uma determinada tabela.
Uma maneira interessante de se tratar esse
problema é criando uma descrição para as tabelas
de sistema. Para isso usamos o comando DML:
E assim por diante. Quando abrimos o utilitário IBExpert, podemos facilmente identificar
as tabelas:
Veja a Imagem 3.
Ou mesmo podemos executar um comando
DML para pesquisar uma determinada tabela pela
sua descrição:
Select rdb$relation_name,
rdb$description from
rdb$relations
where rdb$description
like ‘%rodutos%’;
UPDATE RDB$RELATIONS SET
RDB$DESCRIPTION=’Cadastro
de Produtos’
WHERE RDB$RELATION_NAME=’
T01P007LJ’;
UPDATE RDB$RELATIONS SET
RDB$DESCRIPTION=’Cadastro
Esse nosso comando irá apagar todas as Checks
Constraints que validarem a coluna Tipo_Cliente,
em todas as tabelas do banco de dados. Depois,
podemos recriar as mesmas com a nova regra de
validação. Rápido e Seguro.
Resgatando o MAC Address do Servidor InterBase/Firebird:
Recentemente em um artigo nosso aqui na The
Imagem 3
março 2010
17
Retornaria algo como:
RDB$RELATION_NAME
Nos vemos no próximo artigo para falar mais
sobre o InterBase e seus recursos. Valeu pessoa
e Até lá!
RDB$DESCRIPTION
T01P007LJ
Cadastro de Produtos
T05P015LP
Imagens de Produtos
Referência:
CONCLUSÃO
E esses são apenas alguns exemplos. Novamente explorando mais dos recursos de nossos
bancos de dados. Se pesquisarmos mais e estudarmos as tabelas de sistema de nossos bancos,
podemos extrair muito mais. Claro e novamente
repetindo: tudo com muito cuidado para não derrubar alguma integridade ou mesmo corromper
nossos bancos. Mas recomendo a todos a leitura
complementar do Capitulo 6 do guia Language
Reference do InterBase SMP 2009, que contém
informações completas sobre as tabelas de sistema
e sobre as tabelas temporárias de sistema. Afinal,
18
março 2010
as informações estão lá o tempo todo. Cabe a
nós desenvolvedores irmos mais além, usar essas
informações à nosso favor.
InterBase 2009 Language Reference – cap. 6.
http://edn.embarcadero.com
Sobre o autor
Felipe Santos
Felipe Santos é especialista em InterBase. Trabalha com o InterBase desde
2001. atuando como consultor e instrutor do produto em todo Brasil. Especialista em
ambientes críticos. Atua e trabalha com os maiores clientes do InterBase no Brasil.
Participante ativo na comunidade, com diversos artigos publicados. Participante do
grupo de beta testers mundial do produto. Palestrante em eventos como IB Tour, Borcon
Conference, CodeRage Latin América, Delphi Developers Day, Linux Day, entre outros.
Atualmente trabalhando na área técnica do InterBase na Presence Tecnologia – agente
oficial especializado do produto no Brasil.
[email protected]
STORED PROCEDURES
E TRIGGERS NO MYSQL
As Stored Procedures e Triggers são mais
conhecidas no Firebird, mas também são muito importantes na otimização do desempenho
de um Banco de Dados no MySQL, neste artigo mostrarei o que elas são, como funcionam
no MySQL e farei alguns exemplos.
STORED PROCEDURES
Introduzidas a partir da versão 5.0 do MYSQL
as Stored Procedures (SP) ou Procedimentos Armazenados são um conjunto de comando SQL que
podem ficar armazenados no servidor e poupar
os usuários da necessidade de enviar extensos
comandos SQL ao servidor só sendo necessário
fazer a chamada a SP.
As vantagens do uso das SP’s são muitas, entre
as principais que posso destacar estão:
• Melhora do desempenho – por serem armazenadas e processadas no servidor
elas enviarão ao usuário somente os resultados das consultas diminuindo assim o trafego
na rede;
• Economia de código – é necessária
apenas uma linha de código para se chamar
uma SP já que a instrução SQL está toda encapsulada no corpo da SP, você não terá mais
que escrever várias linhas toda vez que quiser
uma operação específica em seu banco;
• Facilidade de manutenção – elas
podem ser alteradas sem a necessidade de
se alterar as aplicações que as utilizam e sem
importar a linguagem em que foi escrita essa
aplicação;
• Segurança – os usuários terão acesso
somente as SP’s e não as tabelas, isso diminui
a possibilidade de algum usuário fazer alguma
alteração que prejudique o Banco de Dados;
• Distribuição de tarefas – as tarefas
da criação de uma aplicação podem ser divididas entre um profissional especializado em
Banco de Dados e um Programador que criará
a aplicação.
As SP são basicamente classificadas em três
tipos:
1. As que retornam algum valor, como
a contagem de registros de uma tabela;
2. As que retornam registros funcionando como um Select , e;
3. As que fazem ações específicas no
banco, como inserções, alterações, atualizações etc.
março 2010
19
STORED PROCEDURES NO MYSQL
A sintaxe geral de uma SP no MySQL é a
seguinte:
CREATE PROCEDURE nome_
proc([parâmetro ...])
[características]
BEGIN
comandos procedurais executados automaticamente em resposta a algum evento executado no
banco de dados, como por exemplo na inserção de
um registro em uma tabela de pessoas, a trigger
automaticamente gerará na tabela de salários um
campo referente ao salário daquela pessoa.
As triggers são usadas geralmente para:
• Para manter a integridade entre as
tabelas: podem ser criados grandes processos
de controle dos relacionamentos entre as tabelas, principalmente aos usuários de tabelas
MyISAM que não suportam relacionamnetos
via chave estrangeira;
Corpo da SP;
END;
Onde:
• Nome_proc - aqui se define o nome
da procedure, um padrão muito adotado entre os desenvolvedores é SP_nome_da_procedure;
• Parâmetro – os parâmetros utilizados
em SP no MySQL dividem-se em três:
1. IN – São os parâmetros de entrada
que serão trabalhados no corpo da SP e produzirão algum resultado;
2. OUT – É o parâmetro interno que retorna algum resultado para o lado externo;
3. INOUT - É o parâmetro que pode
funcionar das duas formas.
• Características – definem o tipo da
procedure, se determinística ou não, questões
de segurança do banco de dados e linguagem
de escrita da SP,não setem a obrigatoriedade
de declara – las quand se escrevea SP ;
• Corpo da SP – onde são escritos os
comandos SQL.
• Manter a segurança do Banco: as triggers podem controlar o acesso, atualizações
e alterações nas tabelas;
• Melhorar o desempenho do banco:
imagine um banco com 500.000 registros que
de tempos em tempos requer uma simples
alteração nos registros, atrvés de uma trigger
essas alterações podem ser feitas automaticamente através da trigger.;
• Auditoria do Banco de Dados: por
serem executadas automaticamente são
excelentes ferramentas para auditria do BD.
TRIGGERS NO MYSQL.
A sintaxe geral de uma Trigger no MySQL é
a seguinte:
CREATE
[DEFINER = { USER |
CURRENT USER}]
Onde:
• DEFINER: checa quais os privilégios
que usuário do banco tem para disparar a
trigger. Quando a trigger é criada esse campo
é preenchido por padrão com CURRENT_USER
ou pode ser preenchida com o usuário(ex:
‘bruno’@’localhost’);
• nome_trigger: define-se o nome da
trigger, o padrão adotado entre os desenvolvedores é TRG_nome_trigger;
• tempo_trigger: aqui se define quando a trigger será executada:
• BEFORE: a trigger será ativada antes
do comando que a disparou;
• AFTER: a trigger será ativada depois
do comando que a disparou;
• evento trigger: o evento que será
executado quando a trigger for disparada:
• INSERT: um ou mais registros serão
inseridos em uma tabela;
• UPDATE: um ou mais registros serão
atualizados em uma tabela;
• DELETE: um ou mais registros serão
apagados em uma tabela;
• nome_tabela: tabela onde a trigger
trabalhará;
• corpo_trigger: comandos executados
pela trigger.
TRIGGER nome_trigger
tempo_trigger evento_
trigger
TRIGGERS
ON nome_tabela
As triggers (ou gatilhos em português) são
FOR EACH ROW
março 2010
corpo_trigger
EXEMPLOS
Para ilustrar melhor as explicações vamos criar
alguns exemplos de Triggers e Stored Procedures.
O primeiro passo é criar as tabelas, para este
exemplo vamos criar duas tabelas, uma tabela de
pessoas e outra de usuários. Abaixo seguem os
scripts de criação das tabelas:
PESSOAS
Essa tabela servira para o cadastro de pessoas,
como por exemplo clientes e funcionários, essa
especificação se dará no campo PESSOA_TIPO que
receberá G para gerente(que terá todos os privilégios), C – para cliente ou F – para funcionário.
int(11) default NULL,
PRIMARY KEY (`ID_
USUARIO`),
KEY `FK_PESSOA_USUARIO`
(`FK_PESSOA_USUARIO`),
CONSTRAINT `USUARIO_
PESSOA_FK` FOREIGN KEY
(`FK_PESSOA_USUARIO`)
REFERENCES `pessoas` (`ID_
PESSOA`)
) ENGINE=InnoDB DEFAULT
CHARSET=latin1
CREATE PROCEDURE SP_ADD_
USUARIOS (
IN USUARIO VARCHAR (80),
IN SENHA VARCHAR (35),
IN TIPO CHAR(1),
IN FK_PESSOA INT)
BEGIN
INSERT INTO `usuarios`
(USUARIO_NOME, USUARIO_
SENHA, USUARIO_TIPO,FK_
PESSOA_USUARIO)
VALUES
(USUARIO,SENHA,TIPO,FK_
PESSOA);
END;
TRG_CRIP_SENHA
CREATE TABLE `pessoas` (
`ID_PESSOA` INTEGER(11)
NOT NULL AUTO_INCREMENT,
`PESSOA_NOME`
VARCHAR(80) NOT NULL,
`PESSOA_RG` VARCHAR(15)
DEFAULT NULL,
`PESSOA_TIPO` CHAR (1)
DEFAULT NULL,
PRIMARY KEY (`ID_
PESSOA`)
) ENGINE=InnoDB;
Agora vamos criar nossa primeira trigger, essa
trigger se encarregará de criptografar a senha de
usuário quando este for inserido, o método de
criptografia é o MD5 que já é uma função presente
no banco MySQL, o MD5 é um algoritmo unidirecional que criptografa uma string e não permite
que essa criptografia seja revertida. Percebam que
usamos o operador NEW (NEW. USUARIO_SENHA)
esse operador significa que queremos o dado que
acaba de ser inserido, se porventura apagássemos
esse registro poderíamos recuperá – lo através do
operador OLD (OLD. USUARIO_SENHA).
USUARIOS
Essa tabela guardará os dados dos usuários
de um suposto programa, desde que eles sejam
definidos com F no campo PESSOA_TIPO. O campo
USUARIO_TIPO deve ser marcado com A – Administrador ou C- Comum sendo que só o Administrador
tem permissões para inserir registros na tabela
de pessoas.
CREATE TABLE `usuarios` (
`ID_USUARIO` int(11) NOT
NULL auto_increment,
`USUARIO_NOME`
varchar(80) default NULL,
`USUARIO_SENHA`
varchar(35) default NULL,
`USUARIO_TIPO` char(1)
default NULL,
`FK_PESSOA_USUARIO`
CREATE TRIGGER TRG_CRIP_
SENHA BEFORE INSERT ON
`usuarios`
FOR EACH ROW
BEGIN
SET NEW.USUARIO_SENHA =
MD5(NEW.USUARIO_SENHA);
END;
SP_ADD_USUARIOS
O nosso próximo passo é criar uma Stored
Procedure que será usada em conjunto com a
próxima trigger e que quando executada incluirá
dados na tabela de usuários.
TRG_USUARIOS
Essa trigger incluirá automaticamente uma
pessoa cadastrada na tabela de pessoas, desde
que seu pessoa tipo na tabela seja F, na tabela de
usuários como um usuário do sistema. Por padrão,
que será definido na trigger, o nome de desse
usuário será o seu nome em letras minúsculas,
a senha será 123456 e o tipo será definido como
C - Comum.
CREATE TRIGGER TRG_
USUARIOS AFTER INSERT ON
`pessoas`
FOR EACH ROW
BEGIN
IF (NEW.ID_PESSOA IS NOT
NULL) AND (NEW.PESSOA_TIPO
= ‘G’) THEN
CALL SP_ADD_
USUARIOS(LOWER(NEW.PESSOA_
NOME),’123456’,’A’,NEW.
ID_PESSOA);
ELSE
IF (NEW.ID_PESSOA IS
NOT NULL) AND (NEW.PESSOA_
TIPO = ‘F’) THEN
CALL SP_ADD_
USUARIOS(LOWER(NEW.PESSOA_
NOME),’123456’,’C’,NEW.
ID_PESSOA);
END IF;
END IF;
END
março 2010
21
TESTES
Agora vamos efetuar alguns testes nesse
banco para verificar o funcionamento das Triggers
e Stored Procedures. Para efetuar esses testes
estou usando a IDE Gráfica EMS SQL Manager Lite
for MySQL que é gratuita e pode ser encontrada
no seguinte endereço:
Imagem 1
Imagem 2
Vamos inserir um registro na tabela de PESSOAS com o tipo definido com G –GERENTE.
Imagem 3
INSERT INTO `pessoas`
(PESSOA_NOME, PESSOA_RG,
PESSOA_TIPO)
VALUES
(‘BRUNO’,’12.345.6789’,’G’);
Imagem 4
um registro, referente ao funcionário DANIEL
Veja a Imagem 1.
Veja a Imagem 4.
No momento da inserção a trigger que insere
um usuário(TRG_USUARIOS) é automaticamente
executada e gera na tabela de usuários um novo
registro com a senha já criptografada (TRG_CRIP_
SENHA), e como o PESSOA_TIPO é = G esse usuário
será um administrador.
Veja a Imagem 2.
Vamos inserir agora mais dois registros, um
funcionário (que também é um usuário do sistema)
e um cliente.
INSERT INTO `pessoas`
(PESSOA_NOME, PESSOA_RG,
PESSOA_TIPO)
VALUES
(‘DANIEL’,’87.654.3210’,’F’),
(‘FREDERICO’,’87.654.3210’,’C’);
COMMIT;
Veja a Imagem 3.
Na tabela de usuários foi gerado apenas mais
22
março 2010
Vamos criar agora uma Stored Procedure
que controlará a inserção de dados na tabela
PESSOAS.
SP_PERMISSOES
Essa procedure quando executada servirá
para incluir dados na tabela de pessoas, mas ela
controlará quem o fará, só poderão incluir registros
usuários cadastrados como A – Administrador e
que tenham digitado o nome e senha de usuário
correta, caso o usuário seja C – comum retornará
uma mensagem avisando que não é possível fazer
essa inserção.
CREATE PROCEDURE SP_
PERMISSOES (
IN USUARIO VARCHAR (80),
IN SENHA VARCHAR (35),
IN NOME VARCHAR(80),
IN RG VARCHAR(15),
IN TIPO CHAR(1))
BEGIN
DECLARE V_TIPO CHAR(1);
DECLARE V_SENHA VARCHAR
(35);
SELECT USUARIO_TIPO,
USUARIO_SENHA INTO V_TIPO,
V_SENHA
FROM USUARIOS
WHERE USUARIO_NOME =
USUARIO;
IF V_TIPO = ‘A’ AND V_
SENHA = MD5(SENHA) THEN
INSERT INTO `pessoas`
(PESSOA_NOME, PESSOA_RG,
PESSOA_TIPO)
VALUES (NOME, RG,
TIPO);
ELSE
SELECT ‘VOCÊ NÃO TEM
PERMISSÃO PARA EXECUTAR
ESSA TAREFA’ AS AVISO;
END IF;
END
Vamos agora testar essa SP:
CALL SP_PERMISSOES(‘bruno’
,’123456’,’ANTONIO’,’71.82
5.936.-4’,’C’)
Percebam que o registro ANTONIO foi inserido:
Veja a Imagem 5.
Vamos tentar inserir um registro como um
usuário C – comum:
Imagem 5
CALL SP_PERMISSOES(‘daniel
’,’123456’,’JEREMIAS’,’84.
369.521-7’,’G’)
Imagem 6
Ele retornará uma mensagem de erro:
Veja a Imagem 6.
Sobre o autor
Bruno Alcarás
CONCLUSÃO
Neste artigo procurei demonstrar de forma
simples algumas das operações que podem ser
feitas com Triggers e Stored Procedures no MySQL,
mas elas podem ser usadas de muitas outras formas na busca de um melhor desempenho do seu
banco, sempre que possível as utilize.
Consultor Técnico The Club.
[email protected]
E isso é tudo pessoal, até outra hora.
março 2010
23
Olá, Então pessoal como alguns devem
saber no dia 12/04/2010 foi lançado o Visual
Studio 2010 oficialmente e na edição de hoje
eu vou falar sobre algumas novidades dessa
versão, nessa edição eu vou focar nas área e
nas novidades que mais gostei área de arquitetura e modelos UML.
Além dos modelos básicos de programação
WCF, WPF, Windows Form, Silverlight, WebApplication e a novidade agora é Azure ou seja Cloud
Computing, e essa nova versão conta com Unit
Tests, ao contrário da versão Professional do Visual
Studio 2008.
Visual Studio Professional
24
março 2010
• Debugging histórico com IntelliTrace
• Ferramentas de testes compreensi-
Visual Studio Premium (além das funcionalidades da versão Professional):
As versões
Ao contrário de seus antecessores, o Visual
Studio 2010 conta com SKUs (edições) mais simplificadas, de anteriormente 9 para simplesmente 4
agora: Ultimate, Premium, Professional e a versões
Express. Irei abordar aqui individualidades de cada
uma das três versões pagas, Ultimate, Premium e
Professional:
Visual Studio Ultimate (além das funcionalidades da versão Premium):
• Debugging e desenvolvimento de
aplicações avançado
• Unit Tests com cobertura de código
(Code Coverage - mostra quanto por cento
do código está sendo testado), prioritização
de testes, análise, métrica e otimização de
código
• Desenvolvimento e testes unitários
de banco de dados
• Diagramas de arquitetura (apenas
leitura)
vas
• Ferramentas avançadas de UML
• Ferramentas de descoberta de arquitetura
• Test Case e gerenciamento do laboratório de testes
Modelagem UML
Para criar um modelo novo basta clicar em
New Project e escolher a opção Modeling Projects
e escolher o template Modeling Project, depois só
indique o caminho aonde será salvo e pronto você
terá um Projeto de modelos, esse projeto você
pode tranquilamente fazer controle de versão com
o Visual Studio team System ( falarei mais sobre ele
em outro artigo ). Figura 1
Veja a figura 1.
Diagrama de Sequência
A UML significa muito para arquitetos e analistas de sistema. Parqa criar os modelos basta
clicarmos com o botão direito sobre qualquer método de classe que desejemos visualizar o diagrama
de sequência e escolhermos a opção Generate
Sequence Diagram, que em seguida será aberta
uma janela para customização do método, como
profundidade, referências externas, entre outras.
Após o OK, teremos o Diagrama de Sequência do
método, como visto a seguir: Figura 2
Figura 1. Criando um projeto de diagrama
Veja a figura 2.
Diagrama de Dependências
Um sistema, por menor que seja, terá algumas
referências (bibliotecas externas) o acompanhando, seja elas do próprio sistema ou de terceiros.
Mas a medida que o projeto vai crescendo, suas
referências também vão aumentando, dificultando
assim a visualização do que cada parte do sistema
necessita.
Com o diagrama de sequência do do Visual
Studio 2010, fica mais fácil fazer e de visualizar
o mesmo melhorando a vida do arquiteto do
sistema.
Para que geremos um novo diagrama de dependências, basta irmos no menu Architecture ->
Generate Dependency Graph e escolher o tipo de
diagrama que será mostrado, por assembly, por
namespace, entre outras opções. Veja aqui um
Figura 2. Diagrama de sequência
exemplo: Figura 3
Vejaa figura 3.
dendo ser expandida até um nível mais profundo e
com isso os arquitetos, desenvolvedores, analistas
e designers conseguem entender e vizualizar melhor o impacto das alterações a serem realizadas.
Note que cada dependência está contraída, pomarço 2010
25
Diagrama de Componentes
Quando utilizamos componentes de terceiros
em nossos sistemas, várias vezes nos perguntamos
como eles se relacionam com o código desenvolvido pela equipe. Esta pergunta surge principalmente
quando um desenvolvedor novo entra no time que
já tem um projeto em andamento. Como a UML
conta com o diagrama de componentes, a equipe
de desenvolvimento do Visual Studio achou interessante incorporá-lo ao template de projetos de
modelagem, para que seja de fácil visualização e
modificação para aqueles que estão entrando no
time depois de um tempo de desenvolvimento.
Este diagrama contém os seguintes objetos na
toolbox: Component, Provided Interface, Required
Interface, Part Assembly, além dos objetos de relacionamento e comentários. Confira como é seu
design no Visual Studio: Figura 4
Figura 3. Diagrama de dependências
Veja a imagem 4.
Diagrama de Camadas
Hoje em dia, nos deparamos com diversos
padrões de projeto que dividem o sistema em
camadas. Seja MVC (Model-View-Controller),
MVP (Model-View-Presenter), MVVM (ModelView-ViewModel) ou N camadas, esta divisão de
camadas está presente no nosso dia a dia, pois
permite uma manutenibilidade boa, além de não
ficarmos focados em apenas um tipo de visão, ou
banco de dados, por exemplo.
Figura 4. Diagrama de componente
Por isso é importante enxergarmos o sistema
como um todo dividido em algumas partes, para
sabermos qual parte faz o quê. Partindo deste
princípio, o diagrama de camadas foi criado, e
agora o Visual Studio conta com um template para
diagramação das mesmas.
Apenas arrastando itens da toolbox, poderemos facilmente, por exemplo, criar um diagrama
de camadas MVC, de acordo com a figura a seguir:
Figura 5
Veja a figura 5.
Figura 5. Diagrama de camadas
26
março 2010
Agora que já falamos de UML e diagramas
vou falar um pouco das novas funcionalidades
do editor.
References Highlighting
Agora é possível encontrar onde cada propriedade e outros símbolos definidos em determinada
classe estão sendo usados, através do recurso References Highlighting. Clicando sobre qualquer referência de determinada propriedade da sua classe,
a IDE vai destacar todas as suas ocorrências. Além
disto, ainda é possível navegar pelas referências,
com as teclas CTRL + SHIFT + Seta para cima ou CTRL
+ SHIFT + Seta para baixo, levando para a ocorrência
anterior ou superior, respectivamente.
Figura 6. - Propriedade Nome selecionada, mostrando as ocorrências na classe
Veja a figura 6.
Call Hierarchy
Figura 7. - Chamadas ao MetodoFilho, e chamadas do MetodoFilho
Quem nunca precisou saber quais métodos
chamam outros métodos enquanto está melhorando aquele código imenso? A nova versão do
Visual Studio agora lhe possibilita isto, através do
Call Hierarchy.
Como exemplo, criei um projeto Silverlight,
que conta com a MainPage.xaml.cs, uma classe
chamada ClassePai e outra chamada ClasseFilha.
Criei alguns métodos para interpretação, o MetodoPai na ClassePai, que chama o MetodoFilho,
na ClasseFilha. E por sua vez, no construtor da
MainWindow.xaml.cs, o MetodoPai é chamado.
Seria algo parecido como:
Conclusão
Então o que concluimos é que a Microsoft está
trabalhando intensamente em cima das necessidades da comunidade e dos Feedback enviados. E
esses novos diagramas e funcionalidades facilitam
a vida dos arquitetos, analistas e desenvolvedores,
vale a pena conferir. Mais informações podem ser
obtidas em:
http://www.microsoft.com/visualstudio/
en-us/
MainPage.xaml.cs -> MetodoPai -> MetodoFilho.
Indo lá no cabeçalho do MetodoFilho, clicamos
com o botão direito, indo em View Call Hierarchy,
o que nos abrirá a seguinte janela:
Veja a figura 7.
Sobre o autor
Djonatas Tenfen
Trabalha a quase 7 anos com Delphi, trabalha na empresa Benner
Sistemas (www.benner.com.br ) na área de tecnologia desenvolvendo ferramentas em Delphi e como hobby e visão de mercado está migrando seus
conhecimentos para a plataforma .NET. Faz parte do grupo .NET Blumenau
http://dotnetblumenau.ning.com/ . Possue certificação 70-536 (Microsoft
.NET Framework 2.0 Application Development Foundation ) .
Twitter: djonatastenfen - blog http://www.djonatastenfen.blogspot.com/
[email protected]
março 2010
27
Dicas DELPHI
Limitar número de caracteres digitados em um Memo
ou RichEdit
Mude a propriedade MaxLenght do Memo ou RichEdit para o valor
desejado(neste exemplo usaremos 140), adicione também uma label para
mostrarmos a contagem dos caracteres.
Serial,DirLen,Flags,nil,0);
Result := IntToHex(Serial,8);
Except
Result :=’’;
end;
Estado da memória do computador
Adicione um Memo ao Form.
No evento OnChange
Label1.Caption:=
IntToStr(length(Memo1.Text)); //
uma label mostrando o número de
caracteres digitados
const
cBytesPorMb = 1024 * 1024;
var
M: TMemoryStatus;
begin
M.dwLength := SizeOf(M);
GlobalMemoryStatus(M);
No evento KeyUp
Memo1.Clear;
with Memo1.Lines do begin
Add(Format(‘Memória em uso:
if length(Memo1.Text) = 140 then
// se o tamanho do memo igual a 140
então
ShowMessage(‘Somente 140
caracteres permitidos’); // mostra
mensagem
%d%%’, [M.dwMemoryLoad]));
Add(Format(‘Total de memória
física: %f MB’, [M.dwTotalPhys /
cBytesPorMb]));
Add(Format(‘Memória física
disponível: %f MB’, [M.dwAvailPhys
/ cBytesPorMb]));
Add(Format(‘Tamanho máximo
do arquivo de paginação: %f
MB’, [M.dwTotalPageFile /
cBytesPorMb]));
Serial HD
Add(Format(‘Disponível
no arquivo de paginação: %f
MB’, [M.dwAvailPageFile /
Function SerialNum(FDrive: String):
String;
var
Serial:DWord;
DirLen,Flags: DWord;
DLabel : Array[0..11] of Char;
begin
Try
GetVolumeInformation(PC
har(FDrive+’:’),dLabel,12,@
28
março 2010
cBytesPorMb]));
Add(Format(‘Total de memória
virtual: %f MB’, [M.dwTotalVirtual
/ cBytesPorMb]));
Add(Format(‘Memória
virtual disponível: %f MB’,
[M.dwAvailVirtual / cBytesPorMb]));
end;
end;
março 2010
29
Horizontal
30
Vertical
março 2010
março 2010
março 2010
Download

março 2010