Mostrar mensagens com a etiqueta Programação. Mostrar todas as mensagens
Mostrar mensagens com a etiqueta Programação. Mostrar todas as mensagens

segunda-feira, abril 13, 2015

Passar o nome de uma coluna ou tabela como parâmetro num prepared statement

Vou começar por dizer que o que o título diz é parvo, sim é parvo, não porque não dá jeito ou porque a ideia é parva, mas simplesmente porque não é possível fazer. Se quiser fazer algo como o que está em seguida é para esquecer não é possível fazer:

SELECT @column FROM @table

Agora há uma forma mais ou menos elegante de resolver este problema. O que queremos ao termos prepared statements é evitar sql injection, esse é o verdadeiro problema. Então a solução passa por validar se a tabela e a coluna existem na nossa base de dados, e assim até validamos se a query é válida.
       private void AssertValidTableAndColumnName(SqlConnection connection, 
                    SqlCommand cmd, string table, string column)
       {
           cmd.CommandText = "SELECT COUNT(*) FROM SYS.TABLES WHERE NAME = @table";
           SqlParameter tab = new SqlParameter("table", SqlDbType.NVarChar, 500);
           tab.Value = table;
           cmd.Parameters.Add(tab);

           cmd.Prepare();
           int count = (int)(cmd.ExecuteScalar());

           if (count == 0)
           {
               throw new ArgumentException("Invalid table name", table);
           }
           
           cmd.CommandText = @"SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
                                WHERE  TABLE_NAME = @table
                                AND COLUMN_NAME = @column";
           SqlParameter col = new SqlParameter("column", SqlDbType.NVarChar, 500);
           col.Value = column;
           cmd.Parameters.Add(col);

           cmd.Prepare();
           count = (int)(cmd.ExecuteScalar());

           if (count == 0)
           {
               throw new ArgumentException("Invalid column name", column);
           }
       }

Temos assim a garantia que tanto a tabela como a coluna existem, se não existirem a aplicação enviará uma excepção. No meu caso quis mesmo que a aplicação terminasse, mas podemos não ser tão radicais e simplesmente retornar um booleano indicando o sucesso. Basta agora fazer uma query normal sem haver a preocupação que haja sql injection.

[...]
AssertValidTableAndColumnName(connection, cmd, table, column);
cmd.CommandText = string.Format("SELECT id,{1} FROM {0}", table, column);
[...]

sexta-feira, janeiro 23, 2015

Sanitizar HTML por javascript

O significado da palavra sanitizar neste contexto significa limpar o HTML de código potencialmente malicioso, seja ele introduzido propositadamente (na maior parte das vezes) ou seja inadvertidamente por desconhecimento. No caso de utilizar a sanitização por javascript é importante notar que estamos a sanitizar HTML que apenas pode estar errado por desconhecimento de quem o insere, ou então é necessário voltar a revalidar a sanitização do lado do servidor, pois quem quer introduzir especificamente código malicioso facilmente ultrapassará uma limpeza por javascript.

Estando esta salvaguarda feita e querendo eu fazer a sanitização por javascript, andei à procura de algumas bibliotecas de javascript que me pudesse auxiliar, pois de certeza que já mais gente precisou disto. Acabei por fazer uma pré selecção das 3 seguintes:
A primeira é uma biblioteca que inclusivamente é utilizada pelo google, mas ao ler a documentação não  fiquei esclarecido  como se utilizavam as whitelist, e como estava a perder já mais tempo do que eu achava que era razoável acabei por desistir de usar esta biblioteca, inclusivamente ainda andei a olhar o código desta biblioteca e não fiquei convencido que suporte whitelists, mas ao mesmo tempo acho estranho que algo utilizado pelo Google seja tão limitado!

A terceira biblioteca utiliza outras bibliotecas do NPM, e como considerei que era um absurdo a quantidade de bibliotecas que era necessário fazer download para algo tão simples como limpar HTML não gostei muito da solução.

