// Code generated by modernc.org/undup from the per-target sqlite_*.go files; DO NOT EDIT. //go:build (freebsd && arm64) || (linux && arm64) || (linux && ppc64le) || (linux && riscv64) || (openbsd && arm64) package sqlite3 import ( "unsafe" "modernc.org/libc" ) // C documentation // // /* // ** Generate code for the RETURNING trigger. Unlike other triggers // ** that invoke a subprogram in the bytecode, the code for RETURNING // ** is generated in-line. // */ func _codeReturningTrigger(tls *libc.TLS, pParse uintptr, pTrigger uintptr, pTab uintptr, regIn int32) { bp := tls.Alloc(272) defer tls.Free(272) var db, pCol, pFrom, pNew, pReturning, v, v2 uintptr var i, nCol, reg, v1 int32 var _ /* sNC at bp+208 */ TNameContext var _ /* sSelect at bp+0 */ TSelect var _ /* uSrc at bp+120 */ struct { FfromSpace [0][88]Tu8 FsSrc TSrcList F__ccgo_pad2 [80]byte } _, _, _, _, _, _, _, _, _, _, _ = db, i, nCol, pCol, pFrom, pNew, pReturning, reg, v, v1, v2 v = (*TParse)(unsafe.Pointer(pParse)).FpVdbe db = (*TParse)(unsafe.Pointer(pParse)).Fdb if !(int32(Tbft(*(*uint16)(unsafe.Pointer(pParse + 40))&0x8>>3)) != 0) { /* This RETURNING trigger must be for a different statement as ** this statement lacks a RETURNING clause. */ return } pReturning = (*(*struct { FpReturning uintptr })(unsafe.Pointer(&(*TParse)(unsafe.Pointer(pParse)).Fu1))).FpReturning if pTrigger != pReturning+16 { /* This RETURNING trigger is for a different statement */ return } libc.Xmemset(tls, bp, 0, uint64(120)) libc.Xmemset(tls, bp+120, 0, uint64(88)) pFrom = bp + 120 (**(**TSelect)(__ccgo_up(bp))).FpEList = _sqlite3ExprListDup(tls, db, (*TReturning)(unsafe.Pointer(pReturning)).FpReturnEL, 0) (**(**TSelect)(__ccgo_up(bp))).FpSrc = pFrom (*TSrcList)(unsafe.Pointer(pFrom)).FnSrc = int32(1) (*(*TSrcItem)(unsafe.Pointer(pFrom + 8))).FpSTab = pTab (*(*TSrcItem)(unsafe.Pointer(pFrom + 8))).FzName = (*TTable)(unsafe.Pointer(pTab)).FzName /* tag-20240424-1 */ (*(*TSrcItem)(unsafe.Pointer(pFrom + 8))).FiCursor = -int32(1) _sqlite3SelectPrep(tls, pParse, bp, uintptr(0)) if (*TParse)(unsafe.Pointer(pParse)).FnErr == 0 { _sqlite3GenerateColumnNames(tls, pParse, bp) } _sqlite3ExprListDelete(tls, db, (**(**TSelect)(__ccgo_up(bp))).FpEList) pNew = _sqlite3ExpandReturning(tls, pParse, (*TReturning)(unsafe.Pointer(pReturning)).FpReturnEL, pTab) if (*TParse)(unsafe.Pointer(pParse)).FnErr == 0 { libc.Xmemset(tls, bp+208, 0, uint64(56)) if (*TReturning)(unsafe.Pointer(pReturning)).FnRetCol == 0 { (*TReturning)(unsafe.Pointer(pReturning)).FnRetCol = (*TExprList)(unsafe.Pointer(pNew)).FnExpr v2 = pParse + 56 v1 = *(*int32)(unsafe.Pointer(v2)) *(*int32)(unsafe.Pointer(v2)) = *(*int32)(unsafe.Pointer(v2)) + 1 (*TReturning)(unsafe.Pointer(pReturning)).FiRetCur = v1 } (**(**TNameContext)(__ccgo_up(bp + 208))).FpParse = pParse *(*int32)(unsafe.Pointer(bp + 208 + 16)) = regIn (**(**TNameContext)(__ccgo_up(bp + 208))).FncFlags = int32(NC_UBaseReg) (*TParse)(unsafe.Pointer(pParse)).FeTriggerOp = (*TTrigger)(unsafe.Pointer(pTrigger)).Fop (*TParse)(unsafe.Pointer(pParse)).FpTriggerTab = pTab if _sqlite3ResolveExprListNames(tls, bp+208, pNew) == SQLITE_OK && !((*Tsqlite3)(unsafe.Pointer(db)).FmallocFailed != 0) { nCol = (*TExprList)(unsafe.Pointer(pNew)).FnExpr reg = (*TParse)(unsafe.Pointer(pParse)).FnMem + int32(1) _sqlite3ProcessReturningSubqueries(tls, pNew, pTab) **(**int32)(__ccgo_up(pParse + 60)) += nCol + int32(2) (*TReturning)(unsafe.Pointer(pReturning)).FiRetReg = reg i = 0 for { if !(i < nCol) { break } pCol = (*(*TExprList_item)(unsafe.Pointer(pNew + 8 + uintptr(i)*32))).FpExpr /* Due to !db->mallocFailed ~9 lines above */ _sqlite3ExprCodeFactorable(tls, pParse, pCol, reg+i) if libc.Int32FromUint8(_sqlite3ExprAffinity(tls, pCol)) == int32(SQLITE_AFF_REAL) { _sqlite3VdbeAddOp1(tls, v, int32(OP_RealAffinity), reg+i) } goto _3 _3: ; i = i + 1 } _sqlite3VdbeAddOp3(tls, v, int32(OP_MakeRecord), reg, i, reg+i) _sqlite3VdbeAddOp2(tls, v, int32(OP_NewRowid), (*TReturning)(unsafe.Pointer(pReturning)).FiRetCur, reg+i+int32(1)) _sqlite3VdbeAddOp3(tls, v, int32(OP_Insert), (*TReturning)(unsafe.Pointer(pReturning)).FiRetCur, reg+i, reg+i+int32(1)) } } _sqlite3ExprListDelete(tls, db, pNew) (*TParse)(unsafe.Pointer(pParse)).FeTriggerOp = uint8(0) (*TParse)(unsafe.Pointer(pParse)).FpTriggerTab = uintptr(0) } // C documentation // // /* // ** Process time function arguments. argv[0] is a date-time stamp. // ** argv[1] and following are modifiers. Parse them all and write // ** the resulting time into the DateTime structure p. Return 0 // ** on success and 1 if there are any errors. // ** // ** If there are zero parameters (if even argv[0] is undefined) // ** then assume a default value of "now" for argv[0]. // */ func _isDate(tls *libc.TLS, context uintptr, argc int32, argv uintptr, p uintptr) (r int32) { var eType, i, n, v1 int32 var z uintptr _, _, _, _, _ = eType, i, n, z, v1 libc.Xmemset(tls, p, 0, uint64(48)) if argc == 0 { if !(_sqlite3NotPureFunc(tls, context) != 0) { return int32(1) } return _setDateTimeToCurrent(tls, context, p) } v1 = Xsqlite3_value_type(tls, **(**uintptr)(__ccgo_up(argv))) eType = v1 if v1 == int32(SQLITE_FLOAT) || eType == int32(SQLITE_INTEGER) { _setRawDateNumber(tls, p, Xsqlite3_value_double(tls, **(**uintptr)(__ccgo_up(argv)))) } else { z = Xsqlite3_value_text(tls, **(**uintptr)(__ccgo_up(argv))) if !(z != 0) || _parseDateOrTime(tls, context, z, p) != 0 { return int32(1) } } i = int32(1) for { if !(i < argc) { break } z = Xsqlite3_value_text(tls, **(**uintptr)(__ccgo_up(argv + uintptr(i)*8))) n = Xsqlite3_value_bytes(tls, **(**uintptr)(__ccgo_up(argv + uintptr(i)*8))) if z == uintptr(0) || _parseModifier(tls, context, z, n, p, i) != 0 { return int32(1) } goto _2 _2: ; i = i + 1 } _computeJD(tls, p) if int32(uint32(*(*uint8)(unsafe.Pointer(p + 44))&0x2>>1)) != 0 || !(_validJulianDay(tls, (*TDateTime)(unsafe.Pointer(p)).FiJD) != 0) { return int32(1) } if argc == int32(1) && (*TDateTime)(unsafe.Pointer(p)).FvalidYMD != 0 && (*TDateTime)(unsafe.Pointer(p)).FD > int32(28) { /* Make sure a YYYY-MM-DD is normalized. ** Example: 2023-02-31 -> 2023-03-03 */ (*TDateTime)(unsafe.Pointer(p)).FvalidYMD = uint8(0) } return 0 } /* ** The following routines implement the various date and time functions ** of SQLite. */ // C documentation // // /* // ** This is a Walker.xSelectCallback callback for the sqlite3SelectTypeInfo() // ** interface. // ** // ** For each FROM-clause subquery, add Column.zType, Column.zColl, and // ** Column.affinity information to the Table structure that represents // ** the result set of that subquery. // ** // ** The Table structure that represents the result set was constructed // ** by selectExpander() but the type and collation and affinity information // ** was omitted at that point because identifiers had not yet been resolved. // ** This routine is called after identifier resolution. // */ func _selectAddSubqueryTypeInfo(tls *libc.TLS, pWalker uintptr, p uintptr) { var i int32 var pFrom, pParse, pSel, pTab, pTabList uintptr _, _, _, _, _, _ = i, pFrom, pParse, pSel, pTab, pTabList if (*TSelect)(unsafe.Pointer(p)).FselFlags&uint32(SF_HasTypeInfo) != 0 { return } **(**Tu32)(__ccgo_up(p + 4)) |= uint32(SF_HasTypeInfo) pParse = (*TWalker)(unsafe.Pointer(pWalker)).FpParse pTabList = (*TSelect)(unsafe.Pointer(p)).FpSrc i = 0 pFrom = pTabList + 8 for { if !(i < (*TSrcList)(unsafe.Pointer(pTabList)).FnSrc) { break } pTab = (*TSrcItem)(unsafe.Pointer(pFrom)).FpSTab if (*TTable)(unsafe.Pointer(pTab)).FtabFlags&uint32(TF_Ephemeral) != uint32(0) && int32(*(*uint32)(unsafe.Pointer(pFrom + 24 + 4))&0x4>>2) != 0 { /* A sub-query in the FROM clause of a SELECT */ pSel = (*TSubquery)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pFrom + 72)))).FpSelect _sqlite3SubqueryColumnTypes(tls, pParse, pTab, pSel, uint8(SQLITE_AFF_NONE)) } goto _1 _1: ; i = i + 1 pFrom += 80 } } // C documentation // // /* // ** Generate code for an IN expression. // ** // ** x IN (SELECT ...) // ** x IN (value, value, ...) // ** // ** The left-hand side (LHS) is a scalar or vector expression. The // ** right-hand side (RHS) is an array of zero or more scalar values, or a // ** subquery. If the RHS is a subquery, the number of result columns must // ** match the number of columns in the vector on the LHS. If the RHS is // ** a list of values, the LHS must be a scalar. // ** // ** The IN operator is true if the LHS value is contained within the RHS. // ** The result is false if the LHS is definitely not in the RHS. The // ** result is NULL if the presence of the LHS in the RHS cannot be // ** determined due to NULLs. // ** // ** This routine generates code that jumps to destIfFalse if the LHS is not // ** contained within the RHS. If due to NULLs we cannot determine if the LHS // ** is contained in the RHS then jump to destIfNull. If the LHS is contained // ** within the RHS then fall through. // ** // ** See the separate in-operator.md documentation file in the canonical // ** SQLite source tree for additional information. // */ func _sqlite3ExprCodeIN(tls *libc.TLS, pParse uintptr, pExpr uintptr, destIfFalse int32, destIfNull int32) { bp := tls.Alloc(16) defer tls.Free(16) var addrTop, addrTruthOp, destNotNull, destStep2, destStep6, eType, i, ii, labelOk, nVector, op, op1, r2, r3, rLhs, rLhsOrig, regCkNull, v3 int32 var aiMap, p, p1, pColl, pColl1, pLeft, pList, pOp, pRhs, v, zAff, v1 uintptr var okConstFactor Tu8 var _ /* iDummy at bp+4 */ int32 var _ /* iTab at bp+8 */ int32 var _ /* rRhsHasNull at bp+0 */ int32 var _ /* regToFree at bp+12 */ int32 _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = addrTop, addrTruthOp, aiMap, destNotNull, destStep2, destStep6, eType, i, ii, labelOk, nVector, okConstFactor, op, op1, p, p1, pColl, pColl1, pLeft, pList, pOp, pRhs, r2, r3, rLhs, rLhsOrig, regCkNull, v, zAff, v1, v3 **(**int32)(__ccgo_up(bp)) = 0 /* Statement under construction */ aiMap = uintptr(0) /* Map from vector field to index column */ zAff = uintptr(0) /* Where to jump when NULLs seen in step 2 */ destStep6 = 0 /* Top of the step-6 loop */ **(**int32)(__ccgo_up(bp + 8)) = 0 /* Index to use */ okConstFactor = libc.Uint8FromInt32(int32(Tbft(*(*uint16)(unsafe.Pointer(pParse + 40)) & 0x80 >> 7))) pLeft = (*TExpr)(unsafe.Pointer(pExpr)).FpLeft if _sqlite3ExprCheckIN(tls, pParse, pExpr) != 0 { return } zAff = _exprINAffinity(tls, pParse, pExpr) nVector = _sqlite3ExprVectorSize(tls, (*TExpr)(unsafe.Pointer(pExpr)).FpLeft) aiMap = _sqlite3DbMallocZero(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, uint64(libc.Uint64FromInt32(nVector)*uint64(4))) if (*Tsqlite3)(unsafe.Pointer((*TParse)(unsafe.Pointer(pParse)).Fdb)).FmallocFailed != 0 { goto sqlite3ExprCodeIN_oom_error } /* Attempt to compute the RHS. After this step, if anything other than ** IN_INDEX_NOOP is returned, the table opened with cursor iTab ** contains the values that make up the RHS. If IN_INDEX_NOOP is returned, ** the RHS has not yet been coded. */ v = (*TParse)(unsafe.Pointer(pParse)).FpVdbe /* OOM detected prior to this routine */ if destIfFalse == destIfNull { v1 = uintptr(0) } else { v1 = bp } eType = _sqlite3FindInIndex(tls, pParse, pExpr, libc.Uint32FromInt32(libc.Int32FromInt32(IN_INDEX_MEMBERSHIP)|libc.Int32FromInt32(IN_INDEX_NOOP_OK)), v1, aiMap, bp+8) /* Code the LHS, the from " IN (...)". If the LHS is a ** vector, then it is stored in an array of nVector registers starting ** at r1. ** ** sqlite3FindInIndex() might have reordered the fields of the LHS vector ** so that the fields are in the same order as an existing index. The ** aiMap[] array contains a mapping from the original LHS field order to ** the field order that matches the RHS index. ** ** Avoid factoring the LHS of the IN(...) expression out of the loop, ** even if it is constant, as OP_Affinity may be used on the register ** by code generated below. */ libc.SetBitFieldPtr16Uint32(pParse+40, libc.Uint32FromInt32(0), 7, 0x80) rLhs = _exprCodeVector(tls, pParse, pLeft, bp+4) libc.SetBitFieldPtr16Uint32(pParse+40, uint32(okConstFactor), 7, 0x80) /* If sqlite3FindInIndex() did not find or create an index that is ** suitable for evaluating the IN operator, then evaluate using a ** sequence of comparisons. ** ** This is step (1) in the in-operator.md optimized algorithm. */ if eType == int32(IN_INDEX_NOOP) { labelOk = _sqlite3VdbeMakeLabel(tls, pParse) regCkNull = 0 pList = *(*uintptr)(unsafe.Pointer(pExpr + 32)) pColl = _sqlite3ExprCollSeq(tls, pParse, (*TExpr)(unsafe.Pointer(pExpr)).FpLeft) if destIfNull != destIfFalse { regCkNull = _sqlite3GetTempReg(tls, pParse) _sqlite3VdbeAddOp3(tls, v, int32(OP_BitAnd), rLhs, rLhs, regCkNull) } ii = 0 for { if !(ii < (*TExprList)(unsafe.Pointer(pList)).FnExpr) { break } r2 = _sqlite3ExprCodeTemp(tls, pParse, (*(*TExprList_item)(unsafe.Pointer(pList + 8 + uintptr(ii)*32))).FpExpr, bp+12) if regCkNull != 0 && _sqlite3ExprCanBeNull(tls, (*(*TExprList_item)(unsafe.Pointer(pList + 8 + uintptr(ii)*32))).FpExpr) != 0 { _sqlite3VdbeAddOp3(tls, v, int32(OP_BitAnd), regCkNull, r2, regCkNull) } _sqlite3ReleaseTempReg(tls, pParse, **(**int32)(__ccgo_up(bp + 12))) if ii < (*TExprList)(unsafe.Pointer(pList)).FnExpr-int32(1) || destIfNull != destIfFalse { if rLhs != r2 { v3 = int32(OP_Eq) } else { v3 = int32(OP_NotNull) } op = v3 _sqlite3VdbeAddOp4(tls, v, op, rLhs, labelOk, r2, pColl, -int32(2)) _sqlite3VdbeChangeP5(tls, v, uint16(**(**uint8)(__ccgo_up(zAff)))) } else { if rLhs != r2 { v3 = int32(OP_Ne) } else { v3 = int32(OP_IsNull) } op1 = v3 _sqlite3VdbeAddOp4(tls, v, op1, rLhs, destIfFalse, r2, pColl, -int32(2)) _sqlite3VdbeChangeP5(tls, v, libc.Uint16FromInt32(libc.Int32FromUint8(**(**uint8)(__ccgo_up(zAff)))|int32(SQLITE_JUMPIFNULL))) } goto _2 _2: ; ii = ii + 1 } if regCkNull != 0 { _sqlite3VdbeAddOp2(tls, v, int32(OP_IsNull), regCkNull, destIfNull) _sqlite3VdbeGoto(tls, v, destIfFalse) } _sqlite3VdbeResolveLabel(tls, v, labelOk) _sqlite3ReleaseTempReg(tls, pParse, regCkNull) goto sqlite3ExprCodeIN_finished } if eType != int32(IN_INDEX_ROWID) { /* If this IN operator will use an index, then the order of columns in the ** vector might be different from the order in the index. In that case, ** we need to reorder the LHS values to be in index order. Run Affinity ** before reordering the columns, so that the affinity is correct. */ _sqlite3VdbeAddOp4(tls, v, int32(OP_Affinity), rLhs, nVector, 0, zAff, nVector) i = 0 for { if !(i < nVector && **(**int32)(__ccgo_up(aiMap + uintptr(i)*4)) == i) { break } goto _5 _5: ; i = i + 1 } /* Are LHS fields reordered? */ if i != nVector { /* Need to reorder the LHS fields according to aiMap */ rLhsOrig = rLhs rLhs = _sqlite3GetTempRange(tls, pParse, nVector) i = 0 for { if !(i < nVector) { break } _sqlite3VdbeAddOp3(tls, v, int32(OP_Copy), rLhsOrig+i, rLhs+**(**int32)(__ccgo_up(aiMap + uintptr(i)*4)), 0) goto _6 _6: ; i = i + 1 } _sqlite3ReleaseTempReg(tls, pParse, rLhsOrig) } } /* Step 2: Check to see if the LHS contains any NULL columns. If the ** LHS does contain NULLs then the result must be either FALSE or NULL. ** We will then skip the binary search of the RHS. */ if destIfNull == destIfFalse { destStep2 = destIfFalse } else { v3 = _sqlite3VdbeMakeLabel(tls, pParse) destStep6 = v3 destStep2 = v3 } i = 0 for { if !(i < nVector) { break } p = _sqlite3VectorFieldSubexpr(tls, (*TExpr)(unsafe.Pointer(pExpr)).FpLeft, i) if (*TParse)(unsafe.Pointer(pParse)).FnErr != 0 { goto sqlite3ExprCodeIN_oom_error } if _sqlite3ExprCanBeNull(tls, p) != 0 { _sqlite3VdbeAddOp2(tls, v, int32(OP_IsNull), rLhs+**(**int32)(__ccgo_up(aiMap + uintptr(i)*4)), destStep2) } goto _8 _8: ; i = i + 1 } /* Step 3. The LHS is now known to be non-NULL. Do the binary search ** of the RHS using the LHS as a probe. If found, the result is ** true. */ if eType == int32(IN_INDEX_ROWID) { /* In this case, the RHS is the ROWID of table b-tree and so we also ** know that the RHS is non-NULL. Hence, we combine steps 3 and 4 ** into a single opcode. */ _sqlite3VdbeAddOp3(tls, v, int32(OP_SeekRowid), **(**int32)(__ccgo_up(bp + 8)), destIfFalse, rLhs) addrTruthOp = _sqlite3VdbeAddOp0(tls, v, int32(OP_Goto)) /* Return True */ } else { if destIfFalse == destIfNull { /* Combine Step 3 and Step 5 into a single opcode */ if (*TExpr)(unsafe.Pointer(pExpr)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_Subrtn)) != uint32(0) { pOp = _sqlite3VdbeGetOp(tls, v, (*(*struct { FiAddr int32 FregReturn int32 })(unsafe.Pointer(pExpr + 64))).FiAddr) if (*TVdbeOp)(unsafe.Pointer(pOp)).Fp3 > 0 { /* tag-202407032019 */ _sqlite3VdbeAddOp4Int(tls, v, int32(OP_Filter), (*TVdbeOp)(unsafe.Pointer(pOp)).Fp3, destIfFalse, rLhs, nVector) } } _sqlite3VdbeAddOp4Int(tls, v, int32(OP_NotFound), **(**int32)(__ccgo_up(bp + 8)), destIfFalse, rLhs, nVector) goto sqlite3ExprCodeIN_finished } /* Ordinary Step 3, for the case where FALSE and NULL are distinct */ addrTruthOp = _sqlite3VdbeAddOp4Int(tls, v, int32(OP_Found), **(**int32)(__ccgo_up(bp + 8)), 0, rLhs, nVector) } /* Step 4. If the RHS is known to be non-NULL and we did not find ** an match on the search above, then the result must be FALSE. */ if **(**int32)(__ccgo_up(bp)) != 0 && nVector == int32(1) { _sqlite3VdbeAddOp2(tls, v, int32(OP_NotNull), **(**int32)(__ccgo_up(bp)), destIfFalse) } /* Step 5. If we do not care about the difference between NULL and ** FALSE, then just return false. */ if destIfFalse == destIfNull { _sqlite3VdbeGoto(tls, v, destIfFalse) } /* Step 6: Loop through rows of the RHS. Compare each row to the LHS. ** If any comparison is NULL, then the result is NULL. If all ** comparisons are FALSE then the final result is FALSE. ** ** For a scalar LHS, it is sufficient to check just the first row ** of the RHS. */ if destStep6 != 0 { _sqlite3VdbeResolveLabel(tls, v, destStep6) } addrTop = _sqlite3VdbeAddOp2(tls, v, int32(OP_Rewind), **(**int32)(__ccgo_up(bp + 8)), destIfFalse) if nVector > int32(1) { destNotNull = _sqlite3VdbeMakeLabel(tls, pParse) } else { /* For nVector==1, combine steps 6 and 7 by immediately returning ** FALSE if the first comparison is not NULL */ destNotNull = destIfFalse } i = 0 for { if !(i < nVector) { break } r3 = _sqlite3GetTempReg(tls, pParse) p1 = _sqlite3VectorFieldSubexpr(tls, pLeft, i) if (*TExpr)(unsafe.Pointer(pExpr)).Fflags&uint32(EP_xIsSelect) != uint32(0) { pRhs = (*(*TExprList_item)(unsafe.Pointer((*TSelect)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pExpr + 32)))).FpEList + 8 + uintptr(i)*32))).FpExpr pColl1 = _sqlite3BinaryCompareCollSeq(tls, pParse, p1, pRhs) } else { /* If the RHS of the IN(...) expression are scalar expressions, do ** not consider their collation sequences. The documentation says ** "The collating sequence used for expressions of the form "x IN (y, z, ** ...)" is the collating sequence of x.". */ pColl1 = _sqlite3ExprCollSeq(tls, pParse, p1) } _sqlite3VdbeAddOp3(tls, v, int32(OP_Column), **(**int32)(__ccgo_up(bp + 8)), **(**int32)(__ccgo_up(aiMap + uintptr(i)*4)), r3) _sqlite3VdbeAddOp4(tls, v, int32(OP_Ne), rLhs+**(**int32)(__ccgo_up(aiMap + uintptr(i)*4)), destNotNull, r3, pColl1, -int32(2)) _sqlite3ReleaseTempReg(tls, pParse, r3) goto _9 _9: ; i = i + 1 } _sqlite3VdbeAddOp2(tls, v, int32(OP_Goto), 0, destIfNull) if nVector > int32(1) { _sqlite3VdbeResolveLabel(tls, v, destNotNull) _sqlite3VdbeAddOp2(tls, v, int32(OP_Next), **(**int32)(__ccgo_up(bp + 8)), addrTop+int32(1)) /* Step 7: If we reach this point, we know that the result must ** be false. */ _sqlite3VdbeAddOp2(tls, v, int32(OP_Goto), 0, destIfFalse) } /* Jumps here in order to return true. */ _sqlite3VdbeJumpHere(tls, v, addrTruthOp) goto sqlite3ExprCodeIN_finished sqlite3ExprCodeIN_finished: ; goto sqlite3ExprCodeIN_oom_error sqlite3ExprCodeIN_oom_error: ; _sqlite3DbFree(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, aiMap) _sqlite3DbFree(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, zAff) } // C documentation // // /* // ** Subqueries store the original database, table and column names for their // ** result sets in ExprList.a[].zSpan, in the form "DATABASE.TABLE.COLUMN", // ** and mark the expression-list item by setting ExprList.a[].fg.eEName // ** to ENAME_TAB. // ** // ** Check to see if the zSpan/eEName of the expression-list item passed to this // ** routine matches the zDb, zTab, and zCol. If any of zDb, zTab, and zCol are // ** NULL then those fields will match anything. Return true if there is a match, // ** or false otherwise. // ** // ** SF_NestedFrom subqueries also store an entry for the implicit rowid (or // ** _rowid_, or oid) column by setting ExprList.a[].fg.eEName to ENAME_ROWID, // ** and setting zSpan to "DATABASE.TABLE.". This type of pItem // ** argument matches if zCol is a rowid alias. If it is not NULL, (*pbRowid) // ** is set to 1 if there is this kind of match. // */ func _sqlite3MatchEName(tls *libc.TLS, pItem uintptr, zCol uintptr, zTab uintptr, zDb uintptr, pbRowid uintptr) (r int32) { var eEName, n int32 var zSpan uintptr _, _, _ = eEName, n, zSpan eEName = int32(uint32(*(*uint16)(unsafe.Pointer(pItem + 16 + 4)) & 0x3 >> 0)) if eEName != int32(ENAME_TAB) && (eEName != int32(ENAME_ROWID) || pbRowid == uintptr(0)) { return 0 } zSpan = (*TExprList_item)(unsafe.Pointer(pItem)).FzEName n = 0 for { if !(**(**uint8)(__ccgo_up(zSpan + uintptr(n))) != 0 && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zSpan + uintptr(n)))) != int32('.')) { break } goto _1 _1: ; n = n + 1 } if zDb != 0 && (Xsqlite3_strnicmp(tls, zSpan, zDb, n) != 0 || libc.Int32FromUint8(**(**uint8)(__ccgo_up(zDb + uintptr(n)))) != 0) { return 0 } zSpan = zSpan + uintptr(n+int32(1)) n = 0 for { if !(**(**uint8)(__ccgo_up(zSpan + uintptr(n))) != 0 && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zSpan + uintptr(n)))) != int32('.')) { break } goto _2 _2: ; n = n + 1 } if zTab != 0 && (Xsqlite3_strnicmp(tls, zSpan, zTab, n) != 0 || libc.Int32FromUint8(**(**uint8)(__ccgo_up(zTab + uintptr(n)))) != 0) { return 0 } zSpan = zSpan + uintptr(n+int32(1)) if zCol != 0 { if eEName == int32(ENAME_TAB) && _sqlite3StrICmp(tls, zSpan, zCol) != 0 { return 0 } if eEName == int32(ENAME_ROWID) && _sqlite3IsRowid(tls, zCol) == 0 { return 0 } } if eEName == int32(ENAME_ROWID) { **(**int32)(__ccgo_up(pbRowid)) = int32(1) } return int32(1) } // C documentation // // /* // ** Compile the UTF-16 encoded SQL statement zSql into a statement handle. // */ func _sqlite3Prepare16(tls *libc.TLS, db uintptr, zSql uintptr, nBytes int32, prepFlags Tu32, ppStmt uintptr, pzTail uintptr) (r int32) { bp := tls.Alloc(16) defer tls.Free(16) var chars_parsed, rc, sz, sz1 int32 var z, z1, zSql8 uintptr var _ /* zTail8 at bp+0 */ uintptr _, _, _, _, _, _, _ = chars_parsed, rc, sz, sz1, z, z1, zSql8 **(**uintptr)(__ccgo_up(bp)) = uintptr(0) rc = SQLITE_OK **(**uintptr)(__ccgo_up(ppStmt)) = uintptr(0) if !(_sqlite3SafetyCheckOk(tls, db) != 0) || zSql == uintptr(0) { return _sqlite3MisuseError(tls, int32(149329)) } /* Make sure nBytes is non-negative and correct. It should be the ** number of bytes until the end of the input buffer or until the first ** U+0000 character. If the input nBytes is odd, convert it into ** an even number. If the input nBytes is negative, then the input ** must be terminated by at least one U+0000 character */ if nBytes >= 0 { z = zSql sz = 0 for { if !(sz < nBytes && (libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(sz)))) != 0 || libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(sz+int32(1))))) != 0)) { break } goto _1 _1: ; sz = sz + int32(2) } nBytes = sz } else { z1 = zSql sz1 = 0 for { if !(libc.Int32FromUint8(**(**uint8)(__ccgo_up(z1 + uintptr(sz1)))) != 0 || libc.Int32FromUint8(**(**uint8)(__ccgo_up(z1 + uintptr(sz1+int32(1))))) != 0) { break } goto _2 _2: ; sz1 = sz1 + int32(2) } nBytes = sz1 } Xsqlite3_mutex_enter(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex) zSql8 = _sqlite3Utf16to8(tls, db, zSql, nBytes, uint8(SQLITE_UTF16LE)) if zSql8 != 0 { rc = _sqlite3LockAndPrepare(tls, db, zSql8, -int32(1), prepFlags, uintptr(0), ppStmt, bp) } if **(**uintptr)(__ccgo_up(bp)) != 0 && pzTail != 0 { /* If sqlite3_prepare returns a tail pointer, we calculate the ** equivalent pointer into the UTF-16 string by counting the unicode ** characters between zSql8 and zTail8, and then returning a pointer ** the same number of characters into the UTF-16 string. */ chars_parsed = _sqlite3Utf8CharLen(tls, zSql8, int32(int64(**(**uintptr)(__ccgo_up(bp)))-int64(zSql8))) **(**uintptr)(__ccgo_up(pzTail)) = zSql + uintptr(_sqlite3Utf16ByteLen(tls, zSql, nBytes, chars_parsed)) } _sqlite3DbFree(tls, db, zSql8) rc = _sqlite3ApiExit(tls, db, rc) Xsqlite3_mutex_leave(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex) return rc } // C documentation // // /* // ** If the SELECT statement passed as the second argument does not invoke // ** any SQL window functions, this function is a no-op. Otherwise, it // ** rewrites the SELECT statement so that window function xStep functions // ** are invoked in the correct order as described under "SELECT REWRITING" // ** at the top of this file. // */ func _sqlite3WindowRewrite(tls *libc.TLS, pParse uintptr, p uintptr) (r int32) { bp := tls.Alloc(64) defer tls.Free(64) var db, pArgs, pFilter, pGroupBy, pHaving, pMWin, pSort, pSrc, pSub, pTab, pTab2, pWhere, pWin, v, v2 uintptr var nSave, rc, v1 int32 var selFlags Tu32 var _ /* pSublist at bp+0 */ uintptr var _ /* w at bp+8 */ TWalker _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = db, nSave, pArgs, pFilter, pGroupBy, pHaving, pMWin, pSort, pSrc, pSub, pTab, pTab2, pWhere, pWin, rc, selFlags, v, v1, v2 rc = SQLITE_OK if (*TSelect)(unsafe.Pointer(p)).FpWin != 0 && (*TSelect)(unsafe.Pointer(p)).FpPrior == uintptr(0) && (*TSelect)(unsafe.Pointer(p)).FselFlags&uint32(SF_WinRewrite) == uint32(0) && !(libc.Int32FromUint8((*TParse)(unsafe.Pointer(pParse)).FeParseMode) >= libc.Int32FromInt32(PARSE_MODE_RENAME)) { v = _sqlite3GetVdbe(tls, pParse) db = (*TParse)(unsafe.Pointer(pParse)).Fdb pSub = uintptr(0) /* The subquery */ pSrc = (*TSelect)(unsafe.Pointer(p)).FpSrc pWhere = (*TSelect)(unsafe.Pointer(p)).FpWhere pGroupBy = (*TSelect)(unsafe.Pointer(p)).FpGroupBy pHaving = (*TSelect)(unsafe.Pointer(p)).FpHaving pSort = uintptr(0) **(**uintptr)(__ccgo_up(bp)) = uintptr(0) /* Expression list for sub-query */ pMWin = (*TSelect)(unsafe.Pointer(p)).FpWin selFlags = (*TSelect)(unsafe.Pointer(p)).FselFlags pTab = _sqlite3DbMallocZero(tls, db, uint64(120)) if pTab == uintptr(0) { return _sqlite3ErrorToParser(tls, db, int32(SQLITE_NOMEM)) } _sqlite3AggInfoPersistWalkerInit(tls, bp+8, pParse) _sqlite3WalkSelect(tls, bp+8, p) if (*TSelect)(unsafe.Pointer(p)).FselFlags&uint32(SF_Aggregate) == uint32(0) { (**(**TWalker)(__ccgo_up(bp + 8))).FxExprCallback = __ccgo_fp(_disallowAggregatesInOrderByCb) (**(**TWalker)(__ccgo_up(bp + 8))).FxSelectCallback = uintptr(0) _sqlite3WalkExprList(tls, bp+8, (*TSelect)(unsafe.Pointer(p)).FpOrderBy) } (*TSelect)(unsafe.Pointer(p)).FpSrc = uintptr(0) (*TSelect)(unsafe.Pointer(p)).FpWhere = uintptr(0) (*TSelect)(unsafe.Pointer(p)).FpGroupBy = uintptr(0) (*TSelect)(unsafe.Pointer(p)).FpHaving = uintptr(0) **(**Tu32)(__ccgo_up(p + 4)) &= ^libc.Uint32FromInt32(SF_Aggregate) **(**Tu32)(__ccgo_up(p + 4)) |= uint32(SF_WinRewrite) /* Create the ORDER BY clause for the sub-select. This is the concatenation ** of the window PARTITION and ORDER BY clauses. Then, if this makes it ** redundant, remove the ORDER BY from the parent SELECT. */ pSort = _exprListAppendList(tls, pParse, uintptr(0), (*TWindow)(unsafe.Pointer(pMWin)).FpPartition, int32(1)) pSort = _exprListAppendList(tls, pParse, pSort, (*TWindow)(unsafe.Pointer(pMWin)).FpOrderBy, int32(1)) if pSort != 0 && (*TSelect)(unsafe.Pointer(p)).FpOrderBy != 0 && (*TExprList)(unsafe.Pointer((*TSelect)(unsafe.Pointer(p)).FpOrderBy)).FnExpr <= (*TExprList)(unsafe.Pointer(pSort)).FnExpr { nSave = (*TExprList)(unsafe.Pointer(pSort)).FnExpr (*TExprList)(unsafe.Pointer(pSort)).FnExpr = (*TExprList)(unsafe.Pointer((*TSelect)(unsafe.Pointer(p)).FpOrderBy)).FnExpr if _sqlite3ExprListCompare(tls, pSort, (*TSelect)(unsafe.Pointer(p)).FpOrderBy, -int32(1)) == 0 { _sqlite3ExprListDelete(tls, db, (*TSelect)(unsafe.Pointer(p)).FpOrderBy) (*TSelect)(unsafe.Pointer(p)).FpOrderBy = uintptr(0) } (*TExprList)(unsafe.Pointer(pSort)).FnExpr = nSave } /* Assign a cursor number for the ephemeral table used to buffer rows. ** The OpenEphemeral instruction is coded later, after it is known how ** many columns the table will have. */ v2 = pParse + 56 v1 = *(*int32)(unsafe.Pointer(v2)) *(*int32)(unsafe.Pointer(v2)) = *(*int32)(unsafe.Pointer(v2)) + 1 (*TWindow)(unsafe.Pointer(pMWin)).FiEphCsr = v1 **(**int32)(__ccgo_up(pParse + 56)) += int32(3) _selectWindowRewriteEList(tls, pParse, pMWin, pSrc, (*TSelect)(unsafe.Pointer(p)).FpEList, pTab, bp) _selectWindowRewriteEList(tls, pParse, pMWin, pSrc, (*TSelect)(unsafe.Pointer(p)).FpOrderBy, pTab, bp) if **(**uintptr)(__ccgo_up(bp)) != 0 { v1 = (*TExprList)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FnExpr } else { v1 = 0 } (*TWindow)(unsafe.Pointer(pMWin)).FnBufferCol = v1 /* Append the PARTITION BY and ORDER BY expressions to the to the ** sub-select expression list. They are required to figure out where ** boundaries for partitions and sets of peer rows lie. */ **(**uintptr)(__ccgo_up(bp)) = _exprListAppendList(tls, pParse, **(**uintptr)(__ccgo_up(bp)), (*TWindow)(unsafe.Pointer(pMWin)).FpPartition, 0) **(**uintptr)(__ccgo_up(bp)) = _exprListAppendList(tls, pParse, **(**uintptr)(__ccgo_up(bp)), (*TWindow)(unsafe.Pointer(pMWin)).FpOrderBy, 0) /* Append the arguments passed to each window function to the ** sub-select expression list. Also allocate two registers for each ** window function - one for the accumulator, another for interim ** results. */ pWin = pMWin for { if !(pWin != 0) { break } pArgs = *(*uintptr)(unsafe.Pointer((*TWindow)(unsafe.Pointer(pWin)).FpOwner + 32)) if (*TFuncDef)(unsafe.Pointer((*TWindow)(unsafe.Pointer(pWin)).FpWFunc)).FfuncFlags&uint32(SQLITE_SUBTYPE) != 0 { _selectWindowRewriteEList(tls, pParse, pMWin, pSrc, pArgs, pTab, bp) if **(**uintptr)(__ccgo_up(bp)) != 0 { v1 = (*TExprList)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FnExpr } else { v1 = 0 } (*TWindow)(unsafe.Pointer(pWin)).FiArgCol = v1 (*TWindow)(unsafe.Pointer(pWin)).FbExprArgs = uint8(1) } else { if **(**uintptr)(__ccgo_up(bp)) != 0 { v1 = (*TExprList)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FnExpr } else { v1 = 0 } (*TWindow)(unsafe.Pointer(pWin)).FiArgCol = v1 **(**uintptr)(__ccgo_up(bp)) = _exprListAppendList(tls, pParse, **(**uintptr)(__ccgo_up(bp)), pArgs, 0) } if (*TWindow)(unsafe.Pointer(pWin)).FpFilter != 0 { pFilter = _sqlite3ExprDup(tls, db, (*TWindow)(unsafe.Pointer(pWin)).FpFilter, 0) **(**uintptr)(__ccgo_up(bp)) = _sqlite3ExprListAppend(tls, pParse, **(**uintptr)(__ccgo_up(bp)), pFilter) } v2 = pParse + 60 *(*int32)(unsafe.Pointer(v2)) = *(*int32)(unsafe.Pointer(v2)) + 1 v1 = *(*int32)(unsafe.Pointer(v2)) (*TWindow)(unsafe.Pointer(pWin)).FregAccum = v1 v2 = pParse + 60 *(*int32)(unsafe.Pointer(v2)) = *(*int32)(unsafe.Pointer(v2)) + 1 v1 = *(*int32)(unsafe.Pointer(v2)) (*TWindow)(unsafe.Pointer(pWin)).FregResult = v1 _sqlite3VdbeAddOp2(tls, v, int32(OP_Null), 0, (*TWindow)(unsafe.Pointer(pWin)).FregAccum) goto _4 _4: ; pWin = (*TWindow)(unsafe.Pointer(pWin)).FpNextWin } /* If there is no ORDER BY or PARTITION BY clause, and the window ** function accepts zero arguments, and there are no other columns ** selected (e.g. "SELECT row_number() OVER () FROM t1"), it is possible ** that pSublist is still NULL here. Add a constant expression here to ** keep everything legal in this case. */ if **(**uintptr)(__ccgo_up(bp)) == uintptr(0) { **(**uintptr)(__ccgo_up(bp)) = _sqlite3ExprListAppend(tls, pParse, uintptr(0), _sqlite3ExprInt32(tls, db, 0)) } pSub = _sqlite3SelectNew(tls, pParse, **(**uintptr)(__ccgo_up(bp)), pSrc, pWhere, pGroupBy, pHaving, pSort, uint32(0), uintptr(0)) (*TSelect)(unsafe.Pointer(p)).FpSrc = _sqlite3SrcListAppend(tls, pParse, uintptr(0), uintptr(0), uintptr(0)) /* Due to db->mallocFailed test inside ** of sqlite3DbMallocRawNN() called from ** sqlite3SrcListAppend() */ if (*TSelect)(unsafe.Pointer(p)).FpSrc == uintptr(0) { _sqlite3SelectDelete(tls, db, pSub) } else { if _sqlite3SrcItemAttachSubquery(tls, pParse, (*TSelect)(unsafe.Pointer(p)).FpSrc+8, pSub, 0) != 0 { libc.SetBitFieldPtr32Uint32((*TSelect)(unsafe.Pointer(p)).FpSrc+8+24+4, libc.Uint32FromInt32(1), 4, 0x10) _sqlite3SrcListAssignCursors(tls, pParse, (*TSelect)(unsafe.Pointer(p)).FpSrc) **(**Tu32)(__ccgo_up(pSub + 4)) |= libc.Uint32FromInt32(libc.Int32FromInt32(SF_Expanded) | libc.Int32FromInt32(SF_OrderByReqd)) pTab2 = _sqlite3ResultSetOfSelect(tls, pParse, pSub, uint8(SQLITE_AFF_NONE)) **(**Tu32)(__ccgo_up(pSub + 4)) |= selFlags & uint32(SF_Aggregate) if pTab2 == uintptr(0) { /* Might actually be some other kind of error, but in that case ** pParse->nErr will be set, so if SQLITE_NOMEM is set, we will get ** the correct error message regardless. */ rc = int32(SQLITE_NOMEM) } else { libc.Xmemcpy(tls, pTab, pTab2, uint64(120)) **(**Tu32)(__ccgo_up(pTab + 48)) |= uint32(TF_Ephemeral) (*(*TSrcItem)(unsafe.Pointer((*TSelect)(unsafe.Pointer(p)).FpSrc + 8))).FpSTab = pTab pTab = pTab2 libc.Xmemset(tls, bp+8, 0, uint64(48)) (**(**TWalker)(__ccgo_up(bp + 8))).FxExprCallback = __ccgo_fp(_sqlite3WindowExtraAggFuncDepth) (**(**TWalker)(__ccgo_up(bp + 8))).FxSelectCallback = __ccgo_fp(_sqlite3WalkerDepthIncrease) (**(**TWalker)(__ccgo_up(bp + 8))).FxSelectCallback2 = __ccgo_fp(_sqlite3WalkerDepthDecrease) _sqlite3WalkSelect(tls, bp+8, pSub) } } } if (*Tsqlite3)(unsafe.Pointer(db)).FmallocFailed != 0 { rc = int32(SQLITE_NOMEM) } /* Defer deleting the temporary table pTab because if an error occurred, ** there could still be references to that table embedded in the ** result-set or ORDER BY clause of the SELECT statement p. */ _sqlite3ParserAddCleanup(tls, pParse, __ccgo_fp(_sqlite3DbFree), pTab) } return rc } // C documentation // // /* // ** For OP_Column, factor out the case where content is loaded from // ** overflow pages, so that the code to implement this case is separate // ** the common case where all content fits on the page. Factoring out // ** the code reduces register pressure and helps the common case // ** to run faster. // */ func _vdbeColumnFromOverflow(tls *libc.TLS, pC uintptr, iCol int32, t Tu32, iOffset Ti64, cacheStatus Tu32, colCacheCtr Tu32, pDest uintptr) (r int32) { var db, pBuf, pCache, v1 uintptr var encoding, len1, rc int32 _, _, _, _, _, _, _ = db, encoding, len1, pBuf, pCache, rc, v1 db = (*TMem)(unsafe.Pointer(pDest)).Fdb encoding = libc.Int32FromUint8((*TMem)(unsafe.Pointer(pDest)).Fenc) len1 = libc.Int32FromUint32(_sqlite3VdbeSerialTypeLen(tls, t)) if len1 > **(**int32)(__ccgo_up(db + 136)) { return int32(SQLITE_TOOBIG) } if len1 > int32(4000) && (*TVdbeCursor)(unsafe.Pointer(pC)).FpKeyInfo == uintptr(0) { if int32(TBool(*(*uint8)(unsafe.Pointer(pC + 8))&0x10>>4)) == 0 { (*TVdbeCursor)(unsafe.Pointer(pC)).FpCache = _sqlite3DbMallocZero(tls, db, uint64(32)) if (*TVdbeCursor)(unsafe.Pointer(pC)).FpCache == uintptr(0) { return int32(SQLITE_NOMEM) } libc.SetBitFieldPtr8Uint32(pC+8, libc.Uint32FromInt32(1), 4, 0x10) } pCache = (*TVdbeCursor)(unsafe.Pointer(pC)).FpCache if (*TVdbeTxtBlbCache)(unsafe.Pointer(pCache)).FpCValue == uintptr(0) || (*TVdbeTxtBlbCache)(unsafe.Pointer(pCache)).FiCol != iCol || (*TVdbeTxtBlbCache)(unsafe.Pointer(pCache)).FcacheStatus != cacheStatus || (*TVdbeTxtBlbCache)(unsafe.Pointer(pCache)).FcolCacheCtr != colCacheCtr || (*TVdbeTxtBlbCache)(unsafe.Pointer(pCache)).FiOffset != _sqlite3BtreeOffset(tls, *(*uintptr)(unsafe.Pointer(pC + 48))) { if (*TVdbeTxtBlbCache)(unsafe.Pointer(pCache)).FpCValue != 0 { _sqlite3RCStrUnref(tls, (*TVdbeTxtBlbCache)(unsafe.Pointer(pCache)).FpCValue) } v1 = _sqlite3RCStrNew(tls, libc.Uint64FromInt32(len1+int32(3))) (*TVdbeTxtBlbCache)(unsafe.Pointer(pCache)).FpCValue = v1 pBuf = v1 if pBuf == uintptr(0) { return int32(SQLITE_NOMEM) } rc = _sqlite3BtreePayload(tls, *(*uintptr)(unsafe.Pointer(pC + 48)), libc.Uint32FromInt64(iOffset), libc.Uint32FromInt32(len1), pBuf) if rc != 0 { return rc } **(**uint8)(__ccgo_up(pBuf + uintptr(len1))) = uint8(0) **(**uint8)(__ccgo_up(pBuf + uintptr(len1+int32(1)))) = uint8(0) **(**uint8)(__ccgo_up(pBuf + uintptr(len1+int32(2)))) = uint8(0) (*TVdbeTxtBlbCache)(unsafe.Pointer(pCache)).FiCol = iCol (*TVdbeTxtBlbCache)(unsafe.Pointer(pCache)).FcacheStatus = cacheStatus (*TVdbeTxtBlbCache)(unsafe.Pointer(pCache)).FcolCacheCtr = colCacheCtr (*TVdbeTxtBlbCache)(unsafe.Pointer(pCache)).FiOffset = _sqlite3BtreeOffset(tls, *(*uintptr)(unsafe.Pointer(pC + 48))) } else { pBuf = (*TVdbeTxtBlbCache)(unsafe.Pointer(pCache)).FpCValue } _sqlite3RCStrRef(tls, pBuf) if t&uint32(1) != 0 { rc = _sqlite3VdbeMemSetStr(tls, pDest, pBuf, int64(len1), libc.Uint8FromInt32(encoding), __ccgo_fp(_sqlite3RCStrUnref)) v1 = pDest + 20 *(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) | libc.Int32FromInt32(MEM_Term)) } else { rc = _sqlite3VdbeMemSetStr(tls, pDest, pBuf, int64(len1), uint8(0), __ccgo_fp(_sqlite3RCStrUnref)) } } else { rc = _sqlite3VdbeMemFromBtree(tls, *(*uintptr)(unsafe.Pointer(pC + 48)), libc.Uint32FromInt64(iOffset), libc.Uint32FromInt32(len1), pDest) if rc != 0 { return rc } _sqlite3VdbeSerialGet(tls, (*TMem)(unsafe.Pointer(pDest)).Fz, t, pDest) if t&uint32(1) != uint32(0) && encoding == int32(SQLITE_UTF8) { **(**uint8)(__ccgo_up((*TMem)(unsafe.Pointer(pDest)).Fz + uintptr(len1))) = uint8(0) v1 = pDest + 20 *(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) | libc.Int32FromInt32(MEM_Term)) } } v1 = pDest + 20 *(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) & ^libc.Int32FromInt32(MEM_Ephem)) return rc } // C documentation // // /* // ** Attempt the transfer optimization on INSERTs of the form // ** // ** INSERT INTO tab1 SELECT * FROM tab2; // ** // ** The xfer optimization transfers raw records from tab2 over to tab1. // ** Columns are not decoded and reassembled, which greatly improves // ** performance. Raw index records are transferred in the same way. // ** // ** The xfer optimization is only attempted if tab1 and tab2 are compatible. // ** There are lots of rules for determining compatibility - see comments // ** embedded in the code for details. // ** // ** This routine returns TRUE if the optimization is guaranteed to be used. // ** Sometimes the xfer optimization will only work if the destination table // ** is empty - a factor that can only be determined at run-time. In that // ** case, this routine generates code for the xfer optimization but also // ** does a test to see if the destination table is empty and jumps over the // ** xfer optimization code if the test fails. In that case, this routine // ** returns FALSE so that the caller will know to go ahead and generate // ** an unoptimized transfer. This routine also returns FALSE if there // ** is no chance that the xfer optimization can be applied. // ** // ** This optimization is particularly useful at making VACUUM run faster. // */ func _xferOptimization(tls *libc.TLS, pParse uintptr, pDest uintptr, pSelect uintptr, onError int32, iDbDest int32) (r int32) { var addr1, addr2, destHasUniqueIdx, emptyDestTest, emptySrcTest, i, iDbSrc, iDest, iSrc, regAutoinc, regData, regRowid, v4 int32 var db, pDestCol, pDestExpr, pDestIdx, pEList, pItem, pSrc, pSrcCol, pSrcExpr, pSrcIdx, v, zColl, v5 uintptr var idxInsFlags, insFlags Tu8 _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = addr1, addr2, db, destHasUniqueIdx, emptyDestTest, emptySrcTest, i, iDbSrc, iDest, iSrc, idxInsFlags, insFlags, pDestCol, pDestExpr, pDestIdx, pEList, pItem, pSrc, pSrcCol, pSrcExpr, pSrcIdx, regAutoinc, regData, regRowid, v, zColl, v4, v5 db = (*TParse)(unsafe.Pointer(pParse)).Fdb /* Loop addresses */ emptyDestTest = 0 /* Address of test for empty pDest */ emptySrcTest = 0 /* Memory register used by AUTOINC */ destHasUniqueIdx = 0 /* Registers holding data and rowid */ if (*TParse)(unsafe.Pointer(pParse)).FpWith != 0 || (*TSelect)(unsafe.Pointer(pSelect)).FpWith != 0 { /* Do not attempt to process this query if there are an WITH clauses ** attached to it. Proceeding may generate a false "no such table: xxx" ** error if pSelect reads from a CTE named "xxx". */ return 0 } if libc.Int32FromUint8((*TTable)(unsafe.Pointer(pDest)).FeTabType) == int32(TABTYP_VTAB) { return 0 /* tab1 must not be a virtual table */ } if onError == int32(OE_Default) { if int32((*TTable)(unsafe.Pointer(pDest)).FiPKey) >= 0 { onError = libc.Int32FromUint8((*TTable)(unsafe.Pointer(pDest)).FkeyConf) } if onError == int32(OE_Default) { onError = int32(OE_Abort) } } /* allocated even if there is no FROM clause */ if (*TSrcList)(unsafe.Pointer((*TSelect)(unsafe.Pointer(pSelect)).FpSrc)).FnSrc != int32(1) { return 0 /* FROM clause must have exactly one term */ } if int32(*(*uint32)(unsafe.Pointer((*TSelect)(unsafe.Pointer(pSelect)).FpSrc + 8 + 24 + 4))&0x4>>2) != 0 { return 0 /* FROM clause cannot contain a subquery */ } if (*TSelect)(unsafe.Pointer(pSelect)).FpWhere != 0 { return 0 /* SELECT may not have a WHERE clause */ } if (*TSelect)(unsafe.Pointer(pSelect)).FpOrderBy != 0 { return 0 /* SELECT may not have an ORDER BY clause */ } /* Do not need to test for a HAVING clause. If HAVING is present but ** there is no ORDER BY, we will get an error. */ if (*TSelect)(unsafe.Pointer(pSelect)).FpGroupBy != 0 { return 0 /* SELECT may not have a GROUP BY clause */ } if (*TSelect)(unsafe.Pointer(pSelect)).FpLimit != 0 { return 0 /* SELECT may not have a LIMIT clause */ } if (*TSelect)(unsafe.Pointer(pSelect)).FpPrior != 0 { return 0 /* SELECT may not be a compound query */ } if (*TSelect)(unsafe.Pointer(pSelect)).FselFlags&uint32(SF_Distinct) != 0 { return 0 /* SELECT may not be DISTINCT */ } pEList = (*TSelect)(unsafe.Pointer(pSelect)).FpEList if (*TExprList)(unsafe.Pointer(pEList)).FnExpr != int32(1) { return 0 /* The result set must have exactly one column */ } if libc.Int32FromUint8((*TExpr)(unsafe.Pointer((*(*TExprList_item)(unsafe.Pointer(pEList + 8))).FpExpr)).Fop) != int32(TK_ASTERISK) { return 0 /* The result set must be the special operator "*" */ } /* At this point we have established that the statement is of the ** correct syntactic form to participate in this optimization. Now ** we have to check the semantics. */ pItem = (*TSelect)(unsafe.Pointer(pSelect)).FpSrc + 8 pSrc = _sqlite3LocateTableItem(tls, pParse, uint32(0), pItem) if pSrc == uintptr(0) { return 0 /* FROM clause does not contain a real table */ } if (*TTable)(unsafe.Pointer(pSrc)).Ftnum == (*TTable)(unsafe.Pointer(pDest)).Ftnum && (*TTable)(unsafe.Pointer(pSrc)).FpSchema == (*TTable)(unsafe.Pointer(pDest)).FpSchema { /* Possible due to bad sqlite_schema.rootpage */ return 0 /* tab1 and tab2 may not be the same table */ } if libc.BoolInt32((*TTable)(unsafe.Pointer(pDest)).FtabFlags&uint32(TF_WithoutRowid) == uint32(0)) != libc.BoolInt32((*TTable)(unsafe.Pointer(pSrc)).FtabFlags&uint32(TF_WithoutRowid) == uint32(0)) { return 0 /* source and destination must both be WITHOUT ROWID or not */ } if !(libc.Int32FromUint8((*TTable)(unsafe.Pointer(pSrc)).FeTabType) == libc.Int32FromInt32(TABTYP_NORM)) { return 0 /* tab2 may not be a view or virtual table */ } if int32((*TTable)(unsafe.Pointer(pDest)).FnCol) != int32((*TTable)(unsafe.Pointer(pSrc)).FnCol) { return 0 /* Number of columns must be the same in tab1 and tab2 */ } if int32((*TTable)(unsafe.Pointer(pDest)).FiPKey) != int32((*TTable)(unsafe.Pointer(pSrc)).FiPKey) { return 0 /* Both tables must have the same INTEGER PRIMARY KEY */ } if (*TTable)(unsafe.Pointer(pDest)).FtabFlags&uint32(TF_Strict) != uint32(0) && (*TTable)(unsafe.Pointer(pSrc)).FtabFlags&uint32(TF_Strict) == uint32(0) { return 0 /* Cannot feed from a non-strict into a strict table */ } i = 0 for { if !(i < int32((*TTable)(unsafe.Pointer(pDest)).FnCol)) { break } pDestCol = (*TTable)(unsafe.Pointer(pDest)).FaCol + uintptr(i)*16 pSrcCol = (*TTable)(unsafe.Pointer(pSrc)).FaCol + uintptr(i)*16 /* Even if tables t1 and t2 have identical schemas, if they contain ** generated columns, then this statement is semantically incorrect: ** ** INSERT INTO t2 SELECT * FROM t1; ** ** The reason is that generated column values are returned by the ** the SELECT statement on the right but the INSERT statement on the ** left wants them to be omitted. ** ** Nevertheless, this is a useful notational shorthand to tell SQLite ** to do a bulk transfer all of the content from t1 over to t2. ** ** We could, in theory, disable this (except for internal use by the ** VACUUM command where it is actually needed). But why do that? It ** seems harmless enough, and provides a useful service. */ if libc.Int32FromUint16((*TColumn)(unsafe.Pointer(pDestCol)).FcolFlags)&int32(COLFLAG_GENERATED) != libc.Int32FromUint16((*TColumn)(unsafe.Pointer(pSrcCol)).FcolFlags)&int32(COLFLAG_GENERATED) { return 0 /* Both columns have the same generated-column type */ } /* But the transfer is only allowed if both the source and destination ** tables have the exact same expressions for generated columns. ** This requirement could be relaxed for VIRTUAL columns, I suppose. */ if libc.Int32FromUint16((*TColumn)(unsafe.Pointer(pDestCol)).FcolFlags)&int32(COLFLAG_GENERATED) != 0 { if _sqlite3ExprCompare(tls, uintptr(0), _sqlite3ColumnExpr(tls, pSrc, pSrcCol), _sqlite3ColumnExpr(tls, pDest, pDestCol), -int32(1)) != 0 { return 0 /* Different generator expressions */ } } if libc.Int32FromUint8((*TColumn)(unsafe.Pointer(pDestCol)).Faffinity) != libc.Int32FromUint8((*TColumn)(unsafe.Pointer(pSrcCol)).Faffinity) { return 0 /* Affinity must be the same on all columns */ } if Xsqlite3_stricmp(tls, _sqlite3ColumnColl(tls, pDestCol), _sqlite3ColumnColl(tls, pSrcCol)) != 0 { return 0 /* Collating sequence must be the same on all columns */ } if int32(uint32(*(*uint8)(unsafe.Pointer(pDestCol + 8))&0xf>>0)) != 0 && !(int32(uint32(*(*uint8)(unsafe.Pointer(pSrcCol + 8))&0xf>>0)) != 0) { return 0 /* tab2 must be NOT NULL if tab1 is */ } /* Default values for second and subsequent columns need to match. */ if libc.Int32FromUint16((*TColumn)(unsafe.Pointer(pDestCol)).FcolFlags)&int32(COLFLAG_GENERATED) == 0 && i > 0 { pDestExpr = _sqlite3ColumnExpr(tls, pDest, pDestCol) pSrcExpr = _sqlite3ColumnExpr(tls, pSrc, pSrcCol) if libc.BoolInt32(pDestExpr == uintptr(0)) != libc.BoolInt32(pSrcExpr == uintptr(0)) || pDestExpr != uintptr(0) && libc.Xstrcmp(tls, *(*uintptr)(unsafe.Pointer(pDestExpr + 8)), *(*uintptr)(unsafe.Pointer(pSrcExpr + 8))) != 0 { return 0 /* Default values must be the same for all columns */ } } goto _1 _1: ; i = i + 1 } pDestIdx = (*TTable)(unsafe.Pointer(pDest)).FpIndex for { if !(pDestIdx != 0) { break } if libc.Int32FromUint8((*TIndex)(unsafe.Pointer(pDestIdx)).FonError) != OE_None { destHasUniqueIdx = int32(1) } pSrcIdx = (*TTable)(unsafe.Pointer(pSrc)).FpIndex for { if !(pSrcIdx != 0) { break } if _xferCompatibleIndex(tls, pDestIdx, pSrcIdx) != 0 { break } goto _3 _3: ; pSrcIdx = (*TIndex)(unsafe.Pointer(pSrcIdx)).FpNext } if pSrcIdx == uintptr(0) { return 0 /* pDestIdx has no corresponding index in pSrc */ } if (*TIndex)(unsafe.Pointer(pSrcIdx)).Ftnum == (*TIndex)(unsafe.Pointer(pDestIdx)).Ftnum && (*TTable)(unsafe.Pointer(pSrc)).FpSchema == (*TTable)(unsafe.Pointer(pDest)).FpSchema && _sqlite3FaultSim(tls, int32(411)) == SQLITE_OK { /* The sqlite3FaultSim() call allows this corruption test to be ** bypassed during testing, in order to exercise other corruption tests ** further downstream. */ return 0 /* Corrupt schema - two indexes on the same btree */ } goto _2 _2: ; pDestIdx = (*TIndex)(unsafe.Pointer(pDestIdx)).FpNext } if (*TTable)(unsafe.Pointer(pDest)).FpCheck != 0 && (*Tsqlite3)(unsafe.Pointer(db)).FmDbFlags&uint32(DBFLAG_Vacuum) == uint32(0) && _sqlite3ExprListCompare(tls, (*TTable)(unsafe.Pointer(pSrc)).FpCheck, (*TTable)(unsafe.Pointer(pDest)).FpCheck, -int32(1)) != 0 { return 0 /* Tables have different CHECK constraints. Ticket #2252 */ } /* Disallow the transfer optimization if the destination table contains ** any foreign key constraints. This is more restrictive than necessary. ** But the main beneficiary of the transfer optimization is the VACUUM ** command, and the VACUUM command disables foreign key constraints. So ** the extra complication to make this rule less restrictive is probably ** not worth the effort. Ticket [6284df89debdfa61db8073e062908af0c9b6118e] */ if (*Tsqlite3)(unsafe.Pointer(db)).Fflags&uint64(SQLITE_ForeignKeys) != uint64(0) && (*(*struct { FaddColOffset int32 FpFKey uintptr FpDfltList uintptr })(unsafe.Pointer(pDest + 64))).FpFKey != uintptr(0) { return 0 } if (*Tsqlite3)(unsafe.Pointer(db)).Fflags&(libc.Uint64FromInt32(libc.Int32FromInt32(0x00001))<= 0 { addr1 = _sqlite3VdbeAddOp2(tls, v, int32(OP_Rowid), iSrc, regRowid) if (*Tsqlite3)(unsafe.Pointer(db)).FmDbFlags&uint32(DBFLAG_Vacuum) == uint32(0) { addr2 = _sqlite3VdbeAddOp3(tls, v, int32(OP_NotExists), iDest, 0, regRowid) _sqlite3RowidConstraint(tls, pParse, onError, pDest) _sqlite3VdbeJumpHere(tls, v, addr2) } _autoIncStep(tls, pParse, regAutoinc, regRowid) } else { if (*TTable)(unsafe.Pointer(pDest)).FpIndex == uintptr(0) && !((*Tsqlite3)(unsafe.Pointer(db)).FmDbFlags&libc.Uint32FromInt32(DBFLAG_VacuumInto) != 0) { addr1 = _sqlite3VdbeAddOp2(tls, v, int32(OP_NewRowid), iDest, regRowid) } else { addr1 = _sqlite3VdbeAddOp2(tls, v, int32(OP_Rowid), iSrc, regRowid) } } if (*Tsqlite3)(unsafe.Pointer(db)).FmDbFlags&uint32(DBFLAG_Vacuum) != 0 { _sqlite3VdbeAddOp1(tls, v, int32(OP_SeekEnd), iDest) insFlags = libc.Uint8FromInt32(libc.Int32FromInt32(OPFLAG_APPEND) | libc.Int32FromInt32(OPFLAG_USESEEKRESULT) | libc.Int32FromInt32(OPFLAG_PREFORMAT)) } else { insFlags = libc.Uint8FromInt32(libc.Int32FromInt32(OPFLAG_NCHANGE) | libc.Int32FromInt32(OPFLAG_LASTROWID) | libc.Int32FromInt32(OPFLAG_APPEND) | libc.Int32FromInt32(OPFLAG_PREFORMAT)) } if (*Tsqlite3)(unsafe.Pointer(db)).FmDbFlags&uint32(DBFLAG_Vacuum) == uint32(0) { _sqlite3VdbeAddOp3(tls, v, int32(OP_RowData), iSrc, regData, int32(1)) insFlags = libc.Uint8FromInt32(int32(insFlags) & ^libc.Int32FromInt32(OPFLAG_PREFORMAT)) } else { _sqlite3VdbeAddOp3(tls, v, int32(OP_RowCell), iDest, iSrc, regRowid) } _sqlite3VdbeAddOp3(tls, v, int32(OP_Insert), iDest, regData, regRowid) if (*Tsqlite3)(unsafe.Pointer(db)).FmDbFlags&uint32(DBFLAG_Vacuum) == uint32(0) { _sqlite3VdbeChangeP4(tls, v, -int32(1), pDest, -int32(5)) } _sqlite3VdbeChangeP5(tls, v, uint16(insFlags)) _sqlite3VdbeAddOp2(tls, v, int32(OP_Next), iSrc, addr1) _sqlite3VdbeAddOp2(tls, v, int32(OP_Close), iSrc, 0) _sqlite3VdbeAddOp2(tls, v, int32(OP_Close), iDest, 0) } else { _sqlite3TableLock(tls, pParse, iDbDest, (*TTable)(unsafe.Pointer(pDest)).Ftnum, uint8(1), (*TTable)(unsafe.Pointer(pDest)).FzName) _sqlite3TableLock(tls, pParse, iDbSrc, (*TTable)(unsafe.Pointer(pSrc)).Ftnum, uint8(0), (*TTable)(unsafe.Pointer(pSrc)).FzName) } pDestIdx = (*TTable)(unsafe.Pointer(pDest)).FpIndex for { if !(pDestIdx != 0) { break } idxInsFlags = uint8(0) pSrcIdx = (*TTable)(unsafe.Pointer(pSrc)).FpIndex for { if !(pSrcIdx != 0) { break } if _xferCompatibleIndex(tls, pDestIdx, pSrcIdx) != 0 { break } goto _9 _9: ; pSrcIdx = (*TIndex)(unsafe.Pointer(pSrcIdx)).FpNext } _sqlite3VdbeAddOp3(tls, v, int32(OP_OpenRead), iSrc, libc.Int32FromUint32((*TIndex)(unsafe.Pointer(pSrcIdx)).Ftnum), iDbSrc) _sqlite3VdbeSetP4KeyInfo(tls, pParse, pSrcIdx) _sqlite3VdbeAddOp3(tls, v, int32(OP_OpenWrite), iDest, libc.Int32FromUint32((*TIndex)(unsafe.Pointer(pDestIdx)).Ftnum), iDbDest) _sqlite3VdbeSetP4KeyInfo(tls, pParse, pDestIdx) _sqlite3VdbeChangeP5(tls, v, uint16(OPFLAG_BULKCSR)) addr1 = _sqlite3VdbeAddOp2(tls, v, int32(OP_Rewind), iSrc, 0) if (*Tsqlite3)(unsafe.Pointer(db)).FmDbFlags&uint32(DBFLAG_Vacuum) != 0 { /* This INSERT command is part of a VACUUM operation, which guarantees ** that the destination table is empty. If all indexed columns use ** collation sequence BINARY, then it can also be assumed that the ** index will be populated by inserting keys in strictly sorted ** order. In this case, instead of seeking within the b-tree as part ** of every OP_IdxInsert opcode, an OP_SeekEnd is added before the ** OP_IdxInsert to seek to the point within the b-tree where each key ** should be inserted. This is faster. ** ** If any of the indexed columns use a collation sequence other than ** BINARY, this optimization is disabled. This is because the user ** might change the definition of a collation sequence and then run ** a VACUUM command. In that case keys may not be written in strictly ** sorted order. */ i = 0 for { if !(i < libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pSrcIdx)).FnColumn)) { break } zColl = **(**uintptr)(__ccgo_up((*TIndex)(unsafe.Pointer(pSrcIdx)).FazColl + uintptr(i)*8)) if Xsqlite3_stricmp(tls, uintptr(unsafe.Pointer(&_sqlite3StrBINARY)), zColl) != 0 { break } goto _10 _10: ; i = i + 1 } if i == libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pSrcIdx)).FnColumn) { idxInsFlags = libc.Uint8FromInt32(libc.Int32FromInt32(OPFLAG_USESEEKRESULT) | libc.Int32FromInt32(OPFLAG_PREFORMAT)) _sqlite3VdbeAddOp1(tls, v, int32(OP_SeekEnd), iDest) _sqlite3VdbeAddOp2(tls, v, int32(OP_RowCell), iDest, iSrc) } } else { if !((*TTable)(unsafe.Pointer(pSrc)).FtabFlags&libc.Uint32FromInt32(TF_WithoutRowid) == libc.Uint32FromInt32(0)) && int32(uint32(*(*uint16)(unsafe.Pointer(pDestIdx + 100))&0x3>>0)) == int32(SQLITE_IDXTYPE_PRIMARYKEY) { idxInsFlags = libc.Uint8FromInt32(int32(idxInsFlags) | libc.Int32FromInt32(OPFLAG_NCHANGE)) } } if libc.Int32FromUint8(idxInsFlags) != libc.Int32FromInt32(OPFLAG_USESEEKRESULT)|libc.Int32FromInt32(OPFLAG_PREFORMAT) { _sqlite3VdbeAddOp3(tls, v, int32(OP_RowData), iSrc, regData, int32(1)) if (*Tsqlite3)(unsafe.Pointer(db)).FmDbFlags&uint32(DBFLAG_Vacuum) == uint32(0) && !((*TTable)(unsafe.Pointer(pDest)).FtabFlags&libc.Uint32FromInt32(TF_WithoutRowid) == libc.Uint32FromInt32(0)) && int32(uint32(*(*uint16)(unsafe.Pointer(pDestIdx + 100))&0x3>>0)) == int32(SQLITE_IDXTYPE_PRIMARYKEY) { _codeWithoutRowidPreupdate(tls, pParse, pDest, iDest, regData) } } _sqlite3VdbeAddOp2(tls, v, int32(OP_IdxInsert), iDest, regData) _sqlite3VdbeChangeP5(tls, v, libc.Uint16FromInt32(libc.Int32FromUint8(idxInsFlags)|int32(OPFLAG_APPEND))) _sqlite3VdbeAddOp2(tls, v, int32(OP_Next), iSrc, addr1+int32(1)) _sqlite3VdbeJumpHere(tls, v, addr1) _sqlite3VdbeAddOp2(tls, v, int32(OP_Close), iSrc, 0) _sqlite3VdbeAddOp2(tls, v, int32(OP_Close), iDest, 0) goto _8 _8: ; pDestIdx = (*TIndex)(unsafe.Pointer(pDestIdx)).FpNext } if emptySrcTest != 0 { _sqlite3VdbeJumpHere(tls, v, emptySrcTest) } _sqlite3ReleaseTempReg(tls, pParse, regRowid) _sqlite3ReleaseTempReg(tls, pParse, regData) if emptyDestTest != 0 { _sqlite3AutoincrementEnd(tls, pParse) _sqlite3VdbeAddOp2(tls, v, int32(OP_Halt), SQLITE_OK, 0) _sqlite3VdbeJumpHere(tls, v, emptyDestTest) _sqlite3VdbeAddOp2(tls, v, int32(OP_Close), iDest, 0) return 0 } else { return int32(1) } return r }