@@ -325,6 +325,7 @@ SQLRETURN MADB_StmtReset(MADB_Stmt* Stmt)
325325 Stmt->State = MADB_SS_INITED;
326326 MADB_CLEAR_ERROR (&Stmt->Error );
327327 MADB_FREE (Stmt->UniqueIndex );
328+ Stmt->IndexType = 0 ;
328329 MADB_FREE (Stmt->TableName );
329330 }
330331 return SQL_SUCCESS;
@@ -734,8 +735,7 @@ SQLRETURN MADB_StmtPutData(MADB_Stmt *Stmt, SQLPOINTER DataPtr, SQLLEN StrLen_or
734735
735736 if (DataPtr != nullptr && StrLen_or_Ind < 0 && StrLen_or_Ind != SQL_NTS && StrLen_or_Ind != SQL_NULL_DATA)
736737 {
737- MADB_SetError (&Stmt->Error , MADB_ERR_HY090, nullptr , 0 );
738- return Stmt->Error .ReturnValue ;
738+ return MADB_SetError (&Stmt->Error , MADB_ERR_HY090, nullptr , 0 );
739739 }
740740
741741 if (Stmt->DataExecutionType != MADB_DAE_NORMAL)
@@ -750,8 +750,7 @@ SQLRETURN MADB_StmtPutData(MADB_Stmt *Stmt, SQLPOINTER DataPtr, SQLLEN StrLen_or
750750 /* Check if we've already sent any data */
751751 if (false )// we should have some own flags for that, other than MyStmt->stmt->params[Stmt->PutParam].long_data_used)
752752 {
753- MADB_SetError (&Stmt->Error , MADB_ERR_HY011, nullptr , 0 );
754- return Stmt->Error .ReturnValue ;
753+ return MADB_SetError (&Stmt->Error , MADB_ERR_HY011, nullptr , 0 );
755754 }
756755 Record->Type = SQL_TYPE_NULL;
757756 return SQL_SUCCESS;
@@ -760,8 +759,7 @@ SQLRETURN MADB_StmtPutData(MADB_Stmt *Stmt, SQLPOINTER DataPtr, SQLLEN StrLen_or
760759 /* This normally should be enforced by DM */
761760 if (DataPtr == nullptr && StrLen_or_Ind != 0 )
762761 {
763- MADB_SetError (&Stmt->Error , MADB_ERR_HY009, nullptr , 0 );
764- return Stmt->Error .ReturnValue ;
762+ return MADB_SetError (&Stmt->Error , MADB_ERR_HY009, nullptr , 0 );
765763 }
766764/*
767765 if (StrLen_or_Ind == SQL_NTS)
@@ -824,11 +822,9 @@ SQLRETURN MADB_ExecutePositionedUpdate(MADB_Stmt *Stmt, bool ExecDirect)
824822 MADB_CLEAR_ERROR (&Stmt->Error );
825823 if (!Stmt->PositionedCursor ->result )
826824 {
827- MADB_SetError (&Stmt->Error , MADB_ERR_34000, " Cursor has no result set or is not open" , 0 );
828- return Stmt->Error .ReturnValue ;
825+ return MADB_SetError (&Stmt->Error , MADB_ERR_34000, " Cursor has no result set or is not open" , 0 );
829826 }
830827 MADB_StmtDataSeek (Stmt->PositionedCursor , Stmt->PositionedCursor ->Cursor .Position );
831- Stmt->Methods ->RefreshRowPtrs (Stmt->PositionedCursor );
832828
833829 memcpy (&Stmt->Apd ->Header , &Stmt->Ard ->Header , sizeof (MADB_Header));
834830
@@ -3555,12 +3551,6 @@ SQLRETURN MADB_GetCursorName(MADB_Stmt *Stmt, void *CursorName, SQLSMALLINT Buff
35553551}
35563552/* }}} */
35573553
3558- /* {{{ MADB_RefreshRowPtrs */
3559- SQLRETURN MADB_RefreshRowPtrs (MADB_Stmt *Stmt)
3560- {
3561- return SQL_SUCCESS;// MoveNext(Stmt, 1LL);
3562- }
3563-
35643554/* {{{ MADB_RefreshDynamicCursor */
35653555SQLRETURN MADB_RefreshDynamicCursor (MADB_Stmt *Stmt)
35663556{
@@ -3602,7 +3592,7 @@ SQLRETURN MADB_StmtSetPos(MADB_Stmt* Stmt, SQLSETPOSIROW RowNumber, SQLUSMALLINT
36023592 return MADB_SetError (&Stmt->Error , MADB_ERR_24000, nullptr , 0 );
36033593 }
36043594
3605- /* This RowNumber != 1 is based on current SQL_POSITION implementation, and actually does not look to be quite correct
3595+ /* This RowNumber != 1 - we don't support block cursors with RS streaming. But with forward only we actually could
36063596 */
36073597 if (Stmt->Options .CursorType == SQL_CURSOR_FORWARD_ONLY && Operation == SQL_POSITION && RowNumber != 1 )
36083598 {
@@ -3613,34 +3603,44 @@ SQLRETURN MADB_StmtSetPos(MADB_Stmt* Stmt, SQLSETPOSIROW RowNumber, SQLUSMALLINT
36133603 {
36143604 return MADB_SetError (&Stmt->Error , MADB_ERR_HYC00, nullptr , 0 );
36153605 }
3606+ // SQL_ADD does not care about RowNumber. But probably the error still should be if it is not 0?
3607+ if (Operation != SQL_ADD && (RowNumber > Stmt->rs ->rowsCount () || (RowNumber == 0 && Operation == SQL_POSITION)))
3608+ {
3609+ return MADB_SetError (&Stmt->Error , MADB_ERR_HY109, nullptr , 0 );
3610+ }
3611+ // I wonder if for SQL_ALL that is even correct. Application kinda supposed to change values to insert them. If we arefresh data
3612+ // from server, we are overwriting those changes. But maybe should just use correct cursor type or SQLBulkOPerations
3613+ if (Stmt->Options .CursorType == SQL_CURSOR_DYNAMIC && !SQL_SUCCEEDED (Stmt->Methods ->RefreshDynamicCursor (Stmt)))
3614+ {
3615+ return Stmt->Error .ReturnValue ;
3616+ }
36163617
3617- switch (Operation) {
3618+ switch (Operation) {
36183619 case SQL_POSITION:
36193620 {
3620- if (RowNumber < 1 || RowNumber > Stmt->rs ->rowsCount ())
3621- {
3622- MADB_SetError (&Stmt->Error , MADB_ERR_HY109, nullptr , 0 );
3623- return Stmt->Error .ReturnValue ;
3624- }
3625- if (Stmt->Options .CursorType == SQL_CURSOR_DYNAMIC)
3626- if (!SQL_SUCCEEDED (Stmt->Methods ->RefreshDynamicCursor (Stmt)))
3627- return Stmt->Error .ReturnValue ;
3628- Stmt->Cursor .Position += (RowNumber - 1 );
3621+ Stmt->Cursor .Position += (RowNumber - 1 );
36293622 MADB_StmtDataSeek (Stmt, Stmt->Cursor .Position );
36303623 }
3631- break ;
3624+ case SQL_REFRESH:
3625+ /* todo */
3626+ /* Nothing else to do (at least for now) in this 2 cases */
3627+ return SQL_SUCCESS;
3628+ };
3629+
3630+ char * TableName= MADB_GetTableName (Stmt);
3631+ if (!TableName)
3632+ {
3633+ return MADB_SetError (&Stmt->Error , MADB_ERR_IM001, " Updatable Cursors with multiple tables are not supported" , 0 );
3634+ }
3635+ char * CatalogName= MADB_GetCatalogName (Stmt);
3636+
3637+ switch (Operation) {
36323638 case SQL_ADD:
36333639 {
36343640 MADB_DynString DynStmt;
36353641 SQLRETURN ret;
3636- char *TableName= MADB_GetTableName (Stmt);
3637- char *CatalogName= MADB_GetCatalogName (Stmt);
36383642 int column, param= 0 ;
36393643
3640- if (Stmt->Options .CursorType == SQL_CURSOR_DYNAMIC)
3641- if (!SQL_SUCCEEDED (Stmt->Methods ->RefreshDynamicCursor (Stmt)))
3642- return Stmt->Error .ReturnValue ;
3643-
36443644 Stmt->DaeRowNumber = RowNumber;
36453645
36463646 if (Stmt->DataExecutionType != MADB_DAE_ADD)
@@ -3721,35 +3721,17 @@ SQLRETURN MADB_StmtSetPos(MADB_Stmt* Stmt, SQLSETPOSIROW RowNumber, SQLUSMALLINT
37213721 break ;
37223722 case SQL_UPDATE:
37233723 {
3724- char *TableName= MADB_GetTableName (Stmt);
37253724 my_ulonglong Start= 0 ,
37263725 End= Stmt->rs ->rowsCount ();
3727- SQLRETURN result= SQL_INVALID_HANDLE; /* Just smth we cannot normally get */
3728-
3729- if (!TableName)
3730- {
3731- MADB_SetError (&Stmt->Error , MADB_ERR_IM001, " Updatable Cursors with multiple tables are not supported" , 0 );
3732- return Stmt->Error .ReturnValue ;
3733- }
3726+ SQLRETURN result= SQL_INVALID_HANDLE; /* Just smth we cannot normally get */
37343727
37353728 Stmt->AffectedRows = 0 ;
37363729
37373730 if ((SQLLEN)RowNumber > Stmt->LastRowFetched )
37383731 {
3739- MADB_SetError (&Stmt->Error , MADB_ERR_S1107, nullptr , 0 );
3740- return Stmt->Error .ReturnValue ;
3732+ return MADB_SetError (&Stmt->Error , MADB_ERR_S1107, nullptr , 0 );
37413733 }
37423734
3743- if (RowNumber < 0 || RowNumber > End)
3744- {
3745- MADB_SetError (&Stmt->Error , MADB_ERR_HY109, nullptr , 0 );
3746- return Stmt->Error .ReturnValue ;
3747- }
3748-
3749- if (Stmt->Options .CursorType == SQL_CURSOR_DYNAMIC)
3750- if (!SQL_SUCCEEDED (Stmt->Methods ->RefreshDynamicCursor (Stmt)))
3751- return Stmt->Error .ReturnValue ;
3752-
37533735 Stmt->DaeRowNumber = MAX (1 ,RowNumber);
37543736
37553737 /* Cursor is open, but no row was fetched, so we simulate
@@ -3758,11 +3740,12 @@ SQLRETURN MADB_StmtSetPos(MADB_Stmt* Stmt, SQLSETPOSIROW RowNumber, SQLUSMALLINT
37583740 Stmt->Cursor .Position = 1 ;
37593741
37603742 if (RowNumber)
3761- Start= End= Stmt->Cursor .Position + RowNumber - 1 ;
3743+ {
3744+ Start= End = Stmt->Cursor .Position + RowNumber - 1 ;
3745+ }
37623746 else
37633747 {
37643748 Start= Stmt->Cursor .Position ;
3765- /* TODO: if num_rows returns 1, End is 0? Start would be 1, no */
37663749 End= MIN (Stmt->rs ->rowsCount (), Start + Stmt->Ard ->Header .ArraySize - 1 );
37673750 }
37683751 /* Stmt->ArrayOffset will be incremented in StmtExecute() */
@@ -3773,7 +3756,6 @@ SQLRETURN MADB_StmtSetPos(MADB_Stmt* Stmt, SQLSETPOSIROW RowNumber, SQLUSMALLINT
37733756 {
37743757 SQLSMALLINT param= 0 , column;
37753758 MADB_StmtDataSeek (Stmt, Start);
3776- Stmt->Methods ->RefreshRowPtrs (Stmt);
37773759
37783760 /* We don't need to prepare the statement, if SetPos was called
37793761 from SQLParamData() function */
@@ -3839,9 +3821,11 @@ SQLRETURN MADB_StmtSetPos(MADB_Stmt* Stmt, SQLSETPOSIROW RowNumber, SQLUSMALLINT
38393821 ++param;
38403822 } /* End of for(column=0;...) */
38413823 if (Stmt->PutParam == MADB_NEED_DATA)
3824+ {
38423825 return SQL_NEED_DATA;
3843- } /* End of if (!ArrayOffset) */
3844-
3826+ }
3827+ } /* End of if (!ArrayOffset) */
3828+
38453829 if (Stmt->DaeStmt ->Methods ->Execute (Stmt->DaeStmt , FALSE ) != SQL_ERROR)
38463830 {
38473831 Stmt->AffectedRows += Stmt->DaeStmt ->AffectedRows ;
@@ -3865,29 +3849,15 @@ SQLRETURN MADB_StmtSetPos(MADB_Stmt* Stmt, SQLSETPOSIROW RowNumber, SQLUSMALLINT
38653849 }
38663850 case SQL_DELETE:
38673851 {
3852+ SQLRETURN result = SQL_INVALID_HANDLE; /* Just smth we cannot normally get */
38683853 SQLString DynamicStmt (" DELETE FROM " );
38693854 std::size_t baseStmtLen;
38703855 SQLULEN SaveArraySize= Stmt->Ard ->Header .ArraySize ;
38713856 my_ulonglong Start= 0 ,
38723857 End= Stmt->rs ->rowsCount ();
3873- char *TableName= MADB_GetTableName (Stmt);
3874-
3875- if (!TableName)
3876- {
3877- MADB_SetError (&Stmt->Error , MADB_ERR_IM001, " Updatable Cursors with multiple tables are not supported" , 0 );
3878- return Stmt->Error .ReturnValue ;
3879- }
38803858
38813859 Stmt->Ard ->Header .ArraySize = 1 ;
3882- if (Stmt->Options .CursorType == SQL_CURSOR_DYNAMIC)
3883- if (!SQL_SUCCEEDED (Stmt->Methods ->RefreshDynamicCursor (Stmt)))
3884- return Stmt->Error .ReturnValue ;
38853860 Stmt->AffectedRows = 0 ;
3886- if (RowNumber < 0 || RowNumber > End)
3887- {
3888- MADB_SetError (&Stmt->Error , MADB_ERR_HY109, nullptr , 0 );
3889- return Stmt->Error .ReturnValue ;
3890- }
38913861 Start= (RowNumber) ? Stmt->Cursor .Position + RowNumber - 1 : Stmt->Cursor .Position ;
38923862 if (SaveArraySize && !RowNumber)
38933863 {
@@ -3898,39 +3868,44 @@ SQLRETURN MADB_StmtSetPos(MADB_Stmt* Stmt, SQLSETPOSIROW RowNumber, SQLUSMALLINT
38983868 End= Start;
38993869 }
39003870 DynamicStmt.reserve (8182 );
3871+ DynamicStmt.append (TableName);
39013872 baseStmtLen= DynamicStmt.length ();
39023873 while (Start <= End)
39033874 {
39043875 MADB_StmtDataSeek (Stmt, Start);
3905- Stmt->Methods ->RefreshRowPtrs (Stmt);
3906- DynamicStmt.append (TableName);
3907-
3876+
39083877 if (MADB_DynStrGetWhere (Stmt, DynamicStmt, TableName, false ))
39093878 {
3910- return Stmt->Error .ReturnValue ;
3879+ MADB_SETPOS_AGG_RESULT (result, Stmt->Error .ReturnValue );
3880+ /* Continuing to next row. If there is no key - we will get it for all rows and as aggregated result.
3881+ * if we have unique key and NULL value on part of the key - we need to continue to next row (we wouldn't
3882+ * stop here before when we did not care about NULL values)
3883+ */
3884+ }
3885+ else
3886+ {
3887+ std::lock_guard<std::mutex> localScopeLock (Stmt->Connection ->guard ->getLock ());
3888+ Stmt->Connection ->guard ->safeRealQuery (DynamicStmt);
3889+ Stmt->AffectedRows += mysql_affected_rows (Stmt->Connection ->mariadb );
39113890 }
3912-
3913- std::lock_guard<std::mutex> localScopeLock (Stmt->Connection ->guard ->getLock ());
3914- Stmt->Connection ->guard ->safeRealQuery (DynamicStmt);
3915-
3916- Stmt->AffectedRows += mysql_affected_rows (Stmt->Connection ->mariadb );
39173891 ++Start;
39183892 DynamicStmt.erase (baseStmtLen);
3893+ /* Technichally we could combine here all conditions with OR. Other oportunity would be to use
3894+ * bulk operation, but OR is like way easier to make. But we won't know results for individual rows.
3895+ */
39193896 }
39203897 Stmt->Ard ->Header .ArraySize = SaveArraySize;
39213898 /* if we have a dynamic cursor we need to adjust the rowset size */
39223899 if (Stmt->Options .CursorType == SQL_CURSOR_DYNAMIC)
39233900 {
39243901 Stmt->LastRowFetched -= (unsigned long )Stmt->AffectedRows ;
39253902 }
3903+ /* Making sure we do not return initial value */
3904+ return result == SQL_INVALID_HANDLE ? SQL_SUCCESS : result;
39263905 }
39273906 break ;
3928- case SQL_REFRESH:
3929- /* todo*/
3930- break ;
39313907 default :
3932- MADB_SetError (&Stmt->Error , MADB_ERR_HYC00, " Only SQL_POSITION and SQL_REFRESH Operations are supported" , 0 );
3933- return Stmt->Error .ReturnValue ;
3908+ return MADB_SetError (&Stmt->Error , MADB_ERR_HYC00, " Only SQL_POSITION and SQL_REFRESH Operations are supported" , 0 );
39343909 }
39353910 return SQL_SUCCESS;
39363911}
@@ -4113,8 +4088,7 @@ struct st_ma_stmt_methods MADB_StmtMethods=
41134088 MADB_StmtParamData,
41144089 MADB_StmtPutData,
41154090 MADB_StmtBulkOperations,
4116- MADB_RefreshDynamicCursor,
4117- MADB_RefreshRowPtrs
4091+ MADB_RefreshDynamicCursor
41184092};
41194093
41204094MADB_Stmt::MADB_Stmt (MADB_Dbc* Dbc)
0 commit comments