Acabei por escolher a 2ª opção, simples, e em menos de 30 minutos tinha o meu problema resolvido. Gostei da flexibilidade como são definidas as whitelists, não gostei dos nomes das API, não são nada indicativos do que são mas olhando a documentação rapidamente se percebe como se faz. Já existem 3 whitelists disponibilizadas pela biblioteca com diferentes níveis de restrições mas é facílimo definir novas whitelists personalizadas. Deixo aqui um pequeno exemplo de uma possível implementação:

    var sanitizer = new Sanitize({
        elements: ['p','h1','h2','h3','a','b','i','br','ul','ol','li'],
        attributes: {
            a: ['href'],
            '__ALL__': ['width', 'height']
        },
        protocols: {
            a: { href: ['https'] }
        }
    });

    $(".inputToSanitize").each(function (index) {
            
            var sanitized = sanitizer.clean_node($(this).html());
            $(this).html(sanitized);
    }

sexta-feira, janeiro 31, 2014

Programação Orientada à Gambiarra

Dei com este conjunto de slides, há uns dias atrás e achei simplesmente delicioso. Para os não informáticos eles não vão fazer muito sentido, mas para os informáticos/programadores estes slides são quase tão bons como um espectáculo de standup comedy. Segundo sei isto já tem algum tempo mas ainda não tinha sido compilado num local, está escrito em brasileiro o que faz com que as expressões ainda tomem um sentido mais sarcástico.

sexta-feira, dezembro 13, 2013

SQL - Variáveis dentro de Views

Tudo começou quando dentro de uma View queria utilizar o resultado de uma query uma dúzia de vezes. Como essa query demorava cerca de 6 segundos a executar, a ideia era armazenar os valores numa variável table e a partir daí utilizar a variável. Problema, não é possível declarar variáveis dentro de Views. Após alguma pesquisa a solução que encontrei consiste em 2 passos:
  1. Criar uma Table-valued function que faz todo o trabalho que a View deveria ter e retorna o resultado que a View tem de devolver.
  2. A View faz bypass do resultado da Table-valued function

CREATE FUNCTION [dbo].[XPTO] ()
RETURNS @result TABLE 
(
 id int,
 field1 nvarchar(50) 
)
BEGIN

   --Todo o código necessário
   --Aqui já é possível declarar variáveis
   RETURN
END
----------------------------------------------
CREATE VIEW [dbo].[MyView]
AS
  SELECT * FROM [dbo].[XPTO]()

sexta-feira, agosto 30, 2013

Configurações do SQL Management Studio

Existem 2 coisas que costumo alterar nas configurações base do SQL Management Studio, ambas para me simplificarem a vida, mas é importante saber também as consequências que trazem.

A primeira alteração tem a ver com uma mensagem de erro que aparece com alguma frequência: "Saving changes is not permitted. The changes you have made require the following tables to be dropped and re-created. You have either made changes to a table that can't be re-created or enabled the optin Prevent saving changes that require the table to be re-created."

Uma maneira de contornar este erro é exactamente como diz a mensagem desactivar a opção de Prevent saving changes. Para fazer isso basta ir a Tools->Options...->Designers->Tables and Database Designers, e dentro deste menu desactivar a opção Prevent saving changes that require table re-creation. Se desactivar esta opção é ideal quando estamos na fase de estruturação da base de dados, a desenhar as tabelas e relações para a nossa aplicação, temos de ter consciência das suas implicações. Ao desactivar esta opção as tabelas vão ser recreadas sem que haja nenhum aviso ou alerta, e se elas tiverem dados estes vão-se perder.

A segunda alteração nem sempre a faço, só quando estou mais calão e não me apetece fazer updates através de statements e prefiro fazer alterações visualmente no designer, trata-se da opção Edit Top 200 Rows. Imaginemos que tenho uma tabela com 2000 registos e quero editar alguns deles, então o que me dava jeito era ter Edit Top 2000 Rows. Para fazer isso é necessário alterar a configuração  Tools->Options...->SQL Server Object Explorer->Commands, e colocar, por exemplo o valor 2000, na opção Value for Edit Top Rows command. No caso de se querer editar todas as linhas, colocar o valor 0, e aí independentemente do número de tuplos que a tabela tenha será possível editar todos. É preciso também saber que quanto mas linhas tiverem a opção de serem editadas pior será o desempenho e maior carga estaremos a fazer na máquina.


terça-feira, agosto 20, 2013

Create e Update utilizando Integration Services

Uma funcionalidade comum quando se utilizam os Integration Services é a copia de informação de uma tabela para outra. Acontece que o habitual é existir algo que me controle a importação de informação (tabela auxiliar, coluna da tabela a importar, contador, identity, etc), e que me permita saber a partir de que linha preciso retomar a importação pois as anteriores já foram importadas.

Agora existe um problema, como vou lidar com as linhas que já importei previamente, mas que têm valores modificados na tabela de origem? A resolução tradicional para este problema, e que pode ser encontrada em vários posts é a seguinte:
Vamos obter as linhas da tabela base, fazemos um lookup para verificar se a tabela destino já contem a linha, e decidimos então se a linha é para inserir ou para actualizar. Isto acaba por não ser muito penalizador se estivermos a falar de 10.000, 20.000, 50.000 ou até 100.000 linhas, o problema é quando começamos a falar de centenas de milhares de linhas ou mais. 

Enquanto que o processo de inserção funciona com bulks, ou seja, são inseridos blocos de linhas, no caso da caixa marcada a vermelho na imagem anterior as actualizações, estas são feitas uma a uma, o que permitirá inserir valores a rondar as 500-600 linhas por minuto. Já se começa a perceber o problema desta solução, então o objectivo é eliminar o update e substitui-lo por algo diferente.

Então cheguei à solução seguinte, que tem um desempenho muito, mas muito superior:

A alteração principal é a utilização de uma tabela auxiliar que é exactamente igual à tabela principal e agora o processo é extremamente simples.
1) Copiar todas as linhas sejam novas, sejam para actualizar, para a tabela auxiliar
2) Eliminar todas as linhas da tabela principal (utilizando as suas keys), que iriam ser alvo de actualizações
3) Copiar todas as linhas da tabela auxiliar para a tabela principal
4) Apagar todas as linhas da tabela auxiliar, deixando-a pronta para uma nova execução.

