How can an unprepared statement be sent to Postgres in Crystal? - crystal-lang

Is it possible to send an unprepared statement to a Postgres Connection (using the crystal-db and crystal-pg shards)?
I've tried running the following statements using the .query methods, but they failed because they use a prepared statement, which prevents multiple statements from running. Maybe a unprepared statement would work?:
SET LOCAL my.val = 'abc';
SELECT current_setting('my.val') as my_val, 'aa' as now_;

The PG shard allows: an "extended query" protocol (which uses a prepared statement and allows parameters), and a "simple query" protocol (multiple statements with no return value).
In order to prevent some problems, the shard author(s) decided to only return results using the "extended query" protocol. So your only other option would be to use "extended queries" within a transaction. This would allow multiple statements (e.g. SET, SELECT, etc.):
DB.open(uri) do |db|
db.transaction { |tx|
tx.connection.exec "SET LOCAL my.val = 'abc';"
puts tx.connection.scalar("SELECT current_setting('my.val') as my_val;").inspect
}
db.transaction { |tx|
puts tx.connection.scalar("SELECT current_setting('my.val') as my_val;").inspect
}
end
Output:
"abc"
""
Source: https://github.com/will/crystal-pg/issues/139

Related

Using Django SQL Explorer how do I correctly set default dates for paramters with PostgreSQL backend?

Our Django application just migrated from MySQL to PostgreSQL, and we are in the process of updating our user queries to use the correct syntax. These queries are stored/executed via Django-SQL-Explorer.
I have a query that for simplicity's sake looks like this:
SELECT * FROM table t WHERE t.scheduled_start_date BETWEEN $$from_date$$ AND $$to_date$$
The query above works, but I would like to set defaults for today & today+30 respectively.
I've tried the following WHERE clauses to no avail:
Works with user entered date, default throws syntax error
WHERE t.scheduled_start_date BETWEEN date('$$from_date:CURRENT_DATE$$') AND date('$$to_date:CURRENT_DATE + INTERVAL \'30 DAY\'$$')
Error using defaults:
syntax error at or near "30" LINE 28: ...urrent_date') AND date('current_date + interval \'30 day\'') ^
Defaults work correctly, but user entered dates do not:
WHERE t.scheduled_start_date BETWEEN date($$from_date:CURRENT_DATE$$) AND date($$to_date:CURRENT_DATE + INTERVAL '30 DAY'$$)
Error with user dates:
function date(integer) does not exist LINE 28: WHERE t.scheduled_start_date BETWEEN date(2019-09-30) AND da... ^ HINT: No function matches the given name and argument types. You might need to add explicit type casts.
The message about casting makes sense to me since the user enters in string data, however I can't seem to get the syntax right that casts to DATE but only when the default is overridden.
Any suggestions would be helpful. Thanks!
Your input is a string value, current_date is a function call. The former needs quotes whereas the latter does not. Therefore your client side substitution will not work. You can move the default logic into the SQL statement using the COALESCE() function doc.
In case the client sends NULL values for an empty user input this would result in the following where clause:
BETWEEN date(COALESCE('$$from_date$$',current_date))
AND date(COALESCE('$$from_date$$',current_date + interval '30 DAYS'))
You added that your client sends an empty string, not a NULL value. So this should be changed to:
BETWEEN COALESCE(NULLIF('$$from_date$$','')::date, current_date)
AND COALESCE(NULLIF('$$from_date$$','')::date, current_date + interval '30 DAYS')

InfluxDB Grafana templates: Can't select all fields in "Add Query"

I believe I've done everything right when creating my graphite DB. Grafana can see the data but won't let me select all the fields when I try to "Add Query".
Output from my server shows that the DB is working:
show measurements
name: measurements
name
PORT
select * from "PORT"
name: PORT
time CardNo Counter Nodename PortNo value
---- ------ ------- -------- ------ -----
1511214407000000000 18 bcast_inpackets ALPRGAGQPN2 1 500
However, when I try to "Add Query" in Grafana, I can see PORT in "FROM" (which is what I want), but in the "WHERE" section, when I try to narrow my selection using CardNo, Counter, etc., it appears to behave randomly. If I select CardNo first, it will let me select 18 (see picture below), but then clicking "+" to add another criteria doesn't display the option for say "PortNo" (all I get is an empty dialog box). I can enter the field value manually (eg PortNo) but other users will be plotting graphs and won't necessarily know the underlying schema. Also, if I select Nodename first, then I can select CardNo (weird). I'd like it so the end user can specify ALL the fields (in this case CardNo, Counter, Nodename and PortNo).
My graphite template is this:
"[[graphite]]
# Determines whether the graphite endpoint is enabled.
enabled = true
database = "graphite"
# retention-policy = ""
bind-address = ":2003"
protocol = "tcp"
# consistency-level = "one"
templates = [ "ASR.PORT.* .measurement.Nodename.CardNo.PortNo.Counter"
]
and the data I feed to InfluxDB to test my setup is:
echo "ASR.PORT.ALPRGAGQPN2.18.1.bcast_inpackets 500 `date +%s`" | nc localhost 2003
Firstly, template is better written as:
"ASR.PORT.* .measurement.Nodename.CardNo.PortNo.field"
Which makes bcast_inpackets and any other value after PortNo into a field containing data. This reduces cardinality of series, which improves performance and scalability, by combining all counters into multiple fields on the same series as opposed to separate series with unique tags with their own value fields.
Grafana's influx query builder will filter tag values for the value of the already selected tags. In other words, if you select PortNo=1 and try to select another tag, only tag keys where PortNo=1 will be shown.
If you look at queries Grafana runs in browser, you will see something like show tag keys from PORT where PortNo='1' if PortNo=1 is already selected and different queries for other tags.
This is why you may not see other tags and why which tags you see depends on the tags already selected. This is by design so if you want something different you will need to adjust the schema by, for example, making PortNo and CardNo into fields instead of tags.
You might also be interested in InfluxGraph which can query InfluxDB via Graphite API and also supports same template configuration as InfluxDB.

