insert_from over two databases - mysql

I try to move all rows from one database table (source) to another database (target). The source-DB is a local database while target-DB runs on another machine. I want to transfer rows between the two databases and found the Model.insert_from() method for that task. Unfortunately it does nothing and I can't find any reason for that.
The database model is:
databaseSource = MySQLDatabase('sourceDB', **{'host': 'localhost', 'user': 'local', 'password': ''})
databaseTarget = MySQLDatabase('targetDB', **{'host': 'externalserver', 'user': 'external', 'password': ''})
class BaseModelSource(Model):
class Meta:
database = databaseSource
class BaseModelTarget(Model):
class Meta:
database = databaseTarget
class UsersSource(BaseModelSource):
crdate = DateTimeField(constraints=[SQL("DEFAULT CURRENT_TIMESTAMP")])
description = TextField()
firstName = CharField(column_name='first_name')
class Meta:
table_name = 'users'
class UsersTarget(BaseModelTarget):
crdate = DateTimeField(constraints=[SQL("DEFAULT CURRENT_TIMESTAMP")])
description = TextField()
firstName = CharField(column_name='first_name')
class Meta:
table_name = 'users'
With that my task should run with:
import peewee
from dbmodels import *
dataQuery = UsersSource.select(
UsersSource.crdate,
UsersSource.description,
UsersSource.firstName)
insertQuery = UsersTarget.insert_from(dataQuery,[
UsersTarget.crdate,
UsersTarget.description,
UsersTarget.firstName]).execute()
The resulting MySQL-query is this and as you can see, the selected data is empty []:
('INSERT INTO `users` (`crdate`, `description`, `first_name`) SELECT `t1`.`crdate`, `t1`.`description`, `t1`.`first_name` FROM `users` AS `t1`', [])
When I run the SELECT query on my table it outputs:
SELECT `t1`.`crdate`, `t1`.`description`, `t1`.`first_name` FROM `users` AS `t1`;
2018-08-12 16:50:36 valid Heinz
2018-08-12 19:34:45 valid Hilde
2018-08-12 19:33:31 invalid Paul
I searched like hell but didn't find any hint, why my result is empty.
Does anybody know more or a better method?

Peewee cannot insert data between two different database servers/connections. If both databases are on the same server, however, you can use the "schema" Meta option to reference each database from a single connection, and do the INSERT FROM that way:
db = MySQLDatabase('my_db')
class UsersSource(Model):
crdate = DateTimeField(constraints=[SQL("DEFAULT CURRENT_TIMESTAMP")])
description = TextField()
firstName = CharField(column_name='first_name')
class Meta:
database = db
schema = 'source_db_name'
table_name = 'users'
class UsersTarget(Model):
crdate = DateTimeField(constraints=[SQL("DEFAULT CURRENT_TIMESTAMP")])
description = TextField()
firstName = CharField(column_name='first_name')
class Meta:
database = db
schema = 'dest_db_name'
table_name = 'users'
If the databases are on different servers, then you have no other option but to dump it and reload it.

If this is a one-off operation I recommend using mysqldump and then copying the file to the remote server and sourcing the dumped files with the mysql client.
If this needs to be a continual process look at MySQL replication.
To batch transfer it you'll need to iterate over the result set of the SELECT and put this into the INSERT statement as they are on different servers.

Related

Error creating tables in MySQL using peewee and FastAPI

I have below basic code where I am trying to create tables in food_delivery database using peewee ORM. I am receiving error as below:
AttributeError: 'str' object has no attribute 'safe_create_index'
My Code below:
DATABASE = 'food_delivery'
db = MySQLDatabase(
host='localhost',
user='my_user',
password='****',
database=DATABASE
)
class BaseModel(Model):
class Meta:
database = DATABASE
class Customer(BaseModel):
city = CharField()
customer = AutoField(column_name='customer_id')
email = CharField(column_name='email_id',unique=True)
first_name = CharField()
landmark = CharField()
last_name = CharField()
password = CharField()
phone_no = CharField(max_length=10)
pincode = IntegerField()
state = CharField()
class Meta:
table_name = 'customer'
database = DATABASE
def create_tables():
with db:
db.create_tables([Customer])
create_tables()
Can someone suggest what might be wrong with code?
Thanks!
I kept looking for issue and found that I had a logical syntax misplacement basically. Instead of database name under all the table definition in META, I actually had to pass connection instance of database instead of database name. But I wonder how inappropriate the thrown error is and its kind of impossible to fi seeing the error details. This requires much improvement by library maintainers.

