SQLite

Check-in [be1315755e]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix for ticket #71: Correctly handle CR and CRLF line terminators in the input files for the COPY command. (CVS 694)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: be1315755ef801b5ec07f469134e0d33a3ece990
User & Date: drh 2002-07-30 17:20:40.000
Context
2002-07-30
17:42
Fix for ticket #111: Update the documentation to explain that you may not start a transaction in one thread and complete it in another thread under Linux Threads where each thread has its own process ID. (CVS 695) (check-in: 0b0c0492cc user: drh tags: trunk)
17:20
Fix for ticket #71: Correctly handle CR and CRLF line terminators in the input files for the COPY command. (CVS 694) (check-in: be1315755e user: drh tags: trunk)
2002-07-21
23:09
UPDATE triggers on TEMP tables were broken. (CVS 693) (check-in: c080ed01ea user: danielk1977 tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/sqlite.h.in.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This header file defines the interface that the SQLite library
** presents to client programs.
**
** @(#) $Id: sqlite.h.in,v 1.33 2002/06/25 19:31:18 drh Exp $
*/
#ifndef _SQLITE_H_
#define _SQLITE_H_
#include <stdarg.h>     /* Needed for the definition of va_list */

/*
** The version of the SQLite library.







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This header file defines the interface that the SQLite library
** presents to client programs.
**
** @(#) $Id: sqlite.h.in,v 1.34 2002/07/30 17:20:40 drh Exp $
*/
#ifndef _SQLITE_H_
#define _SQLITE_H_
#include <stdarg.h>     /* Needed for the definition of va_list */

/*
** The version of the SQLite library.
380
381
382
383
384
385
386

387
388
389
390
391
392
393
  const char *sqlFormat, /* printf-style format string for the SQL */
  char ***resultp,       /* Result written to a char *[]  that this points to */
  int *nrow,             /* Number of result rows written here */
  int *ncolumn,          /* Number of result columns written here */
  char **errmsg,         /* Error msg written here */
  va_list ap             /* Arguments to the format string */
);


/*
** Windows systems should call this routine to free memory that
** is returned in the in the errmsg parameter of sqlite_open() when
** SQLite is a DLL.  For some reason, it does not work to call free()
** directly.
*/







>







380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
  const char *sqlFormat, /* printf-style format string for the SQL */
  char ***resultp,       /* Result written to a char *[]  that this points to */
  int *nrow,             /* Number of result rows written here */
  int *ncolumn,          /* Number of result columns written here */
  char **errmsg,         /* Error msg written here */
  va_list ap             /* Arguments to the format string */
);
char *sqlite_mprintf(const char*,...);

/*
** Windows systems should call this routine to free memory that
** is returned in the in the errmsg parameter of sqlite_open() when
** SQLite is a DLL.  For some reason, it does not work to call free()
** directly.
*/
Changes to src/sqliteInt.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.140 2002/07/19 17:46:39 drh Exp $
*/
#include "sqlite.h"
#include "hash.h"
#include "vdbe.h"
#include "parse.h"
#include "btree.h"
#include <stdio.h>













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.141 2002/07/30 17:20:40 drh Exp $
*/
#include "sqlite.h"
#include "hash.h"
#include "vdbe.h"
#include "parse.h"
#include "btree.h"
#include <stdio.h>
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
int sqliteExprAnalyzeAggregates(Parse*, Expr*);
Vdbe *sqliteGetVdbe(Parse*);
int sqliteRandomByte(void);
int sqliteRandomInteger(void);
void sqliteBeginTransaction(Parse*, int);
void sqliteCommitTransaction(Parse*);
void sqliteRollbackTransaction(Parse*);
char *sqlite_mprintf(const char *, ...);
int sqliteExprIsConstant(Expr*);
int sqliteExprIsInteger(Expr*, int*);
int sqliteIsRowid(const char*);
void sqliteGenerateRowDelete(sqlite*, Vdbe*, Table*, int, int);
void sqliteGenerateRowIndexDelete(sqlite*, Vdbe*, Table*, int, char*);
void sqliteGenerateConstraintChecks(Parse*,Table*,int,char*,int,int,int,int);
void sqliteCompleteInsertion(Parse*, Table*, int, char*, int, int);







