tdbc::postgres

Check-in [ee2ba4cd4a]
Login
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2019 Conference, Houston/TX, US, Nov 4-8
Send your abstracts to [email protected]
or submit via the online form by Sep 9.

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

Overview
Comment:Properly quote string constants and identifiers
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | medranocalvo-correct-quoting
Files: files | file ages | folders
SHA3-256: ee2ba4cd4a7478be6c9536fde8662facadf20afdb59d3d55355ac70f393b49e5
User & Date: adrianmedranocalvo 2018-09-14 17:57:30
Context
2018-09-14
18:10
Add copyright information check-in: e1181bd5af user: adrianmedranocalvo tags: medranocalvo-correct-quoting
17:57
Properly quote string constants and identifiers check-in: ee2ba4cd4a user: adrianmedranocalvo tags: medranocalvo-correct-quoting
2018-07-01
05:17
Update to latest TEA. DONT_TD_VOID was removed from unixODBC in version 2.3.1, 2011/11/28. check-in: 5cce9b482f user: stu tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to generic/tdbcpostgres.c.

   396    396       ISOL_REPEATABLE_READ,
   397    397       ISOL_SERIALIZABLE,
   398    398       ISOL_NONE = -1
   399    399   };
   400    400   
   401    401   /* Static functions defined within this file */
   402    402   
          403  +static void AppendSQLStringConstant(Tcl_DString *dsPtr, Tcl_Obj *stringObj);
          404  +static void AppendSQLIdentifier(Tcl_DString *dsPtr, Tcl_Obj *stringObj);
          405  +
   403    406   static int DeterminePostgresMajorVersion(Tcl_Interp* interp,
   404    407   					 ConnectionData* cdata,
   405    408   					 int* versionPtr);
   406    409   static void DummyNoticeProcessor(void*, const PGresult*);
   407    410   static int ExecSimpleQuery(Tcl_Interp* interp, PGconn * pgPtr,
   408    411   			   const char * query, PGresult** resOut);
   409    412   static void TransferPostgresError(Tcl_Interp* interp, PGconn * pgPtr);