sexta-feira, março 15, 2013

Eventos de build só para Debug ou Release

Este é o segundo post seguido que faço sobre tecnologia, o que já não acontecia a algum tempo, deve ser da chegada da Primavera que faz florescer o meu lado geek. Indo directo ao assunto, estou no Visual Studio e queria no evento post-build correr um comando, mas só em Release mode pois ele é desnecessário correr sempre que faço build, por demorar alguns segundos e por só ser necessário em Release. Estou a falar de algo que me junta todos os ficheiros .js num só e ainda faz minificação, porreiro para uma versão Release mas desnecessário numa versão Debug.

if $(ConfigurationName) == Release (
   //my command
)

Só uma nota, atenção ao espaço (space) a seguir ao Release, ele é mesmo necessário, e ainda estive algum tempo a "bater" no erro exited with code 255, pela falta daquele maldito espaço.

terça-feira, março 12, 2013

Perguntas para entrevistas de informática

Na minha experiência a maior parte das entrevistas de TI segue um determinado padrão. Já fiz dezenas de entrevistas como entrevistador e cerca de uma dezena de entrevistas como entrevistado e é fácil perceber o porque de existir um padrão. Se vais fazer 5 entrevistas numa semana não tens tempo para preparar 5 entrevistas diferentes, além disso seria difícil comparar os 5 candidatos.

