Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
OCILib: 3.9.3
Oracle client/serveur: v8.1
Système: Windows 7 / VS2010
Bonjour,

Je me suis aperçu d'un petit problème lorsque j'utilise OCI_SetPrefetchSize avec une valeur supérieure à 1.
Dans mon cas, le bug apparait lorsque je fais une requête en récupérant juste 2 colonnes sur les 6 d'une table contenant environ 250 enregistrements.
La colonne 1 est un nombre, et la colonne 2 est un varchar2 qui peut être NULL.
Et voici le petit bout de code que j'utilise pour tester:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
int TestOCILib()
{
	if(OCI_Initialize(err_handler, "C:\\oracle\\ora81\\bin", OCI_ENV_DEFAULT) == false)
	{
		return -1;
	}
 
	printf("OCILib initialized\n");
 
	OCI_Connection* pConnection = OCI_ConnectionCreate(DATABASENAME, USER, PWD, OCI_SESSION_DEFAULT);
	if(pConnection == nullptr)
	{
		return -1;
	}
 
	FILE* pFile = fopen(FILENAME, "wt");
	if(pFile == nullptr)
	{
		return -1;
	}
 
	printf("Connected to database\n");
 
	OCI_Statement* pStatement = OCI_StatementCreate(pConnection);
	const bool bSetPrefetchResult = OCI_SetPrefetchSize(pStatement, PREFETCHSIZE);
	if(bSetPrefetchResult == false)
	{
		return -1;
	}
 
	OCI_ExecuteStmt(pStatement, REQUEST);
	printf("Request in progress...\n");
 
	OCI_Resultset* pResultSet = OCI_GetResultset(pStatement);
 
	bool bFetchOk = true;
	while(bFetchOk == true)
	{
		bFetchOk = OCI_FetchNext(pResultSet) != 0;
 
		if(bFetchOk == true)
		{
			unsigned int const uiColNb = OCI_GetColumnCount(pResultSet);
 
			for(unsigned int uiColIndex = 1; uiColIndex <= uiColNb; uiColIndex++)
			{
				OCI_Column* pColumn = OCI_GetColumn(pResultSet, uiColIndex);
				char szColName[100];
				strcpy(szColName, OCI_GetColumnName(pColumn));
				const char* szType = OCI_GetColumnSQLType(pColumn);
 
				fprintf(pFile, "%s = ", szColName);
 
				// varchar2
				if(strcmp(szType, "VARCHAR2") == 0)
				{
					const char* szColValue = OCI_GetString(pResultSet, uiColIndex);
					fprintf(pFile, "%s", szColValue == nullptr ? "NULL" : szColValue);
				}
				// float
				else if(strcmp(szType, "FLOAT") == 0)
				{
					const float fValue = (float)OCI_GetDouble(pResultSet, uiColIndex);
					fprintf(pFile, "%f", fValue);
				}
				// integer/number
				else if(	strcmp(szType, "INTEGER") == 0
					||	strcmp(szType, "NUMBER") == 0)
				{
					const int iValue = (int)OCI_GetBigInt(pResultSet, uiColIndex);
					fprintf(pFile, "%d", iValue);
				}
 
				fprintf(pFile, "\n");
			}
 
			fprintf(pFile, "\n");
		}
	}
 
	OCI_ReleaseResultsets(pStatement);
	OCI_FreeStatement(pStatement);
	OCI_FreeConnection(pConnection);
 
	fclose(pFile);
 
	printf("\n\nDone!");
 
	return 0;
}
Ca me sort un fichier du genre:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
COLONNE1 = 1
COLONNE2 = un peu de texte
 
COLONNE1 = 2
COLONNE2 = NULL
 
etc...
Et avec un prefetch > 1, arrivé à certains enregistrements pour lesquels la colonne VARCHAR2 est à NULL, la valeur retournée pour cette colonne est celle d'une quinzaine d'enregistrement avant.
Autre fait intéressant, si je modifie ma requête, et que j'écris
Code : Sélectionner tout - Visualiser dans une fenêtre à part
select colonne1, nvl(colonne2, ' ') from ma_table;
Les colonnes qui sont à NULL me retournent toutes bien une chaine de caractères avec uniquement un espace, quelque soit la taille du prefetch.

En voulant tester en appelant directement le code OCI, il est de toute façon nécessaire de spécifier un nvl pour les colonnes qui peuvent être NULL.
Donc le problème, s'il existe dans cette couche de code, n'apparait pas.

Si c'est pas bien clair (et ça ne l'est probablement pas ), j'ajouterai des précisions.