Journal Des emojis en SQL ? C'est possible… et on peut aller au-delà !

Posté par  (site web personnel, Mastodon) .
Étiquettes :
31
9
mar.
2019

Le saviez-vous ?

On peut utiliser des emojis en SQL, et pas seulement pour les manipuler : les emojis peuvent servir d'identifieurs !

Avec PostgreSQL, peut donc faire des choses comme :

CREATE TABLE 👤(
    🔑 INTEGER PRIMARY KEY,
    🗣 varchar(64), -- name
    🗓 DATE -- date of registration
);

Voire carrément :

CREATE TYPE  AS ENUM ('🤢', '☹', '😐', '🙂', '😍');

-- [...]

-- select the most common rating for each book
-- MODE() is another function exclusive to PostgreSQL
--- https://wiki.postgresql.org/wiki/Aggregate_Mode
SELECT 📕.💬, MODE() WITHIN GROUP (ORDER BY 👤🏠📕.) AS MostCommonRating
FROM 👤🏠📕 JOIN 📕 ON 👤🏠📕.📕 = 📕.🔑
GROUP BY  📕.🔑;
             💬            | mostcommonrating
---------------------------+------------------
 Alice in Wonderland       | NULL
 Moby Dick                 | NULL
 Through the Looking-Glass | 🙂
 Example Book              | 😍

Je vous renvoie vers cet article pour les détails, et part du principe que vous l'avez lu dans la suite.

Mais on peut faire mieux !

JPA avec Hibernate permet de gérer nativement ces syntaxes… à condition d'utiliser Kotlin, qui permet d'utiliser les emojis en identifiants.

Le code ci-dessous est donc tout à fait valable, compile et, associé à SpingBoot, démarre :

package fr.spacefox.sqlmoji.model

import javax.persistence.*

@Entity
@Table
data class `✍` (
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        val `🔑`: Int,

        @Column(nullable = false, length = 64) val `🗣`: String,

        @OneToMany(mappedBy = "✍") val `📕`: Collection<`📕`>
)

@Entity
@Table
data class `👤` (
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        val `🔑`: Int,

        @Column(nullable = false, length = 64) val `🗣`: String,
        @Column val `🗓`: LocalDate,

        @ManyToMany
        @JoinTable(
                name = "👤🏠📕",
                joinColumns = arrayOf(JoinColumn(name = "👤" , referencedColumnName = "🔑")),
                inverseJoinColumns = arrayOf(JoinColumn(name = "📕", referencedColumnName = "🔑")))
        var `📕`: List<`📕`> = mutableListOf()
)

@Entity
@Table
data class `📕` (
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        val `🔑`: Int,

        @Column(nullable = false, length = 64) val `💬`: String,  // Title
        @Column(length = 64) val `🔖`: String,  // Genre/Tag

        @ManyToOne val `✍`: `✍`,

        @ManyToMany(mappedBy = "📕")
        var `👤`: List<`👤`> = mutableListOf()
)

La syntaxe bizarre à base d'accents graves autours des emojis1 permet d'utiliser un emoji – ou n'importe quel caractère Unicode qui nécessite plus de 16 bits de représentation – en tant qu'identifiant Kotlin. C'est une spécificité du langage qui n'existe pas à ma connaissance en Java.

Et donc, si couple ça à un SpringBoot, au démarrage ça me génère bien une base de données avec la structure suivante :

create table if not exists "✍"
(
    "🔑" serial not null
        constraint "✍_pkey"
            primary key,
    "🗣" varchar(64) not null
);

create table if not exists "👤"
(
    "🔑" serial not null
        constraint "👤_pkey"
            primary key,
    "🗓" date,
    "🗣" varchar(64) not null
);

create table if not exists "📕"
(
    "🔑" serial not null
        constraint "📕_pkey"
            primary key,
    "💬" varchar(64) not null,
    "🔖" varchar(64),
    "✍_🔑" integer
        constraint fk6bj8134ailsb7wn0rxoxra7t1
            references "✍"
);

create table if not exists "👤🏠📕"
(
    "👤" integer not null
        constraint fktm4c4ip5pvf57bj4fvq9xb4jk
            references "👤",
    "📕" integer not null
        constraint fkqpp0i83yuug00b7rhkbl55m6d
            references "📕"
);

Et… ça s'arrête là.
Si JPA et Hibernate gèrent très bien ce genre de fantaisie, c'est à peu près les seules bibliothèques dont c'est le cas. Toute tentative d'utiliser SpringBoot et ses outils REST avec des classes au nom aussi exotique se solde par un échec.

