Esiste un back-end aziendale per il completamento in modalità interattiva SQL?


9

Sto utilizzando sql-interactive-modee ho bisogno di back-end aziendali che completino le parole chiave SQL e, preferibilmente, anche i nomi di colonne / tabelle del database utilizzato.

Quando mi guardo intorno per qualsiasi completamento, con mia sorpresa, non esiste ancora un backend per SQL. Ho trovato questo frammento , ma non ha funzionato correttamente.

È possibile che non esista ancora e potrei creare un proprio backend per SQL. Ma trovo difficile credere che non esiste un backend aziendale per una delle lingue più comuni.


Il completamento delle parole chiave dovrebbe essere abbastanza semplice con uno dei backend simil-simili. I dati specifici del database sono molto più difficili, specialmente se si desidera che funzioni per più di un database ...
wasamasa,

Se il completamento delle parole chiave sarebbe abbastanza semplice, hai idea del perché non esiste ancora un back-end SQL per l'azienda? E sono d'accordo con te su quest'ultimo, sarebbe difficile, ma quando hai contenuti di colonna nel tuo buffer, sarebbe completo con company-dabbrevimmagino?
ReneFroger,

Sarebbe semplicemente una nuova voce company-keywords.el, quindi sentiti libero di contribuire! E sì, il backend dabbrev lo avrebbe catturato (e tutto il resto nel buffer) ...
wasamasa,

Risposte:


4

Ho avuto un problema simile e ho deciso di creare il mio backend. Uno dei backend esistenti (C ++?) È stato utilizzato come modello e l'ho modificato per creare il nuovo back-end che si comporta come un dizionario.

Nella mia configurazione, i buffer SQLi vengono automaticamente denominati in modo da corrispondere al database a cui si è connessi, ad es. *DB:DBASE1DM*. Il backend contiene un elenco per ciascun database con schemi, tabelle e colonne. Quando voglio completare qualcosa, il nome del buffer viene utilizzato per ottenere l'elenco corretto dei candidati per quel database.

(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)))

Questo ha il rovescio della medaglia che non è un completamento intelligente e che includere nuovi database o apportare modifiche ai database esistenti è un processo manuale. Un paio di query possono essere utilizzate per raccogliere i dati e quindi non è molto difficile massaggiarli nel formato necessario per il back-end.

La funzione seguente gestisce la connessione a un database e la modifica dei nomi dei buffer in modo che corrispondano al database a cui è connesso.

(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 "*"))))

grazie per la tua risposta, è davvero apprezzato! Tuttavia, ho avuto delle difficoltà nel provare la tua funzione. Dopo aver aggiunto alla società con (add-to-list 'company-backends 'ry/company-sql) (add-to-list 'company-backends 'ry/company-sql-alist), ho ottenuto il seguente errore nel M-x sql-mysqldopo aver provato una parola: Company: An error occurred in auto-begin Args out of range: "*SQL*", 4, -3. Come potrei interpretare questo messaggio di errore?
ReneFroger,

Ho aggiornato la risposta per includere la funzione che utilizzo per connettermi a un database. Gestisce la modifica dei nomi dei buffer in modo che corrispondano al database correlato ai buffer. Il nome del buffer è troppo corto, pertanto la sottostringa non funziona. La sottostringa viene utilizzata per rimuovere il *DB:suffisso ambiente e dal nome del buffer per ottenere il nome del database in modo da utilizzare l'elenco corretto di completamenti. La funzione presuppone che il nome del buffer per i completamenti sarà nel modulo *DB:ACCOUNTSDM*. La sottostringa verrebbe estratta ACCOUNTSdal nome del buffer.
Jonakand,

Grazie per la tua risposta. Ho chiaramente bisogno di imparare Lisp, dal momento che non riuscivo a capire come avrei potuto modificarlo mysqlinvece di db2. Ma il tuo contributo è molto apprezzato, quindi ho convalidato la tua risposta. Grazie per quello
ReneFroger,

Forse questa risposta dovrebbe contribuire a Emacs.
Stardiviner il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.