Contudo qualquer entrevistador minimamente inteligente vai sempre tirar alguns coelhos da cartola, perguntas que normalmente não faz e que surgem da conversa que se está a desenrolar porque o perfil do candidato orienta para determinadas perguntas. Estas perguntas normalmente são situações mais práticas, problemas da vida real, algo mais específico que decorre da experiência do entrevistador. Se estas perguntas não chegarem a acontecer é porque o entrevistador não é muito aplicado ou então é porque o entrevistado nem tem capacidades para chegar a essas perguntas.

Depois ainda existem 2 tipos de entrevistador, o primeiro que dispara perguntas sobre tudo e mais alguma coisa, sim porque a área de TI tem imensas sub-áreas, o segundo tipo, no qual eu me gosto de inserir, que vê as características do entrevistado e as características da posição para a qual o candidato está a concorrer, e esmiúça o que o candidato diz que se sente à vontade. Já agora um conselho, não mintam no CV, não digam que sabem coisas que não sabem, lá por terem trabalhado 1 mês numa tecnologia não quer dizer que percebam os mecanismos dessa tecnologia, isto é um tiro no pé porque vão ser entrevistados com base no que dizem que sabem e se não souberem vão sofrer - "É mais fácil apanhar um mentiroso que um coxo".

Quanto às perguntas comportamentais da entrevista só posso falar como entrevistado e o melhor conselho que tenho é, manter a calma e a postura. Tudo deve ser bem doseado, não se deve ser arrogante mas ao mesmo tempo mostrar com clareza e convicção os nossos pontos de vista.

Para terminar deixo aqui alguns links que têm perguntas tipicamente utilizadas em entrevistas de TI:

terça-feira, fevereiro 26, 2013

Bom programador = Bom com o Google

Há uns anos atrás tive uma entrevista no Sapo para integrar a equipa de desenvolvimento. A entrevista foi feita por 3 pessoas, e a dada altura o 'Chico Esperto' que liderava a entrevista, (ele até podia ser muito bom tecnicamente, não sei, mas ali só demonstrou arrogância e falta de social skills) fez-me uma pergunta qualquer daquelas que apelava ao conhecimento bíblico. A minha resposta foi algo como - "Eu não sei, mas de certeza que o meu amigo Google sabe, só tenho de lhe perguntar" - Ao que ele retorquiu - "Essa é a tua resposta? Não tens nada melhor para dizer?" - Eu como já estava farto da arrogância dele e naquela altura já não me via a aturar uma pessoa assim todos os dias respondi algo como - "Sim é, eu não tenho a mania que sei tudo!"

Escusado será dizer que nunca integrei a equipa dele, e que quando me falam em propostas para o Sapo a primeira coisa que pergunto é, quem seria o meu responsável e se for a tal personagem nem me disponho a ser entrevistado. Além disso já obtive algumas informações sobre a pessoa porque podia ter aquele perfil a fazer a entrevista para tentar intimidar o entrevistado e coloca-lo sobre stress, mas parece que não ele e mesmo assim no dia a dia.

Passado estes anos todos encontrei este post muito interessante sobre o que um dos fundadores da Framebase.io, acha sobre o uso do Google, e o que ele ele considera que é um bom programador. Tendo em consideração o percurso deste senhor diria que a sua opinião tem alguma credibilidade.

segunda-feira, dezembro 10, 2012

Relações Many-to-Many em JPA

Apesar de não serem muito comuns há situações onde é necessário utilizar relações many-to-many. Se a nível da BD existe uma tabela intermédia que promove a relação entre outras duas tabelas, a nível de objectos (classes), apenas vão existir 2 em que cada um delas tem uma lista da outra.

Imaginando que temos uma tabela de federateds e uma tabela de scores, em que um federated tem vários scores mas que um score também pode pertencer a vários federateds quando estes formam uma equipa num determinado evento.

Como se pode ver a nível de BD a tabela federated_score promove a relação entre as duas tabelas que realmente interessam a federated e a scores. Agora a nível de código como fica implementando em JPA:

