Mots-clé : mysql

MySQL : mémo / cheatsheet

Voici quelques astuces dont je me sers souvent, pour ne pas avoir à systématiquement les rechercher, je m’en suis fait une copie dans un petit champ texte :

Création d’une base de données

CREATE DATABASE z DEFAULT CHARACTER SET utf8;

Créer un utilisateur pour une base de données (la manière sale)

Important : d’abord sans le ‘.*’ sinon ça ne fonctionne pas, et puis refaire avec le '.*'.
Très important : ici on autorise tout à l’utilisateur qui va être crée. C’est donc une méthode rapide mais de bourrin et ce n’est pas la bonne méthode si vous voulez faire un utilisateur proprement, destiné à exister pour longtemps. Dans ce cas il faut faire quelque chose de plus précis afin de ne pas tout lui autoriser.
GRANT ALL PRIVILEGES ON bd TO 'nomutilisateur'@'192.168.2.16' IDENTIFIED BY 'motdepasse';
GRANT ALL PRIVILEGES ON bd.* TO 'nomutilisateur'@'192.168.2.16' IDENTIFIED BY 'motdepasse';

Initialisation d’une variable via une requête :

SELECT @MON_ID:= ID FROM matable WHERE CHAMP='champ_recherche';
puis on se ressert de cette variable pour faire une insertion en base de données :
INSERT INTO autre_table (ID_CLE_EXTERNE, DESCRIPTION, DOCUMENT) VALUES
(@MON_ID, 'valeur1', './valeur2');

Relancer le service MySQL

  1. service mysqld stop
  2. attendre une trentaine de secondes afin que le cache soit vidé et que toutes les allocations mémoires soient correctement libérées
  3. service mysqld start

Convertir une table en utf8 :

Très important : si vous tapez ce qui suit avec pour objectif de convertir la table et les données cela ne fonctionnera pas :
ALTER TABLE tbl_name CONVERT TO CHARACTER SET charset_name;
Ce n’est qu’en utilisant les ordres suivants que la conversion sera faite par MySQL !
ALTER TABLE t1 CHANGE c1 c1 BLOB;
ALTER TABLE t1 CHANGE c1 c1 TEXT CHARACTER SET utf8;

Renommer un champ :

Ici, je renomme la clé primaire « ID » et je la passe en minuscules (« id« ) :
ALTER TABLE ville CHANGE ID id int(11) NOT NULL auto_increment;

Modification des AUTO_INC

Pour changer la valeur d’un auto_inc (‘réinitialiser la valeur’, comme on le dit dans MySQL ici) :
ALTER TABLE tbl_name AUTO_INCREMENT = N;

Packtlib : Mastering ExtJS : impressions à chaud

Pour les Anglais uniquement, vous serez sûrement intéressées :

Le livre Mastering ExtJS.

