UnQL

Check-in [61dc9bee92]
Login

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

Overview
Comment:Add support for SELECT queries with no FROM clause (i.e. "SELECT <expr>;").
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 61dc9bee92f2ec127ad8c62688472f72240b0df9
User & Date: dan 2011-07-16 06:53:51
Context
2011-07-16
12:22
Add parsing of "in" and "WITHIN" operators. Missing implementions. check-in: a8abdbeadb user: drh tags: trunk
06:53
Add support for SELECT queries with no FROM clause (i.e. "SELECT <expr>;"). check-in: 61dc9bee92 user: dan tags: trunk
2011-07-15
21:15
Added support for the ?: operator. check-in: a9a0c2d16e user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/datasrc.c.

36
37
38
39
40
41
42




43
44
45
46
47
48
49
..
62
63
64
65
66
67
68





69
70
71
72
73
74
75
...
114
115
116
117
118
119
120




121
122
123
124
125
126
127
    case TK_ID: {
      char *zSql = sqlite3_mprintf("SELECT x FROM \"%w\"", p->u.tab.zName);
      sqlite3_prepare_v2(pQuery->pStmt->pConn->db, zSql, -1, 
                         &p->u.tab.pStmt, 0);
      sqlite3_free(zSql);
      break;
    }




  }
  return XJD1_OK;
}

/*
** Advance a data source to the next row.
** Return XJD1_DONE if the data source is empty and XJD1_ROW if
................................................................................
        p->pValue = xjd1JsonParse(zJson, -1);
        rc = XJD1_ROW;
      }else{
        p->u.tab.eofSeen = 1;
        rc = XJD1_DONE;
      }
      break;





    }
  }
  return rc;
}

/*
** Return the document that this data source if the document if the AS
................................................................................
  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);
    }




  }
  return XJD1_DONE;
}

/*
** Return true if the data source is at the end of file
*/







>
>
>
>







 







>
>
>
>
>







 







>
>
>
>







36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
..
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
...
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
    case TK_ID: {
      char *zSql = sqlite3_mprintf("SELECT x FROM \"%w\"", p->u.tab.zName);
      sqlite3_prepare_v2(pQuery->pStmt->pConn->db, zSql, -1, 
                         &p->u.tab.pStmt, 0);
      sqlite3_free(zSql);
      break;
    }

    case TK_NULL:                 /* Initializing a NULL DS is a no-op */
      assert( p->u.null.isDone==0 );
      break;
  }
  return XJD1_OK;
}

/*
** Advance a data source to the next row.
** Return XJD1_DONE if the data source is empty and XJD1_ROW if
................................................................................
        p->pValue = xjd1JsonParse(zJson, -1);
        rc = XJD1_ROW;
      }else{
        p->u.tab.eofSeen = 1;
        rc = XJD1_DONE;
      }
      break;
    }
    case TK_NULL: {
      rc = (p->u.null.isDone ? XJD1_DONE : XJD1_ROW);
      p->u.null.isDone = 1;
      break;
    }
  }
  return rc;
}

/*
** Return the document that this data source if the document if the AS
................................................................................
  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
*/

Changes to src/parse.y.

455
456
457
458
459
460
461
462












463
464
465
466
467
468
469
470
      pNew->eDSType = TK_FLATTENOP;
      pNew->u.flatten.pNext = pLeft;
      pNew->u.flatten.cOpName = pOp->z[0];
      pNew->u.flatten.pList = pArgs;
    }
    return pNew;
  }
}












from(A) ::= .                                    {A = 0;}
from(A) ::= FROM fromlist(X).                    {A = X;}
fromlist(A) ::= fromitem(X).                     {A = X;}
fromlist(A) ::= fromlist(X) COMMA fromitem(Y).   {A = joinDataSrc(p,X,Y);}
fromitem(A) ::= ID(X).                           {A = tblDataSrc(p,&X,0);}
fromitem(A) ::= ID(X) AS ID(Y).                  {A = tblDataSrc(p,&X,&Y);}
fromitem(A) ::= LP select(X) RP AS ID(Y).        {A = subqDataSrc(p,X,&Y);}
fromitem(A) ::= fromitem(X) FLATTENOP(Y) LP eachexpr_list(Z) RP.







