21
21
#include <string.h>
22
22
#include <ctype.h>
23
23
24
+ #include "psqlodbc.h"
24
25
#ifdef MULTIBYTE
25
26
#include "multibyte.h"
26
27
#endif
@@ -938,6 +939,26 @@ into_table_from(const char *stmt)
938
939
return isspace ((unsigned char ) stmt [4 ]);
939
940
}
940
941
942
+ /*----------
943
+ * Check if the statement is
944
+ * SELECT ... FOR UPDATE .....
945
+ * This isn't really a strict check but ...
946
+ *----------
947
+ */
948
+ static BOOL
949
+ table_for_update (const char * stmt , int * endpos )
950
+ {
951
+ const char * wstmt = stmt ;
952
+ while (isspace ((unsigned char ) * (++ wstmt )));
953
+ if (! * wstmt )
954
+ return FALSE;
955
+ if (strnicmp (wstmt , "update" , 6 ))
956
+ return FALSE;
957
+ wstmt += 6 ;
958
+ * endpos = wstmt - stmt ;
959
+ return !wstmt [0 ] || isspace ((unsigned char ) wstmt [0 ]);
960
+ }
961
+
941
962
/*
942
963
* This function inserts parameters into an SQL statements.
943
964
* It will also modify a SELECT statement for use with declare/fetch cursors.
@@ -968,14 +989,17 @@ copy_statement_with_parameters(StatementClass *stmt)
968
989
Oid lobj_oid ;
969
990
int lobj_fd ,
970
991
retval ;
971
- BOOL check_select_into = FALSE; /* select into check */
992
+ BOOL check_cursor_ok = FALSE; /* check cursor restriction */
972
993
BOOL proc_no_param = TRUE;
973
- unsigned int declare_pos ;
994
+ unsigned int declare_pos = 0 ;
974
995
ConnectionClass * conn = SC_get_conn (stmt );
975
996
ConnInfo * ci = & (conn -> connInfo );
976
- BOOL prepare_dummy_cursor = FALSE;
997
+ BOOL prepare_dummy_cursor = FALSE;
998
+ char token_save [32 ];
999
+ int token_len ;
1000
+ BOOL prev_token_end ;
977
1001
#ifdef DRIVER_CURSOR_IMPLEMENT
978
- BOOL ins_ctrl = FALSE;
1002
+ BOOL search_from_pos = FALSE;
979
1003
#endif /* DRIVER_CURSOR_IMPLEMENT */
980
1004
#ifdef PREPARE_TRIAL
981
1005
prepare_dummy_cursor = stmt -> pre_executing ;
@@ -1012,7 +1036,7 @@ copy_statement_with_parameters(StatementClass *stmt)
1012
1036
stmt -> options .scroll_concurrency = SQL_CONCUR_READ_ONLY ;
1013
1037
else if (!stmt -> ti || stmt -> ntab != 1 )
1014
1038
stmt -> options .scroll_concurrency = SQL_CONCUR_READ_ONLY ;
1015
- else ins_ctrl = TRUE;
1039
+ else search_from_pos = TRUE;
1016
1040
}
1017
1041
#endif /* DRIVER_CURSOR_IMPLEMENT */
1018
1042
@@ -1021,7 +1045,10 @@ copy_statement_with_parameters(StatementClass *stmt)
1021
1045
sprintf (stmt -> cursor_name , "SQL_CUR%p" , stmt );
1022
1046
oldstmtlen = strlen (old_statement );
1023
1047
CVT_INIT (oldstmtlen );
1048
+
1024
1049
stmt -> miscinfo = 0 ;
1050
+ token_len = 0 ;
1051
+ prev_token_end = TRUE;
1025
1052
/* For selects, prepend a declare cursor to the statement */
1026
1053
if (stmt -> statement_type == STMT_TYPE_SELECT )
1027
1054
{
@@ -1035,10 +1062,10 @@ copy_statement_with_parameters(StatementClass *stmt)
1035
1062
}
1036
1063
else if (ci -> drivers .use_declarefetch )
1037
1064
SC_set_fetchcursor (stmt );
1038
- sprintf (new_statement , "%s declare %s cursor for " ,
1065
+ sprintf (new_statement , "%sdeclare %s cursor for " ,
1039
1066
new_statement , stmt -> cursor_name );
1040
1067
npos = strlen (new_statement );
1041
- check_select_into = TRUE;
1068
+ check_cursor_ok = TRUE;
1042
1069
declare_pos = npos ;
1043
1070
}
1044
1071
}
@@ -1176,28 +1203,68 @@ copy_statement_with_parameters(StatementClass *stmt)
1176
1203
in_escape = TRUE;
1177
1204
else if (oldchar == '\"' )
1178
1205
in_dquote = TRUE;
1179
- else if (check_select_into && /* select into check */
1180
- opos > 0 &&
1181
- isspace ((unsigned char ) old_statement [opos - 1 ]) &&
1182
- into_table_from (& old_statement [opos ]))
1206
+ else
1183
1207
{
1184
- stmt -> statement_type = STMT_TYPE_CREATE ;
1185
- SC_no_pre_executable (stmt );
1186
- SC_no_fetchcursor (stmt );
1187
- stmt -> options .scroll_concurrency = SQL_CONCUR_READ_ONLY ;
1188
- memmove (new_statement , new_statement + declare_pos , npos - declare_pos );
1189
- npos -= declare_pos ;
1190
- }
1208
+ if (isspace (oldchar ))
1209
+ {
1210
+ if (!prev_token_end )
1211
+ {
1212
+ prev_token_end = TRUE;
1213
+ token_save [token_len ] = '\0' ;
1214
+ if (token_len == 4 )
1215
+ {
1216
+ if (check_cursor_ok &&
1217
+ into_table_from (& old_statement [opos - token_len ]))
1218
+ {
1219
+ stmt -> statement_type = STMT_TYPE_CREATE ;
1220
+ SC_no_pre_executable (stmt );
1221
+ SC_no_fetchcursor (stmt );
1222
+ stmt -> options .scroll_concurrency = SQL_CONCUR_READ_ONLY ;
1223
+ memmove (new_statement , new_statement + declare_pos , npos - declare_pos );
1224
+ npos -= declare_pos ;
1225
+ }
1191
1226
#ifdef DRIVER_CURSOR_IMPLEMENT
1192
- else if (ins_ctrl && /* select into check */
1193
- opos > 0 &&
1194
- isspace ((unsigned char ) old_statement [opos - 1 ]) &&
1195
- strnicmp (& old_statement [opos ], "from" , 4 ) == 0 )
1196
- {
1197
- ins_ctrl = FALSE;
1198
- CVT_APPEND_STR (", CTID, OID " );
1199
- }
1227
+ else if (search_from_pos && /* where's from clause */
1228
+ strnicmp (token_save , "from ", 4 ) == 0 )
1229
+ {
1230
+ search_from_pos = FALSE;
1231
+ npos -= 5 ;
1232
+ CVT_APPEND_STR (", CTID, OID from" );
1233
+ }
1200
1234
#endif /* DRIVER_CURSOR_IMPLEMENT */
1235
+ }
1236
+ if (token_len == 3 )
1237
+ {
1238
+ int endpos ;
1239
+ if (check_cursor_ok &&
1240
+ strnicmp (token_save , "for" , 3 ) == 0 &&
1241
+ table_for_update (& old_statement [opos ], & endpos ))
1242
+ {
1243
+ SC_no_fetchcursor (stmt );
1244
+ stmt -> options .scroll_concurrency = SQL_CONCUR_READ_ONLY ;
1245
+ if (prepare_dummy_cursor )
1246
+ {
1247
+ npos -= 4 ;
1248
+ opos += endpos ;
1249
+ }
1250
+ else
1251
+ {
1252
+ memmove (new_statement , new_statement + declare_pos , npos - declare_pos );
1253
+ npos -= declare_pos ;
1254
+ }
1255
+ }
1256
+ }
1257
+ }
1258
+ }
1259
+ else if (prev_token_end )
1260
+ {
1261
+ prev_token_end = FALSE;
1262
+ token_save [0 ] = oldchar ;
1263
+ token_len = 1 ;
1264
+ }
1265
+ else
1266
+ token_save [token_len ++ ] = oldchar ;
1267
+ }
1201
1268
CVT_APPEND_CHAR (oldchar );
1202
1269
continue ;
1203
1270
}
@@ -1634,7 +1701,7 @@ copy_statement_with_parameters(StatementClass *stmt)
1634
1701
}
1635
1702
1636
1703
#ifdef DRIVER_CURSOR_IMPLEMENT
1637
- if (ins_ctrl )
1704
+ if (search_from_pos )
1638
1705
stmt -> options .scroll_concurrency = SQL_CONCUR_READ_ONLY ;
1639
1706
#endif /* DRIVER_CURSOR_IMPLEMENT */
1640
1707
#ifdef PREPARE_TRIAL
@@ -2142,7 +2209,7 @@ decode(const char *in, char *out)
2142
2209
*-------
2143
2210
*/
2144
2211
int
2145
- convert_lo (StatementClass * stmt , void * value , Int2 fCType , PTR rgbValue ,
2212
+ convert_lo (StatementClass * stmt , const void * value , Int2 fCType , PTR rgbValue ,
2146
2213
SDWORD cbValueMax , SDWORD * pcbValue )
2147
2214
{
2148
2215
Oid oid ;
0 commit comments