Project

General

Profile

« Previous | Next » 

Revision 2142

sql.py: put_table(): Handle DuplicateKeyExceptions by running a select query on the unique constraint columns

View differences:

lib/sql.py
653 653
    @return (table, col) Where the pkeys (from INSERT RETURNING) are made
654 654
        available
655 655
    '''
656
    out_table_clean = clean_name(out_table)
657
    pkeys = out_table_clean+'_pkeys'
656
    temp_prefix = '_'.join(map(clean_name,
657
        [out_table] + list(iters.flatten(mapping.items()))))
658
    pkeys = temp_prefix+'_pkeys'
658 659
    
659
    out_pkey = pkey(db, out_table, recover=True, table_is_esc=table_is_esc)
660
    
661 660
    # Join together input tables
662 661
    in_tables = in_tables[:] # don't modify input!
663 662
    in_tables0 = in_tables.pop(0) # first table is separate
664 663
    in_pkey = pkey(db, in_tables0, recover=True, table_is_esc=table_is_esc)
665
    joins = [in_tables0] + [(t, {in_pkey: join_using}) for t in in_tables]
664
    in_joins = [in_tables0] + [(t, {in_pkey: join_using}) for t in in_tables]
666 665
    
666
    out_pkey = pkey(db, out_table, recover=True, table_is_esc=table_is_esc)
667
    pkeys_cols = [in_pkey, out_pkey]
668
    
667 669
    def mk_select_(cols):
668
        return mk_select(db, joins, cols, limit=limit, start=start,
670
        return mk_select(db, in_joins, cols, limit=limit, start=start,
669 671
            table_is_esc=table_is_esc)
670 672
    
671
    out_pkeys = out_table_clean+'_out_pkeys'
673
    out_pkeys = temp_prefix+'_out_pkeys'
672 674
    def insert_():
673 675
        cur = insert_select(db, out_table, mapping.keys(),
674 676
            *mk_select_(mapping.values()), returning=out_pkey,
......
678 680
        add_row_num(db, out_pkeys) # for joining it with in_pkeys
679 681
        
680 682
        # Get input pkeys corresponding to rows in insert
681
        in_pkeys = out_table_clean+'_in_pkeys'
683
        in_pkeys = temp_prefix+'_in_pkeys'
682 684
        run_query_into(db, *mk_select_([in_pkey]), into=in_pkeys)
683 685
        add_row_num(db, in_pkeys) # for joining it with out_pkeys
684 686
        
685 687
        # Join together out_pkeys and in_pkeys
686 688
        run_query_into(db, *mk_select(db,
687 689
            [in_pkeys, (out_pkeys, {row_num_col: join_using})],
688
            [in_pkey, out_pkey], start=0), into=pkeys)
690
            pkeys_cols, start=0), into=pkeys)
689 691
    
692
    # Do inserts and selects
690 693
    try:
691 694
        # Insert and capture output pkeys
692 695
        with_parsed_errors(db, insert_)
693
        
694
        return (pkeys, out_pkey)
695
    except DuplicateKeyException, e: raise
696
    except DuplicateKeyException, e:
697
        join_cols = util.dict_subset_right_join(mapping, e.cols)
698
        joins = in_joins + [(out_table, join_cols)]
699
        run_query_into(db, *mk_select(db, joins, pkeys_cols,
700
            table_is_esc=table_is_esc), into=pkeys)
701
    
702
    return (pkeys, out_pkey)
696 703

  
697 704
##### Data cleanup
698 705

  

Also available in: Unified diff