Mastering Ext JS montre aux lecteurs comment utiliser le potentiel de Ext JS au complet et créer une application au complet en partant de rien, mais explique aussi comment créer un thème WordPress avec ExtJS. Cette dernière section est assez surprenante, mais semble efficace.

  • Chapter 1. Getting Started
    Les bases pour installer ExtJS (LAMP, ou pour les newbies WAMP etc)
  • Chapter 2. The Login Page
    La plupart des applications ont une page d’identification. L’auteur explique comment faire l’identification « classique » avec ExtJS.
  • Chapter 3. Logout and Multilingual
    La plupart des applications ont une page de déconnexion, et en 2013, il faut savoir rapidement implémenter une autre langue. L’auteur explique comment faire cela : déconnexion et gestion du multilangue.
  • Chapter 4. Advanced Dynamic Menu
    Comment créer des menus dynamiques, qui sont constitués en fonction des droits de la personne connectée (cf chapitres 2 et 3).
  • Chapter 5. User Identification and Security
    Création d’une page de gestion complètes des identifications : comment donner les permissions à des utilisateurs (lister tous les utilisateurs, créer, éditer et supprimer des utilisateurs et aperçu d’une image d’un utilisateur qui va être envoyée).
  • Chapter 6. MySQL Table Management
    Création d’un système modulaire appelé « données statiques ». Liste de toutes les informations d’une table MySQL. Créer de nouveaux enregistrements dans la table. Live search sur les tables. Mettre en place des filtres. Éditer et supprimer des enregistrements. Créer un composant abstrait réutilisable pour toutes les tables.
  • Chapter 7. Content Management
    Gestion de contenu complexe avec ExtJS : comment gérer les associations many-to-many. Comment gérer et faire des formes avec les associations. Explication pour faire des composants réutilisables.
  • Chapter 8. Adding Extra Capabilities
    Possibilités supplémentaires. Comment imprimer des champs d’un panneau de type grille (GridPanel). Comment exporter des champs d’un panneau de type grille (GridPanel) en PDF ou au format Excel. Comment créer des graphiques /courbes. Comment utiliser des composants tiers ou des plugins.
  • Chapter 9. The E-mail Client Module
    Cette partie explique comment développer un client Web mail avec ExtJS. Comment dessiner le client email. Comment lister les emails. Comment créer la boîte de réception (gestion d’un TreePanel). Comment gérer le drag’n’drop entre deux composants (grid et tree). Améliorer le GridPanel de manière impressionnante (customisation).
  • Chapter 10. Preparing for Production
    Comment créer un thème personnaliser. Comment préparer (packager) l’application pour qu’elle soit prête pour la production. Comment utiliser le packager. Il peut sembler y avoir peu de choses dans ce chapitre, mais les explications sont longues et détaillées et j’ai appris énormément de choses.
  • Chapter 11. Building a WordPress Theme
    Je pensais que l’idée était de faire à la main un thème WordPress, mais non : l’idée est d’utiliser tout l’habillage au complet ExtJS, ainsi que le code JavaScript qui va avec, afin de l’intégrer dans une application WordPress. Comment fonctionne WordPress. Comment créer un thème, un header, un footer, une page principale, une Sidebar, une page d’articles et enfin une page de type « Page » (par opposition aux pages de type « Article »)
  • Chapter 12. Debugging and Testing
    C’est un des chapitres les plus pratiques pour la vie quotidienne : la plupart des outils avancés et peu connus y sont, pourtant il sont très utiles : comment déboguer une application ExtJS. Comment tester les applications ExtJS. Les outils utiles (JSLint, YSlow, Sas, Less, YUI Compressor…). Comment passer de ExtJS à une version mobile. Composants tiers et plugins utiles pour développer rapidement. Résumé

Au final, ce livre comporte beaucoup de choses intéressantes, et (à mon sens), même si vous êtes développeur avancé ExtJS, les trois derniers chapitres sont super intéressants et rien que pour ces trois derniers, même si vous trouvez qu’acheter un livre c’est trop cher (ce que je comprends ;)), les quelques 17 € que vous coûteront la version en ligne seront rapidement rentabilisés.

D’ailleurs en parlant de version en ligne, ils ont complètement refait leur reader en ligne, et ce dernier est très bien fait : moi qui suis très critique, je n’ai rien trouvé à redire !

Symfony 2 et Doctrine: comment ajouter les fonctions spécifiques MySQL

Imaginons que vous fassiez un Repository dans lequel vous essayez d’éxecuter une fonction ainsi :

    <?php
    public function findNearest(...) {
        return $this->createQueryBuilder('p')
            ->select(array(
                'p.id',
                'COS(5) as distance'
            ))
            ->having('distance>:dmin')
            ->addOrderBy('distance', 'DESC')
            ->setParameters(array(
                'dmin' => $distance_min,
            ));
    }

Alors vous verrez que Doctrine ne connait pas la fonction cosinus COS().
Vous aurez l’erreur :

[Syntax Error] line 0, col 27: Error: Expected known function, got 'COS'

Doctrine ne connait pas la fonction cosinus COS(), mais aussi plein d’autres fonctions.

Pour les avoir disponibles, il faut aller les chercher sur github, ici.

Ici, vous pourrez récupérer toutes ces fonctions : DateAdd(), Sha1(), NullIf(), Field(), Month(), Sin(), MatchAgainst(), Acos(), Day(), CountIf(), GroupConcat(), Radians(), TimestampDiff(), ConcatWs(), Cot(), IfElse(), FindInSet(), IfNull(), Cos(), Asin(), Md5(), Year(), Sha2(), Week(), CharLength(), DateDiff(), StrToDate(), Atan(), Tan(), Atan2() et Degrees()

