Project

General

Profile

« Previous | Next » 

Revision 3431

sql_io.py: put_table(): Added optimization for only literal values, which does the same operations as put() but with the additional error handling of put_table()

View differences:

sql_io.py
1 1
# Database import/export
2 2

  
3
import operator
4

  
3 5
import exc
4 6
import dicts
5 7
import sql
......
256 258
    if mapping == {}: # need at least one column for INSERT SELECT
257 259
        mapping = {out_pkey: None} # ColDict will replace with default value
258 260
    
259
    # Create input joins from list of input tables
260 261
    in_tables_ = in_tables[:] # don't modify input!
261 262
    in_tables0 = in_tables_.pop(0) # first table is separate
262
    errors_table_ = errors_table(db, in_tables0)
263 263
    in_pkey = sql.pkey(db, in_tables0, recover=True)
264 264
    in_pkey_col = sql_gen.as_Col(in_pkey, in_tables0)
265
    
266
    # Determine if can use optimization for only literal values
267
    is_literals = not reduce(operator.or_, map(sql_gen.is_table_col,
268
        mapping.values()))
269
    is_literals_or_function = is_literals or is_function
270
    
271
    if is_literals:
272
        in_tables0 = None
273
        errors_table_ = None
274
    else:
275
        errors_table_ = errors_table(db, in_tables0)
276
    
277
    # Create input joins from list of input tables
265 278
    input_joins = [in_tables0]+[sql_gen.Join(v,
266 279
        {in_pkey: sql_gen.join_same_not_null}) for v in in_tables_]
267 280
    
268
    if into == None:
269
        into = into_table_name(out_table, in_tables0, mapping, is_func)
270
    into = sql_gen.as_Table(into)
281
    if not is_literals:
282
        if into == None:
283
            into = into_table_name(out_table, in_tables0, mapping, is_func)
284
        into = sql_gen.as_Table(into)
285
        
286
        # Set column sources
287
        in_cols = filter(sql_gen.is_table_col, mapping.values())
288
        for col in in_cols:
289
            if col.table == in_tables0: col.set_srcs(sql_gen.src_self)
290
        
291
        log_debug('Joining together input tables into temp table')
292
        # Place in new table so don't modify input and for speed
293
        in_table = sql_gen.Table('in')
294
        mapping = dicts.join(mapping, sql.flatten(db, in_table, input_joins,
295
            in_cols, preserve=[in_pkey_col]))
296
        input_joins = [in_table]
297
        db.log_debug('Temp table: '+strings.as_tt(in_table.to_str(db)), level=2)
271 298
    
272
    # Set column sources
273
    in_cols = filter(sql_gen.is_table_col, mapping.values())
274
    for col in in_cols:
275
        if col.table == in_tables0: col.set_srcs(sql_gen.src_self)
276
    
277
    log_debug('Joining together input tables into temp table')
278
    # Place in new table for speed and so don't modify input if values edited
279
    in_table = sql_gen.Table('in')
280
    mapping = dicts.join(mapping, sql.flatten(db, in_table, input_joins,
281
        in_cols, preserve=[in_pkey_col]))
282
    input_joins = [in_table]
283
    db.log_debug('Temp table: '+strings.as_tt(in_table.to_str(db)), level=2)
284
    
285 299
    mapping = sql_gen.ColDict(db, out_table, mapping)
286 300
        # after applying dicts.join() because that returns a plain dict
287 301
    
......
295 309
            default = None
296 310
    
297 311
    # Save default values for all rows since in_table may have rows deleted
298
    if is_function: full_in_table = in_table
312
    if is_literals: pass
313
    elif is_function: full_in_table = in_table
299 314
    else:
300 315
        full_in_table = sql_gen.suffixed_table(in_table, '_full')
301 316
        full_in_table_cols = [in_pkey_col]
......
305 320
        sql.run_query_into(db, sql.mk_select(db, in_table, full_in_table_cols,
306 321
            order_by=None), into=full_in_table, add_pkey_=True)
307 322
    
308
    pkeys_names = [in_pkey, out_pkey]
309
    pkeys_cols = [in_pkey_col, out_pkey_col]
323
    if not is_literals:
324
        pkeys_names = [in_pkey, out_pkey]
325
        pkeys_cols = [in_pkey_col, out_pkey_col]
310 326
    
311 327
    pkeys_table_exists_ref = [False]
312 328
    def insert_into_pkeys(joins, cols, **kw_args):
......
321 337
    def mk_main_select(joins, cols):
322 338
        return sql.mk_select(db, joins, cols, limit=limit_ref[0], order_by=None)
323 339
    
324
    insert_in_table = in_table
325
    insert_in_tables = [insert_in_table]
340
    if is_literals: insert_in_table = None
341
    else:
342
        insert_in_table = in_table
