// File: /workspace/github_c_makefile_star2_O2/barabo[P]advanced-shell-history/src/sqlite3.c
// Function: fkLookupParent
static void fkLookupParent(
  Parse *pParse,        /* Parse context */
  int iDb,              /* Index of database housing pTab */
  Table *pTab,          /* Parent table of FK pFKey */
  Index *pIdx,          /* Unique index on parent key columns in pTab */
  FKey *pFKey,          /* Foreign key constraint */
  int *aiCol,           /* Map from parent key columns to child table columns */
  int regData,          /* Address of array containing child table row */
  int nIncr,            /* Increment constraint counter by this */
  int isIgnore          /* If true, pretend pTab contains all NULL values */
){
  int i;                                    /* Iterator variable */
  Vdbe *v = sqlite3GetVdbe(pParse);         /* Vdbe to add code to */
  int iCur = pParse->nTab - 1;              /* Cursor number to use */
  int iOk = sqlite3VdbeMakeLabel(v);        /* jump here if parent key found */

  /* If nIncr is less than zero, then check at runtime if there are any
  ** outstanding constraints to resolve. If there are not, there is no need
  ** to check if deleting this row resolves any outstanding violations.
  **
  ** Check if any of the key columns in the child table row are NULL. If 
  ** any are, then the constraint is considered satisfied. No need to 
  ** search for a matching row in the parent table.  */
  if( nIncr<0 ){
    sqlite3VdbeAddOp2(v, OP_FkIfZero, pFKey->isDeferred, iOk);
  }
  for(i=0; i<pFKey->nCol; i++){
    int iReg = aiCol[i] + regData + 1;
    sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iOk);
  }

  if( isIgnore==0 ){
    if( pIdx==0 ){
      /* If pIdx is NULL, then the parent key is the INTEGER PRIMARY KEY
      ** column of the parent table (table pTab).  */
      int iMustBeInt;               /* Address of MustBeInt instruction */
      int regTemp = sqlite3GetTempReg(pParse);
  
      /* Invoke MustBeInt to coerce the child key value to an integer (i.e. 
      ** apply the affinity of the parent key). If this fails, then there
      ** is no matching parent key. Before using MustBeInt, make a copy of
      ** the value. Otherwise, the value inserted into the child key column
      ** will have INTEGER affinity applied to it, which may not be correct.  */
      sqlite3VdbeAddOp2(v, OP_SCopy, aiCol[0]+1+regData, regTemp);
      iMustBeInt = sqlite3VdbeAddOp2(v, OP_MustBeInt, regTemp, 0);
  
      /* If the parent table is the same as the child table, and we are about
      ** to increment the constraint-counter (i.e. this is an INSERT operation),
      ** then check if the row being inserted matches itself. If so, do not
      ** increment the constraint-counter.  */
      if( pTab==pFKey->pFrom && nIncr==1 ){
        sqlite3VdbeAddOp3(v, OP_Eq, regData, iOk, regTemp);
      }
  
      sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead);
      sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, regTemp);
      sqlite3VdbeAddOp2(v, OP_Goto, 0, iOk);
      sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2);
      sqlite3VdbeJumpHere(v, iMustBeInt);
      sqlite3ReleaseTempReg(pParse, regTemp);
    }else{
      int nCol = pFKey->nCol;
      int regTemp = sqlite3GetTempRange(pParse, nCol);
      int regRec = sqlite3GetTempReg(pParse);
      KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
  
      sqlite3VdbeAddOp3(v, OP_OpenRead, iCur, pIdx->tnum, iDb);
      sqlite3VdbeChangeP4(v, -1, (char*)pKey, P4_KEYINFO_HANDOFF);
      for(i=0; i<nCol; i++){
        sqlite3VdbeAddOp2(v, OP_Copy, aiCol[i]+1+regData, regTemp+i);
      }
  
      /* If the parent table is the same as the child table, and we are about
      ** to increment the constraint-counter (i.e. this is an INSERT operation),
      ** then check if the row being inserted matches itself. If so, do not
      ** increment the constraint-counter. 
      **
      ** If any of the parent-key values are NULL, then the row cannot match 
      ** itself. So set JUMPIFNULL to make sure we do the OP_Found if any
      ** of the parent-key values are NULL (at this point it is known that
      ** none of the child key values are).
      */
      if( pTab==pFKey->pFrom && nIncr==1 ){
        int iJump = sqlite3VdbeCurrentAddr(v) + nCol + 1;
        for(i=0; i<nCol; i++){
          int iChild = aiCol[i]+1+regData;
          int iParent = pIdx->aiColumn[i]+1+regData;
          assert( aiCol[i]!=pTab->iPKey );
          if( pIdx->aiColumn[i]==pTab->iPKey ){
            /* The parent key is a composite key that includes the IPK column */
            iParent = regData;
          }
          sqlite3VdbeAddOp3(v, OP_Ne, iChild, iJump, iParent);
          sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL);
        }
        sqlite3VdbeAddOp2(v, OP_Goto, 0, iOk);
      }
  
      sqlite3VdbeAddOp3(v, OP_MakeRecord, regTemp, nCol, regRec);
      sqlite3VdbeChangeP4(v, -1, sqlite3IndexAffinityStr(v,pIdx), P4_TRANSIENT);
      sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regRec, 0);
  
      sqlite3ReleaseTempReg(pParse, regRec);
      sqlite3ReleaseTempRange(pParse, regTemp, nCol);
    }
  }

  if( !pFKey->isDeferred && !(pParse->db->flags & SQLITE_DeferFKs)
   && !pParse->pToplevel 
   && !pParse->isMultiWrite 
  ){
    /* Special case: If this is an INSERT statement that will insert exactly
    ** one row into the table, raise a constraint immediately instead of
    ** incrementing a counter. This is necessary as the VM code is being
    ** generated for will not open a statement transaction.  */
    assert( nIncr==1 );
    sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY,
        OE_Abort, "foreign key constraint failed", P4_STATIC
    );
  }else{
    if( nIncr>0 && pFKey->isDeferred==0 ){
      sqlite3ParseToplevel(pParse)->mayAbort = 1;
    }
    sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
  }

  sqlite3VdbeResolveLabel(v, iOk);
  sqlite3VdbeAddOp1(v, OP_Close, iCur);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x58, %rsp