@Entity
@Table(name = "scores")
public class Score {
[...]
    @ManyToMany
    @JoinTable(name="federated_score",
       joinColumns=@JoinColumn(name="score_id", referencedColumnName="id"),
       inverseJoinColumns=@JoinColumn(name="federation_code", 
       referencedColumnName="federation_code")
    )
    private Collection<Federated> federateds;
[...]
}

@Entity
@Table(name = "federateds")
public class Federated {
[...]
    @ManyToMany
    @JoinTable(name="federated_score",
       joinColumns=@JoinColumn(name="federation_code", referencedColumnName="federation_code"),
       inverseJoinColumns=@JoinColumn(name="score_id",  referencedColumnName="id")
     )
     private Collection<Score> scores;
[...]
}


segunda-feira, novembro 12, 2012

Subtracção de datas em Java

Para quem vem do C#, e não trabalhava em Java mais a sério já há uns anos, existem coisas que me irritam pela complexidade desnecessária e pouca versatilidade que têm.

Um exemplo disso é a subtracção de datas, algo que em C# faria numa linha aqui tenho de ter meia dúzia de linhas para o fazer. Vejamos uma função que retorna a diferença de anos de uma data qualquer para a data corrente.

public int SubYears(Date data){
                int currentYear = Calendar.getInstance().get(Calendar.YEAR);
                Calendar c = Calendar.getInstance();
                c.setTime(data);
                int yearBirth = c.get(Calendar.YEAR);
               return currentYear - yearBirth;
}

É só a mim ou isto parecem demasiadas 'cambalhotas' para fazer uma coisa tão simples?

sexta-feira, abril 20, 2012

C# - var vs dynamic

Muita coisa há a dizer à cerca do tipo var e do tipo dynamic, mas vou restringir-me a distingui-los pois vejo muitas pessoas a fazerem confusões entre os 2 tipos quando nada têm a ver um com o outro.

O tipo var é uma instância de um tipo qualquer, frequentemente usado na instanciação de tipos anónimos esta é a sua principal utilização. Tudo o que sejam inicializações de variáveis implícitas só porque sim considero um mau hábito (ex: var i=3 deveria ser escrito int i=3, não existe necessidade de ter uma variável implícita).

No caso dos tipos anónimos o mais importante é que apesar de anónimos eles são fortemente tipados, o que parece um contrassenso, mas veja-se o seguinte código:
var anonymousObj = new { Id = 2, Name = "test" };
Olhando para a variável anonymousObj tanto eu como o compilador sabemos exactamente os campos que compõem aquele objecto, isto significa que eu vou ter erros em compile time.

Já no que toca a um tipo dynamic o comportamento é totalmente diferente, nem eu nem o compilador sabemos nada em concreto do objecto, logo todos os erros serão em run time. Com isto quero dizer que o compilador ignora qualquer tipo validações sobre aquele objecto e consequentemente deixa de nos disponibilizar a ajuda do IntelliSense.

Uma das utilizações possíveis para o dynamic é a deserialização de json. Se eu não quiser criar um tipo novo só para deserializar então eu deserializo para um objecto do tipo dynamic.
JavaScriptSerializer serializer = new JavaScriptSerializer();
//json é uma variável que terá a string de json
dynamic obj = serializer.Deserialize < object >(json);
string name = obj["name"];
Com esta utilização eu tenho de ter a certeza que no json me virá uma propriedade chamada name, caso contrário irei ter o tal erro em run time.

quarta-feira, fevereiro 22, 2012

Programar e jogar ao mesmo tempo

Ora aqui está uma maneira bem gira de tentar ser um melhor programador. Para quem programa com o Visual Studio existe um plugin chamado Visual Studio Achievements, cujo objectivo é analisar o código realizado e assim ir cumprindo missões como se fosse um jogo.

As missões no Visual Studio Achievements podem ir de coisas simples como imprimir o código fonte até ter soluções com 50 projectos lá dentro. Também existem achievements para más práticas que infelizmente não dão pontos negativos mas que no perfil ficam marcadas como já executadas. Fica aqui o link para o meu perfil, até agora ainda me faltam bastantes, mas hei-de lá chegar...

