Giter VIP home page Giter VIP logo

pymedoo's Introduction

pymedoo - A lightweight database framework for python

it's inspired by Medoo for PHP and Records for python.

Pypi Github Codacy Codacy coverage Building

Install

pip install medoo

Required packages for databases

Database Package Install
sqlite sqlite3 pip install medoo[sqlite]
mysql pymysql(dropped) Use mysql.connector instead. See #6 pip install medoo[mysql]
pgsql psycopg2 pip install medoo[pgsql]
mssql pymssql pip install medoo[mssql]
oracle cx_Oracle pip install medoo[oracle]

Install forr all supported databases:

pip install medoo[all]

Get started

SELECT

from medoo import Medoo

# For other arguments, please refer to the original connect function of each client.
me = Medoo(dbtype = 'sqlite', database = 'file:///path/to/test.sqlite')

# SELECT * FROM "Customers"
rs = me.select('Customers')

print(rs.export('csv', delimiter = '\t'))
CustomerID CustomerName ContactName Address City PostalCode Country
1 Alfreds Futterkiste Maria Anders Obere Str. 57 Berlin 12209 Germany
2 Ana Trujillo Emparedados y helados Ana Trujillo Avda. de la Constitución 2222 México D.F. 5021 Mexico
3 Antonio Moreno Taquería Antonio Moreno Mataderos 2312 México D.F. 5023 Mexico
4 Around the Horn Thomas Hardy 120 Hanover Sq. London WA1 1DP UK
5 Berglunds snabbköp Christina Berglund Berguvsvägen 8 Luleå S-958 22 Sweden
# SELECT "CustomerID","CustomerName" FROM "Customers"
me.select('Customers', 'CustomerID, CustomerName')
me.select('Customers', ['CustomerID', 'CustomerName'])

# SELECT "C"."CustomerID" AS "CustomerID","C"."CustomerName" AS "name" FROM "Customers" AS "C"
me.select('Customers(C)', ['C.CustomerID(id)', 'C.CustomerName(name)'])

# SELECT DISTINCT "Country" FROM "Customers"
me.select('Customers', 'Country', distinct = True)

# SELECT COUNT("CustomerID") FROM "Customers"
me.select('Customers', 'CustomerID|COUNT')

# SELECT COUNT(DISTINCT "CustomerID") AS "c" FROM "Customers"
me.select('Customers', 'CustomerID|.COUNT(c)')

# SELECT "CustomerID"+1 FROM "Customers"
from medoo import Field, Raw
me.select('Customers', Field('CustomerID')+1)

# SELECT 'Name: ' || CustomerName AS name FROM "Customers"
rs = me.select('Customers', Raw("'Name: ' || CustomerName AS name"))
for r in rs: print(r.name)
Name: Alfreds Futterkiste
Name: Ana Trujillo Emparedados y helados
Name: Antonio Moreno Taquería
Name: Around the Horn
Name: Berglunds snabbköp

WHERE

Single condition

# SELECT * FROM "Customers" WHERE "CustomerID" = 1
me.select('Customers', where = {'CustomerID': 1})

# SELECT * FROM "Customers" WHERE "CustomerID" < 3
me.select('Customers', where = {'CustomerID[<]': 3})

# SELECT * FROM "Customers" WHERE "CustomerID" IN (1,2,3)
me.select('Customers', where = {'CustomerID': (1,2,3)})

# SELECT * FROM "Customers" WHERE "CustomerName" LIKE '%b%' OR "CustomerName" LIKE '%c%'
me.select('Customers', where = {'CustomerName[~]': ('a', 'b')})

# SELECT * FROM "Customers" WHERE "CustomerID" BETWEEN 1 AND 3
me.select('Customers', where = {'CustomerID[<>]': (1,3)})

# SELECT * FROM "Customers" WHERE NOT "CustomerID" BETWEEN 1 AND 3
me.select('Customers', where = {'!CustomerID[<>]': (1,3)})

# SELECT * FROM "Customers" WHERE "CustomerID" IS NULL
me.select('Customers', where = {'CustomerID[is]': None}) # where = {'id[==]': None}

# SELECT * FROM "Customers" WHERE INSTR("CustomerName", 'Antonio')
me.select('Customers', where = {Raw('INSTR("CustomerName", \'Antonio\')'):None})

Compond