|
>
>
>
>
>
>
>
>
>
>
>
>
|







455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
      pNew->eDSType = TK_FLATTENOP;
      pNew->u.flatten.pNext = pLeft;
      pNew->u.flatten.cOpName = pOp->z[0];
      pNew->u.flatten.pList = pArgs;
    }
    return pNew;
  }

  /* Create a new data source that represents an empty FROM clause.
  ** This is used for queries of the form "SELECT <expr>". It returns a
  ** single object with no properties.  
  */
  static DataSrc *nullDataSrc(Parse *p){
    DataSrc *pNew = xjd1PoolMallocZero(p->pPool, sizeof(*pNew));
    if( pNew ){
      pNew->eDSType = TK_NULL;
    }
    return pNew;
  }
}
from(A) ::= .                                    {A = nullDataSrc(p);}
from(A) ::= FROM fromlist(X).                    {A = X;}
fromlist(A) ::= fromitem(X).                     {A = X;}
fromlist(A) ::= fromlist(X) COMMA fromitem(Y).   {A = joinDataSrc(p,X,Y);}
fromitem(A) ::= ID(X).                           {A = tblDataSrc(p,&X,0);}
fromitem(A) ::= ID(X) AS ID(Y).                  {A = tblDataSrc(p,&X,&Y);}
fromitem(A) ::= LP select(X) RP AS ID(Y).        {A = subqDataSrc(p,X,&Y);}
fromitem(A) ::= fromitem(X) FLATTENOP(Y) LP eachexpr_list(Z) RP.

Changes to src/xjd1Int.h.

272
273
274
275
276
277
278



279
280
281
282
283
284
285
      DataSrc *pNext;          /* Data source to the left */
      char cOpName;            /* E or F for "EACH" or "FLATTEN" */
      ExprList *pList;         /* List of arguments */
    } flatten;
    struct {                /* A subquery.  eDSType==TK_SELECT */
      Query *q;                /* The subquery */
    } subq;



  } u;
};

/* Any command, including but not limited to a query */
struct Command {
  int eCmdType;             /* Type of command */
  union {







>
>
>







272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
      DataSrc *pNext;          /* Data source to the left */
      char cOpName;            /* E or F for "EACH" or "FLATTEN" */
      ExprList *pList;         /* List of arguments */
    } flatten;
    struct {                /* A subquery.  eDSType==TK_SELECT */
      Query *q;                /* The subquery */
    } subq;
    struct {                /* An empty FROM clause.  eDSType==TK_NULL */
      int isDone;              /* True if single row already returned */
    } null;
  } u;
};

/* Any command, including but not limited to a query */
struct Command {
  int eCmdType;             /* Type of command */
  union {

Changes to test/base02.test.

99
100
101
102
103
104
105














.result 8 49 69

.testcase 15
SELECT 1 - 7 FROM c1;
SELECT 45 - 4 FROM c1;
SELECT 67 - 2 FROM c1;
.result -6 41 65





















>
>
>
>
>
>
>
>
>
>
>
>
>
>
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
.result 8 49 69

.testcase 15
SELECT 1 - 7 FROM c1;
SELECT 45 - 4 FROM c1;
SELECT 67 - 2 FROM c1;
.result -6 41 65


.testcase 16
SELECT 1.12;
SELECT "hello world";
SELECT a;
SELECT { x: "value" };
SELECT [1,4,9,16,25];
SELECT null;
SELECT true;
SELECT false;
.result 1.12 "hello world" null {"x":"value"} [1,4,9,16,25] null true false