<







908
909
910
911
912
913
914

915
916
917
918
919
920
921
int sqliteExprAnalyzeAggregates(Parse*, Expr*);
Vdbe *sqliteGetVdbe(Parse*);
int sqliteRandomByte(void);
int sqliteRandomInteger(void);
void sqliteBeginTransaction(Parse*, int);
void sqliteCommitTransaction(Parse*);
void sqliteRollbackTransaction(Parse*);

int sqliteExprIsConstant(Expr*);
int sqliteExprIsInteger(Expr*, int*);
int sqliteIsRowid(const char*);
void sqliteGenerateRowDelete(sqlite*, Vdbe*, Table*, int, int);
void sqliteGenerateRowIndexDelete(sqlite*, Vdbe*, Table*, int, char*);
void sqliteGenerateConstraintChecks(Parse*,Table*,int,char*,int,int,int,int);
void sqliteCompleteInsertion(Parse*, Table*, int, char*, int, int);
Changes to src/vdbe.c.
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
** type to the other occurs as necessary.
** 
** Most of the code in this file is taken up by the sqliteVdbeExec()
** function which does the work of interpreting a VDBE program.
** But other routines are also provided to help in building up
** a program instruction by instruction.
**
** $Id: vdbe.c,v 1.165 2002/07/18 00:34:12 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** The following global variable is incremented every time a cursor
** moves, either by the OP_MoveTo or the OP_Next opcode.  The test







|







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
** type to the other occurs as necessary.
** 
** Most of the code in this file is taken up by the sqliteVdbeExec()
** function which does the work of interpreting a VDBE program.
** But other routines are also provided to help in building up
** a program instruction by instruction.
**
** $Id: vdbe.c,v 1.166 2002/07/30 17:20:40 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** The following global variable is incremented every time a cursor
** moves, either by the OP_MoveTo or the OP_Next opcode.  The test
1235
1236
1237
1238
1239
1240
1241


























1242
1243
1244
1245
1246
1247
1248
** with NDEBUG=1, the VERIFY() code is omitted.
*/
#ifdef NDEBUG
# define VERIFY(X)
#else
# define VERIFY(X) X
#endif



























/*
** Execute the program in the VDBE.
**
** If an error occurs, an error message is written to memory obtained
** from sqliteMalloc() and *pzErrMsg is made to point to that memory.
** The return parameter is the number of errors.







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
** with NDEBUG=1, the VERIFY() code is omitted.
*/
#ifdef NDEBUG
# define VERIFY(X)
#else
# define VERIFY(X) X
#endif

/*
** The following routine works like a replacement for the standard
** library routine fgets().  The difference is in how end-of-line (EOL)
** is handled.  Standard fgets() uses LF for EOL under unix, CRLF
** under windows, and CR under mac.  This routine accepts any of these
** character sequences as an EOL mark.  The EOL mark is replaced by
** a single LF character in zBuf.
*/
static char *vdbe_fgets(char *zBuf, int nBuf, FILE *in){
  int i, c;
  for(i=0; i<nBuf-1 && (c=getc(in))!=EOF; i++){
    zBuf[i] = c;
    if( c=='\r' || c=='\n' ){
      if( c=='\r' ){
        zBuf[i] = '\n';
        c = getc(in);
        if( c!=EOF && c!='\n' ) ungetc(c, in);
      }
      i++;
      break;
    }
  }
  zBuf[i]  = 0;
  return i>0 ? zBuf : 0;
}