Ensuite, comme je ne voulais pas tous les fichiers, mais que les extensions, je les ai toutes mises dans mon répertoire dédié : src/HQF/Bundle/PizzasBundle/DQL/MySQL/.
Puis j’ai modifié à la main tous les fichiers en les déclarant dans le namespace adéquat (namespace HQF\Bundle\PizzasBundle\DQL\MySQL;).

Une fois cela fait, j’ai ajouté les déclarations de ces fonctions dans le fichier de config général app/config/config.yml. La petite astuce très importante et qui m’a fait perdre un temps fou (et c’est pour ça que je fait cet article en fait), qui n’est pas très claire dans la documentation : le nom qu’on déclare doit correspondre au texte qu’on trouve dans la fonction. Donc, dans le fichier, on a [nom de la fonction]:[classe] :

J’essayais de déclarer mafonction_acos: HQF\Bundle\PizzasBundle\DQL\MySQL\Acos et ça ne fonctionnait pas. Il fallait donner le nom de la fonction : acos: HQF\Bundle\PizzasBundle\DQL\MySQL\Acos

doctrine:
    ...blabla...
    orm:
        default_entity_manager: default
        entity_managers:
            default:
                connection: default
                ...blabla...
                dql:
                    numeric_functions:
                        acos: HQF\Bundle\PizzasBundle\DQL\MySQL\Acos
                        asin: HQF\Bundle\PizzasBundle\DQL\MySQL\Asin
                        atan2: HQF\Bundle\PizzasBundle\DQL\MySQL\Atan2
                        atan: HQF\Bundle\PizzasBundle\DQL\MySQL\Atan
                        charlength: HQF\Bundle\PizzasBundle\DQL\MySQL\CharLength
                        concatws: HQF\Bundle\PizzasBundle\DQL\MySQL\ConcatWs
                        cos: HQF\Bundle\PizzasBundle\DQL\MySQL\Cos
                        cot: HQF\Bundle\PizzasBundle\DQL\MySQL\Cot
                        countif: HQF\Bundle\PizzasBundle\DQL\MySQL\CountIf
                        dateadd: HQF\Bundle\PizzasBundle\DQL\MySQL\DateAdd
                        datediff: HQF\Bundle\PizzasBundle\DQL\MySQL\DateDiff
                        day: HQF\Bundle\PizzasBundle\DQL\MySQL\Day
                        degrees: HQF\Bundle\PizzasBundle\DQL\MySQL\Degrees
                        field: HQF\Bundle\PizzasBundle\DQL\MySQL\Field
                        findinset: HQF\Bundle\PizzasBundle\DQL\MySQL\FindInSet
                        groupconcat: HQF\Bundle\PizzasBundle\DQL\MySQL\GroupConcat
                        ifelse: HQF\Bundle\PizzasBundle\DQL\MySQL\IfElse
                        ifnull: HQF\Bundle\PizzasBundle\DQL\MySQL\IfNull
                        matchagainst: HQF\Bundle\PizzasBundle\DQL\MySQL\MatchAgainst
                        md5: HQF\Bundle\PizzasBundle\DQL\MySQL\Md5
                        month: HQF\Bundle\PizzasBundle\DQL\MySQL\Month
                        nullif: HQF\Bundle\PizzasBundle\DQL\MySQL\NullIf
                        radians: HQF\Bundle\PizzasBundle\DQL\MySQL\Radians
                        sha1: HQF\Bundle\PizzasBundle\DQL\MySQL\Sha1
                        sha2: HQF\Bundle\PizzasBundle\DQL\MySQL\Sha2
                        sin: HQF\Bundle\PizzasBundle\DQL\MySQL\Sin
                        strtodate: HQF\Bundle\PizzasBundle\DQL\MySQL\StrToDate
                        tan: HQF\Bundle\PizzasBundle\DQL\MySQL\Tan
                        timestampdiff: HQF\Bundle\PizzasBundle\DQL\MySQL\TimestampDiff
                        week: HQF\Bundle\PizzasBundle\DQL\MySQL\Week
                        year: HQF\Bundle\PizzasBundle\DQL\MySQL\Year

Cours optimisation Internet – Ecole d’ingénieurs des Mines

Après avoir fait ma présentation, cela fait toujours plaisir de savoir qu’on est suffisamment intéressé pour demander ma présentation !