sexta-feira, novembro 25, 2011

Debug a um web site live

Uma das coisas que já tinha sentido falta quando implementei interoperabilidade com outros sistemas (ex: Paypal), foi a necessidade de fazer debug do site live. Isto acontece por um motivo, os callbacks desses sistemas externos não sabem o que é o nosso localhost, eles sabem sim o que são URLs (ex: www.xpto.pt), logo os callbacks não podem ser feitos para localhost como é óbvio.

Ontem queria fazer debug às comunicações com o Facebook para saber o que realmente me estava a chegar à mão, então decidi perder tempo a descobrir como fazia o debug do callback. Apesar de ter demorado uma tarde entre configurações de router, configurações de IIS, configurações de debugging e mais uma data de tentativas falhadas, quando cheguei à solução ela até é bastante simples.
  • Colocar o porto 80 do IIS não a apontar para a directoria do nosso site live, tipicamente C:\inetpub\wwwroot, mas sim para a nossa directoria de desenvolvimento.
  • Ir às propriedades do nosso projecto web e meter que o nosso servidor vai ser o IIS

Pode ainda ser necessário arrancar o Visual Studio como administrador devido a alguma restrição de permissões, isto depende das configurações de cada máquina. Finalmente é só arrancar o debugger do Visual Studio e meter os breakpoints que se quiserem, todos os pedidos ao site passam então a ser capturados.

quarta-feira, novembro 23, 2011

Update com Join

Fazer um update a uma coluna com base no valor de uma coluna doutra tabela parecia-me que seria algo de complexo, afinal até é bastante simples.
UPDATE TableToUpdate
SET TableToUpdate.FieldToUpdate = TableWithValues.FieldWithValue
FROM TableToUpdate
INNER JOIN TableWithValues 
ON TableWithValues.FieldWithValue = TableToUpdate.FieldToUpdate 

sexta-feira, outubro 28, 2011

MVC ActionButton

Em MVC um dos métodos mais úteis é o ActionLink que nos permite criar um link, dando pelo menos a acção responsável por tratar a request. Estranhamente não existe o equivalente para botões, tipo ActionButton. Andei a pesquisar no meu amigo Google e depois ter lido alguns disparates e algumas resoluções o mais rebuscadas que se possam imaginar com quilos de código css, para algo tão simples como ter um botão, cheguei a uma implementação minha que para mim é algo simples e eficaz.

        public static IHtmlString ActionButton(this HtmlHelper htmlHelper, 
           string text, string actionName, string controllerName, object routeValues)
        {
            UrlHelper urlHelper = ((Controller)htmlHelper.ViewContext.Controller).Url;
            string url = urlHelper.Action(actionName, controllerName, routeValues);

            var input = new TagBuilder("input");
            input.Attributes.Add("type", "button");
            input.Attributes.Add("onclick", 
               string.Format("javascript:location.href=('{0}')", url));
            input.Attributes.Add("value", text);

            return MvcHtmlString.Create(input.ToString());
        }

quinta-feira, outubro 27, 2011

Vida de programador

Depois de já ter escrito 2 vezes sobre a vida de um programador (link1 e link2), encontrei ontem este site com umas bandas desenhadas deliciosas sobre o dia a dia dos programadores. Deixo aqui só um exemplo.


quarta-feira, outubro 26, 2011

Problemas no deploy de uma aplicação .NET MVC

Este foi o meu primeiro deploy de uma aplicação MVC para um servidor de testes, e devo dizer que bati em mais paredes do que estava à espera. Primeiro passo foi instalar a .NET Framework 4.0, até aqui nada de especial. De seguida instalei o SQL Express 2008 R2, que seria o motor de base de dados que iria utilizar.

Vamos então ao deploy em si, crio um pacote de deploy com o Visual Studio, crio uma directoria virtual no servidor e copio para lá o conteúdo do pacote. Primeiro erro, levo logo com um erro 500.19, que significa que o ficheiro web.config está mal configurado e que não consegue ser interpretado.


Bem fui averiguar e lá descobri o problema, no meu web.config estava a utilizar a tag que me possibilita rescrever URLs, como o IIS não sabia interpretar essa tag estava a devolver o erro 500.19. Solução é instalar no IIS o módulo URL Rewrite.

Voltando a testar novo erro, agora o problema não estava no web.config mas sim nas referências para as assembly. Ao instalar a .NET Framework 4.0, julguei que todas as dlls necessárias estariam na GAC, aparentemente não o que provocou o erro: Could not load file or assembly 'System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified. 

 Uma solução possível passa por dizer ao Visual Studio que aquela referência é para criar uma cópia local, assim quando é feito o pacote a referência é copiada para dentro da pasta bin.

Além do System.Web.Mvc também devem ser incluídas as referências que se encontram na imagem, ou outras que sejam System.Web.*.

Agora é que é pensei eu, bem ainda não estava com sorte e toma lá mais um erro: Could not load file or assembly 'Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. O quê mais assembly que não consegue ser referênciada! Na minha máquina de desenvolvimento esta dll tava na GAC mais uma vez ao contrário do servidor de produção. A solução passa por acrescentar a dll às referências do projecto no Visual Studio e mais uma vez dizer para criar uma cópia local. Alem desta dll ainda são precisas as dlls: System.Web.WebPages.Razor, System.Web.Razor e System.Web.WebPages.Deployment.

É pá o site já responde, vamos lá fazer login e começar a testar...pimba mais um erro, não é possível autenticar no SQL com o utilizador escolhido. No fundo este problema já não tem a ver com a aplicação ser MVC, poderia ser qualquer tipo de outra aplicação que utilizasse o SQL. Vou tentar autenticar-me directamente no SQL Management Studio e o mesmo erro acontece. Vou ver se estou a permitir ligações TCP/IP no SQL Configuration Management e sim estava! Depois de alguma pesquisa, de bater umas quantas vezes na mesa e chamar uns quantos nomes ao servidor lá descobri o problema, no próprio SQL Management Studio também é necessário configurar a autenticação como sendo mixed mode não bastando dizer que são permitidas ligações TCP/IP.


Ufffff, finalmente tudo a funcionar...

terça-feira, julho 26, 2011

Obter um Hash em SQL

Aparentemente obter um Hash em SQL é extremamente fácil...aparentemente...
Então em SQL temos a função HashBytes que recebe o tipo de codificação e a string a codificar.

Select HashBytes('SHA1', 'Test')

E o resultado disto é: 0x640AB2BAE07BEDC4C163F679A746F7AB7FB5D1FA

Porreiro tem bom aspecto, então mas eu quero isto é numa string então vou afectar um nvarchar para colocar o resultado do HashBytes.

Declare @test as nvarchar(40)
set @test = HashBytes('SHA1', 'Test')
select @test

Resultado: ੤몲篠쓭揁秶䚧꯷땿𣏕

Ups...que é isto??? O problema está no retorno do HashBytes que é do tipo VarBinary e não do tipo VarChar. A solução é uma das duas opções seguintes, se uma é melhor que a outra não sei, mas se alguém souber agradecia que me informasse, o facto é que as duas funcionam.

SELECT master.dbo.fn_varbintohexsubstring(0, HashBytes('SHA1', 'Test'), 1, 0)
ou
SELECT CONVERT(NVARCHAR(40),HashBytes('SHA1', 'Test'),2)

Resultado: 640AB2BAE07BEDC4C163F679A746F7AB7FB5D1FA

quarta-feira, junho 08, 2011

A vida de um programador

Ora aqui tá um vídeo demonstrativo do que é ser programador, para quem acha que nós temos uma profissão que é um mar de rosas.



P.S.: O que acontece no final não é bem a realidade!