# SELECT * FROM "Customers" WHERE "CustomerID" IN (1,2,3) AND "CustomerName" LIKE '%b%'
me.select('Customers', where = {
    'CustomerID': (1,2,3),
    'CustomerName[~]': 'b'
})
# SELECT * FROM "Customers"
# WHERE ("CustomerID" IN (1,2,3) AND "CustomerName" LIKE '%b%') AND
# ("CustomerName" = 'cd' OR "CustomerID" = 2) AND
# ("CustomerID" < 3 AND NOT "CustomerName" = 'bc')
me.select('Customers', where = {
    'AND': {
        'CustomerID': (1,2,3),
        'CustomerName[~]': 'b'
    },
    'OR': {
        'CustomerName': 'cd',
        'CustomerID': 2
    },
    # you can use comment to distinguish multiple ANDs and ORs
    'AND #2': {
        'CustomerID[<]': 3,
        '!CustomerName': 'bc'
    }
})

Modifier

# SELECT * FROM "Customers" ORDER BY "CustomerID" DESC, "CustomerName" ASC LIMIT 2 OFFSET 1
# MSSQL:
# SELECT * FROM "Customers" ORDER BY "CustomerID" DESC, "CustomerName" ASC
# OFFSET 1 ROWS FETCH NEXT 2 ROWS ONLY
me.select('Customers', where = {
    'ORDER': {'CustomerID': 'desc', 'CustomerName': 'asc'},
    'LIMIT': (2, 1)
})

# SELECT COUNT("CustomerID") AS "c","CustomerName" FROM "Customers" GROUP BY "Country" HAVING "CustomerID" > 1
me.select('Customers', 'CustomerID|count(c), CustomerName', where = {
    'GROUP': 'Country',
    'HAVING': {'CustomerID[>]': 1}
})

Using subquery

print(me.select('Orders').export('csv', delimiter = '\t'))
OrderID CustomerID OrderDate
10308 2 1996-09-18
10309 37 1996-09-19
10310 77 1996-09-20
# SELECT * FROM "Customers" AS "C",(SELECT "CustomerID" FROM "Orders") AS "O"
#   WHERE "C"."CustomerID" = "O"."CustomerID"
me.select([
    'Customers(C)', # the first table
    me.builder.select('Orders', 'CustomerID', sub = 'O')
], where = {
    'C.CustomerID': Field('O.CustomerID')
})

# SELECT * FROM "Customers" WHERE "CustomerID" IN (SELECT "CustomerID" FROM "Orders")
me.select('Customers', where = {
    'CustomerID': me.builder.select('Orders', 'CustomerID')
})

JOIN

# SELECT "O"."OrderID","C"."CustomerName","O"."OrderDate" FROM "Orders" AS "O"
#   INNER JOIN "Customers" AS "C" ON "C"."CustomerID"="O"."CustomerID"
me.select('Orders(O)', 'O.OrderID,C.CustomerName,O.OrderDate', join = {
    'Customers(C)': 'CustomerID'
})

# equivalent to
me.select('Orders(O)', 'O.OrderID,C.CustomerName,O.OrderDate', join = {
    '[><]Customers(C)': 'CustomerID'
})
# [>] LEFT JOIN, [<] RIGHT JOIN [<>] FULL OUTER JOIN

# Join on multiple columns (same in different tables)
# join = { '[><]Customers(C)': ['CustomerID', 'OtherColumn'] }

# Join on different columns: JOIN "Customers" AS "C" ON "C"."CustomerID"="O"."OtherID"
# join = { '[><]Customers(C)': {'CustomerID', 'OtherID'} }

# You can join multiple tables, use OrderedDict if you want to keep the order.

UNION

# SELECT "CustomerID" FROM "Customers" UNION SELECT "CustomerID" FROM "Orders"
me.union(
    me.builder.select('Customers', 'CustomerID'),
    me.builder.select('Orders', 'CustomerID')
)

# SELECT "CustomerID" FROM "Customers" UNION ALL SELECT "CustomerID" FROM "Orders"
me.union(
    me.builder.select('Customers', 'CustomerID'),
    me.builder.select('Orders', 'CustomerID', sub = True)
)

Records

Medoo.select and Medoo.union return a collection of records, which is basically a generator, but you can still get items from it, as it will consume the generate if necessary. The idea is borrowed from Records.

records = me.select('Customers', 'CustomerID(id)')
record  = records.first() # <Record {'id': 1}>

# equivalent to
record  = records[0]

# you may also select other rows: records[1], records[2]
# or return all rows:
print(records.all())