................................................................................
  1467   1470   				/* Literal pool */
  1468   1471       PGresult* res,* resType;	/* Results of libpq call */
  1469   1472       char* columnName;		/* Name of the column */
  1470   1473       Oid typeOid;		/* Oid of column type */
  1471   1474       Tcl_Obj* retval;		/* List of table names */
  1472   1475       Tcl_Obj* attrs;		/* Attributes of the column */
  1473   1476       Tcl_Obj* name;		/* Name of a column */
  1474         -    Tcl_Obj* sqlQuery = Tcl_NewStringObj("SELECT * FROM ", -1);
  1475         -				/* Query used */
  1476         -
  1477         -    Tcl_IncrRefCount(sqlQuery);
         1477  +    Tcl_DString ds, *dsPtr = &ds;
  1478   1478   
  1479   1479       /* Check parameters */
  1480   1480   
  1481   1481       if (objc < 3 || objc > 4) {
  1482   1482   	Tcl_WrongNumArgs(interp, 2, objv, "table ?pattern?");
  1483   1483   	return TCL_ERROR;
  1484   1484       }
         1485  +
         1486  +    Tcl_DStringInit(dsPtr);
  1485   1487   
  1486   1488       /* Check if table exists by retreiving one row.
  1487   1489        * The result wille be later used to determine column types (oids) */
  1488         -    Tcl_AppendObjToObj(sqlQuery, objv[2]);
         1490  +    Tcl_DStringAppend(dsPtr, "SELECT * FROM ", -1);
         1491  +    AppendSQLIdentifier(dsPtr, objv[2]);
         1492  +    Tcl_DStringAppend(dsPtr, " LIMIT 0", -1);
  1489   1493   
  1490         -    if (ExecSimpleQuery(interp, cdata->pgPtr, Tcl_GetString(sqlQuery),
         1494  +    if (ExecSimpleQuery(interp, cdata->pgPtr, Tcl_DStringValue(dsPtr),
  1491   1495   			&resType) != TCL_OK) {
  1492         -        Tcl_DecrRefCount(sqlQuery);
         1496  +	Tcl_DStringFree(dsPtr);
  1493   1497   	return TCL_ERROR;
  1494   1498       }
  1495   1499   
  1496         -    Tcl_DecrRefCount(sqlQuery);
         1500  +    Tcl_DStringSetLength(dsPtr, 0);
  1497   1501   
  1498   1502       /* Retreive column attributes */
  1499   1503   
  1500         -    sqlQuery = Tcl_NewStringObj("SELECT "
         1504  +    Tcl_DStringAppend(dsPtr, "SELECT "
  1501   1505   	"  column_name,"
  1502   1506   	"  numeric_precision,"
  1503   1507   	"  character_maximum_length,"
  1504   1508   	"  numeric_scale,"
  1505   1509   	"  is_nullable"
  1506   1510   	"  FROM information_schema.columns"
  1507         -	"  WHERE table_name='", -1);
  1508         -    Tcl_IncrRefCount(sqlQuery);
  1509         -    Tcl_AppendObjToObj(sqlQuery, objv[2]);
         1511  +	"  WHERE table_name=", -1);
         1512  +    AppendSQLStringConstant(dsPtr, objv[2]);
  1510   1513   
  1511   1514       if (objc == 4) {
  1512         -	Tcl_AppendToObj(sqlQuery,"' AND column_name LIKE '", -1);
  1513         -	Tcl_AppendObjToObj(sqlQuery, objv[3]);
         1515  +	Tcl_DStringAppend(dsPtr, " AND column_name LIKE ", -1);
         1516  +	AppendSQLStringConstant(dsPtr, objv[3]);
  1514   1517       }
  1515         -    Tcl_AppendToObj(sqlQuery,"'", -1);
  1516   1518   
  1517   1519       if (ExecSimpleQuery(interp, cdata->pgPtr,
  1518         -			Tcl_GetString(sqlQuery), &res) != TCL_OK) {
  1519         -        Tcl_DecrRefCount(sqlQuery);
         1520  +			Tcl_DStringValue(dsPtr), &res) != TCL_OK) {
         1521  +	Tcl_DStringFree(dsPtr);
  1520   1522   	PQclear(resType);
  1521   1523   	return TCL_ERROR;
  1522   1524       } else {
  1523   1525   	int i, j;
  1524   1526   	retval = Tcl_NewObj();
  1525   1527   	Tcl_IncrRefCount(retval);
  1526   1528   	for (i = 0; i < PQntuples(res); i += 1) {
................................................................................
  1579   1581   
  1580   1582   	    Tcl_DictObjPut(NULL, attrs, literals[LIT_NULLABLE],
  1581   1583   		    Tcl_NewIntObj(strcmp("YES",
  1582   1584   			    PQgetvalue(res, i, 4)) == 0));
  1583   1585   	    Tcl_DictObjPut(NULL, retval, name, attrs);
  1584   1586   	}
  1585   1587   
  1586         -	Tcl_DecrRefCount(sqlQuery);
         1588  +	Tcl_DStringFree(dsPtr);
  1587   1589   	Tcl_SetObjResult(interp, retval);
  1588   1590   	Tcl_DecrRefCount(retval);
  1589   1591   	PQclear(resType);
  1590   1592   	PQclear(res);
  1591   1593   	return TCL_OK;
  1592   1594       }
  1593   1595   }