how to get table object and query specific fields in sqlalchemy?

I create a table when user want to add IP address and port to get a url map that refers to the specific ip:port he adds. The table is created based on his email address.
def create_user_table(table_name):
engine = get_sql_engine()
metadata = MetaData(engine)
user_table = Table(table_name, metadata,
Column("userip_id", db.Integer, primary_key=True, autoincrement=True),
Column("date_created", db.DateTime, default=db.func.current_timestamp()),
Column("date_modified", db.DateTime, default=db.func.current_timestamp(),
onupdate=db.func.current_timestamp()),
Column("ipaddress", CIDR, nullable=False),
Column("urlmap", db.String(10), nullable=False, unique=True),
Column("port", db.Integer, index=True),
Column("device", db.String(10)),
Column("path", db.String(30)),
Column("service", db.String(10)),
Column("count_updates", db.Integer, default=0, nullable=False),
)
user_table.create(engine)
return user_table
I have not made ipaddress and port address unique as same user can have different port but same ip and different ip but same port address (I have opted for the later considering a user can be updating )
if I create a table in db inheriting form db.Model I can query like
cls.query.filter(ipaddress=ipaddress).first() this will return me that table object I can check if that Ip has a specific port, but now that I have created table inheriting from sqlalchemy.Table I do not have the query function available .
How do I query and compare if the specific ip has a specific port address mapped to a existing urlmap(not known) ?
Figured out like always :p
# if same ip exists external port address should not exist in mapped in db.
query_table = helpers.get_query_result(user_table_name, "ipaddress", data['ip']).fetchall()
ports_mapped_to_ip_in_db = [item[5] for item in query_table]
if int(data['port']) in ports_mapped_to_ip_in_db:
return jsonify({"status": "{}:{} is already registered.".format(data["ip"], data["port"])})
where get_query_result in helpers module is :
def get_query_result(table_name, field_name=None, value=None):
""" execute query and provide result
"""
engine = get_sql_engine()
if all([field_name, value]):
return engine.execute("SELECT * FROM {} WHERE {}='{}'".format(table_name, field_name, value))
else:
return engine.execute("SELECT * FROM {}".format(table_name))

Python SQL Alchemy Multiple Databases - Binding Automap_Base

I am working through SQL Alchemy but struggling with how to structure the information from the docs into my project. I have two databases, my first will be used to store all new information from the python application. Where as the second database (DB1 in this case) is an existing database that I need to access information from. What is the right way to create this structure using SQLAlchemy?
I used the suggested BINDS method for multiple databases. This seems to be working.
class BaseConfig(object):
SECRET_KEY = "SO_SECURE"
DEBUG = True
SQLALCHEMY_DATABASE_URI = 'mssql+pyodbc://sa:funpassword#(localdb)\MSSQLLocalDB/Testing?driver=SQL+Server+Native+Client+11.0'
SQLALCHEMY_BINDS = {
'DB1': 'mssql+pyodbc://sa:$funpassword#ProdDB/DB1?driver=SQL+Server+Native+Client+11.0'
}
SQLALCHEMY_TRACK_MODIFICATIONS = True
This configuration seems to work okay because I am able to create new models in both of these databases using the code below. (This was done to just confirm that I was able to connect to both). db is my SqlAlchemy(app) initialization in my index.py file.
from index import app, db
#Test Writing To Default DB
class Test(db.Model):
id = db.Column(db.Integer(), primary_key=True)
employeeNum = db.Column(db.String(255), unique=False)
job = db.Column(db.String(255))
def __init__(self, employeeNum, job):
self.employeeNum = employeeNum
self.job = job
# Test Writing To DB1
class Test(db.Model):
__bind_key__ = 'DB1'
id = db.Column(db.Integer(), primary_key=True)
employeeNum = db.Column(db.String(255), unique=False)
job = db.Column(db.String(255))
def __init__(self, employeeNum, job):
self.employeeNum = employeeNum
self.job = job
I have tried many combinations using the table and automap_base from SQLAlchemy docs but this does not seem to work. I am not sure how I can use the bind_key of DB1 when I am trying to map existing tables.
from index import app, db
def loadSession():
Table('employee', db.metadata, Column('emp_num', Text, primary_key=True))
Base = automap_base(metadata=metadata)
Base.prepare()
employee = Base.classes.employee
emp = db.session.query(employee).all()
for i in emp:
print(i.data)
Thanks for any help you can provide.
for your DB1 with existing schema & data you could use reflection to get the tables mapped into sqlalchemy.
For your example it would probably look something like this:
from sqlalchemy.ext.automap import automap_base
from sqlalchemy import MetaData
from index import app, db
def loadSession():
# get a db engine object for DB1 configuration
engine = db.get_engine(bind='DB1')
# create a empty db Metadata object and bind it to DB1
database = MetaData(bind=engine)
# load the DB1 table/column structure into the Metadata object. This is quite a heavy operation and should optimally be done once on app setup and then the created automap_base can be stored / reused on demand until app shutdown
database.reflect(
bind=engine, views=True, autoload_replace=False
)
# create a python class structure out of the db metadata structure
auto_base = automap_base(metadata=database)
auto_base.prepare()
# create a db session for DB1
db_session = scoped_session(sessionmaker(autocommit=False,
autoflush=False,
bind=engine))
# get the reflected employees class from DB1. The employee table must exist in the database
employee = auto_base.classes.employee
# query DB1 with the new session object for all employee records
emp = db_session.query(employee).all()
for i in emp:
print(i.data)
# the following could also be substituted for the query without creating a session object:
for entry in employee.query.all():
print(entry)

