New French Blog / Novo blog em Franc�s

This article is written in English and Portuguese
Este artigo est� escrito em Ingl�s e Portugu�s

English Version:

It's a great pleasure to present you another Informix blog. This one is written in French. The author is Eric Vercelletto, which was a colleague at Informix Portugal. Eric has a long history with Informix. We was working at Informix France and decided to join Informix Portugal mainly to participate in a big and complex project several years ago (before I joined Informix). After that we met and worked together on another customer. At the time I was working mainly with tools and he managed all the engine side stuff. When he decided to embrace other challenges outside Informix, I assumed his position at that customer. It was a big challenge for me (I had relatively low experience with the engine) and Eric was a great help. I still use some of his scripts today, and I learned many things with him.
But the world never stops spinning and currently Eric is back on Informix, and he's enthusiastic about it. I wish him all the best and I really hope he is able to share some of his knowledge about Informix with the community.
He decided to write the blog in French since French people like to take care of their language. This is great news for the French community. As for us, non French speaking people we can try our best to understand it. It would be interesting to see it in English also... (just a challenge Eric ;) ). But for now, the important it to keep a steady rate of articles. And I can assure you it's hard. Welcome Eric!

The blog address is:

http://levillageinformix.blogspot.com/

(something like "the Informix village")



Vers�o Portuguesa:

� um grande prazer poder apresentar-vos um novo blog Informix. Desta feita escrito em Franc�s. O autor � Eric Vercelletto, que foi um colega da Informix Portugal. O Eric tem um longo passado com Informix. Estava a trabalhar na Informix Fran�a e decidiu juntar-se � Informix Portugal, pricipalmente para participar num projecto grande e complexo h� v�rios anos atr�s (antes de eu ingressar na Informix Portugal). Ap�s isso conhecemo-nos e trabalh�mos juntos num outro cliente. Na altura eu trabalhava essencialmente com ferramentas e ele geria o lado do motor.
Quando ele decidiu abra�ar outros desafios fora da Informix, assumi a sua posi��o no cliente. Foi um grande desafio para mim (tinha muito pouca experi�ncia com o motor) e o Eric foi uma grande ajuda. Ainda utilizo alguns dos seus scripts hoje, e aprendi muitas coisas com ele.
Mas o mundo d� voltas e mais voltas e actualmente o Eric est� de volta ao Informix, e continua entusiasta. Desejo-lhe tudo de bom e espero sinceramente que ele consiga partilhar algum do seu conhecimento Informix com a comunidade.
Ele decidiu escrever o blog em Franc�s porque os Franceses gostam de cuidar da sua l�ngua. Isto s�o excelentes not�cias para a comunidade Franc�fona. Quanto a n�s, que n�o dominamos a l�ngua, tentaremos o nosso melhor para o perceber. Era interessante ver o conte�do tamb�m em Ingl�s (s� um desafio Eric... :) ). Mas por agora, o importante � manter um ritmo constante de novos artigos. E posso assegurar que n�o � f�cl. Bem vindo Eric!


O endere�o do blog �:

http://levillageinformix.blogspot.com/

(algo como "a aldeia do Informix", o que vindo da G�lia, tr�s boas recorda��es de crian�a)

Informix ROI webcast

This article is written in English and Portuguese
Este artigo est� escrito em Portugu�s e Ingl�s

English version:

Following the recent announcement of a Forrester study about Informix ROI, a webcast was held on December 13. The replay can be seen here:

https://www.techwebonlineevents.com/ars/eventregistration.do?mode=eventreg&F=1002717&K=4ON

You can listen to it in webcast format and also download the slides and sound file.
The presentation was done by Jon Erickson from Forrester and Richard Wozniak who browses through some of the Panther key features.
Be sure to pass this to your company management!



Vers�o Portuguesa:

No seguimento do recente an�ncio sobre um estudo da Forrester sobre o ROI (return on investment) do Informix, foi apresentado um webcast no dia 13 de Dezembro. Pode rever esta apresenta��o aqui:

https://www.techwebonlineevents.com/ars/eventregistration.do?mode=eventreg&F=1002717&K=4ON

Pode ouvir/ver em formato webcast e tamb�m fazer o download dos ficheiros com os slides e o som.
A apresenta��o foi feita por Jon Erickson da Forrester e Richard Wozniak que abordou algumas das principais funcionalidades da vers�o Panther (11.7)
N�o deixe de divulgar esta informa��o aos gestores da sua organiza��o!

Panther: Name service cache

This article is written in English and Portuguese
Este artigo est� escrito em Ingl�s e Portugu�s

English version:

A recent thread in the IIUG mailing list (relative to a reverse DNS issue) reminded me of a new Panther (version 11.7) functionality that was on my list for articles. I've been avoiding many of the bigger and more important features because they will take a lot of time to write about... I hope this one will be shorter.

Informix needs to read several files or interact with DNS servers each time you try to open a connection. Considering Unix and Linux (Windows is a bit different technically, but not that much conceptually), these are some of the actions the engine must do:
  1. Depending on your host resolution criteria it will probably open the /etc/hosts file to search for your client's IP address. If it's not there it will contact your DNS server in order to request the name associated with the IP address.
    Note that all this is done by a system call.
  2. It will access /etc/passwd (or equivalent) to get your user details (HOME dir, password - this is probably stored in another file like /etc/shadow - , user id, group id etc.)
The engine must also access /etc/services and /etc/group in other situations.
Depending on your environment these activities can take a bit of time, and require some significant CPU usage. There are systems with high number of connections per second which can naturally transform this into a significant issue.
To give you an example I do regular work on a system that used to receive a very large number of requests from CGI programs. So, each request received by HTTP required a new process on the application server, and a new connection on the database server. They had peaks of tens of requests per second. Currently they're using Fast CGI with noticeable improvements.
Anyway, IBM decided to give us the chance to optimize this by caching previous results (file searches and DNS requests). This is done with the new parameter called NS_CACHE (from Name Service Cache). The format of this $ONCONFIG parameter is:

host=num_secs,services=num_secs,user=num_secs,group=num_secs