movq %r9, -0x68(%rbp)
movq %r8, -0x58(%rbp)
movq %rcx, -0x70(%rbp)
movq %rdx, -0x60(%rbp)
movl %esi, -0x34(%rbp)
movq %rdi, %rbx
movl 0x20(%rbp), %eax
movl %eax, -0x50(%rbp)
movl 0x18(%rbp), %r14d
movl 0x10(%rbp), %r15d
callq 0x41ef4
movq %rax, %r13
movq %rbx, -0x40(%rbp)
movl 0x54(%rbx), %ebx
movq %rax, %rdi
callq 0x47934
movl %eax, -0x2c(%rbp)
movl %r14d, -0x30(%rbp)
testl %r14d, %r14d
jns 0x54c4a
movq -0x58(%rbp), %rax
movzbl 0x2c(%rax), %edx
pushq $0x7c
popq %rsi
movq %r13, %rdi
movl -0x2c(%rbp), %ecx
callq 0x41f42
decl %ebx
movl %ebx, -0x44(%rbp)
movq %r15, -0x80(%rbp)
incl %r15d
xorl %ebx, %ebx
pushq $0x49
popq %r12
movq -0x58(%rbp), %rax
movslq 0x28(%rax), %r14
cmpq %r14, %rbx
jge 0x54c86
movq -0x68(%rbp), %rax
movl (%rax,%rbx,4), %edx
addl %r15d, %edx
movq %r13, %rdi
movl %r12d, %esi
movl -0x2c(%rbp), %ecx
callq 0x41f42
incq %rbx
jmp 0x54c5c
cmpl $0x0, -0x50(%rbp)
movq %r13, %rbx
movl -0x44(%rbp), %r13d
jne 0x54f1a
movq -0x70(%rbp), %r12
testq %r12, %r12
je 0x54dbf
movq -0x40(%rbp), %r13
movq %r13, %rdi
movl %r14d, %esi
callq 0x47c2c
movl %eax, %eax
movq %rax, -0x50(%rbp)
movq %r13, %rdi
callq 0x46ff9
movl %eax, -0x74(%rbp)
movq %r13, %rdi
movq %r12, %rsi
callq 0x476ae
movq %rax, %r13
movl 0x50(%r12), %ecx
pushq $0x30
popq %rsi
movq %rbx, %rdi
movl -0x44(%rbp), %edx
movl -0x34(%rbp), %r8d
callq 0x41f4c
pushq $-0x1
popq %rsi
pushq $-0x10
popq %rcx
movq %rbx, %rdi
movq %r13, %rdx
callq 0x1074b
xorl %r12d, %r12d
testl %r14d, %r14d
movl $0x0, %r13d
cmovgl %r14d, %r13d
cmpq %r12, %r13
je 0x54d32
movq -0x68(%rbp), %rax
movl (%rax,%r12,4), %edx
addl %r15d, %edx
movq -0x50(%rbp), %rax
leal (%rax,%r12), %ecx
movq %rbx, %rdi
pushq $0x1c
popq %rsi
callq 0x41f42
incq %r12
jmp 0x54d0a
cmpl $0x1, -0x30(%rbp)
jne 0x54eac
movq -0x58(%rbp), %rax
movq -0x60(%rbp), %rcx
cmpq %rcx, (%rax)
jne 0x54eac
movl 0x34(%rbx), %eax
addl %r14d, %eax
incl %eax
movl %eax, -0x34(%rbp)
xorl %r12d, %r12d
cmpq %r12, %r13
je 0x54e9c
movq -0x68(%rbp), %rax
movl (%rax,%r12,4), %edx
addl %r15d, %edx
movq -0x70(%rbp), %rax
movq 0x8(%rax), %rax
movl (%rax,%r12,4), %eax
leal 0x1(%rax), %r8d
movq -0x60(%rbp), %rcx
movswl 0x40(%rcx), %ecx
cmpl %ecx, %eax
movl $0x0, %eax
cmovel %eax, %r8d
addl -0x80(%rbp), %r8d
movq %rbx, %rdi
pushq $0x4b
popq %rsi
movl -0x34(%rbp), %ecx
callq 0x41f4c
movq 0x8(%rbx), %rax
testq %rax, %rax
je 0x54dba
movslq 0x34(%rbx), %rcx
imulq $0x18, %rcx, %rcx
movb $0x8, -0x15(%rax,%rcx)
incq %r12
jmp 0x54d5b
movq -0x40(%rbp), %rdi
callq 0x46ff9
movl %eax, %r14d
movq -0x68(%rbp), %rax
addl (%rax), %r15d
pushq $0x1d
popq %rsi
movq %rbx, %rdi
movl %r15d, %edx
movl %r14d, %ecx
callq 0x41f42
pushq $0x21
popq %rsi
movq %rbx, %rdi
movl %r14d, %edx
xorl %ecx, %ecx
callq 0x41f42
movl %eax, %r15d
cmpl $0x1, -0x30(%rbp)
jne 0x54e1e
movq -0x58(%rbp), %rax
movq -0x60(%rbp), %rcx
cmpq %rcx, (%rax)
jne 0x54e1e
pushq $0x4c
popq %rsi
movq %rbx, %rdi
movq -0x80(%rbp), %rdx
movl -0x2c(%rbp), %ecx
movl %r14d, %r8d
callq 0x41f4c
pushq $0x30
popq %r8
movq -0x40(%rbp), %rdi
movl %r13d, %esi
movl -0x34(%rbp), %edx
movq -0x60(%rbp), %rcx
callq 0x4200b
pushq $0x3f
popq %rsi
movq %rbx, %rdi
movl %r13d, %edx
xorl %ecx, %ecx
movl %r14d, %r8d
callq 0x41f4c
pushq $0xe
popq %rsi
movq %rbx, %rdi
xorl %edx, %edx
movl -0x2c(%rbp), %ecx
callq 0x41f42
movl 0x34(%rbx), %eax
cmpl $0x2, %eax
jl 0x54e6f
leal -0x2(%rax), %ecx
movq 0x8(%rbx), %rdx
imulq $0x18, %rcx, %rcx
movl %eax, 0x8(%rdx,%rcx)
testl %r15d, %r15d
sets %cl
cmpl %r15d, %eax
setbe %dl
orb %cl, %dl
jne 0x54e8e
movq 0x8(%rbx), %rcx
movl %r15d, %edx
imulq $0x18, %rdx, %rdx
movl %eax, 0x8(%rcx,%rdx)
movq -0x40(%rbp), %rdi
movl %r14d, %esi
callq 0x4701c
jmp 0x54f1a
pushq $0xe
popq %rsi
movq %rbx, %rdi
xorl %edx, %edx
movl -0x2c(%rbp), %ecx
callq 0x41f42
pushq $0x2b
popq %rsi
movq %rbx, %rdi
movq -0x50(%rbp), %rdx
movl %r14d, %ecx
movl -0x74(%rbp), %r12d
movl %r12d, %r8d
callq 0x41f4c
movq %rbx, %rdi
movq -0x70(%rbp), %rsi
callq 0x47ce5
pushq $-0x1
popq %rsi
movq %rbx, %rdi
movq %rax, %rdx
xorl %ecx, %ecx
callq 0x1074b
pushq $0x3d
popq %rsi
movq %rbx, %rdi
movl -0x44(%rbp), %r13d
movl %r13d, %edx
movl -0x2c(%rbp), %ecx
movl %r12d, %r8d
xorl %r9d, %r9d
callq 0x49ffa
movq -0x40(%rbp), %r15
movq %r15, %rdi
movl %r12d, %esi
callq 0x4701c
movq %r15, %rdi
movq -0x50(%rbp), %rsi
movl %r14d, %edx
callq 0x47d6c
movq -0x58(%rbp), %rax
movzbl 0x2c(%rax), %edx
testl %edx, %edx
jne 0x54f5f
movq -0x40(%rbp), %rdi
movq (%rdi), %rax
testb $0x1, 0x2f(%rax)
jne 0x54f43
cmpq $0x0, 0x1d8(%rdi)
jne 0x54f43
cmpb $0x0, 0x23(%rdi)
je 0x54fa5
cmpl $0x0, -0x30(%rbp)
jle 0x54f5f
movq -0x40(%rbp), %rcx
movq 0x1d8(%rcx), %rax
testq %rax, %rax
cmoveq %rcx, %rax
movb $0x1, 0x24(%rax)
pushq $0x7b
popq %rsi
movq %rbx, %rdi
movl -0x30(%rbp), %ecx
callq 0x41f42
cmpl $0x0, -0x2c(%rbp)
jns 0x54f89
movq 0x40(%rbx), %rax
testq %rax, %rax
je 0x54f89
movl -0x2c(%rbp), %edx
notl %edx
movl 0x34(%rbx), %ecx
movl %edx, %edx
movl %ecx, (%rax,%rdx,4)
pushq $0x36
popq %rsi
movq %rbx, %rdi
movl %r13d, %edx
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x42436
leaq 0x168fe(%rip), %rcx     # 0x6b8aa
pushq $0x2
popq %rdx
pushq $-0x2
popq %r8
movl $0x313, %esi            # imm = 0x313
callq 0x478d0
jmp 0x54f6d