Ça vient probablement du fait qu'en interne Java utilise une variante d'UTF-16, et que tout ça implique des caractères que l'on ne peut pas représenter avec un seul bloc de 16 bits.

Et c'est probablement mieux comme ça.


Ce contenu, placé sous licence CC BY 4.0, est une adaptation de ce billet publié sur Zeste de Savoir.


  1. Et qui visiblement ne peut pas s'échapper correctement avec le markdown LinuxFR. 

  • # Unicode

    Posté par  . Évalué à 6.

    Les emojis ne sont que des caractères unicode, donc je n'en suis pas surpris. Le problème c'est oracle java qui a tout un tas soucis avec les caractères unicode.

    • [^] # Re: Unicode

      Posté par  (site web personnel, Mastodon) . Évalué à 2.

      J'ai testé uniquement avec une JVM OpenJDK 11. Si j'y pense, j'essaierai avec une OpenJ9 11 (anciennement IBM, maintenant fondation Eclipse) – mais ça attendra lundi que le PC sur lequel c'est installé soit réparé.

      La connaissance libre : https://zestedesavoir.com

    • [^] # Re: Unicode

      Posté par  (site web personnel, Mastodon) . Évalué à 2.

      D'autre part, au-delà du troll sur Java, je serais curieux de voir le concept poussé dans d'autres langages, pour voir si ça fonctionne vraiment au-delà de la théorie.

      La connaissance libre : https://zestedesavoir.com

      • [^] # Re: Unicode

        Posté par  (site web personnel) . Évalué à 3. Dernière modification le 10 mars 2019 à 09:01.

        En Python 3 les identificateurs se basent sur la classification unicode letter des caractères, ce qui permet d'utiliser caractères accentués, grecs, hiragana… si les emoji ont cette même classification, alors ils sont normalement utilisables.

        Python 3 - Apprendre à programmer dans l'écosystème Python → https://www.dunod.com/EAN/9782100809141

        • [^] # Re: Unicode

          Posté par  (site web personnel) . Évalué à 3.

          Testé avec

          👤=34
          print(👤)

          Ça échoue avec Python 3.6, mais ça tourne avec Python 3.7 (il y a probablement eu une mise à jour dans la table unicode fournie avec le Python).

          Python 3 - Apprendre à programmer dans l'écosystème Python → https://www.dunod.com/EAN/9782100809141

          • [^] # Re: Unicode

            Posté par  (site web personnel, Mastodon) . Évalué à 3.

            Ce qui prouve que Python n'utilise pas la catégorie Unicode Lettre puisque ce caractère, U+1F464 BUST IN SILHOUETTE, a la catégorie Symbole, comme tous les émojis. (Mauvaise idée de Python, à mon avis.)

            • [^] # Re: Unicode

              Posté par  (site web personnel) . Évalué à 8.

              C'est moi qui ai du merder hier, j'ai re-testé et ça ne fonctionne pas avec 👤 (ça marche avec une lettre grecque α).

              Par contre, sur l'aspect autorisation de caractères plus large que les lettres ascii pour les identificateurs, lorsque la discussion a eu lieu sur la liste de développement Python j'étais a priori contre… J'ai changé d'avis suite au post d'un enseignant japonais en primaire qui initiait ses élèves à la programmation avec Python et voulait simplement qu'ils puissent utiliser, pour les identificateurs qu'ils créent, des symboles qui aient un sens pour eux.
              Et finalement, ça ne gène pas les développeurs qui simplement ne les utilisent pas et restent au plus petit dénominateur commun connu dans le métier.

              Python 3 - Apprendre à programmer dans l'écosystème Python → https://www.dunod.com/EAN/9782100809141

          • [^] # Re: Unicode

            Posté par  (site web personnel) . Évalué à 6.

            $ python
            Python 2.7.16 (default, Mar  4 2019, 15:29:09) 
            [GCC 8.3.0] on linux2
            Type "help", "copyright", "credits" or "license" for more information.
            >>> 🐧=42
              File "<stdin>", line 1
                🐧=42
                ^
            SyntaxError: invalid syntax
            
            $ python3
            Python 3.7.2+ (default, Feb 27 2019, 15:41:59) 
            [GCC 8.2.0] on linux
            Type "help", "copyright", "credits" or "license" for more information.
            >>> 🐧=42
              File "<stdin>", line 1
                🐧=42
                ^
            SyntaxError: invalid character in identifier
            
            $ export 🐧=42
            bash: export: « 🐧=42 » : identifiant non valable
            
            $ cat main.c
            int main() {
             int 🐧=42;
             return 🐧;
            }
            $ gcc --version
            gcc (Debian 8.3.0-2) 8.3.0
            Copyright (C) 2018 Free Software Foundation, Inc.
            This is free software; see the source for copying conditions.  There is NO
            warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
            $ gcc main.c 
            main.c: In function ‘main’:
            main.c:2:6: error: stray ‘\360’ in program
              int ����=42;
                  ^
            main.c:2:7: error: stray ‘\237’ in program
              int ����=42;
                   ^
            main.c:2:8: error: stray ‘\220’ in program
              int ���=42;
                    ^
            main.c:2:9: error: stray ‘\247’ in program
              int ��=42;
                     ^
            main.c:2:10: error: expected identifier or ‘(’ before ‘=’ token
              int 🐧=42;
                      ^
            main.c:3:9: error: stray ‘\360’ in program
              return ����;
                     ^
            main.c:3:10: error: stray ‘\237’ in program
              return ����;
                      ^
            main.c:3:11: error: stray ‘\220’ in program
              return ���;
                       ^
            main.c:3:12: error: stray ‘\247’ in program
              return ��;
                        ^
            main.c:3:2: warning: ‘return’ with no value, in function returning non-void
              return 🐧;
              ^~~~~~
            main.c:1:5: note: declared here
             int main() {
                 ^~~~
            
            $ ruby --version
            ruby 2.5.3p105 (2018-10-18 revision 65156) [x86_64-linux-gnu]
            $ irb
            irb(main):001:0> 🐧=42
            => 42
            irb(main):002:0> print 🐧
            42=> nil
            
            $ cat t.pl 
            my $🐧=42;
            print $🐧;
            $ perl --version
            
            This is perl 5, version 28, subversion 1 (v5.28.1) built for x86_64-linux-gnu-thread-multi
            (with 59 registered patches, see perl -V for more detail)
            (...)
            $ perl t.pl 
            Can't use global $� in "my" at t.pl line 1, near "my $�"
            Unrecognized character \x9F; marked by <-- HERE after my $�<-- HERE near column 6 at t.pl line 1.
            
          • [^] # Re: Unicode

            Posté par  (site web personnel) . Évalué à 2. Dernière modification le 11 mars 2019 à 08:42.

            Correction (j'ai du faire une fausse manip hier), ça ne fonctionne pas.

            Python 3 - Apprendre à programmer dans l'écosystème Python → https://www.dunod.com/EAN/9782100809141

    • [^] # Re: Unicode

      Posté par  (site web personnel) . Évalué à 7. Dernière modification le 10 mars 2019 à 08:01.

      Espace et les caractères de ponctuation comme la virgule ou le point sont aussi des caractères unicode. Pourtant, je ne pense pas qu'ils puissent être utilisées comme nom de table ou de colonne.

    • [^] # Re: Unicode

      Posté par  (site web personnel) . Évalué à 10.

      Le problème c'est oracle java qui a tout un tas soucis avec les caractères unicode.

      Je ne suis pas d'accord, certains caractères sont très bien reconnus. La preuve:
      ⚖ 💰 💵 ©

    • [^] # Re: Unicode

      Posté par  . Évalué à 3.

      Le problème c'est oracle java qui a tout un tas soucis avec les caractères unicode.

      Tu en dis trop ou pas assez. Un développement serait le bien venu.

  • # Oui, et ?

    Posté par  . Évalué à 4.

    Salut :)

    C'est bien tout ça, c'est sûr.

    Mais est-ce que les émojis ne pourraient pas être utilisés aussi comme des opérandes ? Ça serait encore plus classe.

    Ah, on me dit dans ma petite oreillette que l'APL a déjà été testé.

    Super zut, encore une idée à mettre à la poubelle.

    Matricule 23415

  • # LOL

    Posté par  . Évalué à 1.

    Alors ça sert à rien, mais en tout cas c'est très drôle !! J'essaie demain :)

  • # Fonctionne avec sqlite, mais pas Mysql/mariadb

    Posté par  (site web personnel) . Évalué à 0. Dernière modification le 02 avril 2019 à 09:43.

    Malheureusement, MySQL et MariaDB ne supportent que les caractères utf-8 sur 3 octets pour les identifiants (noms de tables/noms de colonnes) :
    character_set_system : « The character set used by the server for storing identifiers. The value is always utf8. »

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.