Each comma separated pair (functionality=num_secs) configures the number of seconds that the engine will cache a query result for that functionality. I'm calling it functionality, because it can be implemented through files or system APIs. The documentation could be clearer, but let's check each one:
  • host
    This is the host and IP address resolution service. Depending on your system configuration (on most Unixes and Linux this is specified in /etc/nsswitch.conf) it can be resolved by reading the /etc/hosts file and/or making a request to your DNS servers
  • service
    This should be the map between service names and system ports, usually done by reading /etc/services. The only situation that comes to my mind where this is used is when you're trying to start a listener (either during engine startup or after that with onmode -P) or when you're trying to make a distributed query to another engine, and you use names in your INFORMIXSQLHOSTS instead of port numbers. In any case, I may be missing something...
  • user
    This is very important. It refers to all the user related info that Informix gathers from the OS and that is relevant to Informix. The information can be stored in /etc/passwd, /etc/shadow, or indirectly be managed by external services like LDAP. It can include:
    - Home dir
    - User ID
    - Group ID
    - Password
    - User status (enable or disable
  • group
    This relates to the OS group information. Usually done by reading /etc/group
If the specified number of seconds to cache the information is zero, it means that we don't want to cache it. So the behavior will be the old engine behavior (for each relevant request, the information must be obtained).
The parameter can be changed online with onmode -wm

It's important that you fully understand the implications of caching these kind of information. By asking Informix to cache this info, we're also assuming the risk of working with stale information. Let's imagine a simple scenario. Assume this sequence of events:
  1. At time T0 you connect using user and password to the engine which is setup to cache user information for 600s (10 minutes).
  2. At time T1 you change that user password
  3. At time T2, the same user tries to connect to the Informix database with the new password. It will fail!
  4. At time T3 (T0 + the number of seconds to cache user information) the user repeats the connection attempt with the new password. It will succeed!
How can you avoid situation 3? If you change the cache timeout to 0, it will work as a flush.
If for example you do some changes to your user's information you can run:


onmode -wm NS_CACHE="host=900,service=900,user=0,group=900"
onmode -wm NS_CACHE="host=900,service=900,user=900,group=900"


These commands will flush the user information cache, and then reactivate it.

So, the point I'd like to make is that this feature can help you improve performance (specially for systems with an high connection rate), but it can have some side effects. You can workaround these ones, but for that you must know they exist.


Vers�o Portuguesa:

Uma discuss�o recente na lista de correio do IIUG (relativa a um problema com reverse DNS) lembrou-me de uma funcionalidade nova do Panther (vers�o 11.7) que estava na minha lista de temas a abordar. Tenho andando a evitar muitas das maiores e mais importantes novidades porque vou demorar bastante tempo a escrever sobre elas.... Espero que esta seja mais reduzida.

O Informix tem de ler diversos ficheiros ou interagir com servidores de nomes (DNS) cada vez que abre uma conex�o. Considerando o Unix e Linux (em Windows ser� um pouco diferente tecnicamente, mas n�o muito conceptualmente), estas s�o as ac��es que o motor tem de fazer durante o estabelecimento de uma conex�o:

  1. Dependendo do crit�rio usado para resolver endere�os e nomes, provavelmente ir� abrir o ficheiro /etc/hosts para procurar o IP da conex�o. Se n�o o encontrar ir� provavelmente contactar o servidor de nomes (DNS) e pedir o nome associado ao IP de onde chega a conex�o.
    Note-se que isto � feito com uma chamada de sistema e n�o cabe ao Informix definir os crit�rios.
  2. Ir� aceder ao /etc/passwd (ou equivalente) para obter os dados do utilizador (HOME dir, password - isto deve estar guardado noutro ficheiros como o /etc/shadow- , id de utilizador, id de grupo etc.)
O motor tamb�m tem de aceder ao /etc/services e /etc/group noutras situa��es.
Dependendo do seu ambiente estas opera��es podem demorar um pouco e requerer um consumo de CPU relevante. Existem sistemas com muitas conex�es novas por segundo o que naturalmente pode transformar isto num problema s�rio.
Para dar um exemplo, trabalho regularmente com um sistema que em dada altura recebia um enorme n�mero de pedidos por CGI. Sendo CGI, cada pedido recebido via HTTP requeria um novo processo na m�quina do servidor aplicacional, e uma nova conex�o na base de dados. Tinham picos de dezenas de liga��es por segundo. Actualmente est�o a usar Fast CGIs com benef�cio not�rios.
De qualquer forma a IBM decidiu dar aos utilizadores a oportunidade de optimizarem estes aspectos, atrav�s de uma cache que guarda respostas anteriores (pesquisas em ficheiros e resultados de DNS). Isto � feito com um novo par�metro designado NS_CACHE (de Name Service Cache). O formato do par�mtro do $ONCONFIG �:

host=num_segs,services=num_segs,user=num_segs,group=num_segs

Cada par (funcionalidade=num_segs) separado por v�rgula, configura o n�mero de segundos durante os quais o motor ir� manter em cache o resultado de uma pesquisa para essa funcionalidade. Estou a chamar-lhe "funcionalidade", porque pode ser implementada usando ficheiros ou APIs de sistema. A documenta��o deveria ser mais clara, mas vamos ver cada uma:
  • host
    O servi�o de resolu��o de nomes e endere�os IP. Conforme a configura��o do seu sistema (na maioria dos Unixes e Linux isto � definido em /etc/nsswitch.conf) pode ser resolvido pelo ficheiro /etc/hosts ou fazendo um pedido aos servidores de DNS
  • service
    Este � o mapeamento entre o nome de servi�os e as portas de sistema, habitualmente feito atrav�s da leitura do ficheiro /etc/services. As �nicas situa��es que me ocorrem em que isto � usado � quando arrancamos com um listener (seja no arranque do motor ou depois quando se usa o onmode -P), ou quando tentamos executar uma query distr�buida a outro motor, e usamos nomes no nosso INFORMIXSQLHOSTS em vez de n�meros de portos. Mas pode estar a escapar-me alguma coisa, e haver outras...
  • user
    Este � muito importante. Refere-se a toda a informa��o relativa aos utilizadores que o Informix obt�m do sistema operativo e que � relevante para o Informix. A informa��o � guardada no /etc/passwd e /etc/shadow, ou gerida indirectamente em servi�os externos como LDAP. Pode incluir:
    - Home dir
    - ID de utilizador
    - ID de grupo
    - Palavra passe
    - Estado do utilizador (activo, inactivo)
  • group
    Isto diz respeito � informa��o de grupos do sistema operativo. Normalmente feito por consulta ao ficheiro /etc/group

Se o n�mero de segundos especificado para a cache for zero, significa que n�o queremos fazer caching. Portanto o comportamento ser� o antigo do motor (para cada pedido a informa��o tem de ser obtida).

O par�metro pode ser modificado online com o comando onmode -wm

� importante que entenda completamente todas as implica��es de fazer caching deste tipo de informa��o. Ao pedir ao Informix que guarde e reutilize a informa��o j� obtida, estamos tamb�m a assumir o risco de trabalhar com informa��o entretanto desactualizada. Vamos imaginar um cen�rio simples. Consideremos a seguinte sequ�ncia de eventos:

  1. No momento T0 conectamo-nos usando um utilizador e palavra chave a um motor configurado para efectuar caching por 600 segundos (10 minutos).
  2. No momento T1 mudamos a palavra chave desse mesmo utilizador.
  3. No momento T2 o mesmo utilizador tenta conectar-se ao Informix usando a nova palavra chave. Vai falhar!
  4. No momento T3 (T0+ o n�mero de segundos configurado para a cache de utilizador) o utilizador repete a tentativa de acesso com a nova palavra chave. Vai ter sucesso!
Como pode evitar a situa��o do ponto 3? Se mudar o tempo de cache para 0, funciona como uma limpeza da cache.
Se por exemplo efectuar mudan�as na informa��o dos utilizadores, pode executar:


onmode -wm NS_CACHE="host=900,service=900,user=0,group=900"
onmode -wm NS_CACHE="host=900,service=900,user=900,group=900"


Estes comandos fazem a limpeza da informa��o e depois re-activam a cache.

Portanto, o ponto que gostaria de frisar � que esta funcionalidade pode melhorar o desempenho (especialmente em sistemas com elevada frequ�ncia de novas conex�es), mas tamb�m pode ter efeitos secund�rios. Estes podem ser contornados, mas para isso temos de saber que existem.

Panther: Extending extents / Estendendo os extents

This article is written in English and Portuguese
Este artigo est� escrito em Ingl�s e Portugu�s

English version:

Back to Panther... Although I'm not in the video on the right, I do love Informix. That doesn't mean I ignore some issues it has (or had in this particular case). One thing that always worries an Informix DBA is the number of extents in his tables. Why? Because it used to have a maximum amount, and because that maximum was pretty low (if compared with other databases). But what is an extent? In short an extent is a sequence of contiguous pages (or blocks) that belong to a specific table or table partition. A partition (a table has one or more partitions) has one or more extents.
Before I go on, and to give you some comparison I'd like to tell you about some feedback I had over the years from a DBA (mostly Oracle, but who also managed an Informix instance):
  • A few years ago he spent lots of time running processes to reduce the number of extents in a competitor database that had reach an incredible number of extents (around hundreds of thousands). This was caused by real large tables and real badly defined storage allocation
  • Recently I informed the same customer that Informix was eliminating the extent limits and the same guy told me that he was afraid that it could lead to situations as above. He added, and I quote, "I've always admired the way Informix deals with extents"
So, if a customer DBA is telling that he admires the way we used to handle extents, and he's afraid of this latest change, why am I complaining about the past? As in many other situations, things aren't exactly black and white... Let's see what Informix have done well since ever:

  1. After 16 allocations of new extents Informix automatically doubles the size of the next extent for the table. This decreases the number of times it will try to allocate a new extent. So, using only this rule (which is not correct as we shall see) if you create a table with a next size of 16K, you would reach 4GB with around 225 extents.
  2. If Informix can allocate a new extent contiguous to an already existing one (from the same table of course) than it will not create a new one, but instead it will extend the one that already exists (so it does not increase the number of extents). This is one reason why rule number one may not be seen in practice. In other words, it's more than probable that you can reach 4GB with less than 225 extents.
  3. In version 11.50 if I'm correct, a fix was implemented to prevent excessive extent doubling (rule 1). If the next extent size is X and the dbspace only has a maximum of Y (Y < X) informix will allocate Y and will not raise any error.
    If this happens many times, we could end up having a number of allocated pages relatively small, but a next extent size too big. There's a real problem in this: If in these circumstances we create another chunk in the same dbspace, and after that our table requires another extent, the engine could reserve a large part of the new (and possibly still empty) chunk to our table. This can be much more than the size already allocated to the table. To avoid this, extent doubling will only happen when there is a reasonable relation between the new calculated next extent size and the space effectively allocated to the table.
  4. Extent description in Informix have never been stored in the database catalog. This leads to simpler and efficient space management. Compared to other databases that used to do the management in the catalog, they tend to hit issues in the SQL layer and at the same time these were slower. One of our competitors changed that in their later versions, and DBAs have seen improvement with that (but they had to convert). Informix always worked the better way...
So, these are the good points. Again, why was I complaining? Simply because although Informix has done a pretty good job in preventing the number of extents to grow too much, we had a very low limit for the number of extents. In platforms with a system page size of 2K this was around 220-240 extents (max), and for 4K platforms is was around the double of that (440-480). With version 10 we started to be able to have greater page sizes, and that increases the maximum number of extents per partition.
Why didn't we have a fix limit and why was it different in several platforms? In order to explain that we must dive a bit deeper in the structure of a dbspace and tables. Each partition in Informix has a partition header. Each partition header is stored in exactly one Informix page. There is a special partition in every dbspace (tablespace tablespace) that holds every partition headers from that dbspace. This special partition starts in a specific page but then, it can contain more than one extent.
Also important to understand this is the notion of slot. Most Informix pages contain several slots. For a data page, a slot contains a row (in the simplest cases). A partition header is a page that contains 5 slots:
  1. Slot 1
    This contains the partition structure (things like creation date, partition flags, maximum row size, number of special columns - VARCHAR and BLOB -, number of keys - if it's an index or has index pages -, number of extents and a lot of other stuff. If you want to see all the details check the sysptnhdr table in $INFORMIXDIR/etc/sysmaster.sql. It's basically an SQL interface for the partition headers in the instance.
    In version 11.50 this slot should occupy 100 bytes. Previous versions can have less (no serial 8, and bigserial)
  2. Slot 2
    Contains the database name, the partition owner, the table name and the NLS collation sequence
  3. Slot 3
    Contains details about the special columns. If there are no special columns this slot will be empty
  4. Slot 4
    Contains the description for each key (if it's an index or a mix). Starting with version 9.40, by default the indexes are stored in their own partitions. This was not the case in previous versions. A single partition could contain index pages interleaved with data pages.
    Currently, by default, a partition used for data should not have any key, so this slot will be empty
  5. Slot 5
    Finally, this is the slot that contains the list of extents.
Now we know the list of extents must be stored in the partition header. And the partition header has 5 slots, and the size of first four may vary. This means that the free space for slot 5 (extent list) is variable. These are the reasons why we had a limit and why that limit was not fixed. It would vary with the table structure for example. And naturally it would vary with the page size.
A table that reached it's maximum number of extents was a very real and serious problem in Informix. If you reach the table limit for number of extents and all your table's data pages are full, the engine would need to allocate one more extent in order to complete new INSERTs. But for that it would require some free space in the partition header. If there was no space left, any INSERT would fail with error -136:

-136 ISAM error: no more extents.

After hitting this nasty situation there were several ways to solve it, but all of them would need temporary table unavailability, which in our days is rare... We tend to use 24x7 systems. Even systems that have a maintenance window would suffer with this, because most of the time the problem was noticed during "regular" hours...

So, I've been talking in the past... This used to be a problem. Why isn't it a problem anymore? Because Panther (v11.7) introduced two great features:
  1. The first one is that it is able to automatically extend the partition header when slot 5 (the extent list) becomes full. When this happens it will allocate a new page for the partition header that will be used for the extent list. So you should not see error -136 caused by reaching the extent limit. At first you may think like my customer DBA: "wow! Isn't that dangerous? Will I get tables/partitions with tens of thousands of extents?". The answer is simple. You won't get that high number of extents because all the nice features that were always there (automatic extent concatenation, extent doubling...) are still there. This will just avoid the critical situation where the use of the table would become impossible (new INSERTs). And naturally it doesn't mean that you should not care about the number of extents. For performance reasons it's better to keep them low
  2. The second great feature is an online table defragmenter. They can grow forever, but that's not good. Once you notice you have a table with too many extents you can ask the engine to defragment it. I will not dig into this simply because someone else already did it. I recommend you check the recent DeveloperWorks article entitled "Understand the Informix Server V11.7 defragmenter"

Vers�o Portuguesa:

De volta � Panther... Apesar de n�o estar no v�deo � direita, eu adoro o Informix. Isso n�o significa que ignore alguns problemas que ele tem (ou tinha neste caso particular). Uma coisa que preocupa qualquer DBA Informix � o n�mero de extents das suas tabelas. Porqu�? Porque esse n�mero tinha um m�ximo, e porque esse m�ximo era bastante baixo (se comparado com outras bases de dados). Mas o que � um extent? De forma simples, um extent � uma sequ�ncia cont�gua de p�ginas (ou blocos) que pertencem a uma tabela ou parti��o de tabela. Uma parti��o (uma tabela tem uma ou mais parti��es) tem um ou mais extents.
Antes de continuar, e para estabelecer uma compara��o, gostaria de transmitir algum feedback que ao longo de anos tive de um DBA (essencialmente Oracle, mas tamb�m geria uma inst�ncia Informix):

  • H� alguns anos atr�s passou bastante tempo a executar processos para reduzir o n�mero de extents de uma base de dados concorrente do Informix. Essa base de dados tinha tabelas que atingiram um n�mero incr�vel de extents (na casa das centenas de milhar). Isto foi causado por tabelas verdadeiramente grandes e cl�usulas de aloca��o de espa�o realmente mal definidas
  • Recentemente informei esse mesmo cliente que o Informix ia eliminar o limite de extents, e a mesma pessoa disse-me que tinha receio que isso pudesse levar a situa��es como a de cima. Ele acrescentou, e cito: "Se h� coisa que sempre admirei foi a maneira como o Informix gere os extents".
Assim sendo, se um DBA de um cliente diz que admira a maneira como ger�amos os extents e ele pr�prio receia a elimina��o de limites, porque � que eu me queixo do passado? Como em muitas outras situa��es, as coisas n�o s�o bem a preto e branco... Vejamos o que o Informix sempre fez bem:

  1. Ap�s cada 16 novos extents adicionados, o Informix automaticamente duplica o tamanho do pr�ximo extent da tabela. Isto diminui o n�mero de vezes que tenta reservar um novo extent. Usando apenas esta regra (o que n�o � correcto como veremos a seguir), se criar uma tabela com o extent m�nimo (16KB), a tabela pode crescer at� aos 4GB com cerca de 225 extents.
  2. Se o Informix conseguir reservar um novo extent que seja cont�guo a um que j� esteja alocado � mesma tabela, ent�o em vez de criar um novo, vai alargar o j� existente (portanto n�o aumenta o n�mero de extents). Esta � a raz�o porque a regra anterior pode n�o ser verificada na pr�ctica. Por outras palavaras � mais que prov�vel que consiga atingir os 4GB com menos de 225 extents.
  3. Salvo algum erro, na vers�o 11.50 foi introduzida uma melhoria para prevenir a duplica��o excessiva do tamanho do pr�ximo extent (regra 1). Se o tamanho do pr�ximo extent for X, mas o dbspace s� tiver um m�ximo de Y espa�o livre cont�guo (Y < X) o Informix vai cri�-lo com o tamanho Y e nem se queixar� de nada. Se isto acontecer muitas vezes, podemos acabar por ter um n�mero de p�ginas efectivas de uma tabela ou parti��o relativamente pequeno e um tamanho para o pr�ximo extent muito grande. Existe um problema real nisto: Se nessas cirunst�ncias for criado um novo chunk nesse dbspace, e a tabela precisar de novo extent, pode acontecer que o motor reserve grande parte, ou mesmo a totalidade do novo chunk para a tabela (possivelmente muito mais que o tamanho j� reservado at� ent�o). Para evitar isto, a duplica��o do tamanho do pr�ximo extent s� acontece quando o novo tamanho tem uma rela��o razo�vel com o espa�o reservado at� ent�o. Caso contr�rio o tamanho do pr�ximo extent a alocar n�o � duplicado.
  4. A informa��o dos extents em Informix nunca foi guardada nas tabelas de cat�logo. Isto faz com que a sua gest�o seja mais simples e eficiente. Comparada com outras bases de dados que faziam a gest�o no cat�logo, estas tendiam a encontrar problemas e constrangimentos pr�prios da camada de SQL, e ao mesmo tempo eram mais lentas. Um dos concorrentes mudou isto h� umas vers�es atr�s e os seus utilizadores viram benef�cios bem not�rios (mas tiveram de converter). O Informix sempre trabalhou da melhor forma...
Estes s�o os pontos positivos. Mais uma vez, porque � que me estava a queixar? Simplesmente porque apesar de o Informix sempre ter feito um trabalho extraordin�rio na preven��o contra um elevado n�mero de extents, n�s tinhamos um limite, e era muito baixo. Em plataformas com um tamanho de p�gina de sistema de 2KB este limite rondava os 220-240 extents, e em plataformas de 4KB o limite era cerca do dobro (440-480). Com a vers�o 10 pudemos passar a ter p�ginas maiores, e isso aumenta o limite.
Porque � que o limite n�o � fixo, e porque � diferente consoante a plataforma? Para explicar isto temos de nos debru�ar de forma mais detalhada na estrutura f�sica de um dbspace e tabela. Cada parti��o em Informix tem um cabe�alho. Cada cabe�alho de parti��o � guardado numa p�gina Informix. Existe uma parti��o especial em cada dbspace (designada habitualmente por tablespace tablespace) que guarda todos os cabe�alhos das parti��es criadas nesse dbspace. Esta parti��o especial come�a numa p�gina espec�fica do primeiro chunk do dbspace, mas pode ter mais que um extent.
Igualmente importante para compreender isto � a no��o de slot. A maioria das p�ginas Informix est�o divididas em slots. Para uma p�gina de dados um slot cont�m uma linha de dados da tabela (caso mais simples). Um cabe�alho de parti��o � uma p�gina que cont�m cinco slots:

  1. Slot 1
    Este cont�m a estrutura da parti��o (coisas como a data de cria��o, flags, tamanho m�ximo de uma linha, num�ro de colunas ditas especiais - VARCHAR e BLOBs -, n�mero de chaves - se for um ind�ce ou tiver p�ginas de ind�ce -, n�mero de extents e uma s�rie de outros detalhes. Se tiver curiosidade em saber o que l� est� guardado consulte a tabela sysptnhdr na base de dados sysmaster (ou o ficheiro $INFORMIXDIR/etc/sysmaster.sql). Basicamente esta tabela � um interface SQL sobre todos os cabe�alhos de parti��o da inst�ncia Informix.
    Na vers�o 11.50 este slot ocupa 100 bytes. Vers�es anteriores podem ocupar menos (aus�ncia do serial8 e bigserial)
  2. Slot 2
    Cont�m o nome da base de dados, dono da parti��o, nome da tabela e a NLS collation sequence
  3. Slot 3
    Cont�m detalhes sobre todas as colunas especiais. Se n�o existirem colunas especiais (VARCHAR e BLOB) este slot estar� vazio. Se existirem, o tamanho ocupado depender� da estrutura da tabela.
  4. Slot 4
    Cont�m a descri��o de cada chave (se for um �ndice ou um mix). Desde a vers�o 9.40, por omiss�o os ind�ces s�o guardados em parti��o � parte. Isto n�o era assim em vers�es anteriores. Uma parti��o podia conter p�ginas de ind�ces e de dados.
    Actualmente, por omiss�o, uma parti��o usada para dados n�o deve ter nenhuma chave, e assim este slot deve estar vazio
  5. Slot 5
    Finalmente, este � o slot que cont�m a lista dos extents.

Agora sabemos que a lista de estents tem de ser guardada no cabe�alho da parti��o. E este cont�m cinco slots sendo que o tamanho dos primeiros quatro varia. Isto implica que o espa�o livre para o slot cinco (a lista de extents) � vari�vel. Estas s�o as raz�es porque tinhamos um limite e porque esse limite era vari�vel. Variava por exemplo com a estrutura da tabela. E naturalmente variava com o tamanho da p�gina.
Uma tabela que atingisse o n�mero m�ximo de extents tornava-se num problema s�rio em Informix. Quando tal acontece, se todas as p�ginas de dados estiverem cheias, o motor ter� de reservar um novo extent para completar novos INSERTs. Mas para isso necessitaria de espa�o livre no cabe�alho da parti��o. Portanto, n�o havendo a� espa�o livre todos os INSERTs falhariam com o erro -136:

-136 ISAM error: no more extents.

Depois de batermos nesta situa��o havia v�rias formas de a resolver, mas todas elas necessitavam de indisponibilidade tempor�ria da tabela, o que nos dias que correm � um bem raro... A tend�ncia � usarmos sistemas 24x7. Mesmo sistemas que tenham janela de manuten��o sofreriam com isto, porque na maioria das vezes o problema manifestava-se durante o hor�rio normal ou produtivo...

Bom, mas tenho estado a falar no passado.... Isto costumava ser um problema. Porque � que j� n�o o �? Porque a vers�o 11.7 (Panther) introduziu duas excelentes funcionalidades:

  1. A primeira � que a partir de agora � poss�vel estender automaticamente o cabe�alho da parti��o quando o slot cinco enche. Nesta situa��o, uma nova p�gina � reservada para o cabe�alho da parti��o e a lista de extents pode crescer. Portanto n�o dever� voltar a ver o erro -136 causado por atingir o limite de extents. � primeira vista pode ter a mesma reac��o que o DBA do meu cliente. "Epa! Mas isso n�o � perigoso? Vou passar a ter tabelas/parti��es com dezenas de milhares de extents?". A resposta � simples. N�o vai atingir esses n�meros de extents porque todas as boas caracter�sticas que sempre existiram (jun��o autom�tica de extents, duplica��o de tamanho do pr�ximo extent...) ainda est�o presentes e funcionais. Isto apenas evitar� a situa��o cr�tica em que o uso da tabela se tornava imposs�vel (para novos INSERTs). E naturalmente isto n�o significa que passemos a ignorar o n�mero de extents das nossas tabelas. Por quest�es de desempenho � melhor mant�-los baixos.
  2. A segunda grande funcionalidade � um desfragmentador online de tabelas ou parti��es. O n�mero de extents pode crescer indefinidamente, mas isso n�o � bom. Assim que notar que tem uma parti��o com um n�mero elevado de extents pode pedir ao motor que a desfragmente. N�o vou aprofundar este tema, simplemente porque j� foi feito. Recomendo que consulte um artigo recente do DeveloperWorks intitulado "Understand the Informix Server V11.7 defragmenter". Infelizmente o artigo s� tem vers�o em Ingl�s

UDRs: In transaction? / Em transac��o?

This article is written in English and Portuguese
Este artigo est� escrito em Ingl�s e Portugu�s

English version:

Introduction

I just checked... This will be post 100!!!... I've never been so active in the blog... We have Panther (full of features that I still haven't covered), I did some work with OAT and tasks that I want to share, and besides that I've been trying some new things... Yes... Although I've been working with Informix for nearly 20 years (it's scaring to say this but it's true...) there are aspects that I usually don't work with. I'd say the one I'm going to look into today is not used by the vast majority of the users. And that's a shame because:
  1. It can solve problems that we aren't able to solve in any other way
  2. If it was more used, it would be improved faster
Also, many people think that this is what marked the decline of the Informix company. You probably already figured out that I'm talking about extensibility. To recall a little bit of history, in 1995, Informix had the DSA architecture in version 7. And it acquired the Illustra company, founded by Michael Stonebraker and others. Mr. Stonebraker already had a long history of innovation (which he kept improving up to today) and he stayed with Informix for some years. All the technology around Datablades and extensibility in Informix comes from there... Informix critics say that the company got so absorbed in the extensibility features (that it believed would be the "next wave") that it loosed the market focus. Truth is that the extensibility never became a mainstream feature neither in Informix or in other databases, and all of them followed Informix launch of Universal Server (1996): Oracle, IBM DB2 etc.

But, this article will not focus on the whole extensibility concept. It would be impossible and tedious to try to cover it in one blog article. Instead I'll introduce one of it's aspects: User Defined Routines (UDRs), and in particular routines written using the C language.

There is a manual about UDRs, and I truly recommend that you read it. But here I'll follow another approach: We'll start with a very simple problem that without C UDRs would be impossible to solve, define a solution for it, and go all the way to implement it and use it with an example.


The problem

Have you ever faced a situation where you're writing a stored procedure in SPL, and you want to put some part of it inside a transaction, but you're afraid that the calling code is already in a transaction?
You could workaround this by initiating the transaction and catching the error (already in transaction) with an ON EXCEPTION block.
But this may have other implications (ON EXCEPTION blocks are tricky when the procedure is called from a trigger). So it would be nice to check if the session is already in a transaction. A natural way to do that would be a call to DBINFO(...), but unfortunately current versions (up to 11.7.xC1) don't allow that. Meaning there is no DBINFO() parameter that makes it return that information.


Solution search

One important part of Informix extensibility is the so called Datablade API. It's a set of programmable interfaces that we can use inside Datablades code and also inside C UDRs. The fine infocenter has a reference manual for the Datablade API functions. A quick search there for "transaction" makes a specific function come up: mi_transaction_state()
The documentation states that when calling it (no parameters needed) it will return an mi_integer (let's assume integer for now) type with one of these values:
  • MI_NO_XACT
    meaning we don't have a transaction open
  • MI_IMPLICIT_XACT
    meaning we have an implicit transaction open (for example if we're connected to an ANSI mode database)
  • MI_EXPLICIT_XACT
    meaning we have an explicit transaction open
This is all we need conceptually.... Now we need to transform ideas into runnable code!

Starting the code

In order to implement a C UDR function we should proceed through several steps:
  1. Create the C code skeleton
  2. Create the C code function using the Datablade API
  3. Create a makefile that has all the needed instructions to generate the executable code in a format the engine can use
  4. Compile the code
  5. Use SQL to define the new function, telling the engine where it can find the function and the interface to call it, as well as the language and other function attributes
  6. Test it!



Create the C code skeleton

Informix provides a tool called DataBlade Developers Kit (DBDK) which includes several components: Blade Manager, Blade Pack and Bladesmith. Blade Manager allows us to register the datablades against the databases, the Blade Pack does the "packaging" of all the Datablades files (executable libraries, documentation files, SQL files etc.) that make up a datablade. Finally Bladesmith helps us to create the various components and source code files. It's a development tool that only runs on Windows but can also be used to prepare files for Unix/Linux. For complex projects it may be a good idea to use Bladesmith, but for this very simple example I'll do it by hand. Also note I'm just creating a C UDR. These tools are intended to deal with much more complex projects. A Datablade can include new datatypes, several functions etc.
So, for our example I took a peek at the recent Informix Developer's Handbook to copy the examples.

Having looked at the examples above, it was easy to create the C code:


/*
This simple function returns an integer to the calling SQL code with the following meaning:
0 - We're not within a transaction
1 - We're inside an implicit transaction
2 - We're inside an explicit (BEGIN WORK...) transaction
-1 - Something unexpected happened!
*/

#include <milib.h>

mi_integer get_transaction_state_c( MI_FPARAM *fp)
{
mi_integer i,ret;
i=mi_transaction_state();
switch(i)
{
case MI_NO_XACT:
ret=0;
break;
case MI_IMPLICIT_XACT:
ret=1;
break;
case MI_EXPLICIT_XACT:
ret=2;
break;
default:
ret=-1;
}
return (ret);
}

I've put the above code in a C source file called get_transaction_state_c.c

Create the makefile

Again, for the makefile I copied some examples and came up with the following. Please consider this as an example only. I'm not an expert on makefile building and this is just a small project.


include $(INFORMIXDIR)/incl/dbdk/makeinc.linux

MI_INCL = $(INFORMIXDIR)/incl
CFLAGS = -DMI_SERVBUILD $(CC_PIC) -I$(MI_INCL)/public $(COPTS)
LINKFLAGS = $(SHLIBLFLAG) $(SYMFLAG)


all: get_transaction_state.so

clean:
rm -f get_transaction_state.so get_transaction_state_c.o


get_transaction_state_c.o: get_transaction_state_c.c
$(CC) $(CFLAGS) -o $@ -c $?

get_transaction_state.so: get_transaction_state_c.o
$(SHLIBLOD) $(LINKFLAGS) -o $@ $?


Note that this is a GNU Make makefile. The first line includes a makefile that IBM supplies with Informix. It basically contains variables or macro definitions. You should adapt the include directive to your system (the name of the makefile can vary with the platform) and make sure that the variables I use are also defined in your system base makefile.
After that I define some more variables and I create the makefile targets. I just want it to build the get_transaction_state.so dynamically loadable library and for that I'm including the object (get_transaction_state_c.o) generated from my source code (get_transaction_state_c.c). Pretty simple if you have basic knowledge about makefiles

Compile the code

Once we have the makefile we just need to run a simple command to make it compile:


cheetah@pacman.onlinedomus.net:informix-> make
cc -DMI_SERVBUILD -fpic -I/usr/informix/srvr1150uc7/incl/public -g -o get_transaction_state_c.o -c get_transaction_state_c.c
gcc -shared -Bsymbolic -o get_transaction_state.so get_transaction_state_c.o
cheetah@pacman.onlinedomus.net:informix->
The two commands run are the translation of the macros/variables defined in the makefile(s) and they simply compile the source code (1st command) and then generate the dynamic loadable library. If all goes well (as it naturally happened in the output above), we'll have a library on this location, ready for usage by Informix:


cheetah@pacman.onlinedomus.net:informix-> ls -lia *.so
267913 -rwxrwxr-x 1 informix informix 5639 Nov 23 22:06 get_transaction_state.so
cheetah@pacman.onlinedomus.net:informix-> file *.so
get_transaction_state.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (GNU/Linux), dynamically linked, not stripped
cheetah@pacman.onlinedomus.net:informix->

Use SQL to define the function

Now that we have executable code, in the form of a dynamic loadable library, we need to instruct Informix to use it. For that we will create a new function, telling the engine that it's implemented in C language and the location where it's stored. For that I created a simple SQL file:


cheetah@pacman.onlinedomus.net:informix-> ls *.sql
get_transaction_state_c.sql
cheetah@pacman.onlinedomus.net:informix-> cat get_transaction_state_c.sql
DROP FUNCTION get_transaction_state_c;

CREATE FUNCTION get_transaction_state_c () RETURNING INTEGER
EXTERNAL NAME '/home/informix/udr_tests/get_transaction_state/get_transaction_state.so'
LANGUAGE C;
cheetah@pacman.onlinedomus.net:informix->


So, let's run it...:


cheetah@pacman.onlinedomus.net:informix-> dbaccess stores get_transaction_state_c.sql

Database selected.


674: Routine (get_transaction_state_c) can not be resolved.

111: ISAM error: no record found.
Error in line 1
Near character position 36

Routine created.


Database closed.

cheetah@pacman.onlinedomus.net:informix->


Note that the -674 error is expected, since my SQL includes a DROP FUNCTION. If I were using 11.7 (due to several tests I don't have it ready at this moment) I could have used the new syntax "DROP IF EXISTS...".

So, after this step I should have a function callable from the SQL interface with the name get_transaction_state_c(). It takes no arguments and returns an integer value.

Test it!

Now it's time to see it working. I've opened a session in stores database and did the following:
  1. Run the function. It returned "0", meaning no transaction was opened.
  2. Than I opened a transaction and run it again. It returned "2", meaning an explicit transaction was opened
  3. I closed the transaction and run the function by the third time. As expected it returned "0"
Here is the output:


cheetah@pacman.onlinedomus.net:informix-> dbaccess stores -

Database selected.

> EXECUTE FUNCTION get_transaction_state_c();


(expression)

0

1 row(s) retrieved.

> BEGIN WORK;

Started transaction.

> EXECUTE FUNCTION get_transaction_state_c();


(expression)

2

1 row(s) retrieved.

> ROLLBACK WORK;

Transaction rolled back.

> EXECUTE FUNCTION get_transaction_state_c();


(expression)

0

1 row(s) retrieved.

>

We haven't seen it returning "1". That happens when we're inside an implicit transaction. This situation can be seen if we use the function in an ANSI mode database. For that I'm going to use another database (stores_ansi), and naturally I need to create the function there (using the previous SQL statements). Then I repeat more or less the same steps and the result is interesting:


cheetah@pacman.onlinedomus.net:informix-> dbaccess stores_ansi -

Database selected.

> EXECUTE FUNCTION get_transaction_state_c();


(expression)

0

1 row(s) retrieved.

> SELECT COUNT(*) FROM systables;


(count(*))

83

1 row(s) retrieved.

> EXECUTE FUNCTION get_transaction_state_c();


(expression)

1

1 row(s) retrieved.

>
If you notice it, the first execution returns "0". Since I have not done any operations there is no transaction opened. But just after a simple SELECT, the return is "1", meaning an implicit transaction is opened. This has to do with the nature and behavior of ANSI mode databases.
If you use them and you intend to use this function you must take that into consideration. Or you could simply map the "1" and "2" output of the mi_transaction_state() function return into simply a "1". This would signal that a transaction is opened (omitting the distinction between implicit and explicit transactions).

Final considerations

Please keep in mind that this article serves more as a light introduction to the C language UDRs than to solve a real problem. If you need to know if you're already in transaction (inside a stored procedure for example) you can use this solution, but you could as well try to open a transaction and capture and deal with the error inside an ON EXCEPTION block.

Also note that if this is a real problem for your applications, even if you're inside an already opened transaction, you can make your procedure code work as a unit, by using the SAVEPOINT functionality introduced in 11.50. So, in simple pseudo-code it would be done like this:

  1. Call get_transaction_state_c()
  2. If we're inside a transaction then set TX="SVPOINT" and create a savepoint called "MYSVPOINT" and goto 4)
  3. If we're not inside a transaction than set TX="TX" and create one. Goto 4
  4. Run our procedure code
  5. If any error happens test TX variable. Else goto 8
  6. If TX=="TX" then ROLLBACK WORK. Return error
  7. Else, if TX=="SVPOINT" then ROLLBACK WORK TO SAVEPOINT 'MYSVPOINT'. Return error
  8. Return success
After this introduction, I hope to be able to write a few more articles related to this topic. The basic idea is that sometimes it's very easy to extend the functionality of Informix. And I feel that many customers don't take advantage of this.
Naturally, there are implications on writing C UDRs. The example above is terribly simple, and it will not harm the engine. But when you're writing code that will be run by the engine a lot of questions pop up.... Memory usage, memory leaks, security stability... But there are answers to this concerns. Hopefully some of them (problems and solutions) will be covered in future articles.


Vers�o Portuguesa:

Introdu��o

Acabei de verificar.... Este ser� o cent�simo artigo!!! Nunca estive t�o activo no blog... Temos a vers�o Panther (11.7) (cheia de funcionalidades sobre as quais ainda n�o escrevi), fiz algum trabalho com tarefas do OAT que quero partilhar, e para al�m disso tenho andado a testar coisas novas... Sim... Apesar de j� trabalhar com Informix h� perto de 20 anos (� assustador dizer isto, mas � verdade...) h� �reas de funcionalidade com as quais n�o lido habitualmente. Diria que aquela sobre a qual vou debru�ar-me hoje n�o � usada pela maioria dos utilizadores. E isso � uma pena porque:
  1. Permite resolver problemas que n�o t�m outra solu��o
  2. Se fosse mais usada seria melhorada mais rapidamente
Adicionalmente, existe muita gente que pensa que isto foi o que marcou o decl�nio da empresa Informix. Possivelmente j� percebeu que estou a falar da extensibilidade. Para relembrar um pouco de hist�ria, em 1995, a Informix tinha a arquitectura DSA (Dynamic Scalable Architecture) na vers�o 7. E adquiriu a empresa Illustra, fundada por Michael Stonebraker e outros. O senhor Stonebraker j� tinha um longo passado de inova��o (que prossegue ainda actualmente) e permaneceu na Informix durante alguns anos. Toda a tecnologia � volta dos datablades e extensibilidade teve a� a sua origem.... Os cr�ticos da Informix dizem que a companhia ficou t�o absorvida pelas funcionalidades de extensibilidade (que acreditava serem a pr�xima "vaga") que perdeu o foco do mercado. A verdade � que a extensibilidade nunca se tornou em algo generalizado nem no Informix nem em outras bases de dados, e todas elas seguiram o lan�amento do Informix Universal Server (1996): Oracle, IBM DB2 etc.

Mas este artigo n�o ir� focar todo o conceito de extensibilidade. Seria imposs�vel e entediante tentar cobrir tudo isso num artigo de blog. Em vez disso vou apenas introduzir um dos seus aspectos: User Defined Routines (UDRs), e em particular rotinas escritas usando linguagem C.

Existe um manual que cobre os UDRs, e eu recomendo vivamente a sua leitura. Mas aqui seguirei outra abordagem: Come�arei com um problema muito simples, que sem um UDR em C seria imposs�vel de resolver, definirei uma solu��o para o mesmo, e prosseguirei at� � implementa��o e utiliza��o da solu��o com um exemplo.

O problema

Alguma vez esteve numa situa��o em que estivesse a escrever um procedimento em SPL, e quisesse colocar parte dele dentro de uma transac��o, mas tivesse receio que o c�digo que chama o procedimento j� estivesse com uma transac��o aberta?

Poderia contornar o problema iniciando uma transac��o e apanhando o erro (already in transaction) com um bloco de ON EXCEPTION

Mas isto teria outras implica��es (os blocos de ON EXCEPTION podem criar problemas se o procedimento for chamado de um trigger). Portanto seria bom poder verificar se a sess�o j� est� no meio de uma transac��o. Uma forma natural de o fazer seria recorrer � fun��o DBINFO(...), mas infelizmente as vers�es actuais (at� � 11.7.xC1) n�o permitem isso. Ou seja, n�o h� nenhum par�metro desta fun��o que permita obter a informa��o que necessitamos.

Pesquisa da solu��o

Uma parte importante da extensibilidade no Informix � a chamada Datable API. � um conjunto de interfaces program�veis que podemos usar dentro de datablades e tamb�m dentro de UDRs em C. O infocenter tem um manual de refer�ncia das fun��es do Datablade API. Uma pesquisa r�pida por "transaction" faz aparecer uma fun��o: mi_transaction_state()

A documenta��o indica que quando a chamamos (n�o requer par�metros) ir� retornar um valor do tipo mi_integer (equivale a um inteiro) com um destes valores:
  • MI_NO_XACT
    significa que n�o temos uma transac��o aberta
  • MI_IMPLICIT_XACT
    significa que temos uma transac��o impl�cita aberta (por exemplo se estivermos conectados a uma base de dados em modo ANSI)
  • MI_EXPLICIT_XACT
    significa que temos uma transac��o expl�cita aberta
Isto � tudo o que necessitamos conceptualmente.... Agora precisamos de transformar uma ideia em c�digo execut�vel!

Come�ando o c�digo

Para implementarmos um UDR em C necessitamos de efectuar v�rios passos:
  1. Criar o esqueleto do c�digo C
  2. Criar a fun��o com c�digo C usando o datablade API
  3. Criar um makefile que tenha todas as instru��es necess�rias para gerar o c�digo execut�vel num formato que possa ser usado pelo motor
  4. Compilar o c�digo
  5. Usar SQL para definir uma nova fun��o, indicando ao motor onde pode encontrar a fun��o, o interface para a chamar bem como a linguagem usada e outros atributos da fun��o
  6. Testar!

Criar o c�digo em C

O Informix fornece uma ferramenta chamada DataBlade Developers Kit (DBDK) que inclu� v�rios componentes: Blade Manager, Blade Pack e Bladesmith. O Blade Manager permite-nos registar datablades em bases de dados, o Blade Pack faz o "empacotamento" de todos os ficheiros de um datablade (bibliotecas execut�veis, ficheiros de documenta��o, ficheiros SQL, etc.). Finalmente o Bladesmith ajuda-nos a criar v�rios componentes e c�digo fonte. � uma ferramenta de desenvolvimento que apenas corre em Windows mas que pode ser usado para preparar ficheiros para Unix/Linux. Para projectos complexos ser� boa ideia usar o Bladesmith mas para este exemplo simples farei tudo � m�o. Apenas estou a criar um UDR em C. Estas ferramentas destinam-se a lidar com projectos muito mais complexos. Um Datablade pode incluir novos tipos de dados, v�rias fun��es etc.
Assim, para o nosso exemplo dei uma espreitadela ao recente Informix Developer's Handbook para copiar alguns exemplos.

Depois de ver os exemplos referidos, foi f�cil criar o c�digo em C:
/*
This simple function returns an integer to the calling SQL code with the following meaning:
0 - We're not within a transaction
1 - We're inside an implicit transaction
2 - We're inside an explicit (BEGIN WORK...) transaction
-1 - Something unexpected happened!
*/

#include <milib.h>

mi_integer get_transaction_state_c( MI_FPARAM *fp)
{
mi_integer i,ret;
i=mi_transaction_state();
switch(i)
{
case MI_NO_XACT:
ret=0;
break;
case MI_IMPLICIT_XACT:
ret=1;
break;
case MI_EXPLICIT_XACT:
ret=2;
break;
default:
ret=-1;
}
return (ret);
}

Coloquei o c�digo acima num ficheiro chamado get_transaction_state_c.c


Criar o makefile

Tamb�m para o makefile, limitei-me a copiar alguns exemplos e gerei o seguinte. Por favor considere isto apenas como um exemplo. N�o sou especialista em constru��o de makefiles e isto � apenas um pequeno projecto.


include $(INFORMIXDIR)/incl/dbdk/makeinc.linux

MI_INCL = $(INFORMIXDIR)/incl
CFLAGS = -DMI_SERVBUILD $(CC_PIC) -I$(MI_INCL)/public $(COPTS)
LINKFLAGS = $(SHLIBLFLAG) $(SYMFLAG)


all: get_transaction_state.so

clean:
rm -f get_transaction_state.so get_transaction_state_c.o


get_transaction_state_c.o: get_transaction_state_c.c
$(CC) $(CFLAGS) -o $@ -c $?

get_transaction_state.so: get_transaction_state_c.o
$(SHLIBLOD) $(LINKFLAGS) -o $@ $?


Este makefile destina-se ao GNU Make. A primeira linha inclu� um makefile fornecido pela IBM com o Informix. Este, basicamente, cont�m defini��es de vari�veis e macros. Deve adaptar a directiva include ao seu sistema (o nome do makefile pode variar com a plataforma) e garanta que as vari�veis que usei est�o definidas no makefile base do seu sistema.
Depois disso defini mais algumas vari�veis e criei os targets. Apenas quero que gere a biblioteca din�mica get_transaction_state.so e para isso estou a incluir o objecto (get_transaction_state_c.o) gerado a partir do meu c�digo fonte (get_transaction_state_c.c). Bastante simples se tiver conhecimentos b�sicos de makefiles.


Compilar o c�digo

Depois de termos o makefile apenas necessitamos de um comando simples para executar a compila��o:


cheetah@pacman.onlinedomus.net:informix-> make
cc -DMI_SERVBUILD -fpic -I/usr/informix/srvr1150uc7/incl/public -g -o get_transaction_state_c.o -c get_transaction_state_c.c
gcc -shared -Bsymbolic -o get_transaction_state.so get_transaction_state_c.o
cheetah@pacman.onlinedomus.net:informix->
Os dois comandos executados s�o a tradu��o dos macros/vari�veis definidos no(s) makefiles(s), e apenas compilam o c�digo fonte (primeiro comando) e depois geram a biblioteca din�mica. Se tudo correr bem (como naturalmente aconteceu no output acima), teremos a biblioteca nesta localiza��o, pronta a ser usada pelo Informix:
cheetah@pacman.onlinedomus.net:informix-> ls -lia *.so
267913 -rwxrwxr-x 1 informix informix 5639 Nov 23 22:06 get_transaction_state.so
cheetah@pacman.onlinedomus.net:informix-> file *.so
get_transaction_state.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (GNU/Linux), dynamically linked, not stripped
cheetah@pacman.onlinedomus.net:informix->

Usar SQL para definir a fun��o

Agora que temos o c�digo execut�vel, na forma de uma biblioteca din�mica, precisamos de instruir o Informix para us�-la. Para isso vamos criar uma nova fun��o, dizendo ao motor que est� implementada em linguagem C e qual a localiza��o onde est� guardada. Faremos isso com um script SQL simples:

cheetah@pacman.onlinedomus.net:informix-> ls *.sql
get_transaction_state_c.sql
cheetah@pacman.onlinedomus.net:informix-> cat get_transaction_state_c.sql
DROP FUNCTION get_transaction_state_c;

CREATE FUNCTION get_transaction_state_c () RETURNING INTEGER
EXTERNAL NAME '/home/informix/udr_tests/get_transaction_state/get_transaction_state.so'
LANGUAGE C;
cheetah@pacman.onlinedomus.net:informix->


Vamos execut�-lo...:


cheetah@pacman.onlinedomus.net:informix-> dbaccess stores get_transaction_state_c.sql

Database selected.


674: Routine (get_transaction_state_c) can not be resolved.

111: ISAM error: no record found.
Error in line 1
Near character position 36

Routine created.


Database closed.

cheetah@pacman.onlinedomus.net:informix->


Repare que o erro -674 � expect�vel, dado que o meu SQL inclu� a instru��o DROP FUNCTION (e ela ainda n�o existe). Se estivesse a usar a vers�o 11.7 (devido a v�rios testes n�o a tenho operacional agora) podia ter usado a nova sintaxe "DROP IF EXISTS".

Portanto depois deste passo, devo ter uma fun��o que pode ser chamada pela interface SQL com o nome get_transaction_state_c(). N�o recebe argumentos e retorna um valor inteiro.


Testar!

Agora � tempo de a ver a trabalhar. Abri uma sess�o na base de dados stores e fiz o seguinte:
  1. Corri a fun��o. Retornou "0", o que significa que n�o havia transac��o aberta
  2. Depois abri uma transac��o e executei a fun��o novamente. Retornou "2", o que significa que uma transac��o expl�cita estava aberta
  3. Fechei a transac��o e corri a fun��o pela terceira vez. Como esperado retornou "0"
Aqui est� o output:


cheetah@pacman.onlinedomus.net:informix-> dbaccess stores -

Database selected.

> EXECUTE FUNCTION get_transaction_state_c();


(expression)

0

1 row(s) retrieved.

> BEGIN WORK;

Started transaction.

> EXECUTE FUNCTION get_transaction_state_c();


(expression)

2

1 row(s) retrieved.

> ROLLBACK WORK;

Transaction rolled back.

> EXECUTE FUNCTION get_transaction_state_c();


(expression)

0

1 row(s) retrieved.

>

N�o vimos o retorno "1". Isso acontece quando estamos dentro de uma transac��o impl�cita. Esta situa��o pode ser vista se a fun��o estiver a ser executada numa base de dados em modo ANSI. Para isso vou usar uma outra base de dados (stores_ansi), e naturalmente necessito de criar a fun��o aqui (usando as instru��es SQL anteriores). Depois repito mais ou menos os mesmos passos e o resultado � interessante:

cheetah@pacman.onlinedomus.net:informix-> dbaccess stores_ansi -

Database selected.

> EXECUTE FUNCTION get_transaction_state_c();


(expression)

0

1 row(s) retrieved.

> SELECT COUNT(*) FROM systables;


(count(*))

83

1 row(s) retrieved.

> EXECUTE FUNCTION get_transaction_state_c();


(expression)

1

1 row(s) retrieved.

>
Se reparar, a primeira execu��o retornou "0". Como ainda n�o tinha efectuado nenhuma opera��o n�o havia transac��o aberta. Mas logo a seguir a um simples SELECT j� retorna "1", o que significa que uma transac��o impl�cita estava aberta. Isto prende-se com a natureza e comportamento das bases de dados em modo ANSI.
Se as usa e pretende usar esta fun��o ter� de ter isto em considera��o. Ou poder� simplesmente mapear o retorno "1" e "2" da fun��o mi_transaction_state() no retorno "1" da fun��o criada por si. Isto sinalizaria que uma transac��o estava aberta (omitindo a distin��o entre transac��o impl�cita e expl�cita).

Considera��es finais

Relembro que este artigo serve mais como introdu��o aos UDRs na linguagem C que propriamente para resolver um problema real.
Se necessitar de saber se j� est� numa transac��o (dentro de uma stored procedure por exemplo) pode usar esta solu��o, mas tamb�m podia tentar abrir uma transac��o e capturar e gerir o erro dentro de um bloco ON EXCEPTION.

Chamo a aten��o tamb�m para que se isto � um problema real das suas aplica��es, mesmo que esteja j� dentro de uma transac��o, pode fazer com que o c�digo da sua stored procedure trabalhe como uma unidade, usando a funcionalidade dos SAVEPOINTs, introduzida na vers�o 11.50. Em pseudo-c�digo seria feito assim:

  1. Chamar a get_transaction_state_c()
  2. Se estamos dentro de uma transac��o ent�o estabelecer TX="SVPOINT" e criar um savepoint chamado "MYSVPOINT". Ir para 4)
  3. Se n�o estamos dentro de uma transac��o ent�o estabelecer TX="TX" e criar uma. Ir para 4)
  4. Correr o c�digo da procedure
  5. Se ocorrer algum erro testat a vari�vel TX. Ir para 8)
  6. Se TX =="TX" ent�o ROLLBACK WORK. Retornar erro.
  7. Sen�o, SE TX=="SVPOINT" ent�o ROLLBACK WORK TO SAVEPOINT 'MYSVPOINT'. Retornar erro
  8. Retornar sucesso
Depois desta introdu��o espero conseguir escrever mais alguns artigos relacionados com este t�pico. A ideia base � que algumas vezes � muito f�cil estender a funcionalidade base do Informix. E sinto que muitos clientes n�o tiram partido disto.
Naturalmente h� implica��es em escrever UDRs em C. O exemplo acima � terrivelmente simples, e n�o trar� preju�zo ao motor. Mas quando escrevemos c�digo que ser� executado pelo motor surgem uma s�rie de quest�es... Utiliza��o de mem�ria, fugas de mem�ria, seguran�a, estabilidade.... Mas existem respostas para estas preocupa��es. Espero que alguns (problema e solu��es) sejam cobertos em artigos futuros.

Quiz game / Adivinha

This article is written in English and Portuguese
Este artigo est� escrito em Ingl�s e Portugu�s

English version:

If you have 15m I'd like to propose you a quiz game. Go to this webpage:

http://www-01.ibm.com/software/data/informix/library.html

scroll down to the white papers section and open the one titled "Smart Systems Require an Embedded Database: Six Criteria to Consider"
It's a joint IBM and Cisco whitepaper that talks about the characteristics a database should have to be used as an embeddable database. The characteristics are analyzed through six criteria: installation, integration, performance, resource management, administration and availability.
If you know what have been introduced in Informix in the latest releases you'll find this quite amusing. So what's the quiz? Try to find out what database the paper is talking about. I don't need to tell you the answer, mainly because you'll surely find out by yourself, but also because the answer is discreetly given at the end of the paper...
It's public that some Cisco equipments include Informix (Cisco support forums support this claim). I personally believe this is enough proof that Informix is an excellent product if you need to embed a database in your solution (whether it is software only or software and hardware). If you take some time to check the latest versions new features you'll find lots of improvements for this type of use.



Vers�o Portuguesa:

Se tiver 15m livres gostava de lhe propor um jogo de adivinha. V� at� esta p�gina:

http://www-01.ibm.com/software/data/informix/library.html

des�a at� � sec��o dos white papers e abra o intitulado "Smart Systems Require an Embedded Database: Six Criteria to Consider" (apenas em Ingl�s)
� um documento conjunto entre a IBM e a Cisco que fala sobre as caracter�sticas que uma base de dados deve ter para ser usada como uma base de dados embebida. As caracter�sticas s�o analisadas segundo seis crit�rios: instala��o, integra��o, desempenho, gest�o de recursos, administra��o e disponibilidade.
Se sabe o que tem sido introduzido no Informix nas �ltimas vers�es, vai achar este documento divertido. Portanto qual � a adivinha? Tente descobrir qual � a base de dados falada no documento. N�o necessito de lhe dar a resposta aqui, principalmente porque conseguir� perceber a resposta sozinho, mas tamb�m porque a resposta � dada de forma muito discreta no final do documento...
� p�blico que alguns equipamentos Cisco incluem Informix (os f�runs de suporte da Cisco sustentam esta afirma��o). Pessoalmente acredito que isto � prova suficiente de que o Informix � um excelente produto se necessita de embeber uma base de dados na sua solu��o (seja apenas de software ou software e hardware).
Se tirar algum tempo para verificar as novas funcionalidades das �ltimas vers�es encontrar� imensas melhorias para este tipo de utiliza��o.

IIUG 2011 Conference / Confer�ncia IIUG 2011

This article is written in English and Portuguese
Este artigo est� escrito em Ingl�s e Portugu�s

English Version:

IIUG has just opened the 2011 IIUG conference registration. The conference will be held in May 15-18 2011, at the usual place, the Marriot Overland Park hotel in Overland Park, Kansas City. The conference can cost as little as:
  • $525 for the conference registration (if you register before January 31 and you're an IIUG member)
  • $129 / night (Sunday and week days) plus $99 / night (Friday and Saturday)
  • Travel costs
Regular sessions will be held from Monday to Wednesday and there are special Sunday sessions (tutorials). From Sunday evening to Tuesday, you'll have breakfast, lunch and evening receptions to keep you well fed. So a typical stay (arriving and Sunday afternoon and leaving on Thursday will cost you around $525 + (4 * $129) + travel costs + Wednesday dinner which translates into around $1050 plus travel costs.

That's what you'll pay. What about what you'll get? Well, I can speak for the 2010 conference. It was by far one of the best training events I've ever been. If you work with Informix, or plan to work with Informix you have several options for training: IBM classes, Instructor Led Online (remote online training), custom classes in your company installations and IIUG conference. And one thing I can assure you: You won't get the networking, knowledge transfer and the possibility to interact with the IBM Informix technical staff anywhere else. Typically my biggest problem was to decide which session to attend. And next year, with the recent launch of Panther (v11.7) the sessions should be even more interesting. You also get the chance to take free certification tests (around $150). Besides all this the conference atmosphere is rather amusing and you'll get a lot of fun. Maybe you should omit this from your management or they may prefer to take your place! :)

So if you have a training budget you should consider this. It's also a rare opportunity to speak to the people who drive Informix's future. If you need a new feature, or if you find a limitation in the product there is no better place to explain it than at the conference.

In short, you'll get:
  • More interesting sessions than you'll be able to attend (it's a good idea to take a colleague and each one attend a different session at a time)
  • Free certification tests
  • Opportunity to talk with all the Informix gurus out there
  • Opportunity to interact with the Informix top architects
  • Networking with other users. You can do and promote your business there
  • Relaxed, friendly and fun atmosphere promoted by all the IIUG people
  • Opportunity to understand why the conference takes place in Kansas City (no distractions besides the green fields and having the Informix lab right next door)
All this for maybe less than the cost of a traditional 3 day course

Finally, IIUG is still accepting speakers nominations (until November 15). If you have something to present, be it a deep dive into some particular aspect of Informix, a good use case, a success story etc. please don't hesitate. Speakers will not pay for the conference (less $525 on the budget). Don't hold back if you have something interesting to show. The audience will be friendly and your presentation skills will be less important than your subject.


Vers�o Portuguesa:

O IIUG anunciou a abertura do registo para a sua confer�ncia internacional de utilizadores de 2011. A confer�ncia ter� lugar de 15 a 18 de Maio de 2011, no local habitual, o hotel Marriot Overland Park, em Overland Park, Kansas City, EUA. O custo poder� ser t�o pouco quanto:

  • $525 para o registo na confer�ncia (se se inscrever antes de 31 de Janeiro e for membro do IIUG)
  • $129 / noite (Domingo a quarta-feira) mais $99 / noite (Sexta-feira e S�bado)
  • Custos de viagem

As sess�es normais decorrem de Segunda a Quarta-feira e existem sess�es especiais no Domingo (tutorials). Do final de Domingo at� Quarta-feira ter� pequeno almo�o, almo�o e recep��o nocturna para o manter bem alimentado. Assim, uma ida t�pica (chegada no Domingo ao final da tarde e sa�da na Quinta-feira) custar-lhe-� cerca de $525 + ( 4 * $129) + custos de viagem + jantar de Quarta-feira, o que se traduzir� em cerca de $1050 mais viagens.

Isto � o que custa. E quanto ao que se recebe? Bom, eu posso falar pela confer�ncia deste ano (2010). Foi de longe um dos melhores eventos de forma��o em que estive. Se trabalha com Informix, ou se planeia trabalhar com Informix tem v�rias op��es de forma��o: Cursos da IBM, Instructor Led Online (forma��o online remota), cursos customizados nas instala��es da sua empresa e a confer�ncia do IIUG. E algo posso garantir: N�o vai obter a possibilidade de interac��o, a transfer�ncia de conhecimentos e a possibilidade de interagir com o staff t�cnico da IBM Informix em mais lado nenhum. Regra geral a minha dificuldade foi escolher a sess�o a que iria assistir no hor�rio seguinte. E no ano que vem, com o recente lan�amento da vers�o 11.7 (Panther) as sess�es devem ser ainda mais interessantes. Tamb�m tem a possibilidade de fazer testes gratuitos de certifica��o (rondam os $150).
Para al�m disto, a atmosfera da confer�ncia � bastante engra�ada e divertida. Mas talvez seja melhor omitir isto � sua gest�o, ou podem preferir tomar o seu lugar! :)

Portanto, se tem um or�amento de forma��o deve considerar isto. � tamb�m uma rara oportunidade de falar com as pessoas que decidem o futuro do Informix. Se precisa de uma nova funcionalidade ou se encontrou uma limita��o no produto n�o h� melhor sitio que a confer�ncia para o explicar.

Em resumo obter�:

  • Mais sess�es de interesse que aquelas a que conseguir� assistir (� uma boa ideia levar um colega e dividirem-se pelas sess�es concorrentes no hor�rio)
  • Testes de certifica��o gratuitos
  • Oportunidade de falar com todos os gurus de Informix
  • Oportunidade de interagir com os arquitectos de topo do Informix
  • Interac��o com outros utilizadores. Pode efectuar e promover neg�cios l�
  • Atmosfera descontra�da e divertida, promovida por todos os elementos do IIUG
  • Oportunidade de perceber porque � que a confer�ncia se realiza em Kansas City (poucas distrac��es para al�m dos campos verdes, e ter o laborat�rio de Informix mesmo ao virar da esquina)
Tudo isto possivelmente por menos custo que um curso tradicional de 3 dias.

Por �ltimo, o IIUG ainda est� a aceitar nomea��es para apresenta��es (at� 15 de Novembro de 2010). Se tem algo para apresentar, seja uma vis�o aprofundada de algum aspecto do Informix, um bom caso de utiliza�ao, uma hist�ria de sucesso etc. por favor n�o hesite.
Os apresentadores n�o pagar�o a confer�ncia (menos $525 no or�amento). N�o se retraia caso tenha algo interessante para apresentar. A audi�ncia ser� amig�vel e as suas qualidades de apresenta��o ser�o menos importantes que o tema em si.

Panther: Instance schema / Schema da inst�ncia

This article is written in English and Portuguese
Este artigo est� escrito em Ingl�s e Portugu�s

English version:
This time I'll cover a little but helpful improvement in the dbschema utility. dbschema is the fastest way we have to extract DDL statements about our databases and tables. We can get the full database schema, or just for a table, view, synonym etc. It can also provide all the privileges of objects in the database.

Version 11.7 (Panther) introduces an extension to this tool. We can now obtain the following information at the instance level:

  • Allocated space (dbspaces, chunks...)
  • Location and size of the physical log
  • Location and size of the logical logs
This information was easily available either as the output of onstat commands or by querying the sysmaster database. But then you would need to construct the statements to allocate them. Also note that this could be done by using shell command line interface (onspaces utility) or (since version 11.10) by using the SQL Admin API.

So, now in version 11.7 you can obtain all this info in a ready to use format by running dbschema utility with the new option "-c". By default it will generate SQL statements you can use through the SQL Admin API. But if you also use the "-ns" option (no SQL) it will generate the operating system utilities syntax. Let's see an example of each. I will crop the output so that it does not become too long.


panther@pacman.onlinedomus.net:fnunes-> dbschema -c -q

-- Dbspace 1 -- Chunk 1
-- EXECUTE FUNCTION TASK
('create dbspace', 'rootdbs', 'rootdbs.c1', '250000', '0', '2', '500', '500');

-- Dbspace 2 -- Chunk 2
EXECUTE FUNCTION TASK
('create tempdbspace', 'dbtemp1', 'dbtemp1.c1', '100000', '0', '2', '100', '100');

-- Dbspace 3 -- Chunk 3
EXECUTE FUNCTION TASK
('create sbspace', 'sbs1', 'sbs1.c1', '20000', '0');

-- Dbspace 4 -- Chunk 4
EXECUTE FUNCTION TASK
('create dbspace', 'dbs1', 'dbs1.c1', '250000', '0', '2', '100', '200');

-- Physical Log
EXECUTE FUNCTION TASK
('alter plog', 'rootdbs', '50000');

-- Store pre-existing logical logs information before create new logical logs
DATABASE sysadmin;
CREATE TABLE llog (log smallint, flags smallint);
INSERT INTO llog SELECT number, flags FROM sysmaster:syslogfil;

-- Logical Log 1
EXECUTE FUNCTION TASK
('add log', 'rootdbs', '10000');

-- Logical Log 2
EXECUTE FUNCTION TASK
('add log', 'rootdbs', '10000');

-- [ CUTTED TEXT.... ]
-- [... more logical logs here... ]

-- Logical Log 10
EXECUTE FUNCTION TASK
('add log', 'rootdbs', '10000');

-- Drop all pre-existing logical logs
EXECUTE FUNCTION TASK
('checkpoint');

SELECT TASK ('drop log', log) FROM sysadmin:llog
WHERE sysmaster:bitval(flags,'0x02')==0;

EXECUTE FUNCTION TASK
('checkpoint');

SELECT TASK('onmode', 'l') FROM sysmaster:syslogfil
WHERE chunk = 1 AND sysmaster:bitval(flags,'0x02')>0;

EXECUTE FUNCTION TASK
('checkpoint');

SELECT TASK ('drop log', log) FROM sysadmin:llog
WHERE sysmaster:bitval(flags,'0x02')==1;

DROP TABLE sysadmin:llog;


And now with the -ns option:


panther@pacman.onlinedomus.net:fnunes-> dbschema -c -q -ns
# Dbspace 1 -- Chunk 1
# onspaces -c -d rootdbs -k 2 -p rootdbs.c1 -o 0 -s 250000 -ef 500 -en 500

# Dbspace 2 -- Chunk 2
onspaces -c -d dbtemp1 -k 2 -t -p dbtemp1.c1 -o 0 -s 100000

# Dbspace 3 -- Chunk 3
onspaces -c -S sbs1 -p sbs1.c1 -o 0 -s 20000 -Ms 348

# Dbspace 4 -- Chunk 4
onspaces -c -d dbs1 -k 2 -p dbs1.c1 -o 0 -s 250000 -ef 100 -en 200

# Physical Log
onparams -p -s 50000 -d rootdbs -y

# Store pre-existing logical logs information before create new logical logs
dbaccess sysadmin << END
CREATE TABLE llog (log smallint, flags smallint);
INSERT INTO llog SELECT number, flags FROM sysmaster:syslogfil;
END

# Logical Log 1
onparams -a -d rootdbs -s 10000

# Logical Log 2
onparams -a -d rootdbs -s 10000

## CUTTED TEXT HERE
## ... More logical logs...

# Logical Log 10
onparams -a -d rootdbs -s 10000

# Drop all pre-existing logical logs
onmode -c

dbaccess sysadmin << END
SELECT TASK ('drop log', log) FROM sysadmin:llog
WHERE sysmaster:bitval(flags,'0x02')==0;
END

onmode -c

dbaccess sysadmin << END
SELECT TASK('onmode', 'l') FROM sysmaster:syslogfil
WHERE chunk = 1 AND sysmaster:bitval(flags,'0x02')>0;
END

onmode -c

dbaccess sysadmin << END
SELECT TASK ('drop log', log) FROM sysadmin:llog
WHERE sysmaster:bitval(flags,'0x02')==1;

DROP TABLE sysadmin:llog;
END

This is useful if you want to keep your instance layout for recovery purposes or if you want to recreate a similar instance layout on your test or quality environments.
Just one thing to note. The generated instructions include the statements to create the root dbspace. And as we know, this is created during instance initialization. That chunk instruction should be removed from the scripts but it's important for documentation purposes.

Vers�o Portuguesa:

Desta vez vou abordar uma pequena mas �til melhoria no utilit�rio dbschema. dbschema � a forma mais r�pida de extrair instru��es DDL sobre as nossas bases de dados e tabelas. Podemos obter o esquema completo da base de dados ou apenas de uma tabela, view, sin�nimo etc. Pode tamb�m fornecer todos os privil�gios dos objectos na base de dados.

A vers�o 11.7 (Panther) introduz uma extens�o a esta ferramenta. Podemos agora obter a seguinte informa��o ao n�vel da inst�ncia:

  • Espa�o alocado (dbspaces, chunks...)
  • Localiza��o e tamanho do physical log
  • Localiza��o e tamanho dos logical logs
Esta informa��o j� estava dispon�vel facilmente quer como resultado da execu��o do comando onstat ou atrav�s de queries na base de dados sysmaster. Mas depois tinham de ser criados os comandos para alocar/definir os referidos objectos. Note-se ainda que isto poderia ser feito atrav�s de utilit�rios na shell (utilit�rio onspaces) ou (desde a vers�o 11.10) atrav�s da SQL Admin API.

Agora, na vers�o 11.7, podemos obter esta informa��o num formato "pronto a usar" correndo o utilit�rio dbschema com a op��o "-c". Por pr�-defini��o ir� gerar as instru��es SQL que pode usar atrav�s da SQL Admin API. Mas pode tamb�m usar a op��o "-ns" (no SQL) para que seja gerada a sintaxe utilizando os utilit�rios a correr no sistema operativo. Vejamos um exemplo de cada. Irei cortar o output para que n�o se torne demasiado longo.

panther@pacman.onlinedomus.net:fnunes-> dbschema -c -q

-- Dbspace 1 -- Chunk 1
-- EXECUTE FUNCTION TASK
('create dbspace', 'rootdbs', 'rootdbs.c1', '250000', '0', '2', '500', '500');

-- Dbspace 2 -- Chunk 2
EXECUTE FUNCTION TASK
('create tempdbspace', 'dbtemp1', 'dbtemp1.c1', '100000', '0', '2', '100', '100');

-- Dbspace 3 -- Chunk 3
EXECUTE FUNCTION TASK
('create sbspace', 'sbs1', 'sbs1.c1', '20000', '0');

-- Dbspace 4 -- Chunk 4
EXECUTE FUNCTION TASK
('create dbspace', 'dbs1', 'dbs1.c1', '250000', '0', '2', '100', '200');

-- Physical Log
EXECUTE FUNCTION TASK
('alter plog', 'rootdbs', '50000');

-- Store pre-existing logical logs information before create new logical logs
DATABASE sysadmin;
CREATE TABLE llog (log smallint, flags smallint);
INSERT INTO llog SELECT number, flags FROM sysmaster:syslogfil;

-- Logical Log 1
EXECUTE FUNCTION TASK
('add log', 'rootdbs', '10000');

-- Logical Log 2
EXECUTE FUNCTION TASK
('add log', 'rootdbs', '10000');

-- [ CUTTED TEXT.... ]
-- [... more logical logs here... ]

-- Logical Log 10
EXECUTE FUNCTION TASK
('add log', 'rootdbs', '10000');

-- Drop all pre-existing logical logs
EXECUTE FUNCTION TASK
('checkpoint');

SELECT TASK ('drop log', log) FROM sysadmin:llog
WHERE sysmaster:bitval(flags,'0x02')==0;

EXECUTE FUNCTION TASK
('checkpoint');

SELECT TASK('onmode', 'l') FROM sysmaster:syslogfil
WHERE chunk = 1 AND sysmaster:bitval(flags,'0x02')>0;

EXECUTE FUNCTION TASK
('checkpoint');

SELECT TASK ('drop log', log) FROM sysadmin:llog
WHERE sysmaster:bitval(flags,'0x02')==1;

DROP TABLE sysadmin:llog;


E agora usando a op��o -ns:


panther@pacman.onlinedomus.net:fnunes-> dbschema -c -q -ns
# Dbspace 1 -- Chunk 1
# onspaces -c -d rootdbs -k 2 -p rootdbs.c1 -o 0 -s 250000 -ef 500 -en 500

# Dbspace 2 -- Chunk 2
onspaces -c -d dbtemp1 -k 2 -t -p dbtemp1.c1 -o 0 -s 100000

# Dbspace 3 -- Chunk 3
onspaces -c -S sbs1 -p sbs1.c1 -o 0 -s 20000 -Ms 348

# Dbspace 4 -- Chunk 4
onspaces -c -d dbs1 -k 2 -p dbs1.c1 -o 0 -s 250000 -ef 100 -en 200

# Physical Log
onparams -p -s 50000 -d rootdbs -y

# Store pre-existing logical logs information before create new logical logs
dbaccess sysadmin << END
CREATE TABLE llog (log smallint, flags smallint);
INSERT INTO llog SELECT number, flags FROM sysmaster:syslogfil;
END

# Logical Log 1
onparams -a -d rootdbs -s 10000

# Logical Log 2
onparams -a -d rootdbs -s 10000

## CUTTED TEXT HERE
## ... More logical logs...

# Logical Log 10
onparams -a -d rootdbs -s 10000

# Drop all pre-existing logical logs
onmode -c

dbaccess sysadmin << END
SELECT TASK ('drop log', log) FROM sysadmin:llog
WHERE sysmaster:bitval(flags,'0x02')==0;
END

onmode -c

dbaccess sysadmin << END
SELECT TASK('onmode', 'l') FROM sysmaster:syslogfil
WHERE chunk = 1 AND sysmaster:bitval(flags,'0x02')>0;
END

onmode -c

dbaccess sysadmin << END
SELECT TASK ('drop log', log) FROM sysadmin:llog
WHERE sysmaster:bitval(flags,'0x02')==1;

DROP TABLE sysadmin:llog;
END

Isto � �til se quiser manter um "esqueleto" da sua inst�ncia para prop�sitos de recupera��o ou se quiser recriar uma estrutura semelhante nas suas inst�ncias de teste ou qualidade.
H� que notar um detalhe. As instru��es geradas inclu�m c�digo para criar o root dbspace. E como n�s sabemos, este � criado durante a inicializa��o da inst�ncia. Assim, a instru��o referente a esse chunk dever� ser removida dos scripts. No entanto a sua exist�ncia � importante para efeitos de documenta��o.

Panther: EXISTS or NOT EXISTS

This article is written in English and Portuguese
Este artigo est� escrito em Portugu�s e Ingl�s

English version:

I'll continue with the quick and easy posts about Panther (v11.70). This time I'll focus on some new SQL that was added in Panther. Most (if not all) CREATE and DROP statements now allow for IF NOT EXISTS and IF EXISTS clauses respectively. These clauses allow us to write CREATE/DROP statements that will not raise errors in case the objects already exist and we're trying to create them, or when they don't exist and we're trying to drop them.
As an example:


panther@pacman.onlinedomus.net:fnunes-> onstat -

IBM Informix Dynamic Server Version 11.70.UC1 -- On-Line -- Up 00:03:17 -- 369588 Kbytes

panther@pacman.onlinedomus.net:fnunes-> dbaccess stores -

Database selected.

> DROP TABLE test;

206: The specified table (test) is not in the database.

111: ISAM error: no record found.
Error in line 1
Near character position 15
> DROP TABLE IF EXISTS test;
>

These two clauses can be used for TABLE, PROCEDURE, FUNCTION, DATABASE, INDEX, ROLE etc. (both for create and drop).
This can be used in scripts to prevent that they abort prematurely. Also interesting is the fact that this syntax can be found on mySQL. So it's easier now to port existing code into Informix.



Vers�o Portuguesa:

Vou continuar com os artigos r�pidos e f�ceis sobre a vers�o 11.70 (Panther). Desta vez vou abordar uma mudan�a no SQL que foi adicionada ao Panther. A maior parte (se n�o todas) as instru��es CREATE e DROP suportam agora as cl�usulas IF NOT EXISTS e IF EXISTS respectivamente. Estas cl�usulas permitem-nos escrever instru��es CREATE/DROP que n�o geram erros caso os objectos j� existam e os estejamos a tentar criar, ou quando n�o existem e os estamos a tentar eliminar.
Como exemplo:


panther@pacman.onlinedomus.net:fnunes-> onstat -

IBM Informix Dynamic Server Version 11.70.UC1 -- On-Line -- Up 00:03:17 -- 369588 Kbytes

panther@pacman.onlinedomus.net:fnunes-> dbaccess stores -

Database selected.

> DROP TABLE test;

206: The specified table (test) is not in the database.

111: ISAM error: no record found.
Error in line 1
Near character position 15
> DROP TABLE IF EXISTS test;
>

Estas duas cl�usulas podem ser usadas para TABLE, PROCEDURE, FUNCTION, DATABASE, INDEX, ROLE etc. (tanto para o CREATE como para o DROP).
Isto pode ser usado em scripts para evitar que abortem prematuramente. Tamb�m � interessante o facto de que esta sintaxe pode ser encontrada no mySQL. Portanto ser� agora mais f�cil portar c�digo existente para Informix