................................................................................
  1734   1736   	Tcl_ObjectGetMetadata(thisObject, &connectionDataType);
  1735   1737   				/* Instance data */
  1736   1738       Tcl_Obj** literals = cdata->pidata->literals;
  1737   1739   				/* Literal pool */
  1738   1740       PGresult* res;		/* Result of libpq call */
  1739   1741       char * field;		/* Field value from SQL result */
  1740   1742       Tcl_Obj* retval;		/* List of table names */
  1741         -    Tcl_Obj* sqlQuery = Tcl_NewStringObj("SELECT tablename"
  1742         -					 " FROM pg_tables"
  1743         -					 " WHERE  schemaname = 'public'",
  1744         -					 -1);
  1745         -				/* SQL query for table list */
  1746   1743       int i;
  1747         -    Tcl_IncrRefCount(sqlQuery);
         1744  +    Tcl_DString ds, *dsPtr = &ds;
  1748   1745   
  1749   1746       /* Check parameters */
  1750   1747   
  1751   1748       if (objc < 2 || objc > 3) {
  1752   1749   	Tcl_WrongNumArgs(interp, 2, objv, "");
  1753   1750   	return TCL_ERROR;
  1754   1751       }
  1755   1752   
         1753  +    Tcl_DStringInit(dsPtr);
         1754  +    Tcl_DStringAppend(dsPtr,
         1755  +		      "SELECT tablename"
         1756  +		      " FROM pg_tables"
         1757  +		      " WHERE  schemaname = 'public'",
         1758  +		      -1); /* SQL query for table list */
         1759  +
  1756   1760       if (objc == 3) {
  1757   1761   
  1758   1762   	/* Pattern string is given */
  1759   1763   
  1760         -	Tcl_AppendToObj(sqlQuery, " AND  tablename LIKE '", -1);
  1761         -	Tcl_AppendObjToObj(sqlQuery, objv[2]);
  1762         -	Tcl_AppendToObj(sqlQuery, "'", -1);
         1764  +	Tcl_DStringAppend(dsPtr, " AND  tablename LIKE ", -1);
         1765  +	AppendSQLStringConstant(dsPtr, objv[2]);
  1763   1766       }
  1764   1767   
  1765   1768       /* Retrieve the table list */
  1766   1769   
  1767         -    if (ExecSimpleQuery(interp, cdata ->pgPtr, Tcl_GetString(sqlQuery),
         1770  +    if (ExecSimpleQuery(interp, cdata ->pgPtr, Tcl_DStringValue(dsPtr),
  1768   1771   			&res) != TCL_OK) {
  1769         -	Tcl_DecrRefCount(sqlQuery);
         1772  +	Tcl_DStringFree(dsPtr);
  1770   1773   	return TCL_ERROR;
  1771   1774       }
  1772         -    Tcl_DecrRefCount(sqlQuery);
         1775  +    Tcl_DStringFree(dsPtr);
  1773   1776   
  1774   1777       /* Iterate through the tuples and make the Tcl result */
  1775   1778   
  1776   1779       retval = Tcl_NewObj();
  1777   1780       for (i = 0; i < PQntuples(res); i+=1) {
  1778   1781   	if (!PQgetisnull(res, i, 0)) {
  1779   1782   	    field = PQgetvalue(res, i, 0);
................................................................................
  3411   3414      if (--pgRefCount == 0) {
  3412   3415          Tcl_FSUnloadFile(NULL, pgLoadHandle);
  3413   3416          pgLoadHandle = NULL;
  3414   3417      }
  3415   3418      Tcl_MutexUnlock(&pgMutex);
  3416   3419   
  3417   3420   }
         3421  +
         3422  +/*
         3423  + *-----------------------------------------------------------------------------
         3424  + *
         3425  + * AppendSQLDelimited --
         3426  + *
         3427  + *	Convert a string into a safe delimited string and append it to the
         3428  + *	dynamic string.
         3429  + *
         3430  + *-----------------------------------------------------------------------------
         3431  + */
         3432  +static void
         3433  +AppendSQLDelimited(Tcl_DString *dsPtr, Tcl_Obj *stringObj, char delimiter) {
         3434  +    int b, e;
         3435  +    int len = 0;
         3436  +    char *str = Tcl_GetStringFromObj(stringObj, &len);
         3437  +    Tcl_DStringAppend(dsPtr, &delimiter, 1);
         3438  +    for (b = 0, e = 0; e < len; e++) {
         3439  +	if (str[e] == delimiter) {
         3440  +	    Tcl_DStringAppend(dsPtr, &str[b], e - b);
         3441  +	    Tcl_DStringAppend(dsPtr, &delimiter, 1);
         3442  +	    Tcl_DStringAppend(dsPtr, &delimiter, 1);
         3443  +	    b = e+1;
         3444  +	}
         3445  +    }
         3446  +    Tcl_DStringAppend(dsPtr, &str[b], e - b);
         3447  +    Tcl_DStringAppend(dsPtr, &delimiter, 1);
         3448  +}
         3449  +
         3450  +static void
         3451  +AppendSQLStringConstant(Tcl_DString *dsPtr, Tcl_Obj *stringObj) {
         3452  +    AppendSQLDelimited(dsPtr, stringObj, '\'');
         3453  +}
         3454  +
         3455  +static void
         3456  +AppendSQLIdentifier(Tcl_DString *dsPtr, Tcl_Obj *stringObj) {
         3457  +    AppendSQLDelimited(dsPtr, stringObj, '"');
         3458  +}
         3459  +
  3418   3460   
  3419   3461   /*
  3420   3462    * Local Variables:
  3421   3463    * mode: c
  3422   3464    * c-basic-offset: 4
  3423   3465    * End:
  3424   3466    */