Forums before death by AOL, social media and spammers... "We can't have nice things"
|    comp.os.vms    |    DEC's VAX* line of computers & VMS.    |    264,096 messages    |
[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]
|    Message 262,814 of 264,096    |
|    =?UTF-8?Q?Arne_Vajh=C3=B8j?= to Lawrence D'Oliveiro    |
|    Re: VMS x86-64 database server    |
|    09 Jul 25 20:04:34    |
   
   From: arne@vajhoej.dk   
      
   On 7/9/2025 3:22 AM, Lawrence D'Oliveiro wrote:   
   > On Tue, 8 Jul 2025 20:31:37 -0400, Arne Vajhøj wrote:   
   >> On 7/8/2025 7:37 PM, Lawrence D'Oliveiro wrote:   
   >>> On Tue, 8 Jul 2025 18:20:50 -0400, Arne Vajhøj wrote:   
   >>>> Standards evolve. They add lots of new stuff. And sometimes they   
   >>>> remove stuff that is not needed anymore.   
   >>>   
   >>> But those standards in particular have not evolved.   
   >>   
   >> SQL standard has evolved. Lot of stuff has been added.   
   >   
   > But nothing new in EXEC SQL. For example, did they offer any   
   > equivalent to the following utility functions?   
   >   
   > def sql_string_list(the_list) :   
   > "returns a list containing the quoted items of the_list, suitable" \   
   > " for use in an “in” clause."   
   > return \   
   > "(" + ", ".join([sql_string(s) for s in the_list]) + ")"   
   > #end sql_string_list   
   >   
   > def escape_sql_wild(s, escch) :   
   > "escapes SQL pattern wildcards in s with escch. The same escch   
   needs" \   
   > " to be passed to the ESCAPE clause for the LIKE operator."   
   > if not isinstance(s, str) :   
   > raise TypeError("expecting s to be a string")   
   > #end if   
   > if not isinstance(escch, str) or len(escch) != 1 :   
   > raise TypeError("expecting escch to be a single-character   
   string")   
   > #end if   
   > result = []   
   > for ch in s :   
   > if ch == escch or ch == "%" or ch == "_" :   
   > result.append(escch)   
   > #end if   
   > result.append(ch)   
   > #end for   
   > return "".join(result)   
   > #end escape_sql_wild   
   >   
   > def escape_sql_name(n, escch = "\"") :   
   > "converts n to escaped form to avoid potential conflicts with SQL   
   keywords" \   
   > " and other syntax errors (e.g. from embedded spaces). escch should   
   be “\"”" \   
   > " as per the SQL standard."   
   > assert len(escch) == 1   
   > out = []   
   > for i, split1 in enumerate(n.split(escch)) :   
   > if i != 0 :   
   > out.append(escch * 2)   
   > #end if   
   > out.append(split1)   
   > #end for   
   > return escch + "".join(out) + escch   
   > #end escape_sql_name   
      
   IN is tricky due to the variable number of data.   
      
   But dynamic SQL with dynamic data is still bad.   
      
   I would write your code a little simpler:   
      
   $ type dyn.py   
   import sqlite3   
      
   def esc(s):   
    return "''".join(s.split("'"))   
      
   def q(s):   
    return f"'{s}'"   
      
   def dump_range(con, vals):   
    jvals = ",".join(q(esc(val)) for val in vals)   
    c = con.cursor()   
    c.execute(f"SELECT f1,f2 FROM t1 WHERE f2 IN ({jvals})")   
    for row in c.fetchall():   
    print('%d %s' % (row[0], row[1]))   
      
   with sqlite3.connect('test.db') as con:   
    dump_range(con, ['A', 'CCC', 'EEEEE'])   
    dump_range(con, ['BB', 'DDDD'])   
   $ python dyn.py   
   1 A   
   3 CCC   
   5 EEEEE   
   2 BB   
   4 DDDD   
      
   But it is both simpler and safer to use dynamic SQL   
   with just dynamic non-data:   
      
   $ type sta.py   
   import sqlite3   
      
   def dump_range(con, vals):   
    jparm = ",".join('?' for val in vals)   
    c = con.cursor()   
    c.execute(f"SELECT f1,f2 FROM t1 WHERE f2 IN ({jparm})", vals)   
    for row in c.fetchall():   
    print('%d %s' % (row[0], row[1]))   
      
   with sqlite3.connect('test.db') as con:   
    dump_range(con, ['A', 'CCC', 'EEEEE'])   
    dump_range(con, ['BB', 'DDDD'])   
   $ python sta.py   
   1 A   
   3 CCC   
   5 EEEEE   
   2 BB   
   4 DDDD   
      
   It is even more tricky in embedded SQL, but of course   
   it is possible.   
      
   You can do the same solution with dynamic SQL with just   
   dynamic non-data by using EXEC SQL with PREPARE and EXECUTE   
   (that requires you to use SQLDA).   
      
   Possible but requires some code.   
      
   Easier to use a LOCAL TEMPORARY TABLE and stay static.   
      
   Cobol Rdb example:   
      
   $ type emb.sco   
   identification division.   
   program-id. emb.   
   *   
   data division.   
   working-storage section.   
   EXEC SQL BEGIN DECLARE SECTION END-EXEC   
   EXEC SQL INCLUDE SQLCA END-EXEC.   
   01 con pic x(255).   
   01 f1 pic 9(9) display.   
   01 f2 pic x(50).   
   01 inclause.   
   03 nvals pic 9(9).   
   03 vals pic x(50) occurs 100 times.   
   01 i pic 9(9) comp.   
   EXEC SQL END DECLARE SECTION END-EXEC   
   EXEC SQL DECLARE curs CURSOR FOR SELECT f1,f2 FROM t1 WHERE f2 IN   
   (SELECT f2 FROM f2list) END-EXEC.   
      
   procedure division.   
   main-paragraph.   
    move "FILENAME disk4:[rdb]test" to con   
    EXEC SQL CONNECT TO :con END-EXEC   
    move 2 to nvals   
    move "BB" to vals(1)   
    move "CCC" to vals(2)   
    perform dump-range-paragraph   
    move 2 to nvals   
    move "A" to vals(1)   
    move "BB" to vals(2)   
    perform dump-range-paragraph   
    stop run.   
   dump-range-paragraph.   
    perform varying i from 1 by 1 until i > nvals   
    move vals(i) to f2   
    EXEC SQL INSERT INTO f2list VALUES(:f2) END-EXEC   
    end-perform   
    EXEC SQL OPEN curs END-EXEC   
    move 0 to SQLCODE   
    perform until not SQLCODE = 0   
    EXEC SQL FETCH curs INTO :f1, :f2 END-EXEC   
    if SQLCODE = 0   
    display f1 " " f2   
    end-if   
    end-perform   
    EXEC SQL CLOSE curs END-EXEC   
    EXEC SQL DELETE FROM f2list END-EXEC.   
   $ sqlpre /cob /sqloptions=connect emb   
   $ link emb + sys$library:sql$user73/libr   
   $ run emb   
   000000002 BB   
   000000003 CCC   
   000000001 A   
   000000002 BB   
      
   It could probably be done better by a real Cobol   
   programmer, but ...   
      
   Arne   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   
|
[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]
(c) 1994, bbs@darkrealms.ca