1 | /*
|
---|
2 | ** 2003 April 6
|
---|
3 | **
|
---|
4 | ** The author disclaims copyright to this source code. In place of
|
---|
5 | ** a legal notice, here is a blessing:
|
---|
6 | **
|
---|
7 | ** May you do good and not evil.
|
---|
8 | ** May you find forgiveness for yourself and forgive others.
|
---|
9 | ** May you share freely, never taking more than you give.
|
---|
10 | **
|
---|
11 | *************************************************************************
|
---|
12 | ** This file contains code used to implement the COPY command.
|
---|
13 | **
|
---|
14 | ** $Id: copy.c,v 1.9 2004/02/25 13:47:31 drh Exp $
|
---|
15 | */
|
---|
16 | #include "sqliteInt.h"
|
---|
17 |
|
---|
18 | /*
|
---|
19 | ** The COPY command is for compatibility with PostgreSQL and specificially
|
---|
20 | ** for the ability to read the output of pg_dump. The format is as
|
---|
21 | ** follows:
|
---|
22 | **
|
---|
23 | ** COPY table FROM file [USING DELIMITERS string]
|
---|
24 | **
|
---|
25 | ** "table" is an existing table name. We will read lines of code from
|
---|
26 | ** file to fill this table with data. File might be "stdin". The optional
|
---|
27 | ** delimiter string identifies the field separators. The default is a tab.
|
---|
28 | */
|
---|
29 | void sqliteCopy(
|
---|
30 | Parse *pParse, /* The parser context */
|
---|
31 | SrcList *pTableName, /* The name of the table into which we will insert */
|
---|
32 | Token *pFilename, /* The file from which to obtain information */
|
---|
33 | Token *pDelimiter, /* Use this as the field delimiter */
|
---|
34 | int onError /* What to do if a constraint fails */
|
---|
35 | ){
|
---|
36 | Table *pTab;
|
---|
37 | int i;
|
---|
38 | Vdbe *v;
|
---|
39 | int addr, end;
|
---|
40 | char *zFile = 0;
|
---|
41 | const char *zDb;
|
---|
42 | sqlite *db = pParse->db;
|
---|
43 |
|
---|
44 |
|
---|
45 | if( sqlite_malloc_failed ) goto copy_cleanup;
|
---|
46 | assert( pTableName->nSrc==1 );
|
---|
47 | pTab = sqliteSrcListLookup(pParse, pTableName);
|
---|
48 | if( pTab==0 || sqliteIsReadOnly(pParse, pTab, 0) ) goto copy_cleanup;
|
---|
49 | zFile = sqliteStrNDup(pFilename->z, pFilename->n);
|
---|
50 | sqliteDequote(zFile);
|
---|
51 | assert( pTab->iDb<db->nDb );
|
---|
52 | zDb = db->aDb[pTab->iDb].zName;
|
---|
53 | if( sqliteAuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb)
|
---|
54 | || sqliteAuthCheck(pParse, SQLITE_COPY, pTab->zName, zFile, zDb) ){
|
---|
55 | goto copy_cleanup;
|
---|
56 | }
|
---|
57 | v = sqliteGetVdbe(pParse);
|
---|
58 | if( v ){
|
---|
59 | sqliteBeginWriteOperation(pParse, 1, pTab->iDb);
|
---|
60 | addr = sqliteVdbeOp3(v, OP_FileOpen, 0, 0, pFilename->z, pFilename->n);
|
---|
61 | sqliteVdbeDequoteP3(v, addr);
|
---|
62 | sqliteOpenTableAndIndices(pParse, pTab, 0);
|
---|
63 | if( db->flags & SQLITE_CountRows ){
|
---|
64 | sqliteVdbeAddOp(v, OP_Integer, 0, 0); /* Initialize the row count */
|
---|
65 | }
|
---|
66 | end = sqliteVdbeMakeLabel(v);
|
---|
67 | addr = sqliteVdbeAddOp(v, OP_FileRead, pTab->nCol, end);
|
---|
68 | if( pDelimiter ){
|
---|
69 | sqliteVdbeChangeP3(v, addr, pDelimiter->z, pDelimiter->n);
|
---|
70 | sqliteVdbeDequoteP3(v, addr);
|
---|
71 | }else{
|
---|
72 | sqliteVdbeChangeP3(v, addr, "\t", 1);
|
---|
73 | }
|
---|
74 | if( pTab->iPKey>=0 ){
|
---|
75 | sqliteVdbeAddOp(v, OP_FileColumn, pTab->iPKey, 0);
|
---|
76 | sqliteVdbeAddOp(v, OP_MustBeInt, 0, 0);
|
---|
77 | }else{
|
---|
78 | sqliteVdbeAddOp(v, OP_NewRecno, 0, 0);
|
---|
79 | }
|
---|
80 | for(i=0; i<pTab->nCol; i++){
|
---|
81 | if( i==pTab->iPKey ){
|
---|
82 | /* The integer primary key column is filled with NULL since its
|
---|
83 | ** value is always pulled from the record number */
|
---|
84 | sqliteVdbeAddOp(v, OP_String, 0, 0);
|
---|
85 | }else{
|
---|
86 | sqliteVdbeAddOp(v, OP_FileColumn, i, 0);
|
---|
87 | }
|
---|
88 | }
|
---|
89 | sqliteGenerateConstraintChecks(pParse, pTab, 0, 0, pTab->iPKey>=0,
|
---|
90 | 0, onError, addr);
|
---|
91 | sqliteCompleteInsertion(pParse, pTab, 0, 0, 0, 0, -1);
|
---|
92 | if( (db->flags & SQLITE_CountRows)!=0 ){
|
---|
93 | sqliteVdbeAddOp(v, OP_AddImm, 1, 0); /* Increment row count */
|
---|
94 | }
|
---|
95 | sqliteVdbeAddOp(v, OP_Goto, 0, addr);
|
---|
96 | sqliteVdbeResolveLabel(v, end);
|
---|
97 | sqliteVdbeAddOp(v, OP_Noop, 0, 0);
|
---|
98 | sqliteEndWriteOperation(pParse);
|
---|
99 | if( db->flags & SQLITE_CountRows ){
|
---|
100 | sqliteVdbeAddOp(v, OP_ColumnName, 0, 1);
|
---|
101 | sqliteVdbeChangeP3(v, -1, "rows inserted", P3_STATIC);
|
---|
102 | sqliteVdbeAddOp(v, OP_Callback, 1, 0);
|
---|
103 | }
|
---|
104 | }
|
---|
105 |
|
---|
106 | copy_cleanup:
|
---|
107 | sqliteSrcListDelete(pTableName);
|
---|
108 | sqliteFree(zFile);
|
---|
109 | return;
|
---|
110 | }
|
---|