343
        insert_in_tables = [insert_in_table]
326 344
    join_cols = sql_gen.ColDict(db, out_table)
327 345
    
328 346
    exc_strs = set()
......
371 389
            sql.delete(db, insert_in_table, sql_gen.ColValueCond(in_col, value))
372 390
            if value == None: not_null_cols.add(in_col)
373 391
    
374
    def insert_pkeys_table(which):
375
        return sql_gen.Table(sql_gen.concat(in_table.name,
376
            '_insert_'+which+'_pkeys'))
377
    insert_out_pkeys = insert_pkeys_table('out')
378
    insert_in_pkeys = insert_pkeys_table('in')
392
    if not is_literals:
393
        def insert_pkeys_table(which):
394
            return sql_gen.Table(sql_gen.concat(in_table.name,
395
                '_insert_'+which+'_pkeys'))
396
        insert_out_pkeys = insert_pkeys_table('out')
397
        insert_in_pkeys = insert_pkeys_table('in')
379 398
    
380 399
    # Do inserts and selects
381 400
    while True:
382 401
        if limit_ref[0] == 0: # special case
402
            if is_literals: return None
383 403
            log_debug('Creating an empty pkeys table')
384 404
            cur = sql.run_query_into(db, sql.mk_select(db, out_table,
385 405
                [out_pkey], order_by=None, limit=0), into=insert_out_pkeys)
......
400 420
            if has_joins:
401 421
                insert_args.update(dict(ignore=True))
402 422
            else:
403
                insert_args.update(dict(returning=out_pkey,
404
                    into=insert_out_pkeys))
423
                insert_args.update(dict(returning=out_pkey))
424
                if not is_literals:
425
                    insert_args.update(dict(into=insert_out_pkeys))
405 426
            main_select = mk_main_select([insert_in_table], [sql_gen.with_table(
406 427
                c, insert_in_table) for c in mapping.values()])
407 428
        
408 429
        try:
409 430
            cur = None
410 431
            if is_function:
411
                insert_into_pkeys(input_joins, [in_pkey_col, func_call],
412
                    recover=True)
432
                if is_literals: cur = sql.select(db, fields=[func_call])
433
                else:
434
                    insert_into_pkeys(input_joins, [in_pkey_col, func_call],
435
                        recover=True)
413 436
            else:
414 437
                cur = sql.insert_select(db, out_table, mapping.keys(),
415 438
                    main_select, **insert_args)
......
443 466
            log_debug('Ignoring existing rows, comparing on these columns:\n'
444 467
                +strings.as_inline_table(join_cols, ustr=col_ustr))
445 468
            
469
            if is_literals:
470
                return sql.value(sql.select(db, out_table, [out_pkey_col],
471
                    mapping, order_by=None))
472
            
446 473
            # Uniquify input table to avoid internal duplicate keys
447 474
            insert_in_table = sql.distinct_table(db, insert_in_table,
448 475
                join_cols.values())
......
477 504
    if cur != None and row_ct_ref != None and cur.rowcount >= 0:
478 505
        row_ct_ref[0] += cur.rowcount
479 506
    
480
    if is_function: pass # pkeys table already created
507
    if is_literals_or_function: pass # pkeys table already created
481 508
    elif has_joins:
482 509
        select_joins = input_joins+[sql_gen.Join(out_table, join_cols)]
483 510
        log_debug('Getting output table pkeys of existing/inserted rows')
......
503 530
        
504 531
        sql.empty_temp(db, [insert_out_pkeys, insert_in_pkeys])
505 532
    
506
    if not is_function:
533
    if not is_literals_or_function:
507 534
        log_debug('Setting pkeys of missing rows to '
508 535
            +strings.as_tt(repr(default)))
509 536
        missing_rows_joins = [full_in_table, sql_gen.Join(into,
......
514 541
            sql_gen.NamedCol(out_pkey, default)])
515 542
    # otherwise, there is already an entry for every row
516 543
    
517
    assert (sql.table_row_count(db, into)
518
        == sql.table_row_count(db, full_in_table))
519
    
520
    sql.empty_temp(db, insert_in_tables+[full_in_table])
521
    
522
    srcs = []
523
    if is_func: srcs = sql_gen.cols_srcs(in_cols)
524
    return sql_gen.Col(out_pkey, into, srcs)
544
    if is_literals: return sql.value(cur)
545
    else:
546
        assert (sql.table_row_count(db, into)
547
            == sql.table_row_count(db, full_in_table))
548
        
549
        sql.empty_temp(db, insert_in_tables+[full_in_table])
550
        
551
        srcs = []
552
        if is_func: srcs = sql_gen.cols_srcs(in_cols)
553
        return sql_gen.Col(out_pkey, into, srcs)

Also available in: Unified diff