Cliquez sur le lien pour la récupérer, et n’hésitez pas à laisser une appréciation sur ce qui était bien et ce qui manquait éventuellement, sachant que j’ai fait ce que je pouvais dans un laps de temps aussi court 😉

Cliquez ici.

PDO, MySQL et erreurs détaillées : comment faire

Voici mon ancien code d’exécution des requêtes SQL :

$stmt = self::$_pdo->prepare($sql);
if ($stmt===false) {
}   
foreach ($tab as $key=>$valeur) {
    $stmt->bindValue($key, $valeur);
}   
$stmt->execute();
if ($stmt===false) {
    throw new Exception(
        "Erreur execution de la requete :\n\"".$sql."\"\n".
        "Paramètres de la requete :\n\"".var_export($tab, true)."\"\n".
        "Details de l'erreur : \n".var_export(self::$_pdo->errorInfo(), true)
    );
}

Le seul (gros) problème, c’est sur erreur d’exécution, il n’y avait aucune explication claire (détail = erreur 0x00). J’ai trouvé la solution : il faut dire de lever une exception si erreur :

self::$_pdo->setAttribute(
    PDO::ATTR_ERRMODE,
    PDO::ERRMODE_EXCEPTION
);

Et maintenant, tout problème d’exécution de query lève une exception qui contient une erreur vraiment détaillée et utile de la requête.

Linux, MySQL, utf8 : requêtes et queries : comment éviter le décalage du résultat

Peut être avez-vous déjà rencontré ce problème : vous faites toute une base de données en utf-8.

En suivant les recommandations ici, c’est facile. Le seul problème, et ils ne donnent pas de solution, c’est que lorsqu’on fait les requêtes, les résultats sont bien renvoyés en utf-8 mais il y a un décalage s’il y a des accents :

Image qui montre un décalage de résultat d'une requête mysql en ligne de commande

Comment faire pour éviter ce décalage ? Facile. La solution ici.

En fait dans votre fichier de configuration, il faut aussi configurer le client, pas uniquement le serveur.

Il faut ajouter la directive « default-character-set = utf8 » dans le fichier de configuration :

sudo vim /etc/mysql/my.cnf

[client]
port    = 3306
socket    = /var/run/mysqld/mysqld.sock
default-character-set = utf8

Et puis relancer le service :

sudo service mysql restart

Et voici le résultat : tout est rentré dans l’ordre :

Image qui montre le problème résolu de décalage de résultat d'une requête mysql en ligne de commande

MySQL : solution à « Can’t find any matching row in the user table »

Voilà quel était mon problème, et j’espère vous aider en vous apportant une solution si vous avez ce problème :

j’ai fait un dump complet de toutes les bases de données mysql dans un gros fichier, via l’ordre mysqldump :

mysqldump -u root -pmonmotdepasse --all-databases > a_integrer.sql

Ensuite j’ai copié le fichier sur l’ordinateur destination, et j’ai ré-injecté le sql dans la base de données, ce qui a tout ré-intégré de manière transparente :

mysqldump -u root -pmonmotdepasse < a_integrer.sql

Le seul problème, c’est que, sur l’ordinateur destination, impossible de se connecter sur la base de données, alors que l’utilisateur avait bien été intégré dans la base. En me connectant à la base, j’ai voulu modifier le mot de passe, mais impossible. L’erreur était la suivante :

Can't find any matching row in the user table

Donc impossible de changer le mot de passe alors que l’utilisateur existe bien.

La solution qui a fonctionné est la suivante : supprimer puis recréer l’utilisateur avec les droits d’accès adéquats.

Faites la même chose :

  • un mysqldump total ;
  • ré-injection sur l’ordinateur destination ;
  • si problème avec les mots de passe : suppression à la main du compte mysql concerné, puis re-création avec les bons droits.

Python et autohotkey : exemple concret

