What does hibernate.default_schema mean? - nhibernate

I was reading a blog-post of Ben Scheirman about some NHibernate tweaks he made in order to increase the performance.
In the end of article there is:
Lesson #7: Always make sure you’ve set hibernate.default_schema
What does he mean by hibernate.default_schema?

I'm not a dba so I can't give you a good definition of schema... (to me it is just 'database' in SQL Server).
In NHibernate you can specify the schema two places: in the mapping files, in the configuration.
The Mapping File lets you specify schema per class. This is good when you have classes coming from different schema in the same server.
The SessionFactory configuration lets you specify a default schema (default_schema option) that should be applied to all class mappings that don't explicitly set their schema. So its a catch all.
From reading your link it seems this is beneficial in performance because when you query table "Bar" without specifying the schema (say database is "Foo" so schema "Foo.dbo" in SQL Server) the query plan isn't cached. This is probably due to the SQL Server having to try and resolve which schema to use by your connection string (Initial Catalog, Database, etc) instead of having it explicit in the query ("Bar" implicit - not cached, "Foo.dbo.Bar" explicit - cached).
Again, I'm not a dba so these definitions suck :)
edit:
Here is a link to the configuration stuff (for NH 1.2 ... which is old ... but the default_schema option is there):
https://www.hibernate.org/hib_docs/nhibernate/1.2/reference/en/html/session-configuration.html

Related

rename database field in upgrade wizard of an extension in TYPO3 11

I have an upgrade wizard (TYPO3 11) which changes the data of a table.
This is done with the querybuilder:
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('tt_content');
$queryBuilder
->update('tt_content')
->set('CType', 'newCType')
->where($queryBuilder
->expr()
->eq('CType',$queryBuilder->createNamedParameter('oldCType')))
->execute();
But I also need to rename a field in a table:
ALTER TABLE tt_content RENAME COLUMN tx_myext_old_field TO tx_myext_new_field;
I can't find any documentation or example of doing this with the querybuilder.
The normal way woult be to provide a ext_tables.sql in your extension. This is read by TYPO3 to build a virtual "database scheme" how it should look.
The database schema analyser will than provide the information, and database alteration are suggested.
You could add a database must be up to date constraint to your upgrade wizard, that way it is ensured that the field is changed.
DTL is a special task, and you have to provide the correspinng queries yourself ... which are different for different dbms systems. So using the normal way would be recommended.
The platform/driver may have some generig helper methods providing some native sql parts for doing stuffs like that. The may be possible to provide custom stuff based on SchemaMigrator or SchemaManger etc - but thats low-level stuff.
doctrine/dbal directly do not really provide these DTL as API. And the querybuilder is not meant to be used for that low level stuff at all. That's the wrong tool for such tasks.
You can also change columns of core tables that way, by providing simply the table name and the column defintion only for the field you want to change.
The official way is to handle this with ext_tables.sql and the database schema analyser.
See: https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ExtensionArchitecture/FileStructure/ExtTablesSql.html
The concept of renaming a column could not work:
On installing the extension all new fields are generated (or should be generated if in composer mode). And as the extension should work with the new columns they are already defined.
And before the upgrade wizard could rename a column these columns are existent already which prevents a rename.
In the end I do a content copy enhancing the update query like this:
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('tt_content');
$queryBuilder
->update('tt_content')
->set('CType', 'newCType')
->set('tx_myext_newfield1',$queryBuilder->quoteIdentifier('tx_myext_oldfield1'),false)
->set('tx_myext_newfield2',$queryBuilder->quoteIdentifier('tx_myext_oldfield2'),false)
->where($queryBuilder
->expr()
->eq('CType',$queryBuilder->createNamedParameter('oldCType')))
->executeStatement();

Determine/Find underlying SQL field type of a Django Field

Is there an easy way to determine or find the underlying SQL field type of a Django Field, for any of the supported by default database backends? I have searched on the web and there is no documentation over how the Django fields are represented in SQL in each of the supported databases. The only way for me to see the underlying SQL field type, is to run the mysqlmigrate command of manage.py and examine the SQL code.
The type depends on the database backend, so you need to get a db connection first:
from django.db import connection
and now you can look up the field via the model Meta API:
my_field = MyModel._meta.get_field('my_field_name')
and use its db_type method:
my_field.db_type(connection)
which will return something like "varchar(10)".
Be sure you really need to do this, though. Usually this information is only useful inside migrations.

play20 ebean generated sql throws syntax error on postgresql