# you can also export the records
# this is the courtesy from tablib (https://github.com/kennethreitz/tablib)
# check the kwargs with its documentation
print(records.export('csv', delimiter = '\t'))

# You can also apply tablib's other function on the data:
# records.tldata.<function>(<args>)

# to get the value of each field from a record:
print(record[0]) # 1
print(record['id']) # 1
print(record.id) # 1
print(record.as_dict()) # {'id': 1}

INSERT

# INSERT INTO "Orders" ("OrderID","CustomerID","OrderDate") VALUES (1,2,'1999-09-09'),(2,8,'2001-10-12')
me.insert(
    'Orders', # table
    'OrderID, CustomerID, OrderDate', # fields
    (1,2,'1999-09-09'), # values
    (2,8,'2001-10-12')
    # ...
)
# get the last insert row id
print(me.id()) # 5

# INSERT INTO "Orders" ("OrderID","CustomerID","OrderDate") VALUES (1,2,'1999-09-09'),(2,8,'2001-10,12')
me.insert(
    'Orders', # table
    {'OrderID': 1, 'CustomerID': 2, 'OrderDate': '1999-09-09'}, # fields with the first value
    (2,8,'2001-10-12')
    # ...
)
me.insert(
    'Orders', # table
    {'OrderID': 1, 'CustomerID': 2, 'OrderDate': '1999-09-09'}, # fields with the first value
    {'OrderID': 2, 'CustomerID': 8, 'OrderDate': '2001-10-12'}  # specify the fields as well
    # ...
)
# Or if your values have all the fields
# INSERT INTO "Orders" VALUES (1,2,'1999-09-09'),(2,8,'2001-10-12')
me.insert(
    'Orders', # table
    (1,2,'1999-09-09')
    (2,8,'2001-10-12')
    # ...
)

# You may hold the changes until all data inserted
me.insert(..., commit = False)
me.insert(..., commit = False)
me.insert(..., commit = False)
me.insert(..., commit = False)
me.commit()
# This applies with UPDATE and DELETE as well.

UPDATE

# UPDATE "Orders" SET "CustomerID"=10 WHERE "OrderID" = 2
me.update(
    'Orders', # table
    data  = {'CustomerID': 10},
    where = {'OrderID': 2}
)
# UPDATE "Orders" SET "CustomerID"="CustomerID"+1 WHERE "OrderID" = 2
me.update(
    'Orders', # table
    data  = {'CustomerID[+]': 1},
    where = {'OrderID': 2}
)

DELETE

# DELETE FROM "Orders" WHERE "OrderID" = 2
me.delete('Orders', where = {'OrderID': 2})

Other functions of Medoo

# Fetch a single value
me.get('Customers', 'CustomerID', where = {'CustomerName': 'Around the Horn'}) # == 1

# Check if a record exists
me.has('Customers', where = {'CustomerID': 10}) # == False

# Return the last query
me.last() # SELECT * FROM "Customers" WHERE "CustomerID" = 10

# Show all the queries bound with `me`

# You have to passing `logging = True` to `Medoo(..., logging = True)`
me.log()

# Return the errors
me.error()

# Submit an SQL query
me.query(sql, commit = True)

Extending pymedoo

pymedoo is highly extendable, including the operators in WHERE conditions and UPDATE SET clause, JOIN operators, and some functions such as how to quote the table names, field names and values. All of these have been defined with Dialect class, what you need to do is just extend this class and specify it to the Medoo instance. For example, let's define a case-insensitive LIKE operator using a shortcut ~~:

from medoo import Medoo, Dialect

class MyDialect(Dialect):
    OPERATOR_MAP = {
        '~~': 'ilike'
    }

    @classmethod
    def ilike(klass, field, value):
        # support single value
        if not isinstance(value, list):
            value = [value]

        terms = [
            "UPPER({}) LIKE UPPER({})".format(field, klass.value(v)) # quote the value
            for v in value
        ]
        # use OR to connect
        return ' OR '.join(terms)

# tell medoo to use this dialect
me = Medoo(...)
me.dialect(MyDialect)

# SELECT * FROM "Customers" WHERE UPPER("CustomerName") LIKE UPPER('%an%')
records = me.select('Customers', where = {
    'CustomerName[~~]': '%an%'
})
print(records.export('csv', delimiter = '\t'))
CustomerID CustomerName ContactName Address City PostalCode Country
2 Ana Trujillo Emparedados y helados Ana Trujillo Avda. de la Constitución 2222 México D.F. 5021 Mexico
3 Antonio Moreno Taquería Antonio Moreno Mataderos 2312 México D.F. 5023 Mexico