CRM 2015 Microsoft.Xrm.Sdk: Unexpected results in second CreateQuery call

Microsoft.Xrm.Sdk, Version=7.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
var ctx = new ServiceContext(...);
var result1 = (from f in ctx.CreateQuery<aEntity>()
where f.field1 == "x"
select new { f.Id, f.field2 }).ToList();
var result2 = (from f in ctx.CreateQuery<aEntity>()
where f.field1 == "x"
select f.field1).First();
result2 returns null! After adding f.field1 to the select clause in the first query result2 returns "x". It looks like a internal columnset is created and used in the context of the second call. Looking at the SQL Server trace of both calls we see the expected select-from queries based on the C# code. The returned second result is not expected. Can someone explain this behaviour?
As for me it looks like a caching functionality and it's on the side of CRM because as you mentioned SQL queries were correct. I had the same issue in my applications when tried to make two consecutive queries for the same entity record but selected two different fields, the second request always returned NULL. Here are workarounds that I use when work with the ServiceContext:
Simple one: always retrieve an entity with all fields (without select statement) (even if I want it or not)
or create a service context with disabled caching
Right now I try to use the ServiceContext as less as possible replacing it with QueryBase expressions (even if I love to use LINQ).
Keep in mind LINQ CRM driver implementation is a subset of SQL only.
Could you try something like this?
var result1 = (from f in ctx.CreateQuery<aEntity>()
where f.field1 == "x"
select new CustomClass {
Id = f.aEntityId,
Field2 = f.field2
}).ToList();
You can have complex queries if you want, but you need to know what can be done and what can't be done.
Id property is not always returned by the driver, but the entity's primary key is, which is normally the entity logical name + "Id".

siebel log clarification - queries running twice

I am analysing the siebel log and i see that every query runs twice in the log. Could anyone pls tell me why this happens?
For example the below query is one of the many queries that i found got executed twice in the log
SELECT /*+ ALL_ROWS */
T2.CONFLICT_ID,
T2.LAST_UPD,
T2.CREATED,
T2.LAST_UPD_BY,
T2.CREATED_BY,
T2.MODIFICATION_NUM,
T2.ROW_ID,
T1.BU_ID,
T2.MULTI_LINGUAL_FLG,
:1
FROM
SIEBEL.S_LST_OF_VAL_BU T1,
SIEBEL.S_LST_OF_VAL T2
WHERE
T2.ROW_ID = T1.LST_OF_VAL_ID (+) AND
(T2.TYPE = :2 AND T2.NAME = :3)
ORDER BY
T2.TYPE, T2.ORDER_BY, T2.VAL
The query should NOT run twice, unless the logged in user has repeated an operation, and the Business Component is not cached. You will see the SQLs for LOV values repeated in the log, but the value of bind variable ":2" will be different each time. You can see these values just under the SQL
eg: Bind variable 2: TIME_ZONE_DST_ORDINAL
Bind variable 2: DAY_NAME
Is there any other SQL which is repeated and not for the S_LST_OF_VAL tables ?

Doctrine: Select statement using equals not accepted

According to DDC-2204 issue which states
[Order by With Equals] is supported by including the condition in the SELECT clause, aliasing it, then using it. You might need to use "AS HIDDEN name" to prevent it from appearing in the result
following DQL should be possible:
SELECT main.id = 1 AS test FROM Entity main ORDER BY test
However, when I try this (using 2.4), I get
Error: Expected Doctrine\ORM\Query\Lexer::T_FROM, got '='
It seems the developer-advised method of putting the condition into SELECT does not work. Is this a bug and / or is there another way of selecting and / or ordering by condition.
It is possible to use case statement:
SELECT (CASE WHEN main.id = 1 THEN 1 ELSE 0 END) AS test FROM Entity main ORDER BY test
I'm not sure, if I understand that article correctly, but it seems to refer to using the condition in the order by clause:
SELECT main.id AS test FROM Entity main ORDER BY test = 1