C’est en cherchant des airs connus que je suis tombé sur ce site : http://www.mutopiaproject.org/ qui recense toutes les compositions tombées dans le domaine publique, qui a généré en automatique des fichiers midi en conséquence, et, surtout, qui a utilisé un logiciel du domaine publique extrêmement performant qui a constitué toutes les partitions.
Comme il y en a des centaines, et que tout est organisé de la même façon, je me suis fait un « aspirateur » de ces compositions, et puis, une fois aspirées, je me suis généré un fichier AutoHotKey (cf http://www.autohotkey.com/), logiciel tout simplement extraordinaire avec lequel on peut simuler en script absolument tout ce qu’on veut sous Windows : souris et clavier. J’ai donc « préposté » tous les articles que vous pouvez voir, et j’en fais apparaître un sur deux « réellement » à moi. Comme ça je fais d’une pierre deux coups : je promeus un site extrêmement bien fait et gratuit, et j’alimente mon blog (ces articles se sont étalés sur quatre mois).

Peut-être que cela vous donnera des idées ? 😉

Smarty 3.1 et les plugins : comment faire / howto

Sur la toute dernière version de Smarty (3.1), voici comment créer un plugin personnalisé.
Pour résumer, l’un de mes sites n’était pas assez optimisé.
Le code qui sortait était :

<body class="sbody">
    <div>
....
    </div>
....
</body>

J’ai donc ajouté le filtre d’optimisation qui supprime les espaces en début :

$this->smarty->loadFilter('output', 'trimwhitespace');

Le code de sortie est devenu :

<body class="sbody"><img src="/title.jpg" /><div>....</div>....</body>

Tout mise en une ligne, super !
Le seul problème, c’est que ça ne fonctionnait pas avec le code JavaScript, il faut en effet les retours à la ligne.
J’ai donc crée mon plugin qui ne fait que supprimer les espaces en début de ligne, et remplacer de « retour + line feed » (deux octets) de fin de ligne par un seul octet « retour ».

Voici le code, je vous laisse comprendre, c’est extrêmement simple :

/* Déclarer un plugin "block".
 * Block = il faut un début et une fin.
 * Ici : {triml} {/triml}
 */
$this->smarty->registerPlugin('block',
  'triml', array($this,'smarty_block_trim_l'));

Après avoir déclaré le plugin, il faut faire la fonction adéquate :

/**
 * Fonction de plugin smarty pour supprimer tous les espaces
 * en début de ligne entre les blocs {triml}{/triml}
 * "triml" = trimleft
 * Voir le constructeur et chercher $this->smarty->registerPlugin()
 *
 * @param array $params les paramètres qu'on passe à {strip_nl}
 * @param variant $content Le contenu qu'il y a dans le bloc
 * @param variant $template Le nom du template
 * @param variant &$repeat
 *
 * @return int Description retour
 */
public function smarty_block_trim_l(
  array $params, $content, $template, &$repeat)
{
  $content = preg_replace('/\n[\s]+/', "\n", $content);
  return $content;
}

Et voilà maintenant, vous pourrez aussi optimiser votre site comme un professionnel.
Bien évidemment le gain le plus gros est dans la compression (voir mod_deflate)

ExtJS et Panel : le layout « absolute »

Après plusieurs heures de recherches, j’ai enfin compris comment fonctionnait le layout « absolute ».
L’utilité de la disposition "absolute", est qu’on peut positionner les éléments dans le conteneur à un endroit bien précis, au pixel près.
Voici l’astuce qui m’a fait perdre tellement de temps, et qui, je l’espère, vous en fera gagner :
D’habitude, sur tous les « layout » existants, lorsqu’on les définit, ils s’appliquent sur les éléments contenus. Et non pas sur le conteneur.
La seule exception se trouve avec le layout « absolute » : je le mets en gros et gras, parce que j’ai passé énormément de temps à trouver cette astuce :

Lorsqu’on utilise le layout « absolute », il faut toujours préciser aussi la largeur et la hauteur du conteneur, sinon ce dernier ne sera jamais affiché

Exemple concret :
Voici ce qui ne fonctionnait pas :
MonPanel = function(tab) {
    this.layout = 'absolute';
    this.border = false;
    MonPanel.superclass.constructor.call(this, {
        items: [{
            x: 0,
            y: 5,
            xtype: 'label',
            text: 'To:',
        }]
    });
};

Le panneau n’était pas affiché. Voici ce qui ne fonctionne :
MonPanel = function(tab) {
    this.layout = 'absolute';
    this.border = false;
    this.width = '100%';
    this.height = 150;
    MonPanel.superclass.constructor.call(this, {
        items: [{
            x: 0,
            y: 5,
            xtype: 'label',
            text: 'To:',
        }]
    });
};