/*
** Execute the program in the VDBE.
**
** If an error occurs, an error message is written to memory obtained
** from sqliteMalloc() and *pzErrMsg is made to point to that memory.
** The return parameter is the number of errors.
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
        p->nLineAlloc = 0;
        sqliteFree(p->zLine);
        p->zLine = 0;
        goto no_mem;
      }
      p->zLine = zLine;
    }
    if( fgets(&p->zLine[n], p->nLineAlloc-n, p->pFile)==0 ){
      eol = 1;
      p->zLine[n] = 0;
    }else{
      int c;
      while( (c = p->zLine[n])!=0 ){
        if( c=='\\' ){
          if( p->zLine[n+1]==0 ) break;







|







4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
        p->nLineAlloc = 0;
        sqliteFree(p->zLine);
        p->zLine = 0;
        goto no_mem;
      }
      p->zLine = zLine;
    }
    if( vdbe_fgets(&p->zLine[n], p->nLineAlloc-n, p->pFile)==0 ){
      eol = 1;
      p->zLine[n] = 0;
    }else{
      int c;
      while( (c = p->zLine[n])!=0 ){
        if( c=='\\' ){
          if( p->zLine[n+1]==0 ) break;
Changes to test/copy.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the COPY statement.
#
# $Id: copy.test,v 1.11 2002/06/25 13:16:04 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a file of data from which to copy.
#
set f [open data1.txt w]













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the COPY statement.
#
# $Id: copy.test,v 1.12 2002/07/30 17:20:41 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a file of data from which to copy.
#
set f [open data1.txt w]
35
36
37
38
39
40
41








42
43
44
45
46
47
48
puts $f "11 | 22 | 33"
puts $f "22 | 33 | 11"
close $f
set f [open data5.txt w]
puts $f "11|22|33"
puts $f "22|33|11"
close $f









# Try to COPY into a non-existant table.
#
do_test copy-1.1 {
  set v [catch {execsql {COPY test1 FROM 'data1.txt'}} msg]
  lappend v $msg
} {1 {no such table: test1}}







>
>
>
>
>
>
>
>







35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
puts $f "11 | 22 | 33"
puts $f "22 | 33 | 11"
close $f
set f [open data5.txt w]
puts $f "11|22|33"
puts $f "22|33|11"
close $f
set f [open dataX.txt w]
puts -nonewline $f "11|22|33\r"
puts -nonewline $f "22|33|44\r\n"
puts -nonewline $f "33|44|55\n"
puts -nonewline $f "44|55|66\r"
puts -nonewline $f "55|66|77\r\n"
puts -nonewline $f "66|77|88\n"
close $f

# Try to COPY into a non-existant table.
#
do_test copy-1.1 {
  set v [catch {execsql {COPY test1 FROM 'data1.txt'}} msg]
  lappend v $msg
} {1 {no such table: test1}}
222
223
224
225
226
227
228









229
230
231
232
233

234
235
} {2}
do_test copy-5.7 {
  execsql {
    COPY OR IGNORE t1 FROM 'data5.txt' USING DELIMITERS '|';
  }
} {0}










integrity_check copy-6.0

# Cleanup 
#
file delete -force data1.txt data2.txt data3.txt data4.txt data5.txt data6.txt


finish_test







>
>
>
>
>
>
>
>
>
|



|
>


230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
} {2}
do_test copy-5.7 {
  execsql {
    COPY OR IGNORE t1 FROM 'data5.txt' USING DELIMITERS '|';
  }
} {0}

do_test copy-6.1 {
  execsql {
    PRAGMA count_changes=off;
    CREATE TABLE t2(a,b,c);
    COPY t2 FROM 'dataX.txt' USING DELIMITERS '|';
    SELECT * FROM t2;
  }
} {11 22 33 22 33 44 33 44 55 44 55 66 55 66 77 66 77 88}

integrity_check copy-7.1

# Cleanup 
#
file delete -force data1.txt data2.txt data3.txt data4.txt data5.txt \
                   data6.txt dataX.txt

finish_test