source: tol/tolbase/lib/byswidget/bfunctions/bfsql.tcl

devel
Last change on this file was 87b1c46, checked in by Pedro Gea <pgea@…>, 10 years ago

Refs #1933
Se sustituye BLT por RBC.
Se prescinde de otros widgets no usados, dependientes de BLT. (Véanse loadByswidget.tcl y pkgIndex.tcl)

git-svn-id: ​https://www.tol-project.org/svn/tolp/trunk@7340 be4846ae-f051-483a-831f-b64e7d08527f

  • Property mode set to 100644
File size: 15.1 KB
Line 
1#/////////////////////////////////////////////////////////////////////////////
2# FILE    : bfsql.tcl -> Sql
3# PURPOSE : Bayes Function SQL
4#/////////////////////////////////////////////////////////////////////////////
5
6#///////////////////////////////////////////////////////////////////////////
7proc Sql2Tol { typ } {
8#
9# PURPOSE: For a SQL type returns its equivalent in TOL
10#
11#///////////////////////////////////////////////////////////////////////////
12  set typ [string tolower $typ]
13   
14  switch $typ {
15    "char" -
16    "varchar" -
17    "varchar2" -
18    "bpchar" -
19    "long" {
20      return "Text"
21    }
22    "int" -
23    "number" -
24    "decimal" -
25    "numeric" -
26    "float" -
27        "float8" -
28    "real" -
29    "bit" -
30    "integer" -
31    "money" -
32    "smallmoney" -
33    "tinyint" -
34    "double" {
35      return "Real"
36    }
37    "date" -
38    "datetime" -
39    "smalldatetime" {
40      return "Date"
41    }
42    default {
43      return "Unknown"
44    }
45  }
46}   
47
48#///////////////////////////////////////////////////////////////////////////
49proc NumSql2Tol { typ } {
50#
51# PURPOSE: For a numerical SQL type returns its equivalent in TOL
52#
53#///////////////////////////////////////////////////////////////////////////
54  switch {$typ} {
55    1 - 12 {
56      return "Text"
57    }
58    2 - 3 - 4 - 5 - 6 - 7 - 8 {
59      return "Real"
60    }
61    9 - 10 - 11 {
62      return "Date"
63    }
64    default {
65      return "Text"
66    }
67  }
68}   
69
70#///////////////////////////////////////////////////////////////////////////
71proc SqlListBfilter { db table } {
72#
73# PURPOSE: Creates the list to fill bfilter with all the columns of the
74#          given table.
75#
76#///////////////////////////////////////////////////////////////////////////
77  set cols [$db columns $table]
78  set res {}
79  foreach col $cols {
80    set name [lindex $col 3]
81    set typ [Sql2Tol [lindex $col 5]]
82    set func [list "TolGetFieldValues $table $name $db"]
83    set mcname [mc $name]
84    lappend res "$name $typ {} $func $mcname"
85  }
86  return $res
87}
88
89
90#///////////////////////////////////////////////////////////////////////////
91proc SqlGetDriver {alias} {
92#
93# PURPOSE: Devuelve el driver utilizado por una conexión tclODBC dado el
94#          alias (datasource name).
95#
96#///////////////////////////////////////////////////////////////////////////
97  set driver ""
98  set lst [database datasources]
99  foreach ite $lst {
100    set name [lindex $ite 0]
101    if {$name eq $alias} {
102      set driver [lindex $ite 1]
103      break
104    }
105  }
106  return $driver
107}
108
109#///////////////////////////////////////////////////////////////////////////
110proc SqlGetGestor {driver} {
111#
112# PURPOSE: Devuelve el gestor de una conexión tclODBC dado el driver
113#          TODO: Verificar y ampliar con más drivers
114#
115# RETURNS: Devuelve un identificador de Gestor de Base de Datos o vacio
116#    Mic -> Sql Server
117#    Ora -> Oracle
118#
119#///////////////////////////////////////////////////////////////////////////
120  set gestor ""
121
122  switch -regexp $driver  {
123    SQL.Server   { set gestor Mic }
124    Oracle*      { set gestor Ora }
125    MySql -       
126    MySQL        { set gestor Mys }
127    Postgre*     { set gestor Pos }
128    TDS          { set gestor Mic }
129  }
130  return $gestor
131}
132
133#///////////////////////////////////////////////////////////////////////////
134proc SqlGetTolGestor {gestor} {
135#
136# PURPOSE: Devuelve el gestor asociado a TOL equivalente a gestor TCL
137#          devuelto por la función SqlGetGestor
138#
139#///////////////////////////////////////////////////////////////////////////
140  set tolGestor -1
141  switch $gestor {
142    Mic {set tolGestor 0}
143    Ora {set tolGestor 1}
144    Mys {set tolGestor 2}
145    Acc {set tolGestor 3}
146    Pos {set tolGestor 4}
147  }
148  return $tolGestor
149}
150
151#///////////////////////////////////////////////////////////////////////////
152proc SqlValidateData {P typFie} {
153#
154# PURPOSE: Verifies that a given value observes the rules of a data type
155#
156# PARAMETERS:
157#   P      : value to verify
158#   typFie : data type
159#
160# RETURN: 1 -> OK, 0 -> NO
161#
162#///////////////////////////////////////////////////////////////////////////
163  #Tolcon_Trace "SqlValidateData: Valor: $P   Tipo: $typFie"
164  set ok 1
165  # si no hay ningun caracter no comprobamos
166  if {![string length $P]} {
167    return $ok
168  }
169  # ralizamos las comprobacines
170  set sepDec {.}
171  set typeField [string tolower [lindex $typFie 0]]
172  set lonField  [string tolower [lindex $typFie 1]]
173  #Tolcon_Trace "SqlValidateData: typeField: $typeField   lonField: $lonField" 
174  switch $typeField {
175    # Integers
176    "bigint" {
177      # Datos enteros (números enteros) comprendidos entre -2^63
178      # (-9223372036854775808) y 2^63 -1 (9223372036854775807).
179      set ok [expr {([string match {[-+]} $P] || [string is int $P]) && \
180                    $P>=[expr pow(-2,63)] && $P<=[expr pow(2,63)]}]
181    }
182    "int" {
183      #Datos enteros (números enteros) comprendidos entre -2^31
184      # (-2.147.483.648) y 2^31 - 1 (2.147.483.647).
185      set ok [expr {([string match {[-+]} $P] || [string is int $P]) && \
186                     $P>=[expr pow(-2,31)] && $P<=[expr pow(2,31)]}]
187    }
188    "smallint" {
189      #Datos enteros comprendidos entre 215 (-32.768) y 215 - 1 (32.767).
190      set ok [expr {([string match {[-+]} $P] || [string is int $P]) && \
191                     $P>=-32768 && $P<=32767}]
192    }
193    "tinyint" {
194      #Datos enteros comprendidos 0 y 255.
195      set ok [expr {([string is int $P]) && $P>=0 && $P<=255}]
196    }
197    "bit" {
198      #Datos enteros con valor 1 ó 0
199      set ok [expr {$P==0 || $P==1}]
200    }
201    # Decimal y numeric
202    "number"   -
203    "decimal"  -
204    "numeric" {
205      #Datos de precisión y escala numérica fijas comprendidos
206      # entre -10^38 +1 y 10^38 - 1. Hay que tener encuante la escala y la
207      # precision
208      if {[string length $lonField]} {
209        set lst [split $lonField ,]
210        set sca [expr [lindex $lst 1] + 0]
211        set pre [expr [lindex $lst 0] - $sca]
212        set lst [split $P $sepDec]
213        set np  [string length [lindex $lst 0]]
214        set ns  [expr [llength $lst] == 1 ? 0 : [string length [lindex $lst 1]]]
215        set ok [expr {[string is double $P] && $pre>=$np && $sca>=$ns}]
216      } else  {
217        set ok [expr {[string is double $P] && \
218                      $P>=[expr pow(-10,37) + 1] && \
219                      $P<=[expr pow(10,37)  - 1]}]
220      }
221    }
222    # money y smallmoney
223    "money" {
224      #Valores de moneda comprendidos entre -263 (-922.337.203.685.477,5808)
225      # y 263 - 1 (+922.337.203.685.477,5807), con una precisión de una
226      # diezmilésima de la unidad monetaria. El tamaño es de 8 bytes.
227      set lst [split $P $sepDec]
228      set np  [string length [lindex $lst 0]]
229      set ns  [expr [llength $lst] == 1 ? 0 : [string length [lindex $lst 1]]]
230      set ok [expr ([string is double $P] && 19>=$np && 4>=$ns)]
231    }
232    "smallmoney" {
233      #Valores de moneda comprendidos entre - 214.748,3648 y +214.748,3647,
234      # con una precisión de una diezmilésima de la unidad monetaria.
235      # El tamaño de almacenamiento es 4 bytes.
236      set lst [split $P $sepDec]
237      set np  [string length [lindex $lst 0]]
238      set ns  [expr [llength $lst] == 1 ? 0 : [string length [lindex $lst 1]]]
239      set ok [expr ([string is double $P] && 10>=$np && 4>=$ns)]
240    }
241    # Numéricos con aproximación
242    "float" -
243        "float8" {
244      #Un número de punto flotante es un valor comprendido entre
245      # -1.79E + 308 y 1.79E + 308. n es el número de bits que se
246      # utilizan para almacenar la mantisa del número float en notación
247      # científica y por tanto dicta su precisión y el tamaño de almacenamiento.
248      # n tiene que ser un valor entre 1 y 53.
249      set ok [expr {([string match {[-+]} $P] || [string is double $P]) && \
250                     $P>=[expr -1.79 * pow(10,308)] && \
251                     $P<=[expr  1.79 * pow(10,308)]}]
252    }
253    "real" {
254      #Datos numéricos de punto flotante entre –3.40E + 38 y 3.40E + 38.
255      # El tamaño de almacenamiento es 4 bytes. En SQL Server, el sinónimo
256      # de real es float(24).
257      set ok [expr {([string match {[-+]} $P] || [string is double $P]) && \
258                     $P>=[expr -3.40 * pow(10,38)] && \
259                     $P<=[expr  3.40 * pow(10,38)]}]
260    }
261    # datetime y smalldatetime
262    "date" -
263    "datetime"  -
264    "smalldatetime" {
265      #TODO: Tienen su propio componente
266    }
267    # Cadenas de caracteres
268    "char"     -
269    "varchar"  -
270    "varchar2" -
271    "bpchar"   -
272    "text" {
273      if {[string length $lonField]} {
274        set ok [expr ([string len $P]<=$lonField)]
275      }
276    }
277    "nchar"     -
278    "nvarchar"  -
279    "ntext" {
280    # Cadenas de caracteres Unicode
281      if {[string length $lonField]} {
282        set ok [expr ([string len $P]<=$lonField)]
283      }
284    }
285    "binary"     -
286    "varbinary"  -
287    "image" {
288    # Cadenas binarias
289      # TODO: de momento no es posible editar estos campos
290    }
291    default {puts "SqlValidateData:\n\
292                   WARNING: Tipo no reconocido $typeField"}
293  }
294  return $ok
295}
296
297
298#///////////////////////////////////////////////////////////////////////////
299  proc SqlFormatField {value type gestor {format ""}} {
300# PURPUSE: Formatea un campo field, en función del tipo de dato que sea
301#          para su uso en un gestor de BBDD dado por gestor
302#
303# PARAMETERS:
304#   value  -> Valor a formatear
305#   type   -> Tipo de datos (BBDD) del campo cuyo valor se va a formatear
306#   gestor -> Gestor de BBDD para el que se formatea.
307#                Ora -> Oracle, Mic -> SqlServer
308#   format -> Especificador de formato especial. Por ejemplo para los
309#             campos de tipo fecha, pueden utilizarse formatos especiales.
310#             No implementado por el momento
311#
312# RETURNS: Valor del campo formateado   
313#
314#///////////////////////////////////////////////////////////////////////////
315  set valFor ""
316  if {[string tolower $value] eq "null"} {
317    set valFor $value
318  } else {
319    set typeField [string tolower [lindex $type 0]]
320    Tolcon_Trace "typeField --> $typeField"
321    Tolcon_Trace "type --> $type"
322    switch $typeField {
323      "bigint"     -
324      "int"        -
325      "smallint"   -
326      "tinyint"    -
327      "int4"   -
328      "bit"        -
329      "number"     -
330      "decimal"    -
331      "numeric"    -
332      "money"      -
333      "smallmoney" -
334      "float"      -
335          "float8"     -
336      "double"     -
337      "real"       { set valFor $value }
338      "date"       -
339      "datetime"   -
340      "smalldatetime" {
341        switch $gestor {
342          "Mic" { set valFor "convert(datetime,'${value}',121)"            }
343          "Ora" { set valFor "to_date('${value}','YYYY-MM-DD HH24:MI:SS')" }
344          "Pos" { set valFor "to_date('${value}','YYYYMMDD HH24:MI:SS')" }
345          "Mys" { set valFor "str_to_date('${value}','%Y%m%d %H:%i:%s')" }
346          default { error "Gestor no implementado $gestor"  }
347        }
348      }
349      "char"       -
350      "varchar"    -
351      "bpchar"     -
352      "varchar2"   -
353      "text"       -
354      "nchar"      -
355      "nvarchar"   -
356      "ntext"      { set valFor '${value}' }
357      "binary"     -
358      "varbinary"  -
359      "image"      { set valFor $value  }
360      default      { error "SqlFormatField:\n\ERROR: Tipo no reconocido $type"}
361    }
362  }
363 
364  Tolcon_Trace "valFor --> $valFor" 
365  return $valFor
366}
367
368#///////////////////////////////////////////////////////////////////////////
369  proc SqlGetDelimeterField {type} {
370# PURPUSE: Comprobamos el tipo de un campo e indicamos si sus valores deben
371#          ir precedidos por algun caracter especial. Por ejemplo los textos
372#          van entre comillas, los numeros no cesesitan comillas
373#          TODO: Igual hay que usar las las funciones de TOL
374#
375# RETURN: El texto a concatenar a al valor del campo
376#
377#///////////////////////////////////////////////////////////////////////////
378#puts "SqlGetDelimeterField: $type"
379  set delimeter {}
380  set typeField [string tolower [lindex $type 0]]
381  switch $typeField {
382    # Integers
383    "bigint"   -
384    "int"      -
385    "smallint" -
386    "int4" -
387    "tinyint" {
388      # no necesita ningun delimitador
389    }
390    # bit
391    "bit" {
392      # no necesita ningun delimitador
393    }
394    # Decimal y numeric
395    "number"   -
396    "decimal"  -
397    "numeric" {
398      # no necesita ningun delimitador
399    }
400    # money y smallmoney
401    "money"  -
402    "smallmoney" {
403      # no necesita ningun delimitador
404    }
405    # Numéricos con aproximación
406    "float"  -
407        "float8" -
408    "real" {
409      # no necesita ningun delimitador
410    }
411    # datetime y smalldatetime
412    "date" -
413    "datetime"  -
414    "smalldatetime" {
415      set delimeter {' '}
416      set gestor [string trim [TclGetVar Text DBA] {"}];#"
417      switch $gestor {
418        "SqlServer" {
419          set delimeter {{convert(datetime,'} {',121)}}       
420        }
421        "Oracle" {
422          set delimeter {{to_date('} {','YYYY-MM-DD HH24:MI:SS')}}       
423        }
424        "Pos" {
425          set delimeter {{to_date('} {','YYYYMMDD HH24:MI:SS')}}       
426        }
427        default { error "Variable DBA (Gestor) not defined"  }
428      }
429     }
430    # Cadenas de caracteres
431    "char"     -
432    "varchar"  -
433    "bpchar"   -
434    "varchar2" -
435    "bpchar"   -
436    "text" {
437      set delimeter {' '}
438    }
439    # Cadenas de caracteres Unicode
440    "nchar"     -
441    "nvarchar"  -
442    "ntext" {
443      set delimeter {' '}
444    }
445    # Cadenas binarias
446    "binary"     -
447    "varbinary"  -
448    "image" {
449      # TODO: de momento no es posible editar estos campos
450    }
451    default { error "SqlGetDelimeterField:\n\
452                   WARNING: Tipo no reconocido $typeField"}
453  }
454  #puts "SqlGetDelimeterField: $delimeter"
455  return $delimeter
456}
457
458
459#///////////////////////////////////////////////////////////////////////////
460  proc DBQuery {bodbc args} {
461# PURPUSE: Execute query witch bodbc module
462# PARAMETERS:
463#   bodbc -> name of bodbc module
464#   args  -> arguments of database query
465
466#
467#///////////////////////////////////////////////////////////////////////////
468  # name connection TCL
469  set connection [$bodbc cget -connection]
470  # connection ?
471  $::project::data(bodbc) validateconnection [$bodbc cget -name] 
472  # run
473  eval DBQueryConnection $connection $args
474} 
475
476
477#///////////////////////////////////////////////////////////////////////////
478  proc DBQueryConnection {connection args} {
479# PURPUSE: Execute query witch database connection
480# PARAMETERS:
481#   connection -> name of database connection
482#   args       -> arguments of database query
483#
484#///////////////////////////////////////////////////////////////////////////
485  #NOTE:  move traces to "DBQuery"
486  . configure -cursor watch
487  ::rbc::busy hold .
488  set lst {}
489  Tolcon_Trace "IniQuery: \
490    [clock format [clock seconds] -format "%Y%m%d %T"]:\n[lindex $args 0]"
491  if {([info exists ::project::data(SqlTra)]) && \
492      ($::project::data(SqlTra))} {
493    ::TolConsole::HciWriter \
494      "\nIniQuery. [clock format [clock seconds] -format "%Y%m%d %T"]:\n\
495      [lindex $args 0]"
496  }
497  # eval
498  if { [catch { set lst [eval $connection $args] } result ] } {
499    ShowMessage E $result .
500  } 
501  # trace
502  if {([info exists ::project::data(SqlTra)]) && \
503      ($::project::data(SqlTra))} {
504    ::TolConsole::HciWriter \
505      "\nEndQuery. [clock format [clock seconds] -format "%Y%m%d %T"]"
506  }
507  Tolcon_Trace "EndQuery: [clock format [clock seconds] -format "%Y%m%d %T"]"
508  . configure -cursor ""
509  ::rbc::busy release .
510  update
511  return $lst
512}
513
514
Note: See TracBrowser for help on using the repository browser.