I'm trying to get work my play20 application with postgresql so I can use and later deploy to Heroku. I followed this answer.
Basically, I made connection to database (so connection from local application to Heroku postgresql database worked), but I was not able to initialise database with generated 1.sql evolution. But generated sql was not working because of postgresql is using schema (it should work without schema anyway, but apparently I'm doing something wrong or database is doing something wrong).
create table user (
id bigint not null,
email varchar(255),
gender varchar(1),
constraint pk_user primary key (id));
resulted in
ERROR: syntax error at or near "user"
Position: 14 [ERROR:0, SQLSTATE:42601]
I fixed that with adding schema to table name
create table public.user(
...
);
Ok, everything worked until I tried to read or write to database. I got again sql syntax exception and can't work with database. Seems like sql queries are somehow wrong.
Any suggestions where could be problem?
That's very common mistake while developing application with other database than in production, but fortunately there is also common solution. You can still use User model, however you have to make sure that creates database table with changed name:
#Entity
#Table(name = "users")
public class User extends Model {
...
}
In most cases in your controllers and models name-switch will be transparent for you. Only place where you have to remember the switch are RawSql queries.
BTW, that's good idea to install locally the same database for developing cause there's a lot of differences between most popular databases, like other reserved keywords, other allowed types, even other auto incrementing methods for id, so finding and fixing proper values is just easier on localhost.
Well, due to my little knowledge about postgresql, I was struggling with this all day. Here's simple solution. Don't use table called "user" on postgreqsl. This table is already used.
But why my evolution sql query worked for initialisation of database? Well if I explicitly specify in which schema I want to create table "user", that basically works.
But if schema is not specified, is used current schema. From documentation:
If a schema name is given (for example, CREATE TABLE myschema.mytable ...) then the table is created in the specified schema. Otherwise it is created in the current schema
So that explains it. But for my project, using "user" model was perfectly reasonable and for H2 file based databased it was working, so I assumed that problem was somewhere else...

NHibernate mapping: is it possible to insert values into the database via a mapping file without using a property?

I am writing an application which works with a legacy database (brownfield). I have a couple of tables in which I insert data. These tables have some fields which need values of which I do not want the properties in my domain entities. Is there a way to insert the default value into the field without having to create a property for it my mapping file? I cannot alter the database to create a trigger, so it has to be done via the mapping file/.net application.
Hope someone can help. I hoped I could use a formula, but that doesn't work and I couldn't find any other ways to do it either.
you could use a private / protected property.
That would mean introducing these fields into your domain model / mappings, but they would be limited to those, and not exposed to whoever uses your entities.
seems like a reasonable compromise to me.
You could use EventListeners
in the OnPostInsert / OnPostUpdate event you can get the db connection and ad-hoc execute a sql query.
NH makes it rather easy
using xml see here
using FluentNHibernate see here
the basic idea is to use PropertyAccessor on a non existing property which always has the constant value.

Should the schema always be explicitly defined in the SQL statement?

Earlier I had asked the question:
Where (or how) should I define the schema in a select statement when using PostgreSQL?
The answer I accepted was to modify the search_path for the connecting user so that the schema need not be specified in the SQL. However, now I wonder if I should always specify the schema in SQL rather than allow the schema to be automatically inferred by the search path. This seems like it would be a safer approach and would be more portable to other databases.
This question is different than the previous one in that I want to know what the best practices are for defining the schema in SQL, rather than how it can be done.
Should the schema always be explicitly defined in the SQL statement?
** Note: I would not hard code the schema name but would allow it to be configurable through the Web.config file so that the schema could change from one installation to another. **
It's a bad practice to hardcode schema into SQL statements.
You should keep it in the application settings and issue SET search_path after connecting to the database.
If your application is used by multiple users with their own schemas, your life will be much easier if you don't hardcode schema name into SQL.
In other words,
string query = "SELECT * FROM " + ConfigurationManager.AppSettings.Get("schema") + ".table";
is a bad way;
SQLCommand("SET search_path = " + ConfigurationManager.AppSettings.Get("schema"), connection).ExecuteNonQuery();
string query = "SELECT * FROM table";
is a good way.
Let's see - in the DB of the app I maintain there are around a dozen schemas. What would be the order if I put them in "search_path"? And would I put in the schema names (not the tables name and not the fully-qualified table names) in the configuration?
As you have guessed by now I do not use "search_path". But maybe you could store the fully-qualified table names in the configuration in case you ever change you mind about the names of the schemas or the tables themselves.