PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Convertire rapidamente da array Python a PostgreSQL?

Configurazione

Vuoi creare trigger (ripetutamente?) utilizzando la stessa funzione di trigger come descritto in la mia risposta correlata su dba.SE . Devi passare i valori alla funzione trigger per creare multipli righe con più valori di colonna, da cui l'array bidimensionale. (Ma possiamo lavorare con qualsiasi stringa chiaramente definita!)

L'unico modo per passare valori a una funzione trigger PL/pgSQL (diversa dai valori di colonna della riga di trigger) è text parametri, accessibili all'interno della funzione come 0- array di testo basato nella variabile array speciale TG_ARGV[] . Puoi passare un numero variabile di parametri, ma in precedenza abbiamo discusso di una singola stringa letterale che rappresenta il tuo array bidimensionale.

L'input proviene da un array Python bidimensionale con numero intero con segno numeri, che rientra nel tipo Postgres integer . Usa il tipo Postgres bigint per coprire i numeri interi senza segno, come ha commentato .

La rappresentazione del testo in Python è simile a questa:

[[1,2],[3,4]]

Sintassi per un array di Postgres letterale:

{{1,2},{3,4}}

E vuoi automatizzare il processo.

Automazione completa

Puoi concatenare la stringa per CREATE TRIGGER istruzione nel tuo client oppure puoi persistere la logica in una funzione lato server e passare semplicemente i parametri.

Dimostrazione di una funzione di esempio che prende il nome di una tabella e la stringa passata alla funzione trigger. La funzione di attivazione insaft_function() è definito nella tua domanda precedente su dba.SE .

CREATE OR REPLACE FUNCTION f_create_my_trigger(_tbl regclass, _arg0 text)
  RETURNS void
  LANGUAGE plpgsql AS
$func$
BEGIN
   EXECUTE format($$
      DROP TRIGGER IF EXISTS insaft_%1$s_ids ON %1$s;
      CREATE TRIGGER insaft_%1$s_ids
      AFTER INSERT ON %1$s
      FOR EACH ROW EXECUTE PROCEDURE insaft_function(%2$L)$$
                , _tbl
                , translate(_arg0, '[]', '{}')
      );
END 
$func$;

Chiama:

SELECT f_create_my_trigger('measurements', '[[1,2],[3,4]]');

Oppure:

SELECT f_create_my_trigger('some_other_table', '{{5,6},{7,8}}');

db<>violino qui
Vecchio sqlfiddle

Ora puoi passare [[1,2],[3,4]] (tra parentesi quadre) o {{1,2},{3,4}} (con parentesi graffe). Entrambi funzionano allo stesso modo. translate(_arg0, '[]', '{}' trasforma la prima nella seconda forma.

Questa funzione rilascia un trigger con lo stesso nome se esiste, prima di crearne uno nuovo. Potresti voler eliminare o mantenere questa riga:

DROP TRIGGER IF EXISTS insaft_%1$s_ids ON %1$s;

Questo viene eseguito con i privilegi del ruolo DB chiamante. Potresti farlo funzionare con i privilegi di superutente (o qualsiasi altro), se necessario. Vedi:

Ci sono molti modi per raggiungere questo obiettivo. Dipende dai requisiti esatti.

Spiegare format()

format() e il tipo di dati regclass aiuta a concatenare in modo sicuro il comando DDL e rendere impossibile l'iniezione SQL. Vedi:

Il primo argomento è la "stringa di formato", seguita dagli argomenti da incorporare nella stringa. Uso citazione del dollaro , che non è strettamente necessario per l'esempio, ma generalmente è una buona idea per concatenare stringhe lunghe contenenti virgolette singole:$$DROP TRIGGER ... $$

format() è modellato sulla funzione C sprintf . %1$s è un identificatore di formato del format() funzione. Significa che il primo (1$ ) argomento dopo che la stringa di formato è stata inserita come stringa senza virgolette (%s ), quindi:%1$s . Il primo argomento da formattare è _tbl nell'esempio - il regclass parametro viene visualizzato automaticamente come identificatore legale, se necessario tra virgolette doppie, quindi format() non deve fare di più. Quindi solo %s , non %I (identificatore). Leggi la risposta collegata sopra per i dettagli.
L'altro identificatore di formato in uso è %2$L :Secondo argomento come stringa letterale tra virgolette .

Se non conosci format() , gioca con questi semplici esempi per capire:

SELECT format('input -->|%s|<-- here', '[1,2]')
     , format('input -->|%s|<-- here', translate('[1,2]', '[]', '{}'))
     , format('input -->|%L|<-- here', translate('[1,2]', '[]', '{}'))
     , format('input -->|%I|<-- here', translate('[1,2]', '[]', '{}'));

E leggi il manuale .