Gibt es ein Firmen-Backend für die Fertigstellung im SQL-Interactive-Modus?

9

Ich verwende sql-interactive-modeund benötige ein Unternehmens-Backend, das SQL-Schlüsselwörter und vorzugsweise auch Spalten- / Tabellennamen der verwendeten Datenbank vervollständigt.

Zu meiner Überraschung gab es noch kein Backend für SQL, als ich mich nach einer Fertigstellung umsah. Ich habe diesen Ausschnitt gefunden , aber das hat nicht richtig funktioniert.

Es ist möglich, dass es noch nicht existiert, und ich könnte ein eigenes Backend für SQL erstellen. Es fällt mir jedoch schwer zu glauben, dass es für eine der gängigsten Sprachen kein Unternehmens-Backend gibt.

ReneFroger
quelle
Das Ausfüllen von Schlüsselwörtern sollte mit einem der diktartigen Backends einfach genug sein. Datenbankspezifische Daten sind viel schwieriger, insbesondere wenn Sie möchten, dass sie für mehr als eine Datenbank
funktionieren
iWenn das Ausfüllen von Schlüsselwörtern einfach genug wäre, haben Sie eine Idee, warum es noch kein SQL-Backend für Company gibt? Und ich stimme Ihnen in letzterem Punkt zu, es wäre schwierig, aber wenn Sie Spalteninhalte in Ihrem Puffer haben, würde es wohl mit vervollständigt werden company-dabbrev?
ReneFroger
Es wäre lediglich ein neuer Eintrag für company-keywords.el, also zögern Sie nicht, einen Beitrag zu leisten! Und ja, das Dabbrev-Backend würde das (und alles andere in Ihrem Puffer)
abfangen

Antworten:

4

Ich hatte ein ähnliches Problem und beschloss, mein eigenes Backend zu erstellen. Eines der vorhandenen Backends (C ++?) Wurde als Vorlage verwendet und ich habe es geändert, um das neue Backend zu erstellen, das sich wie ein Wörterbuch verhält.

In meinem Setup werden SQLi-Puffer automatisch so benannt, dass sie mit der Datenbank übereinstimmen, mit der eine Verbindung hergestellt wird, z. *DB:DBASE1DM*. Das Backend enthält eine Liste für jede Datenbank mit den Schemas, Tabellen und Spalten. Wenn ich etwas vervollständigen möchte, wird der Name des Puffers verwendet, um die richtige Liste der Kandidaten für diese Datenbank zu erhalten.

(defun ry/company-sql-upper-lower (&rest lst)
  (nconc (sort (mapcar 'upcase lst) 'string<) lst))

(defvar ry/company-sql-alist
  `(("DBASE1"               ;; Database name w/o environment suffix.
     "DBASE1DM" "DBASE1UM"  ;; Database name with environment suffix.
     "SCHEMA1" "SCHEMA2"
     "TABLE1" "TABLE2"
     "COLUMN1" "COLUMN2")
    ("DBASE2"
     "DBASE2DM" "DBASE2UM"
     "SCHEMA1" "SCHEMA2"
     "TABLE1" "TABLE2"
     "COLUMN1" "COLUMN2"))
    "Alist mapping sql-mode to candidates.")

(defun ry/company-sql (command &optional arg &rest ignored)
  "`company-mode' back-end for SQL mode based on database name."
  (interactive (list 'interactive))
  (cl-case command
    (interactive (company-begin-backend 'ry/company-sql))
    (prefix (and (assoc (substring (buffer-name (current-buffer)) 4 -3) ry/company-sql-alist)
                 (not (company-in-string-or-comment))
                 (or (company-grab-symbol) 'stop)))
    (candidates
     (let ((completion-ignore-case t)
           (symbols (cdr (assoc (substring (buffer-name (current-buffer)) 4 -3) ry/company-sql-alist))))       
       (all-completions arg (if (consp symbols)
                                symbols
                              (cdr (assoc symbols company-sql-alist))))))
    (sorted t)))

Dies hat den Nachteil, dass es sich nicht um eine intelligente Vervollständigung handelt und dass das Einfügen neuer Datenbanken oder das Vornehmen von Änderungen an vorhandenen Datenbanken ein manueller Vorgang ist. Ein paar Abfragen können verwendet werden, um die Daten zu sammeln, und dann ist es nicht sehr schwierig, sie in das für das Backend erforderliche Format zu massieren.

Die folgende Funktion behandelt das Herstellen einer Verbindung zu einer Datenbank und das Ändern der Namen der Puffer, um sie an die Datenbank anzupassen, mit der eine Verbindung besteht.

(defun ry/sql-open-database (database username password)
  "Open a SQLI process and name the SQL statement window with the name provided."
  (interactive (list
                (read-string "Database: ")
                (read-string "Username: ")
                (read-passwd "Password: ")))
  (let ((u-dbname (upcase database)))
    (setq sql-set-product "db2")

    (sql-db2 u-dbname)
    (sql-rename-buffer u-dbname)
    (setq sql-buffer (current-buffer))
    (sql-send-string (concat "CONNECT TO " database " USER " username " USING " password ";"))

    (other-window 1)
    (switch-to-buffer (concat "*DB:" u-dbname "*"))
    (sql-mode)
    (sql-set-product "db2")
    (setq sql-buffer (concat "*SQL: " u-dbname "*"))))
Jonakand
quelle
Vielen Dank für Ihre Antwort, es wird sehr geschätzt! Ich hatte jedoch einige Schwierigkeiten, als ich Ihre Funktion ausprobierte. Nach dem Hinzufügen zu Firma mit habe (add-to-list 'company-backends 'ry/company-sql) (add-to-list 'company-backends 'ry/company-sql-alist)ich M-x sql-mysqlnach dem Ausprobieren eines Wortes den folgenden Fehler erhalten : Company: An error occurred in auto-begin Args out of range: "*SQL*", 4, -3. Wie könnte ich diese Fehlermeldung interpretieren?
ReneFroger
Ich habe die Antwort so aktualisiert, dass sie die Funktion enthält, mit der ich eine Verbindung zu einer Datenbank herstelle. Es behandelt das Ändern der Puffernamen, um mit der Datenbank übereinzustimmen, die sich auf die Puffer bezieht. Ihr Puffername ist zu kurz, sodass der Teilstring fehlschlägt. Die Teilzeichenfolge wird verwendet, um das *DB:Suffix und umgebung aus dem Puffernamen zu entfernen , um den Datenbanknamen abzurufen, damit die richtige Liste der Vervollständigungen verwendet wird. Die Funktion geht davon aus, dass der Puffername für Vervollständigungen im Formular vorliegt *DB:ACCOUNTSDM*. Der Teilstring würde ACCOUNTSaus dem Puffernamen ziehen .
Jonakand
Danke für deine Antwort. Ich muss eindeutig Lisp lernen, da ich nicht herausfinden konnte, wie ich es ändern könnte, mysqlanstatt db2. Aber Ihr Beitrag wird sehr geschätzt, deshalb habe ich Ihre Antwort bestätigt. Dank dafür.
ReneFroger
Vielleicht sollte diese Antwort zu Emacs beitragen.
Stardiviner