INFORMIX Alterar Múltiplas Linhas e Múltiplas Colunas com SubSelect

UPDATE princing SET
(price, increasepercentage, datenewrate)
=
(SELECT nrpp.increasepercentage * princing.price AS price
      , nrpp.increasepercentage
      , SYSDATE
 FROM newrateperproduct AS nrpp
 WHERE nrpp.productid = pricing.productid
   AND nrpp.increasepercentage IS NOT NULL
)
WHERE EXISTS
(SELECT 1
 FROM newrateperproduct AS nrpp
 WHERE nrpp.productid = pricing.productid
   AND nrpp.increasepercentage IS NOT NULL
);

Minha jornada com bancos de dados iniciou-se com o sensacional INFORMIX, não por que eu queria, mas naquela época tratava-se se um processo de downsizing onde tínhamos que iniciar a desativação de um Mainframe UNISYS. O novo sistema escolhido pela empresa trazia consigo o requisito de utilizar também este banco de dados.

Dentre as inúmeras características, a capacidade de processar update com “subselects” de forma genial com uma sintaxe praticamente ANSII me encheu os olhos e me proporcionou uma evolução fantástica na programação com SQL puro. Cheguei a desenvolver sistemas inteiros eliminando a necessidade de linguagem de programação, somente SHELL para interface com usuário e SQL statements para cálculos e transformações de dados. O update com subselect tomou um importante papel neste caso.

Toda vez que aprendo um banco de dados novo eu acabou invariavelmente procurando saber se ele tem suporte a esta capacidade. Com o MySQL você alcança este resultado com o Update Join, o que não é uma sintaxe tão nativa assim, mas o pessoal da MySQL AB mandou muito bem neste caso, eu até já escrevi um artigo aqui no Blog demonstrando isso.

Explicando um pouco sobre a sintaxe, a grande sacada do INFORMIX é permitir mesmo que sejam postas várias colunas para serem alteradas, quando for mais de uma coluna o requerimento é recobrir as colunas com parênteses e pronto. No subselect então basta fazer o “match” quantitivo das colunas e, é claro o match de tipos. Naturalmente a atribuição das colunas é feita por posicionamento simplesmente.

Outra sacada que você não pode ignorar é que, para não incorrer em erros devemos repetir o subselect na cláusula WHERE do UPDATE para que tenhamos a mesma equivalência de registros tanto subselect quanto no update.

E o que mais? Mais nada!

PHP Executar Dinamicamente Métodos Estáticos de uma Classe

class MyClass {
  public static function myFunc(bool $happy) {
    echo "\n";
    echo $happy ? 'I am happy' : 'I am sad';
  }
}

$class = MyClass::class;
$method = 'myFunc';
$arg = true;

$class::{$method}($arg);

Recentemente me deparei com uma situação inusitada… executar métodos estáticos de uma classe de forma dinâmica!

Ao escrever um teste unitário resolvi preparar a suite com Data Provider então naturalmente as opções deste data provider requeriam diferentes métodos para diferentes parâmetros, daí a solução natural foi parametrizar o próprio método como um dos parâmetros… na execução dos testes bastaria simplesmente chamar o método como fazemos com classes instanciáveis, certo?

Pois é, só que ao errar a sintaxe de execução eu acabei indo buscar artigos que explicassem como fazer isso com métodos estáticos e acabei indo para um caminho utilizando o call_user_func.

call_user_func([$class, $method], $arg);

A solução funciona bem e até tem uma sintaxe bastante limpa e bonita, nada contra, mas até o momento não encontrei necessidade real de lançar uso desta função.

Depois encontrei no próprio repositório outras implementações utilizando o call_user_func, só que aplicando uma sintaxe um pouco diferente concatenando a classe e método num único parâmetro.

call_user_func($class . '::' . $method, $arg);

Bom, considero a sintaxe do primeiro bloco a mais correta de ser aplicada como solução para este caso, afinal num mundo competitivo como o nosso, elegância é tudo!

World class technology S2 PHP.