pymedoo's People

Contributors

pwwang avatar void285 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

pymedoo's Issues

When error occurs, Print very long sql may obstruct debugging

I just encountered with a mysql related error, and find error printing in base.py may obstruct debugging when the sql is very long, so I change it like this:

            if len(self.sql) <= 300:
                raise type(ex)(str(ex) + ":\n" + self.sql)
            else:
                raise type(ex)(str(ex) + ":\n" + self.sql[:300] + "\tsql length: " + str(len(self.sql)))

I tried to insert 100 records in one batch, the sql it very long, in this case about 5M, to solve the problem, I have to reduce the amount the records in a batch, this is a mysql related issue, maybe not due to pymedoo.

The error I got is as below, print the whole sql is terrible, so I modify base.py to print the slim version:

Traceback (most recent call last):
  File "/usr/lib/python3.9/site-packages/mysql/connector/network.py", line 159, in send_plain
    self.sock.sendall(packet)
BrokenPipeError: [Errno 32] Broken pipe

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/lib/python3.9/site-packages/medoo/base.py", line 139, in query
    self.cursor.execute(self.sql)
  File "/usr/lib/python3.9/site-packages/mysql/connector/cursor.py", line 564, in execute
    self._handle_result(self._connection.cmd_query(stmt))
  File "/usr/lib/python3.9/site-packages/mysql/connector/connection.py", line 990, in cmd_query
    result = self._handle_result(self._send_cmd(ServerCmd.QUERY, query))
  File "/usr/lib/python3.9/site-packages/mysql/connector/connection.py", line 620, in _send_cmd
    self._socket.send(
  File "/usr/lib/python3.9/site-packages/mysql/connector/network.py", line 161, in send_plain
    raise OperationalError(
mysql.connector.errors.OperationalError: 2055: Lost connection to MySQL server at 'localhost:3306', system error: 32 Broken pipe

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/e/todb.py", line 531, in <module>
    populate_items(seq)
  File "/e/todb.py", line 449, in populate_items
    dbs.insert('table_%s' % (seq), *batch)
  File "/usr/lib/python3.9/site-packages/medoo/base.py", line 83, in insert
    return self.query(sql, kwargs.get("commit", True))
  File "/usr/lib/python3.9/site-packages/medoo/base.py", line 150, in query
    raise type(ex)(str(ex) + ":\n" + self.sql[:300] + "\tsql length: " + str(len(self.sql)))
mysql.connector.errors.OperationalError: 2055: Lost connection to MySQL server at 'localhost:3306', system error: 32 Broken pipe:
INSERT INTO `items` VALUES ('12650774',2973,1637632343,'\r\nLorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." sql length: 5062186
2055
Exception ignored in: <function Base.__del__ at 0x6fffff894ee0>
Traceback (most recent call last):
  File "/usr/lib/python3.9/site-packages/medoo/base.py", line 56, in __del__
  File "/usr/lib/python3.9/site-packages/medoo/base.py", line 46, in close
  File "/usr/lib/python3.9/site-packages/mysql/connector/connection.py", line 585, in close
  File "/usr/lib/python3.9/site-packages/mysql/connector/connection.py", line 1074, in cmd_quit
  File "/usr/lib/python3.9/site-packages/mysql/connector/network.py", line 161, in send_plain
  File "/usr/lib/python3.9/site-packages/mysql/connector/errors.py", line 186, in __init__
  File "/usr/lib/python3.9/site-packages/mysql/connector/locales/__init__.py", line 61, in get_client_error
ImportError: No localization support for language 'eng'

Error if None in value: "sqlite3.OperationalError: no such column: None"

Hi, I encountered error in this code:

#coding: utf-8
from medoo import Medoo

db = Medoo(dbtype="sqlite", database="test.db")
db.query('''create table table_1
    (id integer primary key,
    name varchar not null default "",
    cate varchar not null default "",
    ctime int not null default 0
    );''')
data = [
    {'name': None, 'cate': 'Alysia', 'ctime': 1},
    {'name': 'Gwenda', 'cate': 'Chang', 'ctime': 2},
    {'name': 'Fannie', 'cate': 'Jonelle', 'ctime': 3},
    {'name': 'Meggan', 'cate': 'Oliver', 'ctime': 4},
    {'name': 'Rueben', 'cate': 'Estefana', 'ctime': 5},
]
db.insert('table_1', *data)
Traceback (most recent call last):
  File "test2.py", line 18, in <module>
    db.insert('table_1', *data)
  File "C:\Develop\Python27\lib\site-packages\medoo\base.py", line 70, in insert
    return self.query(sql, kwargs.get('commit', True))
  File "C:\Develop\Python27\lib\site-packages\medoo\base.py", line 116, in query
    raise type(ex)(str(ex) + ':\n' + self.sql)
sqlite3.OperationalError: no such column: None:
INSERT INTO "table_1" ("ctime","name","cate") VALUES (1,None,'Alysia'),(2,'Gwenda','Chang'),(3,'Fannie','Jonelle'),(4,'Meggan','Oliver'),(5,'Rueben','Estefana')

And, I once met with this error in a long and complicated insert, the inserted values have None in it, after replacement of None with empty string, the error disappeared. I have no idea about what may have caused it.

  File "C:\Develop\Python27\lib\site-packages\medoo\base.py", line 113, in query
    raise type(ex)(str(ex) + ':\n' + self.sql)
sqlite3.OperationalError: <exception str() failed>

Unexpected insert result with multiple data

Hi, I try to insert multiple lines but got unexpected result, the columns messed up. the code the result is as below:

#!coding: utf-8
from medoo import Medoo

db = Medoo(dbtype="sqlite", database="test.db")
db.query('''create table table_1
    (id integer primary key,
    name varchar not null default "",
    category varchar not null default "",
    foo1 varchar not null default "",
    bar1 varchar not null default "",
    slug varchar not null default "",
    parent varchar not null default "",
    website varchar not null default "",
    theme boolean not null default 0,
    plugin boolean not null default 0,
    applycnt int not null default 0,
    ctime int not null default 0
    );''')
data = [
    {u'category': 1, 'website': u'Vannesa', 'bar1': u'Kym', u'name': u'Adrianna', 'parent': u'Rod', 'applycnt': 1, u'plugin': 1, 'ctime': 1557943085, 'id': 306, 'theme': 0, 'slug': '', u'foo1': u'Else'},
    {u'category': 1, 'website': u'Pilar', 'bar1': u'Carolann', u'name': u'Laci', 'parent': u'Aura', 'applycnt': 1, u'plugin': 1, 'ctime': 1557943085, 'id': 307, 'theme': 0, 'slug': '', u'foo1': u'Miss'},
    {u'category': 1, 'website': u'Cassi', 'bar1': u'Kareem', u'name': u'Florine', 'parent': u'Kathern', 'applycnt': 1, u'plugin': 1, 'ctime': 1557943085, 'id': 308, 'theme': 0, 'slug': '', u'foo1': u'Pilar'},
    {u'category': 1, 'website': u'Efrain', 'bar1': u'Seema', u'name': u'Chang', 'parent': u'Irish', 'applycnt': 1, u'plugin': 1, 'ctime': 1557943103, 'id': 309, 'theme': 0, 'slug': '', u'foo1': u'Breana'},
    {u'category': 1, 'website': u'Chery', 'bar1': u'Gilbert', u'name': u'Valentine', 'parent': u'Myesha', 'applycnt': 1, u'plugin': 1, 'ctime': 1557943103, 'id': 310, 'theme': 0, 'slug': '', u'foo1': u'Teri'},
    {u'category': 10, 'website': u'Fumiko', 'bar1': u'Debrah', u'name': u'Ranee', 'parent': '', 'plugin': 0, 'ctime': 1557929121, 'id': 1, 'theme': 0, 'applycnt': 1, 'slug': u'Merlin', u'foo1': u'Hershel'},
    {u'category': 23, 'website': u'Yolonda', 'bar1': u'Ava', u'name': u'Genoveva', 'parent': '', 'plugin': 0, 'ctime': 1557929121, 'id': 2, 'theme': 0, 'applycnt': 1, 'slug': u'Lavinia', u'foo1': u'Bev'},
    {u'category': 15, 'website': u'Angeline', 'bar1': u'Stephenie', u'name': u'Faye', 'parent': '', 'plugin': 0, 'ctime': 1557929121, 'id': 3, 'theme': 0, 'applycnt': 1, 'slug': u'Brianne', u'foo1': u'Milagro'},
    {u'category': 12, 'website': u'Leonia', 'bar1': u'Kaitlin', u'name': u'Whitley', 'parent': '', 'plugin': 0, 'ctime': 1557929121, 'id': 4, 'theme': 0, 'applycnt': 1, 'slug': u'Jesse', u'foo1': u'Denver'},
    {u'category': 27, 'website': u'Onie', 'bar1': u'Sondra', u'name': u'Jordon', 'parent': '', 'plugin': 0, 'ctime': 1557929138, 'id': 5, 'theme': 0, 'applycnt': 1, 'slug': u'Taisha', u'foo1': u'Roberto'},
    {u'category': 1, 'website': u'Dwana', 'bar1': u'Sheree', u'name': u'Bobbi', 'parent': '', 'plugin': 0, 'ctime': 1557929138, 'id': 6, 'theme': 0, 'applycnt': 1, 'slug': u'Leia', u'foo1': u'Birgit'},
    {u'category': 1, 'website': u'Sandra', 'bar1': u'Dirk', u'name': u'Gregory', 'parent': u'Ashly', 'plugin': 0, 'ctime': 1557929138, 'id': 7, u'theme': 1, 'applycnt': 1, 'slug': '', u'foo1': u'Walter'},
]
db.insert('table_1', *data)

image

If I change the column theme to 'bl1', then I got a sqlite3.IntegrityError: UNIQUE constraint failed: table_1.id: error.

Traceback (most recent call last):
  File "test.py", line 33, in <module>
    db.insert('table_1', *data)
  File "C:\Develop\Python27\lib\site-packages\medoo\base.py", line 70, in insert
    return self.query(sql, kwargs.get('commit', True))
  File "C:\Develop\Python27\lib\site-packages\medoo\base.py", line 113, in query
    raise type(ex)(str(ex) + ':\n' + self.sql)
sqlite3.IntegrityError: UNIQUE constraint failed: table_1.id:
INSERT INTO "table_1" ("website","bar1","parent","slug","ctime","category","name","plugin","bl1","id","applycnt","foo1") VALUES ('Vannesa','Kym','Rod','',1557943085,1,'Adrianna',1,0,306,1,'Else'),('Pilar','Carolann','Aura','',1557943085,1,'Laci',1,0,307,1,'Miss'),('Cassi','Kareem','Kathern','',1557943085,1,'Florine',1,0,308,1,'Pilar'),('Efrain','Seema','Irish','',1557943103,1,'Chang',1,0,309,1,'Breana'),('Chery','Gilbert','Myesha','',1557943103,1,'Valentine',1,0,310,1,'Teri'),('Fumiko','Debrah','',1,1,1557929121,10,'Ranee',0,0,'Merlin','Hershel'),('Yolonda','Ava','',2,1,1557929121,23,'Genoveva',0,0,'Lavinia','Bev'),('Angeline','Stephenie','',3,1,1557929121,15,'Faye',0,0,'Brianne','Milagro'),('Leonia','Kaitlin','',4,1,1557929121,12,'Whitley',0,0,'Jesse','Denver'),('Onie','Sondra','',5,1,1557929138,27,'Jordon',0,0,'Taisha','Roberto'),('Dwana','Sheree','',6,1,1557929138,1,'Bobbi',0,0,'Leia','Birgit'),('Sandra','Dirk','Ashly',7,1,1557929138,1,'Gregory',0,1,'','Walter')

Two problems with mysql

I have been used pymedoo for several sqlite projects and it works well. Today I try to use it for mysql and found two problems. The script works well if change dbtype to sqlite from mysql.

1. table name quoted error

pymysql.err.ProgrammingError: (1064, u'You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '"test" LIMIT 1' at line 1'):
SELECT * FROM "test" LIMIT 1

I modify quote function in dialect.py to solve the problem, but not sure if this will cause more error.

    @staticmethod
    def quote(item):
        """How to quote values"""
        return str(item)

2. recordset not iteratable

File "C:\Python27\lib\site-packages\medoo\record.py", line 190, in next
nextrow = Record(self.meta, list(next(self._cursor)), readonly = self.readonly)
TypeError: Cursor object is not an iterator

This error occurs both in 0.0.3 with python27 or 0.0.5 with python37.

No localization support error

At the end of every script i get the No localization support support error, everything is working fine it just shows it

Exception ignored in: <function Base.__del__ at 0x0370C388>
Traceback (most recent call last):
  File "C:\Users\x\pythonProjects\x\venv\lib\site-packages\medoo\base.py", line 55, in __del__
  File "C:\Users\x\pythonProjects\x\venv\lib\site-packages\medoo\base.py", line 45, in close
  File "C:\Users\x\pythonProjects\x\venv\lib\site-packages\mysql\connector\connection.py", line 383, in close
  File "C:\Users\x\pythonProjects\x\venv\lib\site-packages\mysql\connector\connection.py", line 768, in cmd_quit
  File "C:\Users\x\pythonProjects\x\venv\lib\site-packages\mysql\connector\network.py", line 166, in send_plain
  File "C:\Users\x\pythonProjects\x\venv\lib\site-packages\mysql\connector\errors.py", line 187, in __init__
  File "C:\Users\x\pythonProjects\x\venv\lib\site-packages\mysql\connector\locales\__init__.py", line 58, in get_client_error
ImportError: No localization support for language 'eng'

UnicodeEncodeError when insert unicode

When do insert action, if I use unicode in data field, It raise the UnicodeEncodeError, if I use str, all is well.

# python2.7
db = Medoo(dbtype="sqlite", database="test.db")
name = "foobar"
data = u"测试中文数据"
db.insert('items', {'name': name, 'data': data, 'ctime': int(time.time())})
Traceback (most recent call last):
  File "test.py", line 24, in <module>
    db.insert('items', {'name': name, 'data': data, 'ctime': int(time.time())})
  File "C:\Python27\lib\site-packages\medoo\base.py", line 70, in insert
    sql = self.builder.insert(table, fields, *values)
  File "C:\Python27\lib\site-packages\medoo\builder.py", line 658, in insert
    self._insert(table, values2, fields)
  File "C:\Python27\lib\site-packages\medoo\builder.py", line 560, in _insert
    valterms.append('({})'.format(','.join([Builder.DIALECT.value(iv) for iv in inval])))
  File "C:\Python27\lib\site-packages\medoo\dialect.py", line 39, in value
    return "'{}'".format(str(item).replace("'", "''"))
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-5: ordinal not in range(128)

get method error with none recordsets

If no recordset returned from select method, get method encountered with the following error, maybe it's better to return None.

  File "C:\Develop\Python27\lib\site-packages\medoo\base.py", line 95, in get
    return rs.first()[0]
TypeError: 'NoneType' object has no attribute '__getitem__'

src:

	def get(self, table, columns = '*', where = None, join = None):
		rs = self.select(table, columns, where, join)
		return rs.first()[0]

A back-slash error with MySQL

Hi,
I just found when string ended with a back slash symbol, insertion to mysql fails for syntax error. With sqlite engine, no error occurs for same table and row data.

The error can be reproduced with code below:

# coding: utf-8
from medoo import Medoo

db = Medoo(dbtype='mysql', database='test', host='localhost', user='root', password='root')

db.query('''create table actors
(id integer primary key,
name varchar(25) not null default '',
city varchar(5) not null default '',
note text not null
);''')

db.insert("actors", (1, 'Ellis Ostiguy', 'Londn', 'A Machu Picchu - \\'))

Sqlite not creating database file

Hi,

I found sqlite engine stop working after the latest update. This code snippet will not create the db file. If I run it with earlier version to create the db file, and run it again with 0.0.6, print(tables) will print [].

from medoo import Medoo

db = Medoo(dbtype="sqlite", database="z:\\test.db")
tables = db.query("SELECT name FROM sqlite_master WHERE type='table';")
tables = [x['name'] for x in tables.all()]
print(tables)
if 'books' not in tables:
    db.query('''create table books
        (id integer primary key,
        title varchar(25) not null default '',
        author varchar(6) not null default ''
        );''')

Originally posted by @qijianjun in #6 (comment)

Error while trying to JOIN another DB with different column names

Used Version: 0.1.0
Python Version: 3.10.7

Hey,

today I tried to join a Table based on 2 unequal names column names (Table blueprint ahead).

My SQL Statement is the following:

 SELECT D.device_name, D.lastSeen, D.error_count_since_last_reboot, D.device_firmware_version, D.device_firmware_version_installed, C.icon from devices AS D JOIN deviceTypes AS C ON C.typeID = D.device_firmware_type;

My code is the following:

db.select('devices(D)', 
 'D.device_name, D.lastSeen, D.error_count_since_last_reboot, D.device_firmware_version, D.device_firmware_version_installed, C.icon', 
  join = {'deviceTypes(C)[>]': {'typeID', 'device_firmware_type'}}
)

The table schemes are the following:

Devices:

devices | CREATE TABLE `devices` (
  `device_id` int(11) NOT NULL AUTO_INCREMENT,
  `mac_address` varchar(32) NOT NULL,
  `device_name` varchar(32) NOT NULL,
  `device_update_token` varchar(64) DEFAULT NULL,
  `device_update_password` varchar(128) DEFAULT NULL,
  `used_chip` varchar(32) NOT NULL,
  `device_hostname` varchar(32) NOT NULL DEFAULT '''not_set''',
  `device_firmware_type` int(32) NOT NULL,
  `device_firmware_version` int(12) NOT NULL DEFAULT 0,
  `device_firmware_version_installed` int(12) NOT NULL DEFAULT 0,
  `device_fs_version` varchar(12) NOT NULL DEFAULT '0.1',
  `device_fs_version_installed` varchar(12) NOT NULL DEFAULT '0.1',
  `device_version` varchar(12) NOT NULL DEFAULT '1.0',
  `last_updated` int(11) NOT NULL DEFAULT 0,
  `last_update_check` int(11) NOT NULL DEFAULT 0,
  `device_state` tinyint(4) NOT NULL DEFAULT 0,
  `device_is_locked` tinyint(4) NOT NULL DEFAULT 0,
  `device_update_modify_locked` tinyint(4) NOT NULL DEFAULT 0,
  `device_to_destroy` tinyint(4) NOT NULL DEFAULT 0,
  `device_is_destroyed` tinyint(4) NOT NULL DEFAULT 0,
  `force_update` tinyint(4) NOT NULL DEFAULT 0,
  `ip_address` varchar(32) DEFAULT '0.0.0.0',
  `ip_netmask` varchar(32) DEFAULT '0.0.0.0',
  `ip_gateway` varchar(32) DEFAULT '0.0.0.0',
  `dns_server` varchar(32) DEFAULT '0.0.0.0',
  `ssid` varchar(64) DEFAULT 'not set',
  `uptime` int(11) DEFAULT 0,
  `lastSeen` datetime DEFAULT NULL,
  `error_count_since_last_reboot` int(11) NOT NULL DEFAULT 0,
  `last_error_message_captured` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`device_id`),
  KEY `device_firmware_type` (`device_firmware_type`),
  KEY `device_firmware_version` (`device_firmware_version`),
  KEY `device_firmware_version_installed` (`device_firmware_version_installed`),
  CONSTRAINT `devices_ibfk_1` FOREIGN KEY (`device_firmware_type`) REFERENCES `deviceTypes` (`typeID`),
  CONSTRAINT `devices_ibfk_2` FOREIGN KEY (`device_firmware_version`) REFERENCES `software` (`releaseID`),
  CONSTRAINT `devices_ibfk_3` FOREIGN KEY (`device_firmware_version_installed`) REFERENCES `software` (`releaseID`)
) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=utf8mb4 | 

and the deviceTypes table:

deviceTypes | CREATE TABLE `deviceTypes` (
  `typeID` int(11) NOT NULL AUTO_INCREMENT,
  `typename` varchar(32) NOT NULL,
  `usedChip` varchar(25) NOT NULL DEFAULT 'esp8266',
  `typeDescription` varchar(512) NOT NULL,
  `path` varchar(100) NOT NULL DEFAULT 'general',
  `disabled` tinyint(4) DEFAULT 0,
  `icon` varchar(50) NOT NULL DEFAULT 'bi-cpu',
  PRIMARY KEY (`typeID`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 | ```


I'm not exactly sure if this is a Bug or if I'm to stupid to read the doc. correctly :^) - but imho I think I need to use this:
>>Documentation on PyPi.org

Join on different columns: JOIN "Customers" AS "C" ON "C"."CustomerID"="O"."OtherID"
join = { 'Customers(C)[><]': {'CustomerID', 'OtherID'} }


The error I get from python (Flask) is: 
```        def __init__( [Open an interactive python shell in this frame] 

            self, key, val, maintable=None

        ):  # pylint: disable=too-many-branches

            matching = re.match(JoinTerm.REGEX_KEY, key)

            if not matching:

>>>>     raise JoinParseError("Unrecognized table in JOIN.")    <<<<

            self.jointype = matching.group(1)

            self.table = TableFrom(matching.group(2), alias=matching.group(3))

            self.onfields = []

            fieldtable = self.table.alias or self.table.table

            if isinstance(maintable, TableFrom):

    medoo.exception.JoinParseError: Unrecognized table in JOIN. ```


Hope you can help me ^^

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.