Escolar Documentos
Profissional Documentos
Cultura Documentos
março 2010
índice Editorial Delphi Delphi
04 05 10
Espero que nesse mês todos Manipulando Streams no Delphi Utilizando componentes ABCr no
tenham recebido 2010 Delphi 2010
muitos ovinhos do
coelhinho. Quem
não recebeu seja
um bom menino... Autor: Antonio Spitaleri Autor: Antonio Spitaleri
14 19 24
Indo mais além eplorando as Stored Procedures e Triggers no Novidades do Visual Studio 2010
tabelas de sistema MySQL
Interbase/Firebird
28
- Dicas Delphi
30
- Cruzada
Legenda
Iniciante
Intermediário
Avançado
março 2010 03
Bem-vindo Av. Profº Celso Ferreira da Silva, 190
Espero que nesse mês todos tenham recebido muitos ovinhos do coelhinho. Jd. Europa - Avaré - SP - CEP 18.707-150
Informações: (14) 3732-1529
Quem não recebeu seja um bom menino ou menina que no próximo ano ele Suporte: (14) 3733-1588
vem.
Internet
Aproveito para convidar nossos leitores a comparecerem ao “Microsoft http://www.theclub.com.br
Cadastro: cadastro@theclub.com.br
TechDay” que será realizado em Blumenau-SP no dia 24/04 e que tem com um Suporte: suporte@theclub.com.br
dos idealizadores nosso colunista Djonatas Tenfen. O The Club tem prazer em Informações: info@theclub.com.br
Skype Cadastro: theclub_cadastro
apoiar essa iniciativa. Tenho certeza que será um grande evento. Saiba mais Skype Suporte: theclub_linha1
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 www.twitter.com/theclubbr
que apesar de ser pouco utilizado nos dias de hoje, pode ser muito importante
Copyright The Club Megazine 2009
para alguns pontos específicos dos nossos aplicativos. No segundo, ”Utilizando
os Componente ACBr com Impressoras Fiscais no Delphi 2010” ele fala sobre os
Diretor Técnico
componentes Open Source ACBr que são uma verdadeira “mão na roda” para Marcos César Silva
nós desenvolvedores trabalharmos com ECF.
Diagramação e Arte
Iniciando as páginas dedicadas a Banco de Dados dessa edição, Felipe Santos Vitor M. Rodrigues
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/ Revisão
Tassiane Fileto
Firebird visando uma melhor manutenção dos nossos Bancos de Dados.
Colunistas
Nosso consultor Jr. Bruno Alcarás neste mês nos trás o artigo “Stored Procedure Antonio Spitaleri Neto
e Triggers no MySQL”, nos dando uma visão geral sobre esses ótimos recursos Bruno Alcarás
Djonatas Tenfen
que são mais conhecidos em Banco de Dados Firebird mas que também tem um Felipe Santos
papel muito importante no desenvolvimento de um Banco MySQL.
Impressão e acabamento:
Djonatas Tenfen no seu artigo “Novidades do Visual Studio 2010” nos apresenta GRIL - Gráfica e Editora
Taquarituba-SP - Tel. (14) 3762-1345
as principais novidades dessa nova versão do Visual Studio que foi oficialmente
lançado no dia 12/04.
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
Um grande abraço
Megazine” são terminantemente proibidos sem autorização
escrita dos titulares dos direitos autorais.
04 março 2010
Delphi
Manipulando Streams
no Delphi 2010
FileStream
Entre os vários recursos que existem Nesse artigo estarei abordando de forma
Como o próprio nome já sugere, a classe TFileS-
desde versões mais antigas do Delphi e ainda prática o uso dos Streams utilizando a versão tream, descendente de TStream, manipula arquivos
assim são pouco explorados pelos desen- 2010 do Delphi. Porém os exemplos funcio- em disco na forma de Streams. Em geral utilizamos
volvedores especializados na ferramenta, nam em versões anteriores do Delphi com essa forma de Stream para manipular arquivos de
sem dúvida um dos mais destacados são os pouca ou nenhuma modificação. texto, mas a utilização da mesma para outros tipos
de arquivos é perfeitamente possível.
Streams. Streams são objetos que remetem
ao início dos tempos da programação, quando Mãos a obra!
Inicie uma nova aplicação no Delphi e monte
a manipulação de dados era feita byte a byte. o layout da mesma conforme a figura 1:
Com o surgimento de novas tecnologias, a uti-
lização dos Streams ficou restrita a situações
em que os mesmos são imprescindíveis.
Figura 1
março 2010 05
O que faremos a seguir é carregar um arquivo cionado, iremos realizar a carga do mesmo para o
texto para um objeto FileStream e em seguida car- FileStream e exibir o conteúdo do mesmo no objeto Veja a Figura 2.
regar esse Stream no objeto Memo para exibição memo que inserimos na aplicação.
do mesmo.
Segue o código: Stream com imagens
Quando criamos um objeto FileStream no
construtor do mesmo temos de informar além do Embora não seja o mais recomendado, todos
caminho do arquivo o modo de abertura desse os servidores de banco de dados utilizados com
arquivo. FileStream nos possibilita quatro formas procedure TForm1. o Delphi aceitam o armazenamento de dados na
de abertura que são: btnexibirClick(Sender: forma binária através de campos Blob. Esse tipo de
TObject); campo em geral é utilizado para o armazenamento
var de imagens no banco de dados, mas pode ser uti-
Fmcreate- Caso o arquivo não exista, será sFilename:string; lizado para armazenar vídeos, textos entre outros
criado. Caso exista, será zerado e a escrita no oFileStream:TFileStream; dados de forma binária.
mesmo irá sobrescrever seu conteúdo atual; begin
try Para se trabalhar com campos Blob nos com-
Fmopenread- Abre o arquivo apenas ponentes DataSet existentes no Delphi, podemos
para leitura; lançar mão de mais duas classes: TBlobStream,
sFilename:=edtcaminho. para os componentes BDE, e TMemorystream
Fmopenwrite- Abre o arquivo apenas Text; ou a própria classe TStream para demais tipos de
para escrita; DataSets. Com essas classes poderão ser feitos o
oFileStream:=TFileStream. envio e recuperação de dados a partir de campos
Fmopenreadwrite- Abre o arquivo para Create(sFilename,fmOpenRead); Blob. Lembrando que para o Stream independe
leitura e escrita. memstream.Lines. se o campo Blob contém um texto, uma imagem
LoadFromStream(oFileStream); ou outra forma de dado. Sua função é apenas
finally servir de veículo para envio e recuperação dessas
O primeiro passo será a busca do arquivo com informações.
o OpenDialog, que será feita no evento OnClick do FreeAndNil(oFileStream);
botão “Carregar”. end; Vamos a um exemplo prático com Blob em
end; combinação com outros dois objetos para carga
Segue o código: de imagens. No PageControl de nossa aplicação,
adicione uma nova página e coloque como caption
Salve as alterações e teste o aplicativo. Se da mesma “Blobstream”. Em seguida adicione a
procedure TForm1. tudo correu bem, o resultado será semelhante ao página um componente Clientdataset, alterando
btncarregarClick(Sender: mostrado na figura 2: seu nome para CdsBlob. Abra o FieldsEditor do
TObject);
var
sFilename:string;
begin
if(OpenDialog1.Execute)
then
sFilename:=OpenDialog1.
FileName;
edtcaminho.
Text:=sFilename;
end;
março 2010
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.
Figura 3
Os outros dois objetos que estaremos utilizan-
do são: TStream para a recuperação do conteúdo
do Blob após o mesmo ter sido carregado. E TJpe- procedure TForm1.SalvarClick(Sender: TObject);
gImage para armazenar a imagem proveniente do var
campo Blob. sFilename:string;
oFilestream:TFileStream;
oMemorystream:TStream;
Veja a Figura 3.
oImage:TJPEGImage;
begin
Lembrando que o componente OpenDialog try
não precisa ser criado novamente, será utilizado o sFilename:=edtcaminhoimg.Text;
que já havíamos criado na primeira página. oFilestream:=TFileStream.
Create(sFilename,fmOpenRead);
Iremos selecionar o caminho de uma imagem oMemorystream:=TMemoryStream.Create;
para em seguida enviá-lo para o Blobstream. Para oImage:=TJPEGImage.Create;
a seleção do arquivo, no evento OnClick do botão cdsblob.Open;
“Selecionar” faça: cdsblob.Append;
cdsblobIMAGEM.LoadFromStream(oFilestream);
cdsblob.Post;
oMemorystream:=cdsblob.CreateBlobStream(cdsbl
procedure TForm1.
obIMAGEM,bmRead);
SelecionarClick(Sender:
oImage.LoadFromStream(oMemorystream);
TObject);
Image1.Picture.Assign(oImage);
begin
finally
OpenDialog1. FreeAndNil(oFilestream);
Filter:=EmptyStr; FreeAndNil(oMemorystream);
OpenDialog1. FreeAndNil(oImage);
Filter:=’Image Files|*. end;
Listagem 4
jpg’;
if(OpenDialog1.Execute)
then
edtcaminhoimg. seguida salvamos o caminho do arquivo de imagem nada em um FileStream, salvá-la no campo blob
Text:=OpenDialog1. na Edit edtcaminho. e depois recuperá-la com a técnica do blobstream
FileName; combinada com o Jpegimage.
end; Como estamos trabalhando com imagens em
formato Jpeg devemos adicionar na uses da unit a Veja a codificação no evento OnClick do botão
biblioteca Jpeg. “Salvar”:
Alteramos o filtro do OpenDialog para que
apenas aceite imagens com a extensão jpeg e em Iremos agora salvar essa imagem já selecio- 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.
Veja a Figura 4.
Figura 4
Figura 5
Antes de passarmos a prática com buffers, é
importante destacar duas propriedades importan-
tes de um Stream, que são: Size e Position.
Botão “Selecionar Arquivo”:
Size retorna um inteiro com o tamanho ocu-
pado pelo Stream, e Position também retorna um
inteiro com a posição atual do cursor de leitura do procedure TForm1.btnarqselecionarClick(Sender:
Stream. Assim como os datasets, Streams também TObject);
possuem um cursor interno responsável pela leitura begin
dos dados. if(OpenDialog1.Execute)then
edtcaminhoarq.Text:=OpenDialog1.FileName;
Vamos a prática. Adicione uma nova página end;
ao PageControl da aplicação e monte seu layout
conforme a figura 5:
Botão “Copiar”:
Veja a Figura 5.
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 a Figura 6.
Conclusão
Sobre o autor
Antonio Spitaleri Neto
Consultor Técnico The Club.
antonio@theclub.com.br
março 2010 09
Utilizando os componentes
ACBr com Impressoras
Fiscais no Delphi 2010
Iniciando a aplicação
No dia-a-dia do desenvolvimento voltado Outro ponto importante a se destacar no
para a área de automação comercial, uma Acbr é o fato de utilizar muitos dos conceitos Criaremos uma aplicação que irá realizar as
grande preocupação dos desenvolvedores da orientação a objetos. Conceitos esses principais operações relacionadas às impressoras
é a comunicação do aplicativo com as cha- muito raramente utilizados quando se trata fiscais, como por exemplo: Leitura X, Redução Z,
madas impressoras fiscais, conhecidas pela de aplicativos e bibliotecas desenvolvidos além é claro das operações de registro de itens
sigla “ECF”. Para quem trabalha nesse ramo em Delphi. O fato de utilizar orientação a em uma venda.
a algum tempo, a solução mais simples e co- objetos tornou o código do ACBr mais legível
mumente utilizada eram as dll’s dos próprios e extensível e ao longo dos últimos anos várias Veja como ficará o layout principal da aplicação
desenvolvedores da ECF utilizada. melhorias tem sido aplicadas ao projeto. na figura 1:
Recorrer a essas dll’s sem dúvida torna o Nesse artigo, estarei mostrando como No alto e a esquerda da tela, temos dois
trabalho de se comunicar com as ECF’s mais podemos utilizar o ACBr para fazermos nosso componentes ComboBox onde no primeiro iremos
tranqüilo, porém apresenta um incoveniente: aplicativo se comunicar com uma impresso- colocar na propriedade Items uma lista com os
E se o modelo e\ou fabricante da ECF for ra fiscal. Para os que não dispõem de uma modelos suportados pelo Acbr. São eles:
trocada pelo cliente? Ou ainda se um cliente impressora fiscal para testes, é importante
novo utilizar um modelo de um fabricante ressaltar que o exemplo funciona com emu-
diferente? Para essas situações, se faz ne- ladores de ECF sem problemas. ecfNenhum, ecfNaoFiscal, ecfBematech,
cessário readaptar o aplicativo para trabalhar ecfSweda, ecfDaruma, ecfSchalter,
com o novo modelo\fabricante de ECF. No artigo não estarei mostrando a insta- ecfMecaf, ecfYanco, ecfDataRegis,
lação dos componentes ACBr no Delphi 2010, ecfUrano, ecfICash, ecfQuattro, ecfFiscNET,
O projeto ACBr vem de encontro a esse já que instruções para instalação acompa- ecfEpson, ecfNCR, ecfSwedaSTX;
problema. Esse conjunto de componentes e nham o componente.
rotinas totalmente Open Source e desenvol-
vido em Delphi, permite que a aplicação que Também não será abordada no artigo No segundo componente ComboBox, coloca-
irá se comunicar com a ECF seja desenvolvida a instalação e configuração de emuladores remos uma lista com os nomes das portas COM
apenas uma vez, e a troca de modelo ou de ECF. disponíveis no computador. No exemplo fiz a lista
fabricante de componente deixa de ser um com as portas COM1 até COM6.
problema.
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.
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.
frmvenderitem:=Tfrmvenderitem.
Create(Self); Botão “Sair”:
Operação de venda de itens
frmvenderitem.
ShowModal;
Adicione um novo formulário a aplicação e finally procedure Tfrmvenderitem.
monte o layout do mesmo conforme mostrado btnsairClick(Sender:
na figura 2: FreeAndNil(frmvenderitem); TObject);
end; var
Veja a Figura 2. end; sValorpagamento:string;
begin
12 março 2010
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’,’’);
Figura 3
Form1.ACBrECF1.Efetu
aPagamento(‘01’,StrToFloat
(sValorpagamento));
Form1.ACBrECF1.
FechaCupom(‘Obrigado Volte
O projeto ACBr, é totalmente open source,
Sempre!’);
podendo ser adquirido nos seguintes links:
Close;
end;
end;
14 março 2010
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 co-
mandos 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.
Imagem 2
SQL> show system;
RDB$CHARACTER_SETS
RDB$CHECK_CONSTRAINTS uma coluna Char/Varchar. Por exemplo: Precisamos outra tabela principal, por exemplo. Precisamos
RDB$COLLATIONS ampliar a coluna NOME de 30 para 60 caracteres. então rodar comandos do tipo Alter Trigger ... Inac-
RDB$DATABASE Mas como fazer de uma só vez em todas as tabelas tive/Active. Mas como fazer isso de forma prática
RDB$DEPENDENCIES do banco de dados onde essa coluna existe? Mani- quando temos centenas / milhares de Triggers?
RDB$EXCEPTIONS pulando as tabelas de sistema: Executando o comando DML abaixo:
[...]
SQL>
Update UPDATE
rdb$fields RDB$TRIGGERS
2. Usando o utilitário gráfico IBConsole, Set SET
selecionamos no menu: rdb$field_length = 60 rdb$trigger_inactive = 1
Where WHERE
rdb$field_name = (rdb$system_flag = 0 or
(select f.rdb$field_ rdb$system_flag IS NULL)
source AND
from rdb$relation_ rdb$trigger_name NOT LIKE
fields f ‘CHECK%’ AND
where f.rdb$field_name rdb$trigger_name NOT LIKE
= ‘NOME’) ‘RDB$%’
16 março 2010
Club Megazine comentamos a respeito do uso das
DELETE UDFs. Segue um exemplo de uso de UDF contra de Tamanhos’
FROM RDB$RELATION_ uma tabela de sistema: WHERE RDB$RELATION_NAME=’
CONSTRAINTS A T02P007LJ’;
Where UPDATE RDB$RELATIONS SET
(Select count(*) from RDB$DESCRIPTION=’Cadastro
Select F_UUID1MACMAC(F_
RDB$CHECK_CONSTRAINTS B, de Cores’
UUID1MAC()) from
RDB$TRIGGERS C WHERE RDB$RELATION_NAME=’
rdb$database;
where T03P007LJ’;
(A.RDB$CONSTRAINT_TYPE = UPDATE RDB$RELATIONS SET
‘CHECK’) and RDB$DESCRIPTION=’Tabelas de
(A.RDB$CONSTRAINT_ Esse comando executado a partir de qual- Preco’
NAME = B.RDB$CONSTRAINT_ quer computador cliente retornará o endereço WHERE RDB$RELATION_NAME=’
NAME) and Mac Address do servidor do banco de dados. Isso T04P009LJ’;
(B.RDB$TRIGGER_NAME = pode ser muito útil por exemplo para se criar uma UPDATE RDB$RELATIONS SET
C.RDB$TRIGGER_NAME) and rotina de validação da aplicação para liberação de RDB$DESCRIPTION=’Imagens de
(C.RDB$TRIGGER_TYPE = licenças de uso. Produtos’
1) and WHERE RDB$RELATION_NAME=’
(A.RDB$RELATION_NAME T05P015LP’;
in Trabalhando com Descrições em
(SELECT Tabelas:
DISTINCT E assim por diante. Quando abrimos o uti-
r.rdb$relation_name litário IBExpert, podemos facilmente identificar
Esse é outro ponto interessante. É muito
FROM rdb$check_
comum encontrar bancos de dados com centenas as tabelas:
constraints C JOIN
de tabelas, mas onde o nome da tabela não iden-
rdb$relation_
constraints R tifica seu real propósito. Por exemplo: ao invés de Veja a Imagem 3.
ON chamar uma tabela de cadastros de produto de
(C.rdb$constraint_name = TABPRODUTOS, o nome da tabela é algo do tipo Ou mesmo podemos executar um comando
R.rdb$constraint_name) T01P007LJ. Então novo desenvolvedor ou mesmo DML para pesquisar uma determinada tabela pela
WHERE um usuário mais experiente acaba ficando perdido sua descrição:
C.rdb$trigger_ ao tentar encontrar uma determinada tabela.
name IN
(SELECT Uma maneira interessante de se tratar esse Select rdb$relation_name,
D.rdb$dependent_name problema é criando uma descrição para as tabelas rdb$description from
FROM rdb$relations
de sistema. Para isso usamos o comando DML:
rdb$dependencies D where rdb$description
WHERE like ‘%rodutos%’;
D.rdb$field_
UPDATE RDB$RELATIONS SET
name = ‘TIPO_CLIENTE’ and
RDB$DESCRIPTION=’Cadastro
de Produtos’
d.rdb$dependent_name like
WHERE RDB$RELATION_NAME=’
‘CHECK%’))
T01P007LJ’;
UPDATE RDB$RELATIONS SET
)) > 0;
RDB$DESCRIPTION=’Cadastro
março 2010 17
Retornaria algo como:
Nos vemos no próximo artigo para falar mais
sobre o InterBase e seus recursos. Valeu pessoa
RDB$RELATION_NAME RDB$DESCRIPTION
e Até lá!
T01P007LJ Cadastro de Produtos
T05P015LP Imagens de Produtos
Referência:
CONCLUSÃO as informações estão lá o tempo todo. Cabe a InterBase 2009 Language Reference – cap. 6.
nós desenvolvedores irmos mais além, usar essas http://edn.embarcadero.com
E esses são apenas alguns exemplos. Nova- informações à nosso favor.
mente explorando mais dos recursos de nossos
bancos de dados. Se pesquisarmos mais e estu-
darmos as tabelas de sistema de nossos bancos, Sobre o autor
podemos extrair muito mais. Claro e novamente Felipe Santos
repetindo: tudo com muito cuidado para não der- Felipe Santos é especialista em InterBase. Trabalha com o InterBase desde
2001. atuando como consultor e instrutor do produto em todo Brasil. Especialista em
rubar alguma integridade ou mesmo corromper ambientes críticos. Atua e trabalha com os maiores clientes do InterBase no Brasil.
Participante ativo na comunidade, com diversos artigos publicados. Participante do
nossos bancos. Mas recomendo a todos a leitura 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.
complementar do Capitulo 6 do guia Language Atualmente trabalhando na área técnica do InterBase na Presence Tecnologia – agente
Reference do InterBase SMP 2009, que contém oficial especializado do produto no Brasil.
18 março 2010
STORED PROCEDURES
E TRIGGERS NO MYSQL
As Stored Procedures e Triggers são mais • Melhora do desempenho – por se- alteração que prejudique o Banco de Dados;
conhecidas no Firebird, mas também são mui- rem armazenadas e processadas no servidor
to importantes na otimização do desempenho elas enviarão ao usuário somente os resulta- • Distribuição de tarefas – as tarefas
de um Banco de Dados no MySQL, neste arti- dos das consultas diminuindo assim o trafego da criação de uma aplicação podem ser divi-
go mostrarei o que elas são, como funcionam na rede; didas entre um profissional especializado em
no MySQL e farei alguns exemplos. Banco de Dados e um Programador que criará
• Economia de código – é necessária a aplicação.
apenas uma linha de código para se chamar
uma SP já que a instrução SQL está toda en-
STORED PROCEDURES capsulada no corpo da SP, você não terá mais
que escrever várias linhas toda vez que quiser As SP são basicamente classificadas em três
Introduzidas a partir da versão 5.0 do MYSQL uma operação específica em seu banco; tipos:
as Stored Procedures (SP) ou Procedimentos Ar-
mazenados são um conjunto de comando SQL que • Facilidade de manutenção – elas
podem ficar armazenados no servidor e poupar podem ser alteradas sem a necessidade de 1. As que retornam algum valor, como
os usuários da necessidade de enviar extensos se alterar as aplicações que as utilizam e sem a contagem de registros de uma tabela;
comandos SQL ao servidor só sendo necessário importar a linguagem em que foi escrita essa
fazer a chamada a SP. aplicação; 2. As que retornam registros funcionan-
do como um Select , e;
As vantagens do uso das SP’s são muitas, entre • Segurança – os usuários terão acesso
as principais que posso destacar estão: somente as SP’s e não as tabelas, isso diminui 3. As que fazem ações específicas no
a possibilidade de algum usuário fazer alguma banco, como inserções, alterações, atualiza-
ções etc.
março 2010 19
STORED PROCEDURES NO MYSQL comandos procedurais executados automatica-
mente em resposta a algum evento executado no corpo_trigger
A sintaxe geral de uma SP no MySQL é a banco de dados, como por exemplo na inserção de
seguinte: um registro em uma tabela de pessoas, a trigger
automaticamente gerará na tabela de salários um Onde:
campo referente ao salário daquela pessoa.
CREATE PROCEDURE nome_
proc([parâmetro ...]) As triggers são usadas geralmente para: • DEFINER: checa quais os privilégios
[características] que usuário do banco tem para disparar a
BEGIN trigger. Quando a trigger é criada esse campo
• Para manter a integridade entre as é preenchido por padrão com CURRENT_USER
Corpo da SP; ou pode ser preenchida com o usuário(ex:
tabelas: podem ser criados grandes processos
de controle dos relacionamentos entre as ta- ‘bruno’@’localhost’);
END;
belas, principalmente aos usuários de tabelas
MyISAM que não suportam relacionamnetos • nome_trigger: define-se o nome da
via chave estrangeira; trigger, o padrão adotado entre os desenvol-
Onde:
vedores é TRG_nome_trigger;
• Manter a segurança do Banco: as tri-
ggers podem controlar o acesso, atualizações • tempo_trigger: aqui se define quan-
• Nome_proc - aqui se define o nome
e alterações nas tabelas; do a trigger será executada:
da procedure, um padrão muito adotado en-
tre os desenvolvedores é SP_nome_da_pro-
• Melhorar o desempenho do banco: • BEFORE: a trigger será ativada antes
cedure;
imagine um banco com 500.000 registros que do comando que a disparou;
EXEMPLOS
TRIGGERS ON nome_tabela
março 2010
alguns exemplos de Triggers e Stored Procedures.
O primeiro passo é criar as tabelas, para este int(11) default NULL, CREATE PROCEDURE SP_ADD_
exemplo vamos criar duas tabelas, uma tabela de PRIMARY KEY (`ID_ USUARIOS (
USUARIO`), IN USUARIO VARCHAR (80),
pessoas e outra de usuários. Abaixo seguem os
KEY `FK_PESSOA_USUARIO` IN SENHA VARCHAR (35),
scripts de criação das tabelas: IN TIPO CHAR(1),
(`FK_PESSOA_USUARIO`),
IN FK_PESSOA INT)
CONSTRAINT `USUARIO_
BEGIN
PESSOA_FK` FOREIGN KEY
PESSOAS (`FK_PESSOA_USUARIO`)
INSERT INTO `usuarios`
(USUARIO_NOME, USUARIO_
REFERENCES `pessoas` (`ID_ SENHA, USUARIO_TIPO,FK_
Essa tabela servira para o cadastro de pessoas, PESSOA`) PESSOA_USUARIO)
como por exemplo clientes e funcionários, essa ) ENGINE=InnoDB DEFAULT VALUES
especificação se dará no campo PESSOA_TIPO que CHARSET=latin1 (USUARIO,SENHA,TIPO,FK_
receberá G para gerente(que terá todos os privilé- PESSOA);
gios), C – para cliente ou F – para funcionário. END;
TRG_CRIP_SENHA
CREATE TABLE `pessoas` (
`ID_PESSOA` INTEGER(11) Agora vamos criar nossa primeira trigger, essa TRG_USUARIOS
NOT NULL AUTO_INCREMENT, trigger se encarregará de criptografar a senha de
`PESSOA_NOME` usuário quando este for inserido, o método de Essa trigger incluirá automaticamente uma
VARCHAR(80) NOT NULL, pessoa cadastrada na tabela de pessoas, desde
criptografia é o MD5 que já é uma função presente
`PESSOA_RG` VARCHAR(15) que seu pessoa tipo na tabela seja F, na tabela de
no banco MySQL, o MD5 é um algoritmo unidire-
DEFAULT NULL, usuários como um usuário do sistema. Por padrão,
cional que criptografa uma string e não permite
`PESSOA_TIPO` CHAR (1)
que essa criptografia seja revertida. Percebam que que será definido na trigger, o nome de desse
DEFAULT NULL,
usamos o operador NEW (NEW. USUARIO_SENHA) usuário será o seu nome em letras minúsculas,
PRIMARY KEY (`ID_
esse operador significa que queremos o dado que a senha será 123456 e o tipo será definido como
PESSOA`)
) ENGINE=InnoDB; acaba de ser inserido, se porventura apagássemos C - Comum.
esse registro poderíamos recuperá – lo através do
operador OLD (OLD. USUARIO_SENHA).
CREATE TRIGGER TRG_
USUARIOS AFTER INSERT ON
USUARIOS
`pessoas`
CREATE TRIGGER TRG_CRIP_
FOR EACH ROW
Essa tabela guardará os dados dos usuários SENHA BEFORE INSERT ON
BEGIN
de um suposto programa, desde que eles sejam `usuarios`
IF (NEW.ID_PESSOA IS NOT
FOR EACH ROW
definidos com F no campo PESSOA_TIPO. O campo NULL) AND (NEW.PESSOA_TIPO
BEGIN
USUARIO_TIPO deve ser marcado com A – Adminis- = ‘G’) THEN
SET NEW.USUARIO_SENHA =
trador ou C- Comum sendo que só o Administrador CALL SP_ADD_
MD5(NEW.USUARIO_SENHA);
tem permissões para inserir registros na tabela USUARIOS(LOWER(NEW.PESSOA_
END;
de pessoas. NOME),’123456’,’A’,NEW.
ID_PESSOA);
ELSE
CREATE TABLE `usuarios` ( IF (NEW.ID_PESSOA IS
SP_ADD_USUARIOS
`ID_USUARIO` int(11) NOT NOT NULL) AND (NEW.PESSOA_
NULL auto_increment, TIPO = ‘F’) THEN
O nosso próximo passo é criar uma Stored CALL SP_ADD_
`USUARIO_NOME`
varchar(80) default NULL,
Procedure que será usada em conjunto com a USUARIOS(LOWER(NEW.PESSOA_
`USUARIO_SENHA` próxima trigger e que quando executada incluirá NOME),’123456’,’C’,NEW.
varchar(35) default NULL, dados na tabela de usuários. ID_PESSOA);
`USUARIO_TIPO` char(1) END IF;
default NULL, END IF;
`FK_PESSOA_USUARIO` END
março 2010 21
TESTES
Imagem 1
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 Imagem 2
no seguinte endereço:
Imagem 3
22 março 2010
Veja a Imagem 5.
CALL SP_PERMISSOES(‘daniel
’,’123456’,’JEREMIAS’,’84.
369.521-7’,’G’)
Imagem 6
março 2010 23
Além dos modelos básicos de programação Visual Studio Ultimate (além das funcionalida-
Olá, Então pessoal como alguns devem WCF, WPF, Windows Form, Silverlight, WebAppli- des da versão Premium):
saber no dia 12/04/2010 foi lançado o Visual cation e a novidade agora é Azure ou seja Cloud
Studio 2010 oficialmente e na edição de hoje Computing, e essa nova versão conta com Unit
eu vou falar sobre algumas novidades dessa Tests, ao contrário da versão Professional do Visual • Debugging histórico com IntelliTra-
versão, nessa edição eu vou focar nas área e Studio 2008. ce
nas novidades que mais gostei área de arqui- • Ferramentas de testes compreensi-
tetura e modelos UML. Visual Studio Premium (além das funcionali- vas
dades da versão Professional): • Ferramentas avançadas de UML
• Ferramentas de descoberta de arqui-
As versões tetura
• Debugging e desenvolvimento de • Test Case e gerenciamento do labo-
Ao contrário de seus antecessores, o Visual aplicações avançado ratório de testes
Studio 2010 conta com SKUs (edições) mais simpli- • Unit Tests com cobertura de código
ficadas, de anteriormente 9 para simplesmente 4 (Code Coverage - mostra quanto por cento
agora: Ultimate, Premium, Professional e a versões do código está sendo testado), prioritização
Express. Irei abordar aqui individualidades de cada de testes, análise, métrica e otimização de
uma das três versões pagas, Ultimate, Premium e código
Professional: • Desenvolvimento e testes unitários
de banco de dados
Visual Studio Professional • Diagramas de arquitetura (apenas
leitura)
24 março 2010
Modelagem UML
Veja a figura 1.
Diagrama de Sequência
Figura 1. Criando um projeto de diagrama
A UML significa muito para arquitetos e ana-
listas 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
Veja a figura 2.
Diagrama de Dependências
Veja a imagem 4.
Diagrama de Camadas
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
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á melho-
rando aquele código imenso? A nova versão do
Visual Studio agora lhe possibilita isto, através do
Conclusão
Call Hierarchy.
Então o que concluimos é que a Microsoft está
trabalhando intensamente em cima das necessi-
Como exemplo, criei um projeto Silverlight,
dades da comunidade e dos Feedback enviados. E
que conta com a MainPage.xaml.cs, uma classe
esses novos diagramas e funcionalidades facilitam
chamada ClassePai e outra chamada ClasseFilha.
a vida dos arquitetos, analistas e desenvolvedores,
Criei alguns métodos para interpretação, o Me-
vale a pena conferir. Mais informações podem ser
todoPai na ClassePai, que chama o MetodoFilho,
obtidas em:
na ClasseFilha. E por sua vez, no construtor da
MainWindow.xaml.cs, o MetodoPai é chamado.
http://www.microsoft.com/visualstudio/
Seria algo parecido como:
en-us/
MainPage.xaml.cs -> MetodoPai -> Metodo-
Filho.
djonatas.tenfen@gmail.com
março 2010 27
Dicas DELPHI Serial,DirLen,Flags,nil,0);
Result := IntToHex(Serial,8);
Except
Limitar número de caracteres digitados em um Memo Result :=’’;
ou RichEdit end;
Label1.Caption:= const
IntToStr(length(Memo1.Text)); // cBytesPorMb = 1024 * 1024;
uma label mostrando o número de var
caracteres digitados 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:
%d%%’, [M.dwMemoryLoad]));
if length(Memo1.Text) = 140 then
Add(Format(‘Total de memória
// se o tamanho do memo igual a 140
então física: %f MB’, [M.dwTotalPhys /
ShowMessage(‘Somente 140 cBytesPorMb]));
caracteres permitidos’); // mostra Add(Format(‘Memória física
mensagem 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 /
cBytesPorMb]));
Function SerialNum(FDrive: String):
String; Add(Format(‘Total de memória
var virtual: %f MB’, [M.dwTotalVirtual
Serial:DWord; / cBytesPorMb]));
DirLen,Flags: DWord; Add(Format(‘Memória
DLabel : Array[0..11] of Char; virtual disponível: %f MB’,
begin [M.dwAvailVirtual / cBytesPorMb]));
Try end;
GetVolumeInformation(PC end;
har(FDrive+’:’),dLabel,12,@
28 março 2010
março 2010 29
Horizontal Vertical
30 março 2010
março 2010
março 2010