How to safely use reserved SQL names? - sql-server

I'm using Cakephp 3 using sqlserver as datasource server. I am sure there's no problem with my database connection.. as home.ctp prompts that I am connected to my database.. and I'm as well using migrations plugin to create my tables.. it seems like there is no problem working with these tools. but after I bake my MVC, I only got page full of errors..
for example
$bin\cake bake all tests
there are no errors I found and MVC are in its specific folder, testController.php, testTable, etc.
and in browsers
localhost:8765\tests
but all I got is page of different errors.. Im seeing
Error: SQLSTATE[42000]: [Microsoft][SQL Server Native Client 11.0][SQL Server]Incorrect syntax near the keyword 'desc'.
SELECT * FROM (SELECT Tests.id AS [Tests__id], Tests.desc AS [Tests__desc], (ROW_NUMBER() OVER (ORDER BY (SELECT NULL))) AS [_cake_page_rownum_] FROM tests Tests) _cake_paging_ WHERE _cake_paging_._cake_page_rownum_ <= :c0
and more errors on the left side.
I assume this is because of controllers with wrong queries or queries generated by bake is for mysql only. I just wanna know how to deal with this. is there a setting I forgot to do? please advice. I am new to Cakephp, and English is not my native language, sorry if I can't explain my question properly. thanks in advance.

As already mentioned by Vishal Gajjar in the comments, you are using the reserved keyword desc for your column name, hence the error, it's not bakes fault, it's yours.
In order to be able to use such reserved words, the column name needs to be quoted properly, however CakePHP 3 doesn't auto-quote by default anymore, as it's an expensive operation.
If you insist on using reserved words, enable identifier quoting via the quoteIdentifiers option in your app.php config, or enable it manually using the autoQuoting() (enableAutoQuoting() as of CakePHP 3.4) method of the DB driver.
See also
Cookbook > Database Access & ORM > Database Basics > Identifier Quoting
Cookbook > 3.x Migration Guide > New ORM Upgrade Guide > Identifier Quoting Disabled by Default
API > \Cake\Database\Driver::autoQuoting()
API > \Cake\Database\Driver::enableAutoQuoting()

You can use this code before problematic query:
$this->Tests->connection()->driver()->autoQuoting(true);
and when you are finished you can turn auto quoting off:
$this->Tests->connection()->driver()->autoQuoting(false);
So bad performance would be only on problematic query.

Use this :
SELECT * FROM (SELECT Tests.id AS [Tests__id], Tests.[desc] AS [Tests__desc],
(ROW_NUMBER() OVER (ORDER BY (SELECT NULL))) AS [_cake_page_rownum_] FROM tests Tests) _cake_paging_
WHERE _cake_paging_._cake_page_rownum_ <= :c0
If you do use a keyword, use it in square braces [ ]

Related

<MSDialect_pyodbc, TIMESTAMP> error when comparing tables in DVT - BigQuery and SQL Server