Join two database table zend framework 1.12

I have used two mysql database in our projects. one database is connected the basic user information and another database used to store the daily activities. Now need to combine two database tables .
fetch user daily activity with user information , then need to join with master databases.
I found the solution in in PHP. But i want the solution on zend framework 1.12 ?
I used multidb functionality used to fetch different action .
resources.multidb.tb.adapter = "pdo_mysql"
resources.multidb.tb.host = "localhost"
resources.multidb.tb.username = "root"
resources.multidb.tb.password = ""
resources.multidb.tb.dbname = "#####"
resources.multidb.tb.default = true
resources.multidb.pl.adapter = "pdo_mysql"
resources.multidb.pl.host = "localhost"
resources.multidb.pl.username = "root"
resources.multidb.pl.password = ""
resources.multidb.pl.dbname = "#######"
But I want to query for join 2 tables in different databases.
example
SELECT db1.table1.somefield, db2.table1.somefield FROM db1.table1
INNER JOIN db2.table1 ON db1.table1.someid = db2.table1.someid WHERE
db1.table1.somefield = 'queryCrit';
Having in mind Zend's Join Inner declaration:
public function joinInner($name, $cond, $cols = self::SQL_WILDCARD, $schema = null)
And being '$this', for example, a Zend_Db_Table_Abstract implementation with adapter set to db1 (with _setAdapter()) and schema to "#####" (this is not really necessary because it'll use it as default):
$select = $this->select(true)->setIntegrityCheck(false)
->from(array('t1'=>'table1'),array('somefield')
->joinInner(array('t1b'=>'table1'),
't1.someid = t1b.someid',
array('t1b.somefield'),
'######')
->where('t1.somefield = ?', $queryCrit);
Please, note the the fourth parameter of the Inner Join method.
Hope this helps.

Getting blank statement in django model charfield with mysql

I just migrated my django application from sqlite3 to mysql 5.1.41. I have a charfield in a model defined like this:
class HostData(models.Model):
Host = models.CharField(max_length=50, null=True)
HostStatus = models.CharField(max_length=200, null=True)
Alarm = models.BooleanField()
Everything works the same except HostStatus, which usually returns a string like "Up, waiting". In mysql, however, it is blank. I created my table with character set to utf-8. What am I doing wrong? Thanks in advance.
I can't see anything wrong with that model code.
How have you migrated your data over to MySQL? When you enter data via the django admin, does it enter data into the db?
If a view is entering this data, can you post the view code.
The issue was the way I was assigning the value to the model. I dont know why it worked well in sqlite, but it was bad coding anyways. This is what I was doing:
myarray = stdout_ssh
myobject = test.object.get(id=3)
myobject.Host = stdout_ssh[0]
myobject.HostStatus = status
status = stdout_ssh[1]
myobject.Alarm = False
myobject.save()
I changed this to:
myarray = stdout_ssh
myobject = test.object.get(id=3)
myobject.Host = stdout_ssh[0]
myobject.HostStatus = stdout_ssh[1]
myobject.Alarm = False
myobject.save()
And everything was ok.