Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add support for joins. |
---|---|
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
8c6e6a4ed7b6aa3582c7e38c1ced9ee2 |
User & Date: | drh 2011-07-16 20:00:10 |
Context
2011-07-18
| ||
09:39 | Fix handling of "AS" in FROM clauses. check-in: e7c27a9690 user: dan tags: trunk | |
2011-07-16
| ||
20:00 | Add support for joins. check-in: 8c6e6a4ed7 user: drh tags: trunk | |
19:42 | Fix compiler warnings. Remove an unused declaration. check-in: dba083d964 user: drh tags: trunk | |
Changes
Changes to src/datasrc.c.
53 54 55 56 57 58 59 60 61 62 63 64 65 66 .. 95 96 97 98 99 100 101 102 103 104 105 106 107 108 ... 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
** Return XJD1_DONE if the data source is empty and XJD1_ROW if ** the step results in a row of content being available. */ int xjd1DataSrcStep(DataSrc *p){ int rc= XJD1_DONE; if( p==0 ) return XJD1_DONE; switch( p->eDSType ){ case TK_ID: { rc = sqlite3_step(p->u.tab.pStmt); xjd1JsonFree(p->pValue); p->pValue = 0; if( rc==SQLITE_ROW ){ const char *zJson = (const char*)sqlite3_column_text(p->u.tab.pStmt, 0); p->pValue = xjd1JsonParse(zJson, -1); ................................................................................ return xjd1JsonRef(p->pValue); } switch( p->eDSType ){ case TK_COMMA: { pRes = xjd1DataSrcDoc(p->u.join.pLeft, zDocName); if( pRes==0 ) pRes = xjd1DataSrcDoc(p->u.join.pRight, zDocName); break; } case TK_ID: { if( zDocName==0 || strcmp(p->u.tab.zName, zDocName)==0 ){ pRes = xjd1JsonRef(p->pValue); } break; } ................................................................................ ** Return XJD1_DONE if the data source is empty and XJD1_ROW if ** the rewind results in a row of content being available. */ int xjd1DataSrcRewind(DataSrc *p){ if( p==0 ) return XJD1_DONE; xjd1JsonFree(p->pValue); p->pValue = 0; switch( p->eDSType ){ case TK_ID: { sqlite3_reset(p->u.tab.pStmt); return xjd1DataSrcStep(p); } case TK_NULL: { p->u.null.isDone = 0; return xjd1DataSrcStep(p); } } return XJD1_DONE; } /* ** Return true if the data source is at the end of file */ int xjd1DataSrcEOF(DataSrc *p){ return 1; } /* ** The destructor for a Query object. */ int xjd1DataSrcClose(DataSrc *p){ if( p==0 ) return XJD1_OK; xjd1JsonFree(p->pValue); p->pValue = 0; switch( p->eDSType ){ |
> > > > > > > > > > > > > > > > > > > > > > > > > < < < < < < < |
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 ... 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 ... 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
** Return XJD1_DONE if the data source is empty and XJD1_ROW if ** the step results in a row of content being available. */ int xjd1DataSrcStep(DataSrc *p){ int rc= XJD1_DONE; if( p==0 ) return XJD1_DONE; switch( p->eDSType ){ case TK_COMMA: { rc = xjd1DataSrcStep(p->u.join.pRight); if( rc==XJD1_DONE ){ xjd1DataSrcRewind(p->u.join.pRight); rc = xjd1DataSrcStep(p->u.join.pLeft); } break; } case TK_SELECT: { rc = xjd1QueryStep(p->u.subq.q); break; } case TK_ID: { rc = sqlite3_step(p->u.tab.pStmt); xjd1JsonFree(p->pValue); p->pValue = 0; if( rc==SQLITE_ROW ){ const char *zJson = (const char*)sqlite3_column_text(p->u.tab.pStmt, 0); p->pValue = xjd1JsonParse(zJson, -1); ................................................................................ return xjd1JsonRef(p->pValue); } switch( p->eDSType ){ case TK_COMMA: { pRes = xjd1DataSrcDoc(p->u.join.pLeft, zDocName); if( pRes==0 ) pRes = xjd1DataSrcDoc(p->u.join.pRight, zDocName); break; } case TK_SELECT: { pRes = xjd1QueryDoc(p->u.subq.q, zDocName); break; } case TK_ID: { if( zDocName==0 || strcmp(p->u.tab.zName, zDocName)==0 ){ pRes = xjd1JsonRef(p->pValue); } break; } ................................................................................ ** Return XJD1_DONE if the data source is empty and XJD1_ROW if ** the rewind results in a row of content being available. */ int xjd1DataSrcRewind(DataSrc *p){ if( p==0 ) return XJD1_DONE; xjd1JsonFree(p->pValue); p->pValue = 0; switch( p->eDSType ){ case TK_COMMA: { xjd1DataSrcRewind(p->u.join.pLeft); xjd1DataSrcRewind(p->u.join.pRight); break; } case TK_SELECT: { xjd1QueryRewind(p->u.subq.q); break; } case TK_ID: { sqlite3_reset(p->u.tab.pStmt); return xjd1DataSrcStep(p); } case TK_NULL: { p->u.null.isDone = 0; return xjd1DataSrcStep(p); } } return XJD1_DONE; } /* ** The destructor for a Query object. */ int xjd1DataSrcClose(DataSrc *p){ if( p==0 ) return XJD1_OK; xjd1JsonFree(p->pValue); p->pValue = 0; switch( p->eDSType ){ |
Changes to src/query.c.
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
...
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
|
*/ int xjd1QueryRewind(Query *p){ if( p==0 ) return XJD1_OK; if( p->eQType==TK_SELECT ){ xjd1DataSrcRewind(p->u.simple.pFrom); }else{ xjd1QueryRewind(p->u.compound.pLeft); p->u.compound.doneLeft = xjd1QueryEOF(p->u.compound.pLeft); xjd1QueryRewind(p->u.compound.pRight); } return XJD1_OK; } /* ** Advance a query to the next row. Return XDJ1_DONE if there is no ................................................................................ pOut = xjd1QueryDoc(p->pOuter, zDocName); } } return pOut; } /* Return true if there are no more rows available on this query */ int xjd1QueryEOF(Query *p){ int rc; if( p->eQType==TK_SELECT ){ rc = xjd1DataSrcEOF(p->u.simple.pFrom); }else{ rc = 0; if( !p->u.compound.doneLeft ){ rc = xjd1QueryEOF(p->u.compound.pLeft); if( rc ) p->u.compound.doneLeft = 1; } if( p->u.compound.doneLeft ){ rc = xjd1QueryEOF(p->u.compound.pRight); } } return rc; } /* ** The destructor for a Query object. */ int xjd1QueryClose(Query *pQuery){ int rc = XJD1_OK; if( pQuery==0 ) return rc; if( pQuery->eQType==TK_SELECT ){ |
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
...
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
*/ int xjd1QueryRewind(Query *p){ if( p==0 ) return XJD1_OK; if( p->eQType==TK_SELECT ){ xjd1DataSrcRewind(p->u.simple.pFrom); }else{ xjd1QueryRewind(p->u.compound.pLeft); p->u.compound.doneLeft = 0; xjd1QueryRewind(p->u.compound.pRight); } return XJD1_OK; } /* ** Advance a query to the next row. Return XDJ1_DONE if there is no ................................................................................ pOut = xjd1QueryDoc(p->pOuter, zDocName); } } return pOut; } /* ** The destructor for a Query object. */ int xjd1QueryClose(Query *pQuery){ int rc = XJD1_OK; if( pQuery==0 ) return rc; if( pQuery->eQType==TK_SELECT ){ |
Changes to src/xjd1Int.h.
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 ... 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 ... 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 |
/* Marker for routines not intended for external use */ #define PRIVATE /* Additional tokens above and beyond those generated by the parser and ** found in parse.h */ #define TK_NOT_LIKEOP (TK_LIKEOP+128) #define TK_NOT_IS (TK_IS+128) #define TK_FUNCTION 100 #define TK_SPACE 101 #define TK_ILLEGAL 102 #define TK_CREATECOLLECTION 103 #define TK_DROPCOLLECTION 104 #define TK_ARRAY 105 #define TK_STRUCT 106 ................................................................................ void xjd1Unref(xjd1*); void xjd1Error(xjd1*,int,const char*,...); /******************************** datasrc.c **********************************/ int xjd1DataSrcInit(DataSrc*,Query*); int xjd1DataSrcRewind(DataSrc*); int xjd1DataSrcStep(DataSrc*); int xjd1DataSrcEOF(DataSrc*); int xjd1DataSrcClose(DataSrc*); JsonNode *xjd1DataSrcDoc(DataSrc*, const char*); /******************************** delete.c ***********************************/ int xjd1DeleteStep(xjd1_stmt*); /******************************** expr.c *************************************/ ................................................................................ /******************************** pragma.c ***********************************/ int xjd1PragmaStep(xjd1_stmt*); /******************************** query.c ************************************/ int xjd1QueryInit(Query*,xjd1_stmt*,Query*); int xjd1QueryRewind(Query*); int xjd1QueryStep(Query*); int xjd1QueryEOF(Query*); int xjd1QueryClose(Query*); JsonNode *xjd1QueryDoc(Query*, const char*); /******************************** stmt.c *************************************/ JsonNode *xjd1StmtDoc(xjd1_stmt*, const char*); /******************************** string.c ***********************************/ |
< < < |
30 31 32 33 34 35 36 37 38 39 40 41 42 43 ... 324 325 326 327 328 329 330 331 332 333 334 335 336 337 ... 366 367 368 369 370 371 372 373 374 375 376 377 378 379 |
/* Marker for routines not intended for external use */ #define PRIVATE /* Additional tokens above and beyond those generated by the parser and ** found in parse.h */ #define TK_NOT_LIKEOP (TK_LIKEOP+128) #define TK_FUNCTION 100 #define TK_SPACE 101 #define TK_ILLEGAL 102 #define TK_CREATECOLLECTION 103 #define TK_DROPCOLLECTION 104 #define TK_ARRAY 105 #define TK_STRUCT 106 ................................................................................ void xjd1Unref(xjd1*); void xjd1Error(xjd1*,int,const char*,...); /******************************** datasrc.c **********************************/ int xjd1DataSrcInit(DataSrc*,Query*); int xjd1DataSrcRewind(DataSrc*); int xjd1DataSrcStep(DataSrc*); int xjd1DataSrcClose(DataSrc*); JsonNode *xjd1DataSrcDoc(DataSrc*, const char*); /******************************** delete.c ***********************************/ int xjd1DeleteStep(xjd1_stmt*); /******************************** expr.c *************************************/ ................................................................................ /******************************** pragma.c ***********************************/ int xjd1PragmaStep(xjd1_stmt*); /******************************** query.c ************************************/ int xjd1QueryInit(Query*,xjd1_stmt*,Query*); int xjd1QueryRewind(Query*); int xjd1QueryStep(Query*); int xjd1QueryClose(Query*); JsonNode *xjd1QueryDoc(Query*, const char*); /******************************** stmt.c *************************************/ JsonNode *xjd1StmtDoc(xjd1_stmt*, const char*); /******************************** string.c ***********************************/ |
Changes to test/base01.test.
12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
SELECT FROM abc; .result {"name":"abc"} .testcase 120 SELECT FROM def; .result {"name":"def"} .testcase 130 SELECT { p:1, q:2 } FROM abc; .result {"p":1,"q":2} .testcase 131 SELECT {p:1, q:2+3} FROM abc; .result {"p":1,"q":5} .testcase 132 |
> > > > |
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
SELECT FROM abc; .result {"name":"abc"} .testcase 120 SELECT FROM def; .result {"name":"def"} .testcase 125 SELECT FROM abc UNION ALL SELECT FROM def; .result {"name":"abc"} {"name":"def"} .testcase 130 SELECT { p:1, q:2 } FROM abc; .result {"p":1,"q":2} .testcase 131 SELECT {p:1, q:2+3} FROM abc; .result {"p":1,"q":5} .testcase 132 |
Added test/base04.test.
> > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
-- Basic sanity checking. -- .new t1.db .testcase 100 CREATE COLLECTION c1; INSERT INTO c1 VALUE {a:1, b:"one"}; INSERT INTO c1 VALUE {a:2, b:"two"}; CREATE COLLECTION c2; INSERT INTO c2 VALUE {a:1, c:"once"}; INSERT INTO c2 VALUE {a:2, c:"twice"}; INSERT INTO c2 VALUE {a:3, c:"thrice"}; SELECT {a:c1.a, b:c1.b, c:c2.c} FROM c1, c2 WHERE c1.a==c2.a; .result {"a":1,"b":"one","c":"once"} {"a":2,"b":"two","c":"twice"} |