Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit36580c8

Browse files
committed
PyGreSQL inserttable patch
=====================I suggested an improvement of the inserttable in the PyGreSQL interfacealready in January, but seemingly it was never implemented. I was told thisis the right place to get patches in for PyGreSQL, so I'm reposting my patchhere.I consider the inserttable methode essential in populating the databasebecause of its benefits in performance compared to insert, so I think thispatch is quite essential. The attachment is an improved version of thecorresponding pg_inserttable function in pgmodule.c, which fixes thefollowing problems:* The function raised exceptions because PyList_GetItem was used beyond thesize of the list. This was checked by comparing the result with NULL, butthe exception was not cleaned up, which could result in mysterious errors inthe following Python code. Instead of clearing the exception usingPyErr_Clear or something like that, I avoided throwing the exception at allby at first requesting the size of the list. Using this opportunity, I alsochecked the uniformity of the size of the rows passed in the lists/tuples.The function also accepts (and silently ignores) empty lists and sublists.* Python "None" values are now accepted and properly converted to PostgreSQLNULL values* The function now generates an error message in case of a line bufferoverflow* It copes with tabulators, newlines and backslashes in strings now* Rewrote the buffer filling code which should now run faster by avoidingunnecessary string copy operations forth and backChristoph Zwerschke
1 parentd851f00 commit36580c8

File tree

1 file changed

+181
-98
lines changed

1 file changed

+181
-98
lines changed

‎src/interfaces/python/pgmodule.c

Lines changed: 181 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -2324,18 +2324,21 @@ static char pg_inserttable__doc__[] =
23242324
staticPyObject*
23252325
pg_inserttable(pgobject*self,PyObject*args)
23262326
{
2327-
PGresult*result;
2328-
char*table,
2329-
*buffer,
2330-
*temp;
2331-
chartemp_buffer[256];
2332-
PyObject*list,
2333-
*sublist,
2334-
*item;
2335-
PyObject*(*getitem) (PyObject*,int);
2336-
PyObject*(*getsubitem) (PyObject*,int);
2327+
PGresult*result;
2328+
char*table,
2329+
*buffer,
2330+
*bufpt,
2331+
*temp;
2332+
size_tbufsiz;
2333+
PyObject*list,
2334+
*sublist,
2335+
*item;
2336+
PyObject*(*getitem) (PyObject*,int);
2337+
PyObject*(*getsubitem) (PyObject*,int);
23372338
inti,
2338-
j;
2339+
j,
2340+
m,
2341+
n;
23392342

23402343
if (!self->cnx)
23412344
{
@@ -2347,123 +2350,203 @@ pg_inserttable(pgobject * self, PyObject * args)
23472350
if (!PyArg_ParseTuple(args,"sO:filter",&table,&list))
23482351
{
23492352
PyErr_SetString(PyExc_TypeError,
2350-
"tableinsert(table, content), with table (string) "
2351-
"and content (list).");
2353+
"tableinsert(table, content), with table (string) "
2354+
"and content (list).");
23522355
returnNULL;
23532356
}
23542357

23552358
/* checks list type */
23562359
if (PyTuple_Check(list))
2360+
{
2361+
m=PyTuple_Size(list);
23572362
getitem=PyTuple_GetItem;
2363+
}
23582364
elseif (PyList_Check(list))
2365+
{
2366+
m=PyList_Size(list);
23592367
getitem=PyList_GetItem;
2368+
}
23602369
else
23612370
{
23622371
PyErr_SetString(PyExc_TypeError,
2363-
"second arg must be some kind of array.");
2372+
"second arg must be some kind of array.");
23642373
returnNULL;
23652374
}
23662375