GIT CHECKOUT Para Restaurar um Único Arquivo já Comitado

git log
// encontre o hash da versão que você deseja retornar um arquivo
git checkout <commit hash> <caminho-completo-para-o-arquivo-desejado>
git status
git commit

Devs utilizando a metodologia “PMF” estão em constante evolução de seus códigos e muitas vezes podem acabar numa sinuca de bico e invariavelmente em algum momento podem querer reverter suas alterações.

Mas e se a reversão a ser feita envolve apenas um único arquivo e usar o git reset pode dar aquele medo de piorar as coisas?

Bom, nessas horas você pode fazer uso do git checkout mesmo, afinal este comando é bastante comum pois usamos este comando o tempo todo, então não haveria razão para ter medo de usá-lo. Haveria?

A sacada aqui é apenas combinar o git checkout com o hash do commit que tem a versão do arquivo a ser restaurado adicionando-se também o caminho completo para o arquivo desejado. A versão do arquivo então é baixada para a “working area” e depois de você verificar o conteúdo dele basta apenas comitar novamente o arquivo para o repositório.

É claro que você poderia alcançar o mesmo resultado com outros comandos GIT como o reset ou o revert. Mas se o git checkout faz este trabalho pra você com uma sintaxe extremamente limpa, pra que complicar?

Vale ressaltar que este fluxo o git checkout não irá funcionar para arquivos novos que acabaram de ser comitados, isto por que um arquivo novo não existirá em um commit hash anterior e no commit hash atual ele é o que é, um arquivo novo.

Nesta situação é recomendado o uso do git rm que irá funcionar perfeitamente para esta necessidade… eu já escrevi um artigo sobre git rm aqui no blog, recomendo dar uma olhada nele para maiores detalhes de uso.

Agora sem complicações, vai de git checkout bro! …ou de git rm quando for um arquivo novo.

GIT RM Para Remover Arquivos já Comitados para um Repositório

git rm --cached <caminho-completo-para-o-arquivo-a-ser-removido>

Como devs nossa missão é criar códigos, mas tem aqueles momentos que precisamos mesmo é remover código para prosseguir com a evolução dos processos.

Imagine que você refatorou um processo e acabou por inutilizar completamente um determinado arquivo; git rm nele!

Ou então você se precipitou, o que não é incomum, e acabou comitando um arquivo novo e depois se arrependeu ou percebeu que não era preciso ou então não era o momento ideal de enviar o arquivo para o repositório; git rm nele!

A grande sacada é que com o git rm –cached o arquivo é preparado para ser removido do repositório, mas ele não desaparece por completo. O Git deixa ele disponível na working area para que você possa ainda fazer qualquer operação com o seu conteúdo.

Agora você já sabe, git rm para manter a casa limpa!

PHP Higienizando Variáveis com Operador Elvis ?:

function defaultValues(int $index, string $sku, string $code, string name, int $quantity, float $price)
    $index = $index ?: 1;
    $sku = $sku ?: 'NOT INFORMED';
    $code = $code ?: 'NOT INFORMED';
    $name = $name ?: 'NOT INFORMED';
    $quantity = $quantity ?: 0;
    $price = $price ?: 0.0;
}

Há algum tempo eu vinha observando em meus códigos um uso excessivo do operador ternário para limpeza e padronização de variáveis, dai recentemente eu dei uma olhada com mais carinho no operador Elvis. Em alguns artigos eu encontrei explicações de que ele seria a parte FALSE do operador ternário, mas eu nunca tinha aplicado ele na prática de uma forma tão contundente.

Então surgiu uma nova oportunidade e fui olhar a documentação novamente e “voila”. Não é que serviu direitinho pra fazer higienização de variáveis?!

Mas por que não usar o operador ternário? Porque a higienização requer uma ação apenas e o ternário exige duas.

E o operador Null Coalesce? Bom, o null coalesce testa somente nulls e no meu caso conteúdo vazio também precisaria ser higienizado.