I'm trying to compare the table data between two databases (on-prem SQL Server and BigQuery). I'm currently using Data-Validation-Tool for that (DVT).
Using the instructions from Github (link: https://github.com/GoogleCloudPlatform/professional-services-data-validator/tree/develop/docs), I installed and created a connection for DVT.
When tried to compare two table from single source, it works fine and provide correct output. But when checked for two different source, it returns dtype: <MSDialect_pyodbc, TIMESTAMP> error.
Details:
I tried to validate over level count but still same error. Command -
data-validation validate column -sc wc_sql_conn -tc my_bq_conn -tbls EDW.dbo.TableName=project_id.dataset_name.TableName --primary-keys PK_Col_Name --count '*'
Also, When checked for schema level validation -
data-validation validate schema -sc wc_sql_conn -tc my_bq_conn -tbls EDW.dbo.TableName=project_id.dataset_name.TableName
I tried to add only INT/STRING columns in custom query and then comparing it.
Custom Query -
SELECT PK_Col_Name, Category FROM EDW.dbo.TableName
Similar custom query prepared for BQ and command for custom query comparison -
data-validation validate custom-query -sc wc_sql_conn -tc my_bq_conn -cqt 'column' -sqf sql_query.txt -tqf bq_query.txt -pk PK_Col_Name --count '*'
data-validation validate custom-query -sc wc_sql_conn -tc my_bq_conn -cqt 'row' -sqf sql_query.txt -tqf bq_query.txt -pk PK_Col_Name --count '*'
Even when using multiple approaches and the scenario doesn't involve a datetime/timestamp column, I typically only get one error -
NotImplementedError: Could not find signature for dtype: <MSDialect_pyodbc, TIMESTAMP>
I tried to google down the error, but no luck. Could someone please help me identify the error?
Additionally, there are no data-validation-tool or google-pso-data-validator tags available. If someone could add that, it may be used in the future and reach the right people.

Accessing properties from Mappers

I have a linked server in SQL Server so when I query something, it has to be something like this:
SELECT * FROM [SERVERNAME].[DBNAME].[SCHEMA].[TABLE]
Now I have to implement this way of querying to an existing project with the servername, dbname and schema provided in my application.properties.
Is there any way to access these properties from my Mapper(xml)?
You can use properties.
With MyBatis-Spring-Boot, you can define properties in your application.properties with the prefix mybatis.configuration.variables. [1].
mybatis.configuration.variables.db_servername=YOUR_SERVER_NAME
mybatis.configuration.variables.db_dbname=YOUR_DB_NAME
mybatis.configuration.variables.db_schema=YOUR_SCHEMA
It is also possible to reference variables defined in the same application.properties.
mybatis.configuration.variables.db_servername=${servername}
mybatis.configuration.variables.db_dbname=${dbname}
mybatis.configuration.variables.db_schema=${schema}
Then you can use these variables in mappers using ${}.
SELECT * FROM [${db_servername}].[${db_dbname}].[${db_schema}].[TABLE]
Note: #{} won't work. See this FAQ entry for the difference.
[1] The doc says that the prefix is mybatis.configuration-properties., but I just tested it and it didn't work. It could be my mistake, though. I plan to investigate when I have some spare time.

The Microsoft Access Database Engine does not recognize

I use Access at work, I'm mostly self-taught and I know very little code . I've built a data base for handling HR KPI´S. In some of my queries, since 2016 started (2015 still runs), several reports I run now pops the error:
"The Microsoft Access Database Engine does not recognize 'C_Hrs_Permiso_TI_NT.NOTRAB' as a valid field name or expression".
I'm not sure why the report would be giving me an error about it.
Query Code:
TRANSFORM Sum(Hrs_Permiso_TI_NT.MONTOO) AS SumaDeMONTOO
SELECT Hrs_Permiso_TI_NT.EMPRESA,
Hrs_Permiso_TI_NT.CENCOS,
Left([Hrs_Permiso_TI_NT]![AMES],4) AS Año,
Right([Hrs_Permiso_TI_NT]![AMES],2) AS Mes,
Hrs_Permiso_TI_NT.CODIGO,
Fecha_maxmes_Calendario.MáxDeFecha
FROM Hrs_Permiso_TI_NT INNER JOIN Fecha_maxmes_Calendario
ON Hrs_Permiso_TI_NT.AMES=Fecha_maxmes_Calendario.Ames
GROUP BY Hrs_Permiso_TI_NT.EMPRESA,
Hrs_Permiso_TI_NT.CENCOS,
Left([Hrs_Permiso_TI_NT]![AMES],4),
Right([Hrs_Permiso_TI_NT]![AMES],2),
Hrs_Permiso_TI_NT.CODIGO,
Fecha_maxmes_Calendario.MáxDeFecha
PIVOT Hrs_Permiso_TI_NT.COHADE;
As soon as this query doesn't contain C_Hrs_Permiso_TI_NT, it means that the problem is one of queries 'Hrs_Permiso_TI_NT' or Fecha_maxmes_Calendario. Try to open them and locate error

Rails 3, ActiveRecord, PostgreSQL - ".uniq" command doesn't work?

I have following query:
Article.joins(:themes => [:users]).where(["articles.user_id != ?", current_user.id]).order("Random()").limit(15).uniq
and gives me the error
PG::Error: ERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list
LINE 1: ...s"."user_id" WHERE (articles.user_id != 1) ORDER BY Random() L...
When I update the original query to
Article.joins(:themes => [:users]).where(["articles.user_id != ?", current_user.id]).order("Random()").limit(15)#.uniq
so the error is gone... In MySQL .uniq works, in PostgreSQL not. Exist any alternative?
As the error states for SELECT DISTINCT, ORDER BY expressions must appear in select list.
Therefore, you must explicitly select for the clause you are ordering by.
Here is an example, it is similar to your case but generalize a bit.
Article.select('articles.*, RANDOM()')
.joins(:users)
.where(:column => 'whatever')
.order('Random()')
.uniq
.limit(15)
So, explicitly include your ORDER BY clause (in this case RANDOM()) using .select(). As shown above, in order for your query to return the Article attributes, you must explicitly select them also.
I hope this helps; good luck
Just to enrich the thread with more examples, in case you have nested relations in the query, you can try with the following statement.
Person.find(params[:id]).cars.select('cars.*, lower(cars.name)').order("lower(cars.name) ASC")
In the given example, you're asking all the cars for a given person, ordered by model name (Audi, Ferrari, Porsche)
I don't think this is a better way, but may help to address this kind of situation thinking in objects and collections, instead of a relational (Database) way.
Thanks!
I assume that the .uniq method is translated to a DISTINCT clause on the SQL. PostgreSQL is picky (pickier than MySQL) -- all fields in the select list when using DISTINCT must be present in the ORDER_BY (and GROUP_BY) clauses.
It's a little unclear what you are attempting to do (a random ordering?). In addition to posting the full SQL sent, if you could explain your objective, that might be helpful in finding an alternative.
I just upgraded my 100% working and tested application from 3.1.1 to 3.2.7 and now have this same PG::Error.
I am using Cancan...
#users = User.accessible_by(current_ability).order('lname asc').uniq
Removing the .uniq solves the problem and it was not necessary anyway for this simple query.
Still looking through the change notes between 3.1.1 and 3.2.7 to see what caused this to break.

SOQL - Convert Date To Owner Locale

We use the DBAmp for integrating Salesforce.com with SQL Server (which basically adds a linked server), and are running queries against our SF data using OPENQUERY.
I'm trying to do some reporting against opportunities and want to return the created date of the opportunity in the opportunity owners local date time (i.e. the date time the user will see in salesforce).
Our dbamp configuration forces the dates to be UTC.
I stumbled across a date function (in the Salesforce documentation) that I thought might be some help, but I get an error when I try an use it so can't prove it, below is the example useage for the convertTimezone function:
SELECT HOUR_IN_DAY(convertTimezone(CreatedDate)), SUM(Amount)
FROM Opportunity
GROUP BY HOUR_IN_DAY(convertTimezone(CreatedDate))
Below is the error returned:
OLE DB provider "DBAmp.DBAmp" for linked server "SALESFORCE" returned message "Error 13005 : Error translating SQL statement: line 1:37: expecting "from", found '('".
Msg 7350, Level 16, State 2, Line 1
Cannot get the column information from OLE DB provider "DBAmp.DBAmp" for linked server "SALESFORCE".
Can you not use SOQL functions in OPENQUERY as below?
SELECT
*
FROM
OPENQUERY(SALESFORCE,'
SELECT HOUR_IN_DAY(convertTimezone(CreatedDate)), SUM(Amount)
FROM Opportunity
GROUP BY HOUR_IN_DAY(convertTimezone(CreatedDate))')
UPDATE:
I've just had some correspondence with Bill Emerson (I believe he is the creator of the DBAmp Integration Tool):
You should be able to use SOQL functions so I am not sure why you are
getting the parsing failure. I'll setup a test case and report back.
I'll update the post again when I hear back. Thanks
A new version of DBAmp (2.14.4) has just been released that fixes the issue with using ConvertTimezone in openquery.
Version 2.14.4
Code modified for better memory utilization
Added support for API 24.0 (SPRING 12)
Fixed issue with embedded question marks in string literals
Fixed issue with using ConvertTimezone in openquery
Fixed issue with "Invalid Numeric" when using aggregate functions in openquery
I'm fairly sure that because DBAmp uses SQL and not SOQL, SOQL functions would not be available, sorry.
You would need to expose this data some other way. Perhaps it's possible with a Salesforce report, web-service, or compiling the data through the program you are using to access the (DBAmp) SQL Server.
If you were to create a Salesforce web service, the following example might be helpful.
global class MyWebService
{
webservice static AggregateResult MyWebServiceMethod()
{
AggregateResult ar = [
SELECT
HOUR_IN_DAY(convertTimezone(CreatedDate)) Hour,
SUM(Amount) Amount
FROM Opportunity
GROUP BY HOUR_IN_DAY(convertTimezone(CreatedDate))];
system.debug(ar);
return ar;
}
}

Resources