Cannes Festival Touchwall
I wanted to share another video on the Touchwall.
It was made for the Cannes Lions Festival which is the largest advertising and PR conference of the year.
I wanted to share another video on the Touchwall.
It was made for the Cannes Lions Festival which is the largest advertising and PR conference of the year.
I’m super happy for my colleagues on the success of the biggest touch wall ever!
I needed to switch all foreign keys from one table to another using PL/SQL in Oracle. This was the result:
Necesitaba un script para pasar los foreign keys de una tabla a otra en Oracle, al final este es el resultado:
/**
* Modifies all references to entity_old and switch them to entity
*
* Process
* 1. Disable Foreign Keys
* 2. Drop foreign key
* 3. Create the foreign key, pointing to the new location
*/
var v_old_table varchar2(100);
var v_new_table varchar2(100);
var v_sql varchar2(500);
var v_sql_delete varchar2(500);
exec :v_old_table := 'OLD_TABLE_NAME_HERE';
exec :v_new_table := 'NEW_TABLE_NAME_HERE';
SET SERVEROUTPUT ON;
BEGIN
FOR row_entity IN (SELECT ac.CONSTRAINT_NAME,
ac.CONSTRAINT_TYPE,
ac.TABLE_NAME,
ac.R_CONSTRAINT_NAME,
ac.STATUS,
ac.DELETE_RULE,
cc.COLUMN_NAME,
sr.COLUMN_NAME AS COLUMN_SOURCE
FROM ALL_CONSTRAINTS ac,
USER_CONS_COLUMNS cc,
USER_CONS_COLUMNS sr
WHERE ac.CONSTRAINT_NAME = cc.CONSTRAINT_NAME
AND ac.R_CONSTRAINT_NAME = sr.CONSTRAINT_NAME
AND ac.CONSTRAINT_TYPE = 'R'
AND ac.R_CONSTRAINT_NAME IN (SELECT CONSTRAINT_NAME
FROM ALL_CONSTRAINTS
WHERE CONSTRAINT_TYPE IN ('P','U')
AND TABLE_NAME = :v_old_table))
LOOP
BEGIN
-- Disable the foreign key IF is enable
IF row_entity.STATUS = 'ENABLED' THEN
:v_sql := 'ALTER TABLE ' || row_entity.TABLE_NAME ||
' MODIFY CONSTRAINT ' || row_entity.CONSTRAINT_NAME ||
' DISABLE';
-- Print SQL Statement
DBMS_OUTPUT.PUT_LINE(:v_sql || ';');
EXECUTE IMMEDIATE :v_sql;
END IF;
IF row_entity.DELETE_RULE = 'CASCADE' THEN
:v_sql_delete := ' ON DELETE CASCADE';
ELSE
:v_sql_delete := '';
END IF;
-- Drop the table reference
:v_sql := 'ALTER TABLE '|| row_entity.TABLE_NAME ||
' DROP CONSTRAINT ' || row_entity.CONSTRAINT_NAME;
DBMS_OUTPUT.PUT_LINE(:v_sql || ';');
EXECUTE IMMEDIATE :v_sql;
-- Re-create the table reference
:v_sql := 'ALTER TABLE '|| row_entity.TABLE_NAME ||
' ADD CONSTRAINT ' || row_entity.CONSTRAINT_NAME ||
' FOREIGN KEY (' || row_entity.COLUMN_NAME || ')' ||
' REFERENCES ' || :v_new_table || ' (' || row_entity.COLUMN_SOURCE || ')' ||
:v_sql_delete;
DBMS_OUTPUT.PUT_LINE(:v_sql || ';');
EXECUTE IMMEDIATE :v_sql;
END;
END LOOP;
END;
/
show errors;
After a while struggling with the php function set_include_path() on windows, became to my attention that using the windows registry to set php configuration values they are set using the php_admin_value which forbids overriding it on run time.
So for example, if you set the include_path on the windows registry and then you call the set_include_path function in your application, it will return false and won’t change the include_path.
The same applies if you use php_admin_value on your .htaccess file or virtual host file.
Después de un tiempo luchando con la la función de PHP set_include_path() en windows, que me retornaba false cuando la llamaba, noté que cuando se usa el registro de windows (windows registry) para modificar la configuracion de PHP (Ver: Registro de windows y la configuracion de PHP), es como utilizar php_admin_value la cual no deja que se modifiquen en tiempo de ejecución.
Por ejemplo, si se usa el registro de windows con la configuración de PHP "include_path” y luego se llama la función set_include_path en la aplicación, esta retorna false (false) y no cambiará la configuración.
Esto aplica también si utiliza php_admin_value en el archivo .htaccess o donde se defina un host virtual.
Instalé Zend Server en mi computadora ya que estoy probando y comparando XDebug y Zend Server. (Ver Instalación de XDebug)
La instalación realmente fue sencilla y me quedo funcionando de maravilla. Lo único que noté es que Zend Server no instala a PHP como un módulo sino como CGI.
Esto hace que si creo un archivo de configuracion .htaccess con valores de configuracion específicos de PHP en el archivo, me de un error “Internal Server Error”.
Mi archivo .htaccess para la aplicación específica, tenía una serie de configuraciones para PHP específicas que funcionaban bien cuando PHP corria como un módulo:
php_value display_errors "On" php_value log_errors "On" php_value session.auto_start 0 php_value error_log "D:/webserver/logs/php_app_error.log"
Solución
Revisando en al documentación de PHP, encontré que uno puede hacer configuraciones específicas por directorio en Windows, utilizando el registro de la máquina.
En vez de poner las configuraciones específicas de PHP en el archivo .htaccess, las puse en el registro de windows y funcionó muy bien.
Espero que le sirva aquellos que estan teniendo problemas con esto.
Asumiendo que el Webserver inicia en “D:\webserver\www” hice este archivo .reg, para crear las entradas necesarias en el registro de Windows:
Webserver.reg
Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\PHP\Per Directory Values\D\webserver\www] "display_errors"="On" "log_errors"="On" "session.auto_start"="0" "error_log"="D:/webserver/logs/php_app_error.log"
Changing PHP configuration via the Windows registry
When running PHP on Windows, the configuration values can be modified on a per-directory basis using the Windows registry. The configuration values are stored in the registry key HKLM\SOFTWARE\PHP\Per Directory Values, in the sub-keys corresponding to the path names. For example, configuration values for the directory c:\inetpub\wwwroot would be stored in the key HKLM\SOFTWARE\PHP\Per Directory Values\c\inetpub\wwwroot. The settings for the directory would be active for any script running from this directory or any subdirectory of it. The values under the key should have the name of the PHP configuration directive and the string value. PHP constants in the values are not parsed. However, only configuration values changeable in PHP_INI_USER can be set this way, PHP_INI_PERDIR values can not.
Referencia:
Este tutorial enseña como ejecutar un script PHP paso a paso haciendo su depuración más sencilla y fácil. Tambien muestra paso a paso como instalar Eclipse PDT y configurarlo para usar XDebug.
Este mismo tutorial esta disponible para descargar, haga click aquí
Que necesita:
Para este tutorial, se asume lo siguiente:
1. Descargue eclipse.
2. Una vez que se ha descargado por completo, descomprímalo en el disco duro (Para efectos de este tutorial usaremos “c:\”)
3. Haga click derecho sobre “eclipse.exe” y seleccione “Send To / Enviar a” > “Desktop / Escritorio” para crear un acceso directo en el escritorio.
4. ¡Listo!
1. Descargue XDebug. (Se asume que se quiere instalar para Apache 2)
2. Guárdelo en el directorio donde esta PHP. (Para efectos de este tutorial usaremos c:\php).
3. Abra y agregue estas líneas al final del archivo de configuración de PHP php.ini de la siguiente manera:
[XDebug] zend_extension_ts="C:\php\php_xdebug-2.0.4-5.2.8.dll" xdebug.remote_enable=1 xdebug.remote_host=127.0.0.1 xdebug.remote_port=9000 xdebug.remote_handler=dbgp xdebug.profiler_enable=1 xdebug.profiler_output_dir="RUTA DE UN DIRECTORIO PARA ARCHIVOS TEMPORALES"
NOTA: Si tiene instalado Zend Server o alguna configuración para hacer debug con Zend Server, debe deshabilitarla, ya que Zend Server y XDebug no son compatibles:
[Zend] ;zend.install_dir="C:\Program Files\Zend\ZendServer" ;zend.conf_dir="C:\Program Files\Zend\ZendServer\etc\" ;zend.pid_dir="C:\Program Files\Zend\ZendServer\logs" ;zend.temp_dir="C:\Program Files\Zend\ZendServer\tmp" ;zend.log_dir="C:\Program Files\Zend\ZendServer\logs" ;zend.data_dir="C:\Program Files\Zend\ZendServer\data" ;zend.httpd_uid=HTTPD_UID ;zend.httpd_gid=HTTPD_GID ;zend.ini_scandir=cfg ;zend.serial_number= ;zend.user_name=
4. Reinicie Apache.
TIP: Si al reiniciar Apache no le funcionaba, asegurese que tenga la configuración correcta en el archivo php.ini, también asegurese que la directriz “xdebug.profiler_output_dir” tiene un directorio válido.
En la raíz del directorio del servidor web, haga una página nueva que se llame “phpinfo.php” y escriba este código:
<?php phpinfo();
Ejecútela en el navegador http://localhost/phpinfo.php y busque XDebug:
1. Inicie Eclipse (puede usar el acceso directo que se hizo en los pasos anteriores)
2. En la barra de menú, haga click en: “Window –> Preferences”
3. En el menú de la izquierda, seleccione PHP – Debug, y en las opciones de la derecha seleccione XDebug. Una vez seleccionado, haga click en “Ok”.
4. Cree un nuevo proyecto, para efectos de este tutorial crearemos un proyecto llamado “XDebug Test”
5. Cree una nueva página con el nombre de “index.php”
6. Escriba el siguiente código:
<?php
for ($i = 1; $i < 10; $i++) {
echo "\$i contiene: {$i} <br />\n";
}
echo "Terminó!";
7. Seleccione “Run – Debug”
8. Haga click en “ok” para confirmar que quiere cambiar la perspectiva a “Debug”. En esta perspectiva tiene varias opciones para depuración, algunas de ellas son:
9. En esta perspectiva se pueden ver los siguientes paneles:
10. Una vez que completa el proceso de depuración veremos esta ventana:
11. Para volver a la perspectiva de desarrollo, haga click en la opción de PHP:
Espero que les ayude.
Invito a tod@s los que quieran participar de la próxima reunión de la comunidad de PHP en Costa Rica:
Donde? Universidad Latina de Costa Rica
Cuando? Jueves 25 de Junio, apartir de las 6pm
Sala de Video conferencias, 3 piso Edificio de ciencias médicas.
Mas info: http://www.costaricaphp.org/archives/50
El grupo es abierto, tod@s estan invitados, desde estudiantes del lenguaje hasta programadores avanzados.
¡Hola a tod@s!
Por fin tenemos fecha para la proxima reunión.
Fecha: Jueves 25 de Junio, apartir de las 6 pm.
Lugar: Universidad Latina de Costa Rica
Se estará dicutiendo la nueva versión de PHP 5.3, que hay de nuevo y ejemplos de código.
Los invito a tod@s a asistir, y también a invitar a todas aquellas personas que les interese PHP.
Estaba haciendo unos procedimientos almacenados en MySQL 5 y cuando estaba hanciedo pruebas, me comenzó a dar este error:
Buscando donde estaba el error, me di cuenta que el procedimiento almacenado que estaba probando utiliza un cursor comparando un String de parametro con una tabla definida explicitamente con una colación (COLLATION) latin1_general_ci.
Este es un ejemplo de como generar el error. Se crea una tabla “tabla_ejemplo” y un procedimiento almacenado “recorrer_ejemplo”. El procedimiento lo únicamente lo que hace es definir un cursor a la tabla “recorrer_ejemplo”, abrirlo y recorrerlo contando el numero de registros que contiene. (No tiene mucho sentido pero es para ejemplo solamente)
create table tabla_ejemplo(
id int unsigned not null auto_increment,
temp_key varchar(32) not null,
description varchar(250),
primary key (id)
) engine = InnoDB
default charset latin1 collate latin1_general_ci;
DELIMITER //
CREATE PROCEDURE recorrer_ejemplo(
IN p_temp_key VARCHAR(32),
IN p_description VARCHAR(250),
OUT total_ejemplos INT UNSIGNED)
BEGIN
-- Declaracion de variables
DECLARE v_id VARCHAR(100);
DECLARE v_temp_key VARCHAR(32);
DECLARE v_description VARCHAR(100);
DECLARE v_done INT DEFAULT 0;
-- Declaracion del cursor
DECLARE cur_ejemplo CURSOR FOR
SELECT id,
temp_key,
description
FROM tabla_ejemplo
WHERE temp_key = p_temp_key;
-- Handler para el cursor
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_done = 1;
-- ***************************
-- ** AQUI ME DA ERROR ***
-- ****************************
OPEN cur_ejemplo;
SET total_ejemplos = 0;
-- Inicio del repeat
REPEAT
-- Traiga los datos del cursor
FETCH cur_ejemplo
INTO v_id,
v_temp_key,
v_description;
-- ... ++ OPERACIONES ++ ...
SET total_ejemplos = total_ejemplos + 1;
-- Fin del repeat
UNTIL v_done END REPEAT;
END;
//
DELIMITER ;
INSERT INTO tabla_ejemplo
VALUES (NULL, MD5('pablo'), 'Desc 1 ...'),
(NULL, MD5('pablo'), 'Desc 2 ...'),
(NULL, MD5('pablo'), 'Desc 3 ...');
SET @p_temp_key = MD5('pablo');
SET @p_description = 'Desc 2 ...';
SET @total_ejemplos = NULL;
CALL recorrer_ejemplo(
@p_temp_key,
@p_description,
@total_ejemplos);
SELECT @total_ejemplos;
Al ejecutar todas las instrucciones, me genera este error:
Script line: 74 Illegal mix of collations (latin1_general_ci,IMPLICIT) and (latin1_swedish_ci,IMPLICIT) for operation ‘=’
El problema está en que MySQL no sabe como resolver la conversión de datos internamente (ver referencias). Es decir, no sabe cual colación debería seguir.
Este comportamiento se llama “coercibility” (coercitivas) y basicamente significa la capacidad de poder ser convertido. En este caso, la capacidad de poder convertir un dato con una collation latin1_swedish_ci a latin1_general_ci.
Los parametros del procedimiento almacenado, tienen una colación latin1_swedish_ci, y cuando lo compara con el campo temp_key con una colación latin1_general_ci general el error, ya que MySQL no sabe cual colación usar a la hora de compara los campos VARCHAR.
Solución:
Convertir el parametro usando la funcion CONVERT y dandole la colación adecuada, ya que la colación default de latin1 es latin1_swedish_ci.
-- Declaracion del cursor
DECLARE cur_ejemplo CURSOR FOR
SELECT id,
temp_key,
description
FROM tabla_ejemplo
WHERE temp_key = CONVERT(p_temp_key USING latin1)
COLLATE latin1_general_ci;
Reglas de Coercibilidad (Coercibility).
En la gran mayoría de consultas, resulta obvio qué colación usa MySQL para resolver una operación de comparación. Por ejemplo, en los siguientes casos, debe quedar claro que la colación es “la colación de la columna x”:
SELECT x FROM T WHERE x = x;
Sin embargo, cuando están implicados varios operandos, puede haber ambigüedad. Por ejemplo:
SELECT x FROM T WHERE x = 'Y';
¿Esta consulta debe usar la colación de la columna x, o de la columna de caracteres literal ‘Y’?
SQL estándar resuelve tales cuestiones usando lo que se solía llamar reglas “coercitivas”. Es decir: Como x e ‘Y’ tienen colaciones, ¿cuál tiene precedencia? Puede ser difícil de resolver, pero las siguientes reglas resuelven la mayoría de situaciones:
Estas reglas resuelven ambigüedades como:
Ejemplos:
| columna1 = ‘A’ | Usa colación de columna1 |
| columna1 = ‘A’ COLLATE x | Usa colación de ‘A’ |
| columna1 COLLATE x = ‘A’ COLLATE y | Error |
Referencias:
He querido escribir sobre hostings desde hace rato.
Cuando iniciamos con la comunidad de PHP www.costaricaphp.org un amigo nos ofreció hospedar el sitio gratis en un server que el tenía y a administraba, pero fue un toque feo, ya que todo habia que pedirle a el cualqueir cosa y se duraba mucho haciendo un cambio, en fin, decidimos pagar por un servicio de hosting nosotros mismos.
Consideramos varias opciones, la verdad nunca me habia puesto a buscar un hosting provider enserio, siempre amigos/personas preguntaban y nunca tenia una respuesta clara.
Yo tenia una cuenta en GoDaddy, pero es horrible!, asi que GoDaddy estaba descartado, fue cuando nos encontramos Hostmonster que pareció una buena opción en el momento.
Al cabo de 1 año en Hostmonster, estaba sumamente desilucionado, todo era complicado, no permitian multiples dominios en una misma cuena, no tenian SVN el cual es sumamente importante para un desarrollador web, etc. De nuevo tuve que buscar otro hosting provider….
Pregunte a varios compañeros y me dijeron que ellos usaban Dreamhost.
Me meti al site de ellos y realmente me costo creer que ofrecieran espacio ilimitado en disco y ancho de banda ilimitado, parecia muy bueno para ser verdad.
Investigue un poco y BINGO, repositorios ilimitados de SUBVERSION!!! ahi dije “LO COMPRO!”.
Normalmente pago el servicio anual, asi no me preocupo en el año por el hosting y pruebo como es la cosa.
Llevo un año con ellos y la verdad no puedo estar mas feliz, tengo el sitio de la comunidad de PHP ahi y mi sitio personal, además de varios otros subdominios para demos o instalar aplicaciones para probar.
Me encanta que me den espacio ilimitado en el disco, ancho de banda ilimitada y sobre todo subversion, además que tambien tengo acceso al shell usando SSH.
Para terminar, me di cuenta que cuando hacia “sign-up”, tenian un espacio de “cupones de descuento” y me di cuenta que solo tenia que buscar…. y encontré.
Para compartir con quien halla tenido las mismas experiencias y ande buscando un hosting… aqui están los cupones de descuento de dreamhost! ¡PROVECHO!
La dirección de Dreamhost es: http://www.dreamhost.com/
| Cupón de descuento | Descripción |
| 60DESCUENTO1ANNO | $50 de descuento el primer año. Tarifa normal $119, con el cupon $69.4 |
| 33DESCUENTO2ANNO | 33% de descuento por 2 años. Tarifa normal $214.8, con el cupón $142.8 |
| 25DESCUENTO3ANNO | 25% de descuento por 3 años. Tarifa normal $286.2, con el cupón $214.2 |
| 2DOM20DESCUENTO | 2 Dominios gratis para siempre + 20% descuento por un año Tarifa normal $119, con el cupon $99.4 + 2 dominios gratis. |
| IP_UNICA_20DESC | 1 IP única grátis de por vida + $23 de descuento Tarifa normal $119, con el cupon $96.4 + 1 dirección IP única gratis para siempre. |