A melhor opção então recaiu sobre o operador Elvis, por que ele executa ação para todo e qualquer conteúdo avaliado como FALSEY. Grosseiramente falando o FALSEY equivale a qualquer conteúdo convertido para boolean que resulta em falso… veja os exemplos abaixo:

var_dump(null ?: 'null is falsey');      // "null is falsey"
var_dump(true ?: 'true is truthy');      // bool(true)
var_dump(false ?: 'false is falsey');    // "false is falsey"
var_dump('' ?: 'empty string is falsey');// "empty string is falsey"
var_dump(' '?: 'space is truthy');       // " "
var_dump(empty(null) ?: 'empty null is truthy'); // bool(true)
var_dump(0 ?: 'zero int is falsey');     // "zero int is falsey"
var_dump(0.0 ?: 'zero float is falsey'); // "zero float is falsey"

Agora compare os resultados com o NULL COALESCE…

var_dump(null ?? 'null is coalesced');        // "null is coalesced"
var_dump(true ?? 'true is not coalesced');    // bool(true)
var_dump(false ?? 'false is not coalesced');  // bool(false)
var_dump('' ?? 'empty string is not coalesced'); // ""
var_dump(' ' ?? 'space is not coalesced');       // " "
var_dump(empty(null) ?? 'empty null is not coalesced'); // bool(true)
var_dump(0 ?? 'zero is not coalesced');         // int(0)
var_dump(0.0 ?? 'zero float is not coalesced'); // float(0)

Claramente a escolha correta é usar o operador Elvis para a higienização pois nulls, zeros integer or float, boolean false, empty string, todos sem excessão irão disparar a ação para higienização, evitando assim o uso de ifs e outros testes desnecessários.

Happy CleanCode!

Elvis Operator

GIT Stash Como Nomear seu Stash

git stash push -m "Escreva um texto que identifique seu stash"

Quando iniciamos a utilizar o GIT vamos aprendendo aos poucos as várias utilidades que ele possui, uma das bastante corriqueiras é é salvar para área de STASH uma alteração em andamento que ainda não está pronta para fazer commit par uma branch.

Assim, você deve ser bem familiar aos comando de stash bem simples, como por exemplo:

git stash list
git stash
git stash pop
git stash apply

O ponto aqui é que o git stash simples registra como comentário padrão o nome da branch atual e ele provavelmente não vai remeter o entendimento ao real conteúdo que foi salvo.

Quando você for precisar salvar o stash por um longo tempo ou precisará identificar um stash específico entre muitos outros stashes você vai precisar usar a sintaxe com o git stash push.

Fantástico recurso… mão na roda pros devs!

PHP Como Verificar Se Um Array é 100% Sequencial

function isArrayFullySequential(array $array): bool {
    return count(array_filter($array, 'is_int', ARRAY_FILTER_USE_KEY)) === count($array);
}

Então… há algum tempo eu escrevi aqui no blog uma função para testar se um array era 100% associativo e no começo do texto eu comentei que não sabia quando você precisaria usar uma função como essa. Pois é, mordendo a língua eu acabei precisando agora testar o contrário, se um array era composto por índices 100% numéricos.

Ao integrar o sistema com uma API externa estruturada com XML tendo um elemento previsto com até 1000 ocorrências que seria carregado a partir de um array. Decidi por utilizar o índice do array como ID das ocorrências no XML, assim implantei o requisito de ter este array indexado 100% com chaves numéricas.

Ainda estou pensando se vou manter esta abordagem ou não, talvez eu acabe flexibilizando a carga do array e controle apenas o total de ocorrências.

De qualquer forma segue abaixo a função que valida se os índices numéricos do array estão dentro dos limítrofes esperados.

hasItemsIndexOutOfBounds(array $array): bool {
    $keys = array_keys($array);
    return count($keys)
        && (min($keys) < 1 || max($keys) > 1000);
}

Ea í, curtiu? Não sei quando você vai precisar usar usar uma destas funções, mas fica aí o exemplo pra quando aparecer a necessidade.