But he was to be able to provide the args as {‘0’:’one, ‘10’:’ten’} and since 
he only uses positional rags 1 and 10 that it be OK, i.e. positional args are 
treated as key word args, and only those actually used are needed. THAT can’t 
be provided by the API.

> On Jul 22, 2019, at 9:22 AM, Keith Medcalf <kmedc...@dessus.com> wrote:
> 
> 
> I don't see what is so hard.  APSW does it:
> 
>> python
> Python 2.7.16 (v2.7.16:413a49145e, Mar  4 2019, 01:30:55) [MSC v.1500 32 bit 
> (Intel)] on win32
> Type "help", "copyright", "credits" or "license" for more information.
>>>> import apsw
>>>> db = apsw.Connection('')
>>>> db.execute('select ?, ?10;', ('one', 'ten')).fetchone()
> Traceback (most recent call last):
>  File "<stdin>", line 1, in <module>
>  File "C:\python\lib\site-packages\Local\newapsw.py", line 39, in execute
>    return self.cursor().execute(*args, **kwargs)
> apsw.BindingsError: Incorrect number of bindings supplied.  The current 
> statement uses 10 and there are 2 supplied.  Current offset is 0
>>>> 
> 
> The statement required 10 parameters and only 2 were supplied.  ERROR!
> 
> Internally it uses sqlite3_bind_parameter_count to find out how many 
> parameters need binding and requires that the number of "parameters" passed 
> match the number of parameters "expected" when binding positionally.
> 
>>>> db.execute('select :1, :10;', {'2': 'one', '10': 'ten'}).fetchone()
> Row(_0=None, _1=u'ten')
>>>> db.execute('select :1, :10;', {'1': 'one', '10': 'ten'}).fetchone()
> Row(_0=u'one', _1=u'ten')
>>>> 
> 
> When binding by name, it looks up the names in the provided dictionary and 
> binds those it finds.
> 
> You can also bind named parameters to a positional list (in which case it is 
> the programmers job to keep track of what they are doing) since a named 
> parameter is merely syntactic sugar on top of positional parameters:
> 
>>>> db.execute('select :1, :10;', ('one', 'two')).fetchone()
> Row(_0=u'one', _1=u'two')
>>>> 
> 
> It is not very difficult.  You call sqlite3_bind_parameter_count.  Then if 
> you are binding positionally you make sure there are sufficient positional 
> parameters provided to bind them all.  It you are binding by name, you cycle 
> through the parameters, get the name, and then bind the given named parameter 
> to that parameter.  apsw chooses to ignore missing items when binding by name 
> -- sounds like you simply want to ERROR instead ...
> 
> The only issue I can see is that when requesting the name of an positional 
> parameter that has no name it returns null rather than the positional name, 
> however, this is pretty easy to work around in pretty much any programming 
> language ... that is if sqlite3_parameter_name(stmt, x) return null then the 
> name is a ? followed by x in decimal (sprintf("?%d", x) or thereabouts having 
> appropriate accomodations for the language syntax and buffer safety, etc)
> 
> However, you cannot bind to positional parameters by name:
> 
>>>> db.execute('select ?1, ?10;', {'2': 'one', '10': 'ten'}).fetchone()
> Traceback (most recent call last):
>  File "<stdin>", line 1, in <module>
>  File "C:\python\lib\site-packages\Local\newapsw.py", line 39, in execute
>    return self.cursor().execute(*args, **kwargs)
> apsw.BindingsError: Binding 1 has no name, but you supplied a dict (which 
> only has names).
> 
> 
> *the builtin python sqlite3 wrapper does the same thing I expect (though I 
> have never actually looked) but it is somewhat braindead otherwise, so I 
> don't use it and haven't bothered to test what it does in these 
> circumstances.  Though my expectation is that it would behave somewhat 
> similarly.
> -- 
> The fact that there's a Highway to Hell but only a Stairway to Heaven says a 
> lot about anticipated traffic volume.
> 
> 
>> -----Original Message-----
>> From: sqlite-users [mailto:sqlite-users-
>> boun...@mailinglists.sqlite.org] On Behalf Of test user
>> Sent: Monday, 22 July, 2019 06:36
>> To: SQLite mailing list
>> Subject: Re: [sqlite] [EXTERNAL] Determining valid statement
>> placeholders.
>> 
>> I understand the problem, but I want my library to be able to detect
>> the
>> problem programatically.
>> 
>> Currently if a user mixes index-based and key-based placeholders, the
>> only
>> thing a library using SQLite can do us run the query with unbound
>> placeholders set to null (the SQLite default).
>> 
>> Id like the ability to instead throw an error in this case.
>> 
>> 
>> I think SQLite internally knows how many placeholders are in the
>> query at
>> parse time.
>> 
>> My question is how can I get the data via the API, or if it would be
>> considered to add a function to get this data?
>> 
>> 
>> On Mon, Jul 22, 2019 at 12:29 PM Keith Medcalf <kmedc...@dessus.com>
>> wrote:
>> 
>>> 
>>> On Monday, 22 July, 2019 04:34, Enzo <contact.enz...@gmail.com>
>> wrote:
>>> 
>>>> It is not the same information.
>>> 
>>>> I want to be able to determine "has the user bound all placeholder
>>>> values with data?".
>>> 
>>>> The user provides this as input:
>>> 
>>>> query="SELECT ?, ?10"
>>>> data={"0": "data-a", "10": "data-b"}
>>> 
>>>> Note: This IS valid, as they have provided all data for
>> placeholders.
>>> 
>>>> Using the APIs you mentioned:
>>> 
>>>> count=10
>>>> name(10) = "?10"
>>> 
>>>> So according to the API, the indexes [1, 2, 3, 4, 5, 6, 7, 8, 9,
>> 10]
>>>> are placeholders in the query.
>>> 
>>>> As you can see, only indexes [1, 10] are valid placeholders in the
>>>> query.
>>> 
>>>> So, as far as I can tell, it is not possible to get this from the
>>>> API:
>>> 
>>>> query="SELECT ?, ?10"
>>>> valid_placeholder_indexes=[1, 10]
>>> 
>>>> It is only possible to get this:
>>> 
>>>> query="SELECT ?, ?10"
>>>> maybe_placeholder_indexes=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> 
>>> The fundamental issue is that you are confusing POSITIONAL
>> parameters with
>>> NAMED parameters.  ?nnn where nnn is numeric describe POSITIONAL
>>> parameters, so in the query SELECT ?, ?10 you are using positional
>>> parameter 1 and positional parameter 10.  That implies that there
>> are 10
>>> positional parameters.  The fact that you are only using those
>> positional
>>> parameters sparsely (only using positional parameter 1 and
>> positional
>>> parameter 10) does not mean that you are using two parameters, it
>> means
>>> that you are using 10, but only referencing 2 of them.
>>> 
>>> Said another way, you are declaring a function that looks like
>> this:
>>> 
>>> int stmt(a, b, c, d, e, f, g, h, i, j)
>>>   return a + j
>>> 
>>> and expecting to be able to call it as
>>> 
>>> z = stmt(1, 6)
>>> 
>>> expecting some magic to know that the second parameter is really
>> parameter
>>> 10.
>>> 
>>> https://www.sqlite.org/lang_expr.html#varparam
>>> 
>>> There may be many positional parameters (like 999 in the default
>> build)
>>> and sqlite3_bind_parameter_count returns the "index" of the
>> greatest
>>> parameter number used in the statement.  Having created 10
>> parameters
>>> sqlite has absolutely no clue that you happen to be using only
>> parameter 1
>>> and parameter 10.  If you only needed 2 parameters you should have
>> only
>>> created 2, not 10.  That is what NAMED parameters are for.
>>> 
>>> If you change from using positional (?) parameters to using named
>> (:) or
>>> (@) what happens?
>>> 
>>> select :1, :10; should only create 2 parameters named :1 and :10
>> ...
>>> 
>>> --
>>> The fact that there's a Highway to Hell but only a Stairway to
>> Heaven says
>>> a lot about anticipated traffic volume.
>>> 
>>> 
>>> 
>>> 
>>> _______________________________________________
>>> sqlite-users mailing list
>>> sqlite-users@mailinglists.sqlite.org
>>> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-
>> users
>>> 
>> _______________________________________________
>> sqlite-users mailing list
>> sqlite-users@mailinglists.sqlite.org
>> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users
> 
> 
> 
> _______________________________________________
> sqlite-users mailing list
> sqlite-users@mailinglists.sqlite.org
> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users

_______________________________________________
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to