2017-07-05 2 views
0

La fusion de Python et de SQL dans MonetDB est un bon début pour déplacer une grande partie de la logique métier dans le serveur de base de données. Cependant, la documentation actuelle contient quelques obstacles à franchir par un novice dans ce jeu. Considérez la fonction suivante:Gestion des UDF Python dans MonetDB

sql>select * from getsourceattributes('tables'); 
+---------------+ 
| c    | 
+===============+ 
| id   | 
| name   | 
| schema_id  | 
| query   | 
| type   | 
| system  | 
| commit_action | 
| access  | 
| temporary  | 
+---------------+ 

et le tableau suivant pour recueillir quelques statistiques:

create table dummy(tbl string, col string, stat integer); 

savoir Maintenant que PTBL est un tableau numpy, j'ai essayé les éléments suivants:

create function gatherStatistics(ptbl string) 
returns string 
language python { 
    for p in ptbl: 
     attr = _conn.execute("select * from getSourceAttributes('"+ str(p) +"');") 
     for col in attr : 
      stat = _conn.execute("select count(*) from "+ str(p) +";") 
      _conn_execute("insert into dummy values('"+ str(p)+"','"+ str(col) +"',"+ str(stat)+");") 
    return ptbl; 
}; 

et appeler avec

select gatherstatistics('tables'); 
SELECT: no such table 't' 
Python exception 
    3.  attr = _conn.execute("select * from getSourceAttributes('"+ str(p) +"');") 
    4.  for col in attr : 

    5.  stat = _conn.execute("select count(*) from "+ str(p) +";") 

    6.  _conn_execute("insert into dummy values('"+ str(p)+"','"+ str(col) +"',"+str(stat)+");") 
    7. return ptbl; 
SQL Query Failed: ParseException:SQLparser:42S02!SELECT: no such table 't' 
  • ne sait pas d'où vient le 't'?
  • Quelle est la mauvaise conception?

Répondre

0

Le problème que vous avez, c'est que vous traitez une chaîne scalaire comme un tableau. Vous appelez SELECT gatherstatistics ('tables'); et passez en revue les valeurs de ptbl. Dans ce cas, vous itérez sur les caractères de la chaîne 'tables', le premier étant le caractère 't'. Les variables des UDF Python sont converties en (1) tableaux NumPy, si la fonction est appelée avec une colonne en entrée, ou (2) valeurs scalaires, si la fonction est appelée avec une valeur scalaire en entrée.

Tenir compte de la fonction suivante, qui renvoie le type de ses paramètres d'entrée comme une chaîne:

CREATE FUNCTION get_type(s STRING) 
RETURNS STRING 
LANGUAGE PYTHON 
{ 
    return str(type(s)) 
}; 

Maintenant, si nous interrogeons à l'aide d'une valeur scalaire, nous obtenons le résultat suivant:

SELECT get_type('hello'); 
+------------------+ 
| L2    | 
+==================+ 
| <type 'unicode'> | 
+------------------+ 

Mais si nous l'interroger avec une colonne, nous obtenons la sortie suivante:

SELECT get_type(name) FROM tables; 
+------------------------+ 
| L40     | 
+========================+ 
| <type 'numpy.ndarray'> | 
+------------------------+ 

Généralement vous créez une fonction qui n'accepte qu'une entrée valide pour un paramètre donné. Par exemple, vous pouvez créer une fonction appelée log qui prend en entrée un tableau de valeurs numériques et une base scalaire pour le logarithme.

Si vous souhaitez créer une fonction qui fonctionne à la fois sur des valeurs scalaires et des valeurs de tableau, un moyen simple consiste à vérifier le type des paramètres d'entrée. Si ce n'est pas un tableau NumPy, nous le convertissons en un.

Par exemple, considérons la fonction suivante qui inverse une chaîne et fonctionne sur les deux tableaux et valeurs scalaires:

CREATE OR REPLACE FUNCTION reverse_string(s STRING) 
RETURNS STRING 
LANGUAGE PYTHON 
{ 
    if not isinstance(s, numpy.ndarray): 
     s = numpy.array([s]) 
    return [x[::-1] for x in s] 
}; 
SELECT reverse_string('hello'); 
+-------+ 
| L2 | 
+=======+ 
| olleh | 
+-------+ 
SELECT reverse_string(name) FROM tables LIMIT 3; 
+-----------+ 
| L40  | 
+===========+ 
| samehcs | 
| sepyt  | 
| snoitcnuf | 
+-----------+