Using Sqlite InMemory DB for unittesting MSSQL-DB - sql-server

I am trying to implement this solution:
NHibernate-20-SQLite-and-In-Memory-Databases
The only problem is that we have hbms like this:
<class name="aTable" table="[dbo].[aTable]" mutable="true" lazy="false">
with [dbo] in the table name, because we are working with mssql, and this does not work with Sqlite.
I found this posting on the rhino-tools-dev group where they talk about just removing the schema from the mapping, but on NH2 there doesn't seem to be a classMapping.Schema.
There is a classMapping.Table.Schema, but it seems to be read-only. For example, this doesn't work:
foreach (PersistentClass cp in configuration.ClassMappings) {
// Does not work - throws a
//System.IndexOutOfRangeException: Index was outside the bounds of the array.
cp.Table.Schema = "";
}
Is there a way to tell Sqlite to ignore the [dbo] (I tried attach database :memory: as dbo, but this didn't seem to help)?
Alternatively, can I programmatically remove it from the classmappings (unfortunately changing the hbms is not possible right now)?

We had too many problems with SQLite which eventually pushed us to switch to SQL Express.
Problems I remember:
SQLite, when used in-memory, discards the database when Session is closed
SQLite does not support bunch of SQL constructs such basic ones as ISNULL, but also more advanced like common table expressions and others added in SQL 2005 and 2008. This becomes important when you start writing complex named queries.
SQLite's datetime has bigger range of possible values than SQL Server's
The API NHibernate uses for SQLite behaves differently than ADO.NET for MS SQL Server when used in scope of transaction. One example is the hbm-to-ddl tool whose Execute method does not work inside transaction with SQL Server but works fine with SQLite.
To summarize, SQLite-based unit-testing is very far from being conclusively representative of the issues you'll encounter when using MS SQL Server in PROD and therefore undermines the credibility of unit-testing overall.

We are using Sqlite to run unit tests with NH 2.0.1. Actually, I didn't run into this problem. I just didn't specify dbo, I think it is default on SqlServer.
By the way, there is a default_schema parameter in the configuration file. This is actually the database name, but you can try putting the dbo there, only for the SqlServer configuration of course.

After looking through the source of NH and some experimenting i think i found a simple workaround -
foreach (PersistentClass cp in configuration.ClassMappings)
{
// Input : [dbo].[Tablename] Output : Tablename
cp.Table.Name = Regex.Replace(cp.Table.Name, #"^\[.*\]\.\[", "");
cp.Table.Name = Regex.Replace(cp.Table.Name, #"\]$", "");
// just to be sure
cp.Table.Schema = null;
}
note that i can set Table.Schema to null while an empty string threw an exception ...
thanks for the answers !

Related

IS NOT NULL AS ... - Convert Query from MySQL to MS-SQL

I have an application that is working fine using a MySQL/MariaDB-Database.
I did make it more flexible and now I am basically able to use a Microsoft SQL-Server database.
I found out, that some SQL-queries do NOT work anymore.
I don't have experience with MS-SQL and I am looking for support to convert the following query to make it work with MS-SQL. It would be great, if the query could be converted to work in both MS-SQL and MySQL ...
I have created an SQL-Fiddle with some example-data.
Link: http://sqlfiddle.com/#!18/5fb718/2
The Query itself looks like this:
SELECT computermapping.PrinterGUID, computerdefaultprinter.PrinterGUID IS NOT NULL AS isDefaultPrinter
FROM computermapping
LEFT JOIN computerdefaultprinter ON computerdefaultprinter.ComputerGUID = computermapping.ComputerGUID
AND computerdefaultprinter.PrinterGUID = computermapping.PrinterGUID
WHERE computermapping.ComputerGUID = "5bec3779-b002-46ba-97c4-19158c13001f"
When I run this on SQL-Fiddle I get the following error:
Incorrect syntax near the keyword 'IS'.
When I run this Query in Microsoft SQL Server Management Studio I get the same Error. I have an German-Installation ...
Meldung 156, Ebene 15, Status 1, Zeile 1
Falsche Syntax in der Nähe des IS-Schlüsselworts.
I was looking on the Internet to find information on how to use the IS NOT NULL AS in MS-SQL. Maybe I was using the wrong keywords, but I was not able to find a solution myself.
If it does matter, I am using "SQL-Server 2014 SP3" at the moment.
Thank you
Convert
computerdefaultprinter.PrinterGUID IS NOT NULL AS isDefaultPrinter
to
CASE
WHEN computerdefaultprinter.PrinterGUID IS NOT NULL THEN 1
ELSE 0
END AS isDefaultPrinter
Demo here
Also bear in mind that there is no BOOLEAN type in SQL Server. BIT type is used instead.
Finally
WHERE computermapping.ComputerGUID = "5bec3779-b002-46ba-97c4-19158c13001f"
should be converted to
WHERE computermapping.ComputerGUID = '5bec3779-b002-46ba-97c4-19158c13001f'
since the single quote character is used to delimit strings in SQL Server
MySql evaluates boolean expressions like:
computerdefaultprinter.PrinterGUID IS NOT NULL
as 1 for TRUE or 0 for FALSE.
SQL Server does not do such an evaluation, so you need a CASE expression:
CASE WHEN computerdefaultprinter.PrinterGUID IS NOT NULL THEN 1 ELSE 0 END
The exact question was already answered, but you should really, really try using the SQL Server Migration Assistant for MySQL. No database supports the SQL standard beyond a basic compatibility level and MySQL is one of the quirkiest databases when it comes to SQL compatibility.
The SQL standard process is sloooow so all vendors implement features long before they're standardized. Different databases have different priorities too, and MySQL's priority for the first decade at least wasn't enterprise applications, so SQL compatibility wasn't a high priority.
Some common features were added only in MySQL 8. Some hacks allowed (but discouraged) in MySQL, like non-aggregate columns in a grouping query, or quirky updates to calculate row numbers, don't work in any other databases because logically, they lead to unpredictable results.
Even in MySQL, non-aggregate columns can cause serious performance degradation when upgrading from one 5.x version to the next. There's at least one SO question about this.
The Migration assistant will convert tables and types where possible and flag any stored procedure or view queries that can't be translated. It can also copy data from an existing MySQL database to a SQL Server database

use database with mixed case is not working via ODBC

I have a database with mixed case, i.e testDATABASE.
I run(using ODBC) the query use database ""testDATABASE";", then I run the query use schema "PUBLIC",
the query fail with the error:
ERROR: SQL compilation error:
Object does not exist, or operation cannot be performed.
Error Code: 2043
Query = use schema "PUBLIC"
when I run it not via odbc but in the notebook it works fine.
same queries with database that does not contain mixed case works fine.
if i run use schema "testDATABASE"."PUBLIC" it runs OK via ODBC and notebook.
is there a known issue about it? how can i run it with 2 queries in ODBCand make it work?
Thanks.
In your question it looks like your use database command had double double quotes,
but your schema didn't, perhaps that might be the issue.
Overall Suggestions :
When you make object names MiXeD-CaSe it simply makes use of the objects more difficult, so I'd recommend trying to not do mixed case if you can avoid it. You may not be able to avoid this, that's OK, it's just a suggestion.
if you can't avoid it, the only time I'd use the double quotes is when the object name
(in this case, the database name) has mixed case.
In your case, you should be able to run (you may have to double-double quote it in ODBC):
use database "testDATABASE";
and then this - note no double quotes needed because it's not mixed case
use schema PUBLIC;
this document illustrates how you don't need to prefix the schema with the database:
https://docs.snowflake.com/en/sql-reference/sql/use-schema.html
something else I recommend to folks getting started, for each user I like to set all the default context items (role, warehouse, namespace)
ALTER USER rich SET DEFAULT_ROLE = 'RICH_ROLE';
ALTER USER rich SET DEFAULT_WAREHOUSE = 'RICH_WH' ;
ALTER USER rich SET DEFAULT_NAMESPACE = 'RICH_DB.TEST_SCHEMA';

RepoDb does not seem to work for SQL Server tables with dot in the name

I'm starting to use RepoDb, but my SQL Server 2016 database has tables with a dot in the middle like this: User.Data.
Moving from full .NET Entity Framework to RepoDb, I'm facing this issue. I'm using the fluent mapping and I wrote something like this:
FluentMapper
.Entity<UserData>()
.Table("[User.Data]")
.Primary(u => u.UserId)
I get the exception: MissingFieldsException and it says:
There are no database fields found for table '[User.Data]'. Make sure that the target table '[User.Data]' is present in the database and/or at least a single field is available.
Just for curiosity, I created a table UserData with the same attributes and primary key and it worked great (change the fluent mapper whit: .Table("[UserData]").
Am I missing something?
Thanks for helping me
The support to this in only available at RepoDb.SqlServer (v1.0.13) version or above. You can use either of the approaches below. Make sure to specify the quotes if you are using the database and schema.
Via built-in MapAttribute.
[Map("[User.Data]")]
Via TableAttribute of the System.ComponentModel.DataAnnotations namespace.
[Table("[User.Data]")]
Via FluentMapper as you did.
FluentMapper
.Entity<UserData>()
.Table("[User.Data]");

Is it possible to run a snowflake sql script without qualifying the database name.?

Is it possible to run a SQL script without qualifying the database name?
Currently, we are using the program like below,
SELECT I.XXXX_LOC_SKEY,
C.COUNTRY_SKEY
FROM
DEV_XXXX_DB.STAGING.XX_TABLE_LOCATION_SALES F,
DEV_XXXX_PRESENTATION_DB.DIMS.XXXX_LOCATIONS_D I,
DEV_XXXX_PRESENTATION_DB.DIMS.COUNTRY_D C,
DEV_XXXX_PRESENTATION_DB.DIMS.XXXX_DAILY_CALENDAR_D H
WHERE
F.STORE_CODE = I.DOOR
AND I.CHANNEL = 'XXXX'
AND F.COUNTRY = C.COUNTRY_CODE
AND I.COUNTRY_SKEY = C.COUNTRY_SKEY
AND F.DATE = H.DATE;
We would like to run the same script, without mentioning the database names as below.
SELECT I.XXXX_LOC_SKEY,
C.COUNTRY_SKEY
FROM
STAGING.XX_TABLE_LOCATION_SALES F,
DIMS.XXXX_LOCATIONS_D I,
DIMS.COUNTRY_D C,
DIMS.XXXX_DAILY_CALENDAR_D H
WHERE
F.STORE_CODE = I.DOOR
AND I.CHANNEL = 'XXXX'
AND F.COUNTRY = C.COUNTRY_CODE
AND I.COUNTRY_SKEY = C.COUNTRY_SKEY
AND F.DATE = H.DATE;
This is how unqualified objects are resolved:
https://docs.snowflake.net/manuals/sql-reference/name-resolution.html.
Note you can customize the SEARCH_PATH to search multiple schemas.
Alternatively you can put the fully qualified names in variable:
set f = 'DEV_XXXX_DB.STAGING.XX_TABLE_LOCATION_SALES';
select f.* from table($f) f;
select f.* from identifier($f) f;
Although the snowflake Web GUI remembers your last database, and other eg. ETL tools may configure a default database for a connection, Snowflake has no concept of a default database. All tools including the Web GUI have to issue the following command to set the database according to tool configuration:
USE DATABASE db_name;
If you want to avoid referencing a database in a command, you have to use the USE DATABASE command beforehand in the session.
Inferring a bit based on the SQL provided, you have embedded the environment into your database name (DEV_XXXX_DB). Since you have multiple databases per environment, this forces you to explicitly add the database name to every sql which crosses DB as SimonD has pointed out.
If you haven't discovered this yet, you're going to have a really hard time promoting code between environments b/c everywhere you're going to have to replace DEV_XXXX_DB with PRD_XXXX_DB.
If you're not that far down the journey of Snowflake implementation, I would suggest that you rethink your DB.SCHEMA strategy and create just 1 DB per environment (env_XXXX_DB) and put all the schemas w/in that DB (env_XXXX_DB.STAGING, env_XXXX_DB.DIMS).
If you have many databases but most of the data comes from one of them, you can create views in the one database pointing across to the other one. That way all of your objects can be queried without needing the database.
i.e. CREATE VIEW MY_VIEW as SELECT * FROM DATABASE.SCHEMA.TABLE
I can see your SQL accessing the data from different database then you have run SQL with fully qualified name of the object.
If snowflake current session is pointing to the location of the object then you can run SQL without qualifying the database name.

What is the ProgressDB equivalent to SQL Server's statement Select ID = '1'?

When attempting to use a query I wrote against a Progress DB, I assumed I could use the following statement:
SELECT ID = '1' FROM Table
That returns a syntax error, but it's perfectly normal syntax for SQL Server.
Rule #1 -- Progress is not SQL. The more you try to make it act like SQL the unhappier you will be.
There is a SQL-92 interface. Naturally it does not support much in the way of syntax specific to Microsoft or Oracle. "Perfectly normal for MS SQL Server" is no assurance that Progress will think it normal.
There is an older still SQL-89 embedded within the 4GL engine. This is even less likely to behave like MS SQL.
Of course a great deal depends on which of these engines you are using and what version of Progress you are working with.
Having said that -- you have no table name. I'm just a Progress guy and maybe that's some sort of fancy-pants MS SQL magic or a code snippet from the midst of something more interesting but that looks like a problem to me. I would have been coding something more like:
SELECT name FROM customer WHERE id = 1

Resources