2367-
/* checks sublists type */
2368-
for (i=0; (sublist=getitem(list,i))!=NULL;i++)
2376+
if (m)
23692377
{
2370-
if (!PyTuple_Check(sublist)&& !PyList_Check(sublist))
2378+
/* checks sublists type and size */
2379+
for (i=0;i<m;i++)
23712380
{
2372-
PyErr_SetString(PyExc_TypeError,
2373-
"second arg must contain some kind of arrays.");
2374-
returnNULL;
2375-
}
2376-
}
2377-
2378-
/* allocate buffer */
2379-
if (!(buffer=malloc(MAX_BUFFER_SIZE)))
2380-
{
2381-
PyErr_SetString(PyExc_MemoryError,"can't allocate insert buffer.");
2382-
returnNULL;
2383-
}
2384-
2385-
/* starts query */
2386-
sprintf(buffer,"copy %s from stdin",table);
2387-
2388-
Py_BEGIN_ALLOW_THREADS
2389-
result=PQexec(self->cnx,buffer);
2390-
Py_END_ALLOW_THREADS
2391-
2392-
if (!result)
2393-
{
2394-
free(buffer);
2395-
PyErr_SetString(PyExc_ValueError,PQerrorMessage(self->cnx));
2396-
returnNULL;
2397-
}
2398-
2399-
PQclear(result);
2400-
2401-
/* feeds table */
2402-
for (i=0; (sublist=getitem(list,i))!=NULL;i++)
2403-
{
2404-
if (PyTuple_Check(sublist))
2405-
getsubitem=PyTuple_GetItem;
2406-
else
2407-
getsubitem=PyList_GetItem;
2408-
2409-
/* builds insert line */
2410-
buffer[0]=0;
2411-
2412-
for (j=0; (item=getsubitem(sublist,j))!=NULL;j++)
2413-
{
2414-
/* converts item to string */
2415-
if (PyString_Check(item))
2416-
temp=PyString_AS_STRING(item);
2417-
elseif (PyInt_Check(item))
2418-
{
2419-
longk;
2420-
2421-
k=PyInt_AsLong(item);
2422-
sprintf(temp_buffer,"%ld",k);
2423-
temp=temp_buffer;
2424-
}
2425-
elseif (PyLong_Check(item))
2381+
sublist=getitem(list,i);
2382+
if (PyTuple_Check(sublist))
2383+
j=PyTuple_Size(sublist);
2384+
elseif (PyList_Check(sublist))
2385+
j=PyList_Size(sublist);
2386+
else
24262387
{
2427-
longk;
2428-
2429-
k=PyLong_AsLong(item);
2430-
sprintf(temp_buffer,"%ld",k);
2431-
temp=temp_buffer;
2388+
PyErr_SetString(PyExc_TypeError,
2389+
"second arg must contain some kind of arrays.");
2390+
returnNULL;
24322391
}
2433-
elseif (PyFloat_Check(item))
2392+
if (i)
24342393
{
2435-
doublek;
2436-
2437-
k=PyFloat_AS_DOUBLE(item);
2438-
sprintf(temp_buffer,"%g",k);
2439-
temp=temp_buffer;
2394+
if (j!=n)
2395+
{
2396+
PyErr_SetString(PyExc_TypeError,
2397+
"arrays contained in second arg must have same size.");
2398+
returnNULL;
2399+
}
24402400
}
24412401
else
2402+
n=j;
2403+
}
2404+
if (n)
2405+
{
2406+
/* allocate buffer */
2407+
if (!(buffer=malloc(MAX_BUFFER_SIZE)))
2408+
{
2409+
PyErr_SetString(PyExc_MemoryError,
2410+
"can't allocate insert buffer.");
2411+
returnNULL;
2412+
}
2413+
2414+
/* starts query */
2415+
sprintf(buffer,"copy %s from stdin",table);
2416+
2417+
Py_BEGIN_ALLOW_THREADS
2418+
result=PQexec(self->cnx,buffer);
2419+
Py_END_ALLOW_THREADS
2420+
2421+
if (!result)
24422422
{
24432423
free(buffer);
2444-
PyErr_SetString(PyExc_ValueError,
2445-
"items must be strings, integers, "
2446-
"longs or double (real).");
2424+
PyErr_SetString(PyExc_ValueError,PQerrorMessage(self->cnx));
24472425
returnNULL;
24482426
}
24492427

2450-
/* concats buffer */
2451-
if (strlen(buffer))
2452-
strncat(buffer,"\t",MAX_BUFFER_SIZE-strlen(buffer));
2428+
PQclear(result);
24532429

2454-
strncat(buffer,temp,MAX_BUFFER_SIZE-strlen(buffer));
2455-
}
2430+
/* feeds table */
2431+
for (i=0;i<m;i++)
2432+
{
2433+
sublist=getitem(list,i);
2434+
if (PyTuple_Check(sublist))
2435+
getsubitem=PyTuple_GetItem;
2436+
else
2437+
getsubitem=PyList_GetItem;
2438+
2439+
/* builds insert line */
2440+
bufpt=buffer;
2441+
bufsiz=MAX_BUFFER_SIZE-1;
2442+
2443+
for (j=0;j<n;j++)
2444+
{
2445+
item=getsubitem(sublist,j);
2446+
/* converts item to string */
2447+
if (item==Py_None)
2448+
{
2449+
if (bufsiz>2)
2450+
{
2451+
*bufpt++='\\';*bufpt++='N';
2452+
bufsiz-=2;
2453+
}
2454+
else
2455+
bufsiz=0;
2456+
}
2457+
elseif (PyString_Check(item))
2458+
{
2459+
temp=PyString_AS_STRING(item);
2460+
while (*temp&&bufsiz)
2461+
{
2462+
if (*temp=='\\'
2463+
||*temp=='\t'
2464+
||*temp=='\n')
2465+
{
2466+
*bufpt++='\\';--bufsiz;
2467+
if (!bufsiz)break;
2468+
}
2469+
*bufpt++=*temp++;--bufsiz;
2470+
}
2471+
}
2472+
elseif (PyInt_Check(item))
2473+
{
2474+
longk;
2475+
inth;
2476+
2477+
k=PyInt_AsLong(item);
2478+
h=snprintf(bufpt,bufsiz,"%ld",k);
2479+
if (h>0)
2480+
{
2481+
bufpt+=h;bufsiz-=h;
2482+
}
2483+
else
2484+
bufsiz=0;
2485+
}
2486+
elseif (PyLong_Check(item))
2487+
{
2488+
longk;
2489+
inth;
2490+
2491+
k=PyLong_AsLong(item);
2492+
h=snprintf(bufpt,bufsiz,"%ld",k);
2493+
if (h>0)
2494+
{
2495+
bufpt+=h;bufsiz-=h;
2496+
}
2497+
else
2498+
bufsiz=0;
2499+
}
2500+
elseif (PyFloat_Check(item))
2501+
{
2502+
doublek;
2503+
inth;
2504+
2505+
k=PyFloat_AS_DOUBLE(item);
2506+
h=snprintf(bufpt,bufsiz,"%g",k);
2507+
if (h>0)
2508+
{
2509+
bufpt+=h;bufsiz-=h;
2510+
}
2511+
else
2512+
bufsiz=0;
2513+
}
2514+
else
2515+
{
2516+
free(buffer);
2517+
PyErr_SetString(PyExc_ValueError,
2518+
"items must be strings, integers, "
2519+
"longs or double (real).");
2520+
returnNULL;
2521+
}
2522+
2523+
if (j<n-1)
2524+
{
2525+
*bufpt++='\t';--bufsiz;
2526+
}
2527+
2528+
if (bufsiz <=0)
2529+
{
2530+
free(buffer);
2531+
PyErr_SetString(PyExc_MemoryError,
2532+
"insert buffer overflow.");
2533+
returnNULL;
2534+
}
24562535

2457-
strncat(buffer,"\n",MAX_BUFFER_SIZE-strlen(buffer));
2536+
}
24582537

2459-
/* sends data */
2460-
PQputline(self->cnx,buffer);
2461-
}
2538+
*bufpt++='\n';*bufpt='\0';
24622539

2463-
/* ends query */
2464-
PQputline(self->cnx,"\\.\n");
2465-
PQendcopy(self->cnx);
2466-
free(buffer);
2540+
/* sends data */
2541+
PQputline(self->cnx,buffer);
2542+
}
2543+
2544+
/* ends query */
2545+
PQputline(self->cnx,"\\.\n");
2546+
PQendcopy(self->cnx);
2547+
free(buffer);
2548+
}
2549+
}
24672550

24682551
/* no error : returns nothing */
24692552
Py_INCREF(Py_None);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp